cgal/Packages/Intersections_2/web/intersection_2_1.fw

2424 lines
58 KiB
Plaintext

@i cgal_util.fwi
Bbox_2_Line_2_pair::intersection
@B@<2D Bbox Line intersection@>
@O@<../include/CGAL/Line_2_Bbox_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Line_2_Bbox_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Bbox_2_Line_2_intersection.h>
@}
@O@<../include/CGAL/Bbox_2_Line_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Bbox_2_Line_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#ifndef CGAL_BBOX_2_LINE_2_INTERSECTION_H
#define CGAL_BBOX_2_LINE_2_INTERSECTION_H
#include <CGAL/Bbox_2.h>
#include <CGAL/Line_2.h>
//#include <CGAL/Segment_2.h>
//#include <CGAL/Point_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
class Bbox_2_Line_2_pair_impl;
class Bbox_2_Line_2_pair {
public:
enum Intersection_results {NO, POINT, SEGMENT};
Bbox_2_Line_2_pair() ;
Bbox_2_Line_2_pair(Bbox_2_Line_2_pair const &);
Bbox_2_Line_2_pair(Bbox_2 const &bbox,
double line_a, double line_b, double line_c);
~Bbox_2_Line_2_pair() ;
Bbox_2_Line_2_pair &operator=(Bbox_2_Line_2_pair const &o);
// set_bbox(Bbox_2 const &bbox);
// set_line(double line_a, double line_b, double line_c);
Intersection_results intersection_type() const;
bool intersection(double &x, double &y) const;
bool intersection(double &x1, double &y1, double &x2, double &y2) const;
protected:
Bbox_2_Line_2_pair_impl *pimpl;
};
template <class Line>
Bbox_2_Line_2_pair intersection_computer_line_2(
Bbox_2 const &bbox, Line const &line)
{
return Bbox_2_Line_2_pair(bbox, to_double(line->a()),
to_double(line->b()), to_double(line->c()));
}
inline bool do_intersect_line_2(
const Bbox_2 &box, double line_a, double line_b, double line_c)
{
Bbox_2_Line_2_pair pair(box, line_a, line_b, line_c);
return pair.intersection_type() != Bbox_2_Line_2_pair::NO;
}
template <class Line>
bool do_intersect_line_2(
Bbox_2 const &bbox, Line const &line)
{
return do_intersect_line_2(bbox, to_double(line->a()),
to_double(line->b()), to_double(line->c()));
}
template <class Line>
bool do_intersect_line_2(
Line const &line, Bbox_2 const &bbox)
{
return do_intersect_line_2(bbox, to_double(line->a()),
to_double(line->b()), to_double(line->c()));
}
template <class R>
inline bool do_intersect(
const Line_2<R> &line,
const Bbox_2 &box)
{
return do_intersect(box, line);
}
CGAL_END_NAMESPACE
#endif
@}
@$@<Bbox_2_Line_2_pair implementation@>==@{
CGAL_BEGIN_NAMESPACE
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
Bbox_2_Line_2_pair::Intersection_results
Bbox_2_Line_2_pair::intersection_type() const
@<Bbox_2_Line_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
bool
Bbox_2_Line_2_pair::intersection(
double &x1, double &y1, double &x2, double &y2) const
{
if (!pimpl->_known)
intersection_type();
if (pimpl->_result != SEGMENT)
return false;
Rcart::Point_2 p1(pimpl->_line.point()
+ pimpl->_min*pimpl->_line.direction().to_vector());
Rcart::Point_2 p2(pimpl->_line.point()
+ pimpl->_max*pimpl->_line.direction().to_vector());
x1 = p1.x();
y1 = p1.y();
x2 = p2.x();
y2 = p2.y();
return true;
}
bool
Bbox_2_Line_2_pair::intersection(
double &x, double &y) const
{
if (!pimpl->_known)
intersection_type();
if (pimpl->_result != POINT)
return false;
Rcart::Point_2 pt(pimpl->_line.point()
+ pimpl->_min*pimpl->_line.direction().to_vector());
x = pt.x();
y = pt.y();
return true;
}
CGAL_END_NAMESPACE
@}
The following body of the intersection type member function is used twice.
Once inline (which the g++ compiler wants because of a bug) and once outline.
@$@<Bbox_2_Line_2_pair intersection_type body@>@M==@{@-
{
if (pimpl->_known)
return pimpl->_result;
// The non const this pointer is used to cast away const.
pimpl->_known = true;
const Rcart::Point_2 &ref_point = pimpl->_line.point();
const Rcart::Vector_2 &dir =
pimpl->_line.direction().to_vector();
bool to_infinity = true;
// first on x value
if (dir.x() == 0.0) {
if (ref_point.x() < pimpl->_bbox.xmin()) {
pimpl->_result = NO;
return pimpl->_result;
}
if (ref_point.x() > pimpl->_bbox.xmax()) {
pimpl->_result = NO;
return pimpl->_result;
}
} else {
double newmin, newmax;
if (dir.x() > 0.0) {
newmin = (pimpl->_bbox.xmin()-ref_point.x())/dir.x();
newmax = (pimpl->_bbox.xmax()-ref_point.x())/dir.x();
} else {
newmin = (pimpl->_bbox.xmax()-ref_point.x())/dir.x();
newmax = (pimpl->_bbox.xmin()-ref_point.x())/dir.x();
}
if (to_infinity) {
pimpl->_min = newmin;
pimpl->_max = newmax;
} else {
if (newmin > pimpl->_min)
pimpl->_min = newmin;
if (newmax < pimpl->_max)
pimpl->_max = newmax;
if (pimpl->_max < pimpl->_min) {
pimpl->_result = NO;
return pimpl->_result;
}
}
to_infinity = false;
}
// now on y value
if (dir.y() == 0.0) {
if (ref_point.y() < pimpl->_bbox.ymin()) {
pimpl->_result = NO;
return pimpl->_result;
}
if (ref_point.y() > pimpl->_bbox.ymax()) {
pimpl->_result = NO;
return pimpl->_result;
}
} else {
double newmin, newmax;
if (dir.y() > 0.0) {
newmin = (pimpl->_bbox.ymin()-ref_point.y())/dir.y();
newmax = (pimpl->_bbox.ymax()-ref_point.y())/dir.y();
} else {
newmin = (pimpl->_bbox.ymax()-ref_point.y())/dir.y();
newmax = (pimpl->_bbox.ymin()-ref_point.y())/dir.y();
}
if (to_infinity) {
pimpl->_min = newmin;
pimpl->_max = newmax;
} else {
if (newmin > pimpl->_min)
pimpl->_min = newmin;
if (newmax < pimpl->_max)
pimpl->_max = newmax;
if (pimpl->_max < pimpl->_min) {
pimpl->_result = NO;
return pimpl->_result;
}
}
to_infinity = false;
}
CGAL_kernel_assertion(!to_infinity);
if (pimpl->_max == pimpl->_min) {
pimpl->_result = POINT;
return pimpl->_result;
}
pimpl->_result = SEGMENT;
return pimpl->_result;
}
@}
@$@<Bbox2_2 cartesian double Line_2 intersection@>==@{
CGAL_BEGIN_NAMESPACE
class Bbox_2_Line_2_pair_impl
{
public:
Bbox_2_Line_2_pair_impl() {}
Bbox_2_Line_2_pair_impl(Bbox_2 const &bb, Rcart::Line_2 const &line)
: _bbox(bb), _line(line), _known(false) {}
Bbox_2 _bbox;
Rcart::Line_2 _line;
mutable bool _known;
mutable Bbox_2_Line_2_pair::Intersection_results _result;
mutable double _min, _max;
};
Bbox_2_Line_2_pair::~Bbox_2_Line_2_pair()
{
delete pimpl;
}
Bbox_2_Line_2_pair::Bbox_2_Line_2_pair()
{
pimpl = new Bbox_2_Line_2_pair_impl;
pimpl->_known = false;
}
Bbox_2_Line_2_pair::Bbox_2_Line_2_pair(Bbox_2_Line_2_pair const &o)
{
pimpl = new Bbox_2_Line_2_pair_impl(*o.pimpl);
}
Bbox_2_Line_2_pair::Bbox_2_Line_2_pair(
Bbox_2 const &bbox, double line_a, double line_b, double line_c)
{
pimpl = new Bbox_2_Line_2_pair_impl(bbox,
Rcart::Line_2(line_a, line_b, line_c));
}
Bbox_2_Line_2_pair &
Bbox_2_Line_2_pair::operator=(Bbox_2_Line_2_pair const &o)
{
*pimpl = *o.pimpl;
return *this;
}
CGAL_END_NAMESPACE
@<Bbox_2_Line_2_pair implementation@>
@}
@B@<2D Ray Bbox intersection@>
@O@<../include/CGAL/Bbox_2_Ray_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Bbox_2_Ray_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Ray_2_Bbox_2_intersection.h>
@}
@O@<../include/CGAL/Ray_2_Bbox_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Ray_2_Bbox_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_RAY_2_BBOX_2_INTERSECTION_H
#define CGAL_RAY_2_BBOX_2_INTERSECTION_H
#include <CGAL/Bbox_2.h>
#include <CGAL/Ray_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
class Bbox_2_Ray_2_pair_impl;
class Bbox_2_Ray_2_pair {
public:
enum Intersection_results {NO, POINT, SEGMENT};
~Bbox_2_Ray_2_pair() ;
Bbox_2_Ray_2_pair() ;
Bbox_2_Ray_2_pair(Bbox_2_Ray_2_pair const &o) ;
Bbox_2_Ray_2_pair(Bbox_2 const &box,
double x, double y, double dx, double dy) ;
Bbox_2_Ray_2_pair& operator=(Bbox_2_Ray_2_pair const &o) ;
Intersection_results intersection_type() const;
bool intersection(double &x, double &y) const;
bool intersection(double &x1, double &y1, double &x2, double &y2) const;
protected:
Bbox_2_Ray_2_pair_impl *pimpl;
};
bool do_intersect_ray_2(
const Bbox_2 &box, double x, double y, double dx, double dy);
template <class Ray>
bool do_intersect_ray_2(
const Bbox_2 &box,
const Ray &ray)
{
double startx = to_double(ray->start().x());
double starty = to_double(ray->start().y());
double dx = to_double(ray->direction().to_vector().x());
double dy = to_double(ray->direction().to_vector().y());
return do_intersect_ray_2(box, startx, starty, dx, dy);
}
template <class Ray>
inline bool do_intersect_ray_2(
const Ray &ray,
const Bbox_2 &box)
{
return do_intersect_ray_2(box, ray);
}
CGAL_END_NAMESPACE
#endif
@}
@$@<Ray_2_Bbox_2_pair implementation@>==@{
CGAL_BEGIN_NAMESPACE
Bbox_2_Ray_2_pair::Intersection_results
Bbox_2_Ray_2_pair::intersection_type() const
@<Ray_2_Bbox_2_pair intersection_type body@>
bool Bbox_2_Ray_2_pair::
intersection(double &x1, double &y1, double &x2, double &y2) const
{
if (!pimpl->_known)
intersection_type();
if (pimpl->_result != SEGMENT)
return false;
Rcart::Point_2 p1(pimpl->_ref_point + pimpl->_min*pimpl->_dir);
Rcart::Point_2 p2(pimpl->_ref_point + pimpl->_max*pimpl->_dir);
x1 = p1.x();
y1 = p1.y();
x2 = p2.x();
y2 = p2.y();
return true;
}
bool Bbox_2_Ray_2_pair::intersection(double &x, double &y) const
{
if (!pimpl->_known)
intersection_type();
if (pimpl->_result != POINT)
return false;
Rcart::Point_2 pt = pimpl->_ref_point + pimpl->_min*pimpl->_dir;
x = pt.x();
y = pt.y();
return true;
}
bool do_intersect_ray_2(
const Bbox_2 &box, double x, double y, double dx, double dy)
{
Bbox_2_Ray_2_pair pair(box, x, y, dx, dy);
return pair.intersection_type() != Bbox_2_Ray_2_pair::NO;
}
CGAL_END_NAMESPACE
@}
@$@<Ray_2_Bbox_2_pair intersection_type body@>@M==@{@-
{
if (pimpl->_known)
return pimpl->_result;
pimpl->_known = true;
bool to_infinity = true;
// first on x value
if (pimpl->_dir.x() == 0.0) {
if (pimpl->_ref_point.x() < pimpl->_box.xmin()) {
pimpl->_result = NO;
return pimpl->_result;
}
if (pimpl->_ref_point.x() > pimpl->_box.xmax()) {
pimpl->_result = NO;
return pimpl->_result;
}
} else {
double newmin, newmax;
if (pimpl->_dir.x() > 0.0) {
newmin =(pimpl->_box.xmin()-pimpl->_ref_point.x())/pimpl->_dir.x();
newmax =(pimpl->_box.xmax()-pimpl->_ref_point.x())/pimpl->_dir.x();
} else {
newmin =(pimpl->_box.xmax()-pimpl->_ref_point.x())/pimpl->_dir.x();
newmax =(pimpl->_box.xmin()-pimpl->_ref_point.x())/pimpl->_dir.x();
}
if (newmin > pimpl->_min)
pimpl->_min = newmin;
if (to_infinity) {
pimpl->_max = newmax;
} else {
if (newmax < pimpl->_max)
pimpl->_max = newmax;
}
if (pimpl->_max < pimpl->_min){
pimpl->_result = NO;
return pimpl->_result;
}
to_infinity = false;
}
// now on y value
if (pimpl->_dir.y() == 0.0) {
if (pimpl->_ref_point.y() < pimpl->_box.ymin()) {
pimpl->_result = NO;
return pimpl->_result;
}
if (pimpl->_ref_point.y() > pimpl->_box.ymax()) {
pimpl->_result = NO;
return pimpl->_result;
}
} else {
double newmin, newmax;
if (pimpl->_dir.y() > 0.0) {
newmin =(pimpl->_box.ymin()-pimpl->_ref_point.y())/pimpl->_dir.y();
newmax =(pimpl->_box.ymax()-pimpl->_ref_point.y())/pimpl->_dir.y();
} else {
newmin =(pimpl->_box.ymax()-pimpl->_ref_point.y())/pimpl->_dir.y();
newmax =(pimpl->_box.ymin()-pimpl->_ref_point.y())/pimpl->_dir.y();
}
if (newmin > pimpl->_min)
pimpl->_min = newmin;
if (to_infinity) {
pimpl->_max = newmax;
} else {
if (newmax < pimpl->_max)
pimpl->_max = newmax;
}
if (pimpl->_max < pimpl->_min) {
pimpl->_result = NO;
return pimpl->_result;
}
to_infinity = false;
}
CGAL_kernel_assertion(!to_infinity);
if (pimpl->_max == pimpl->_min) {
pimpl->_result = POINT;
return pimpl->_result;
}
pimpl->_result = SEGMENT;
return pimpl->_result;
}
@}
@$@<Bbox2_2 cartesian double Ray_2 intersection@>==@{
CGAL_BEGIN_NAMESPACE
class Bbox_2_Ray_2_pair_impl
{
public:
Bbox_2_Ray_2_pair_impl():_known(false) {}
Bbox_2_Ray_2_pair_impl(Bbox_2 const &bbox, Rcart::Point_2 const &pt,
Rcart::Vector_2 const &dir)
:_box(bbox), _known(false), _ref_point(pt), _dir(dir), _min(0.0) {}
Ray_2< Rcart > _ray;
Bbox_2 _box;
bool _known;
Bbox_2_Ray_2_pair::Intersection_results _result;
Rcart::Point_2 _ref_point;
Rcart::Vector_2 _dir;
double _min, _max;
};
Bbox_2_Ray_2_pair::~Bbox_2_Ray_2_pair()
{
delete pimpl;
}
Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair()
{
pimpl = new Bbox_2_Ray_2_pair_impl;
}
Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair(Bbox_2_Ray_2_pair const &o)
{
pimpl = new Bbox_2_Ray_2_pair_impl(*o.pimpl);
}
Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair(
Bbox_2 const &bbox, double x, double y, double dx, double dy)
{
pimpl = new Bbox_2_Ray_2_pair_impl(bbox,
Rcart::Point_2(x,y), Rcart::Vector_2(dx,dy));
}
Bbox_2_Ray_2_pair &
Bbox_2_Ray_2_pair::operator=(Bbox_2_Ray_2_pair const &o)
{
*pimpl = *o.pimpl;
return *this;
}
CGAL_END_NAMESPACE
@<Ray_2_Bbox_2_pair implementation@>
@}
@O@<../include/CGAL/Line_2_Line_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Line_2_Line_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_LINE_2_LINE_2_INTERSECTION_H
#define CGAL_LINE_2_LINE_2_INTERSECTION_H
#include <CGAL/Line_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
template <class R>
class Line_2_Line_2_pair {
public:
enum Intersection_results {NO, POINT, LINE};
Line_2_Line_2_pair() ;
Line_2_Line_2_pair(Line_2<R> const *line1,
Line_2<R> const *line2);
~Line_2_Line_2_pair() {}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
Intersection_results intersection_type() const;
#else
Intersection_results intersection_type() const
@<Line_2_Line_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
bool intersection(Point_2<R> &result) const;
bool intersection(Line_2<R> &result) const;
protected:
Line_2<R> const* _line1;
Line_2<R> const * _line2;
mutable bool _known;
mutable Intersection_results _result;
mutable Point_2<R> _intersection_point;
};
@<do_intersect macro@>@(Line_2@,Line_2@)
CGAL_END_NAMESPACE
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Line_2<R> &line1, const Line_2<R> &line2)
{
typedef Line_2_Line_2_pair<R> is_t;
is_t linepair(&line1, &line2);
switch (linepair.intersection_type()) {
case is_t::NO:
default:
return Object();
case is_t::POINT: {
Point_2<R> pt;
linepair.intersection(pt);
return make_object(pt);
}
case is_t::LINE:
return make_object(line1);
}
}
CGAL_END_NAMESPACE
@<Line_2_Line_2_pair implementation@>
#endif
@}
Momentarily, we use a help function to construct the intersection point and
check whether this point is valid.
Because the template mechanism of the compilers do not yet comply to the
(proposed) standard, we use the following implementation.
Note that @{R::FT@} should actually be @{typename R::FT@}.
@$@<Line_2_Line_2_pair implementation@>+=@{
CGAL_BEGIN_NAMESPACE
template <class R, class POINT, class RT>
bool construct_if_finite(POINT &pt, RT x, RT y, RT w, R &)
{
typedef typename R::FT FT;
CGAL_kernel_precondition(::CGAL::is_finite(x)
&& ::CGAL::is_finite(y)
&& w != RT(0));
FT xw = FT(x)/FT(w);
FT yw = FT(y)/FT(w);
if (!::CGAL::is_finite(xw) || !::CGAL::is_finite(yw))
return false;
pt = POINT(x, y, w);
return true;
}
CGAL_END_NAMESPACE
@}
A not working, but conformant implementation is the following.
Note that this function should be called with an explicit template argument
specified: @{construct_if_finite<R>(pt, x, y, w);@}.
@$@<temporarily not used@>@Z+=@{
CGAL_BEGIN_NAMESPACE
template <class R>
bool construct_if_finite(Point_2<R> &pt,
typename R::RT x, typename R::RT y, typename R::RT w)
{
typedef typename R::FT FT;
typedef typename R::RT RT;
CGAL_kernel_precondition(::CGAL::is_finite(x)
&& ::CGAL::is_finite(y) && w != (RT) 0);
FT xw = FT(x)/FT(w);
FT yw = FT(y)/FT(w);
if (!::CGAL::is_finite(xw) || !::CGAL::is_finite(yw))
return false;
pt = Point_2<R>(x, y, w);
return true;
}
CGAL_END_NAMESPACE
@}
@$@<Line_2_Line_2_pair implementation@>+=@{@-
CGAL_BEGIN_NAMESPACE
template <class R>
Line_2_Line_2_pair<R>::Line_2_Line_2_pair()
{
_line1 = 0;
_line2 = 0;
_known = false;
}
template <class R>
Line_2_Line_2_pair<R>::Line_2_Line_2_pair(
Line_2<R> const *line1, Line_2<R> const *line2)
{
_line1 = line1;
_line2 = line2;
_known = false;
}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
typename Line_2_Line_2_pair<R>::Intersection_results
Line_2_Line_2_pair<R>::intersection_type() const
@<Line_2_Line_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
bool
Line_2_Line_2_pair<R>::intersection(Point_2<R> &pt) const
{
if (!_known)
intersection_type();
if (_result != POINT)
return false;
pt = _intersection_point;
return true;
}
template <class R>
bool
Line_2_Line_2_pair<R>::intersection(Line_2<R> &l) const
{
if (!_known)
intersection_type();
if (_result != LINE)
return false;
l = *_line1;
return true;
}
CGAL_END_NAMESPACE
@}
@$@<Line_2_Line_2_pair intersection_type body@>@M==@{@-
{
typedef typename R::RT RT;
if (_known)
return _result;
RT nom1, nom2, denom;
// The non const this pointer is used to cast away const.
_known = true;
denom = _line1->a()*_line2->b() - _line2->a()*_line1->b();
if (denom == RT(0)) {
if (RT(0) == (_line1->a()*_line2->c() - _line2->a()*_line1->c()) &&
RT(0) == (_line1->b()*_line2->c() - _line2->b()*_line1->c()))
_result = LINE;
else
_result = NO;
return _result;
}
nom1 = (_line1->b()*_line2->c() - _line2->b()*_line1->c());
if (!::CGAL::is_finite(nom1)) {
_result = NO;
return _result;
}
nom2 = (_line2->a()*_line1->c() - _line1->a()*_line2->c());
if (!::CGAL::is_finite(nom2)) {
_result = NO;
return _result;
}
R dummyR;
if (!construct_if_finite(_intersection_point,
nom1, nom2, denom, dummyR)){
_result = NO;
return _result;
}
_result = POINT;
return _result;
}
@}
@B@<2D Segment Line intersection@>
@O@<../include/CGAL/Line_2_Segment_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Line_2_Segment_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Segment_2_Line_2_intersection.h>
@}
@O@<../include/CGAL/Segment_2_Line_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Segment_2_Line_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_SEGMENT_2_LINE_2_INTERSECTION_H
#define CGAL_SEGMENT_2_LINE_2_INTERSECTION_H
#include <CGAL/Line_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
template <class R>
class Segment_2_Line_2_pair {
public:
enum Intersection_results {NO, POINT, SEGMENT};
Segment_2_Line_2_pair() ;
Segment_2_Line_2_pair(Segment_2<R> const *seg,
Line_2<R> const *line);
~Segment_2_Line_2_pair() {}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
Intersection_results intersection_type() const;
#else
Intersection_results intersection_type() const
@<Segment_2_Line_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
bool intersection(Point_2<R> &result) const;
bool intersection(Segment_2<R> &result) const;
protected:
Segment_2<R> const*_seg;
Line_2<R> const * _line;
mutable bool _known;
mutable Intersection_results _result;
mutable Point_2<R> _intersection_point;
};
@<do_intersect macro@>@(Segment_2@,Line_2@)
CGAL_END_NAMESPACE
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Segment_2<R> &seg, const Line_2<R> &line)
{
typedef Segment_2_Line_2_pair<R> is_t;
is_t ispair(&seg, &line);
switch (ispair.intersection_type()) {
case is_t::NO:
default:
return Object();
case is_t::POINT: {
Point_2<R> pt;
ispair.intersection(pt);
return make_object(pt);
}
case is_t::SEGMENT:
return make_object(seg);
}
}
template <class R>
class Line_2_Segment_2_pair: public Segment_2_Line_2_pair<R> {
public:
Line_2_Segment_2_pair(
Line_2<R> const *line,
Segment_2<R> const *seg) :
Segment_2_Line_2_pair<R>(seg, line) {}
};
@<do_intersect macro@>@(Line_2@,Segment_2@)
template <class R>
inline Object
intersection(const Line_2<R> &line, const Segment_2<R> &seg)
{
return intersection(seg, line);
}
CGAL_END_NAMESPACE
@<Segment_2_Line_2_pair implementation@>
#endif
@}
@$@<Segment_2_Line_2_pair implementation@>==@{
#include <CGAL/Line_2_Line_2_intersection.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Segment_2_Line_2_pair<R>::Segment_2_Line_2_pair()
{
_seg = 0;
_line = 0;
_known = false;
}
template <class R>
Segment_2_Line_2_pair<R>::Segment_2_Line_2_pair(
Segment_2<R> const *seg, Line_2<R> const *line)
{
_seg = seg;
_line = line;
_known = false;
}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
typename Segment_2_Line_2_pair<R>::Intersection_results
Segment_2_Line_2_pair<R>::intersection_type() const
@<Segment_2_Line_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
bool
Segment_2_Line_2_pair<R>::intersection(Point_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != POINT)
return false;
result = _intersection_point;
return true;
}
template <class R>
bool
Segment_2_Line_2_pair<R>::intersection(Segment_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != SEGMENT)
return false;
result = *_seg;
return true;
}
CGAL_END_NAMESPACE
@}
@$@<Segment_2_Line_2_pair intersection_type body@>@M==@{@-
{
if (_known)
return _result;
// The non const this pointer is used to cast away const.
_known = true;
const Line_2<R> &l1 = _seg->supporting_line();
Line_2_Line_2_pair<R> linepair(&l1, _line);
switch ( linepair.intersection_type()) {
case Line_2_Line_2_pair<R>::NO:
_result = NO;
break;
case Line_2_Line_2_pair<R>::POINT:
linepair.intersection(_intersection_point);
_result = (_seg->collinear_has_on(_intersection_point) )
? POINT : NO;
break;
case Line_2_Line_2_pair<R>::LINE:
_result = SEGMENT;
break;
}
return _result;
}
@}
@B@<2D Segment Segment intersection@>
@O@<../include/CGAL/Segment_2_Segment_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Segment_2_Segment_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_SEGMENT_2_SEGMENT_2_INTERSECTION_H
#define CGAL_SEGMENT_2_SEGMENT_2_INTERSECTION_H
#include <CGAL/Segment_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
template <class R>
class Segment_2_Segment_2_pair {
public:
enum Intersection_results {NO, POINT, SEGMENT};
Segment_2_Segment_2_pair() ;
Segment_2_Segment_2_pair(Segment_2<R> const *seg1,
Segment_2<R> const *seg2);
~Segment_2_Segment_2_pair() {}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
Intersection_results intersection_type() const;
#else
Intersection_results intersection_type() const
@<Segment_2_Segment_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
bool intersection(Point_2<R> &result) const;
bool intersection(Segment_2<R> &result) const;
protected:
Segment_2<R> const* _seg1;
Segment_2<R> const * _seg2;
mutable bool _known;
mutable Intersection_results _result;
mutable Point_2<R> _intersection_point, _other_point;
};
template <class R>
inline bool
do_intersect(const Segment_2<R> &seg1, const Segment_2<R> &seg2);
CGAL_END_NAMESPACE
@<Segment_2_Segment_2 do_intersect implementation@>
@<Segment_2_Segment_2_pair implementation@>
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Segment_2<R> &seg1, const Segment_2<R>&seg2)
{
typedef Segment_2_Segment_2_pair<R> is_t;
is_t ispair(&seg1, &seg2);
switch (ispair.intersection_type()) {
case is_t::NO:
default:
return Object();
case is_t::POINT: {
Point_2<R> pt;
ispair.intersection(pt);
return make_object(pt);
}
case is_t::SEGMENT: {
Segment_2<R> iseg;
ispair.intersection(iseg);
return make_object(iseg);
}
}
}
CGAL_END_NAMESPACE
#endif
@}
The segment segment intersection test implementation can best be understood
as a line sweep algorithm. The endpoints of the segments are sorted
(lexicographically, first along x then along y coordinate).
In the sweep, the first two point that are inserted second should be from
different segments (otherwise, the segments don't intersect because they
can be separated by a vertical line).
We check for the second and third inserted point on which side of the line
through the other segment they lie. (The other segment can be the same for
both points -the contained case- or different -the crossing case).
@$@<Segment_2_Segment_2 do_intersect implementation@>==@{
#include <cassert>
#include <CGAL/predicates_on_points_2.h>
namespace CGAL {
@<seg_seg do_intersect case crossing@>
@<seg_seg do_intersect case contained@>
template <class R>
bool
do_intersect(const Segment_2<R> &seg1, const Segment_2<R> &seg2)
{
typename R::Point_2 const & A1 = seg1.source();
typename R::Point_2 const & A2 = seg1.target();
typename R::Point_2 const & B1 = seg2.source();
typename R::Point_2 const & B2 = seg2.target();
@<seg_seg do_intersect y-test@>
if (lexicographically_xy_smaller(A1,A2)) {
@<seg seg do_intersect step 1@>@(A1@,A2@,B1@,B2@)
} else {
@<seg seg do_intersect step 1@>@(A2@,A1@,B1@,B2@)
}
CGAL_kernel_assertion(false);
return false;
}
} // end namespace CGAL
@}
At step 1 we know that argument 2 is not lexicograpically smaller than
argument 1.
@$@<seg seg do_intersect step 1@>@(@4@)@M==@{@-
if (lexicographically_xy_smaller(@3,@4)) {
@<seg seg do_intersect step 2@>@(@1@,@2@,@3@,@4@)
} else {
@<seg seg do_intersect step 2@>@(@1@,@2@,@4@,@3@)
}@-
@}
At step 2 we know that argument 1 lexicograpically smaller than (or equal to)
argument 2 and argument 3 is smaller than (or equal to) argument 4.
@$@<seg seg do_intersect step 2@>@(@4@)@M==@{@-
switch(compare_lexicographically_xy(@1,@3)) {
case SMALLER:
@<seg seg do_intersect step 3@>@(@1@,@2@,@3@,@4@)
case EQUAL:
return true;
case LARGER:
@<seg seg do_intersect step 3@>@(@3@,@4@,@1@,@2@)
}@-
@}
At step 3 we know that argument 1 lexicograpically smaller than
argument 3.
@$@<seg seg do_intersect step 3@>@(@4@)@M==@{@-
switch(compare_lexicographically_xy(@2,@3)) {
case SMALLER:
return false;
case EQUAL:
return true;
case LARGER:
@<seg seg do_intersect step 4@>@(@1@,@2@,@3@,@4@)
}@-
@}
At step 4 we know that argument 1 < argument 3 < argument 2
and that argument 3 <= argument 4
@$@<seg seg do_intersect step 4@>@(@4@)@M==@{@-
switch(compare_lexicographically_xy(@2,@4)) {
case SMALLER:
return seg_seg_do_intersect_crossing(@1,@2,@3,@4);
case EQUAL:
return true;
case LARGER:
return seg_seg_do_intersect_contained(@1,@2,@3,@4);
}@-
@}
// precondition: p1<p3<p2<p4
@$@<seg_seg do_intersect case crossing@>==@{
template <class PT>
bool seg_seg_do_intersect_crossing(
PT const &p1, PT const &p2, PT const &p3, PT const &p4)
{
switch (orientation(p1,p2,p3)) {
case LEFT_TURN:
return !right_turn(p3,p4,p2);
case RIGHT_TURN:
return !left_turn(p3,p4,p2);
case COLLINEAR:
return true;
}
CGAL_kernel_assertion(false);
return false;
}
@}
// precondition: p1<p3<=p4<p2
@$@<seg_seg do_intersect case contained@>==@{
template <class PT>
bool seg_seg_do_intersect_contained(
PT const &p1, PT const &p2, PT const &p3, PT const &p4)
{
switch (orientation(p1,p2,p3)) {
case LEFT_TURN:
return !left_turn(p1,p2,p4);
case RIGHT_TURN:
return !right_turn(p1,p2,p4);
case COLLINEAR:
return true;
}
CGAL_kernel_assertion(false);
return false;
}
@}
The y-test tests if the segments have an interval in common in the y-direction.
This is not necessary for the correctness of the computation, but it leads to
a similar computation time for symmetric cases. Together with the tests on
x coordinates this is effectively a bounding box test.
Comparing coordinates is usually cheaper than orientation tests, so I expect
that this test will help efficiency on average.
@$@<seg_seg do_intersect y-test@>==@{@-
if (lexicographically_yx_smaller(A1,A2)) {
if (lexicographically_yx_smaller(B1,B2)) {
if (lexicographically_yx_smaller(A2,B1)
|| lexicographically_yx_smaller(B2,A1))
return false;
} else {
if (lexicographically_yx_smaller(A2,B2)
|| lexicographically_yx_smaller(B1,A1))
return false;
}
} else {
if (lexicographically_yx_smaller(B1,B2)) {
if (lexicographically_yx_smaller(A1,B1)
|| lexicographically_yx_smaller(B2,A2))
return false;
} else {
if (lexicographically_yx_smaller(A1,B2)
|| lexicographically_yx_smaller(B1,A2))
return false;
}
}@-
@}
@$@<Segment_2_Segment_2_pair implementation@>==@{
#include <CGAL/Line_2.h>
#include <CGAL/Line_2_Line_2_intersection.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Segment_2_Segment_2_pair<R>::Segment_2_Segment_2_pair()
{
_seg1 = 0;
_seg2 = 0;
_known = false;
}
template <class R>
Segment_2_Segment_2_pair<R>::Segment_2_Segment_2_pair(
Segment_2<R> const *seg1, Segment_2<R> const *seg2)
{
_seg1 = seg1;
_seg2 = seg2;
_known = false;
}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
typename Segment_2_Segment_2_pair<R>::Intersection_results
Segment_2_Segment_2_pair<R>::intersection_type() const
@<Segment_2_Segment_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
bool
Segment_2_Segment_2_pair<R>::intersection(Point_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != POINT)
return false;
result = _intersection_point;
return true;
}
template <class R>
bool
Segment_2_Segment_2_pair<R>::intersection(Segment_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != SEGMENT)
return false;
result = Segment_2<R>(_intersection_point, _other_point);
return true;
}
CGAL_END_NAMESPACE
@}
@$@<Segment_2_Segment_2_pair intersection_type body@>@M==@{@-
{
if (_known)
return _result;
_known = true;
if (!do_intersect(*_seg1, *_seg2)) {
_result = NO;
return _result;
}
Line_2<R> const &l1 = _seg1->supporting_line();
Line_2<R> const &l2 = _seg2->supporting_line();
Line_2_Line_2_pair<R> linepair(&l1, &l2);
switch ( linepair.intersection_type()) {
case Line_2_Line_2_pair<R>::NO:
_result = NO;
break;
case Line_2_Line_2_pair<R>::POINT:
linepair.intersection(_intersection_point);
_result = POINT;
break;
case Line_2_Line_2_pair<R>::LINE:
@<Segment_2_Segment_2_pair collinear case@>
}
return _result;
}
@}
@C@<Collinear Case@>
We decide on a main direction (x or y) in which the segment changes
the fastest.
@$@<Segment_2_Segment_2_pair collinear case@>==@{@-
{
typedef typename R::RT RT;
Point_2<R> const &start1 = _seg1->start();
Point_2<R> const &end1 = _seg1->end();
Point_2<R> const &start2 = _seg2->start();
Point_2<R> const &end2 = _seg2->end();
Vector_2<R> diff1 = end1-start1;
Point_2<R> const *minpt;
Point_2<R> const *maxpt;
if (CGAL_NTS abs(diff1.x()) > CGAL_NTS abs(diff1.y())) {
@<Segment_2_Segment_2_pair collinear case 2@>@(x@)
} else {
@<Segment_2_Segment_2_pair collinear case 2@>@(y@)
}
} @-
@}
The first parameter in the following macro should either be x or y.
The macro sorts the four endpoints of the two segments according to this
parameter. Then a check is made to see if there is an overlapping interval.
@$@<Segment_2_Segment_2_pair collinear case 2@>@(@1@)@M==@{@-
if (start1.@1() < end1.@1()) {
minpt = &start1;
maxpt = &end1;
} else {
minpt = &end1;
maxpt = &start1;
}
if (start2.@1() < end2.@1()) {
if (start2.@1() > minpt->@1()) {
minpt = &start2;
}
if (end2.@1() < maxpt->@1()) {
maxpt = &end2;
}
} else {
if (end2.@1() > minpt->@1()) {
minpt = &end2;
}
if (start2.@1() < maxpt->@1()) {
maxpt = &start2;
}
}
if (maxpt->@1() < minpt->@1()) {
_result = NO;
return _result;
}
if (maxpt->@1() == minpt->@1()) {
_intersection_point = *minpt;
_result = POINT;
return _result;
}
_intersection_point = *minpt;
_other_point = *maxpt;
_result = SEGMENT;
return _result; @-
@}
@B@<2D Ray Line intersection@>
@O@<../include/CGAL/Line_2_Ray_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Line_2_Ray_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Ray_2_Line_2_intersection.h>
@}
@O@<../include/CGAL/Ray_2_Line_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Ray_2_Line_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_RAY_2_LINE_2_INTERSECTION_H
#define CGAL_RAY_2_LINE_2_INTERSECTION_H
#include <CGAL/Line_2.h>
#include <CGAL/Ray_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
template <class R>
class Ray_2_Line_2_pair {
public:
enum Intersection_results {NO, POINT, RAY};
Ray_2_Line_2_pair() ;
Ray_2_Line_2_pair(Ray_2<R> const *ray,
Line_2<R> const *line);
~Ray_2_Line_2_pair() {}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
Intersection_results intersection_type() const;
#else
Intersection_results intersection_type() const
@<Ray_2_Line_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
bool intersection(Point_2<R> &result) const;
bool intersection(Ray_2<R> &result) const;
protected:
Ray_2<R> const * _ray;
Line_2<R> const * _line;
mutable bool _known;
mutable Intersection_results _result;
mutable Point_2<R> _intersection_point;
};
@<do_intersect macro@>@(Ray_2@,Line_2@)
CGAL_END_NAMESPACE
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Ray_2<R> &ray, const Line_2<R>&line)
{
typedef Ray_2_Line_2_pair<R> is_t;
is_t ispair(&ray, &line);
switch (ispair.intersection_type()) {
case is_t::NO:
default:
return Object();
case is_t::POINT: {
Point_2<R> pt;
ispair.intersection(pt);
return make_object(pt);
}
case is_t::RAY: {
return make_object(ray);
}
}
}
template <class R>
class Line_2_Ray_2_pair: public Ray_2_Line_2_pair<R> {
public:
Line_2_Ray_2_pair(
Line_2<R> const *line,
Ray_2<R> const *ray) :
Ray_2_Line_2_pair<R>(ray, line) {}
};
@<do_intersect macro@>@(Line_2@,Ray_2@)
template <class R>
inline Object
intersection(const Line_2<R> &line, const Ray_2<R> &ray)
{
return intersection(ray, line);
}
CGAL_END_NAMESPACE
@<Ray_2_Line_2_pair implementation@>
#endif
@}
@$@<Ray_2_Line_2_pair implementation@>==@{
#include <CGAL/Line_2_Line_2_intersection.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Ray_2_Line_2_pair<R>::Ray_2_Line_2_pair()
{
_ray = 0;
_line = 0;
_known = false;
}
template <class R>
Ray_2_Line_2_pair<R>::Ray_2_Line_2_pair(
Ray_2<R> const *ray, Line_2<R> const *line)
{
_ray = ray;
_line = line;
_known = false;
}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
typename Ray_2_Line_2_pair<R>::Intersection_results
Ray_2_Line_2_pair<R>::intersection_type() const
@<Ray_2_Line_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
bool
Ray_2_Line_2_pair<R>::intersection(Point_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != POINT)
return false;
result = _intersection_point;
return true;
}
template <class R>
bool
Ray_2_Line_2_pair<R>::intersection(Ray_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != RAY)
return false;
result = *_ray;
return true;
}
CGAL_END_NAMESPACE
@}
@$@<Ray_2_Line_2_pair intersection_type body@>@M==@{@-
{
if (_known)
return _result;
// The non const this pointer is used to cast away const.
_known = true;
const Line_2<R> &l1 = _ray->supporting_line();
Line_2_Line_2_pair<R> linepair(&l1, _line);
switch ( linepair.intersection_type()) {
case Line_2_Line_2_pair<R>::NO:
_result = NO;
break;
case Line_2_Line_2_pair<R>::POINT:
linepair.intersection(_intersection_point);
_result = (_ray->collinear_has_on(_intersection_point) ) ?
POINT : NO;
break;
case Line_2_Line_2_pair<R>::LINE:
_result = RAY;
break;
}
return _result;
}
@}
@B@<2D Ray Segment intersection@>
@O@<../include/CGAL/Segment_2_Ray_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Segment_2_Ray_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Ray_2_Segment_2_intersection.h>
@}
@O@<../include/CGAL/Ray_2_Segment_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Ray_2_Segment_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_RAY_2_SEGMENT_2_INTERSECTION_H
#define CGAL_RAY_2_SEGMENT_2_INTERSECTION_H
#include <CGAL/Ray_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
template <class R>
class Ray_2_Segment_2_pair {
public:
enum Intersection_results {NO, POINT, SEGMENT};
Ray_2_Segment_2_pair() ;
Ray_2_Segment_2_pair(Ray_2<R> const *ray,
Segment_2<R> const *line);
~Ray_2_Segment_2_pair() {}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
Intersection_results intersection_type() const;
#else
Intersection_results intersection_type() const
@<Ray_2_Segment_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
bool intersection(Point_2<R> &result) const;
bool intersection(Segment_2<R> &result) const;
protected:
Ray_2<R> const * _ray;
Segment_2<R> const * _seg;
mutable bool _known;
mutable Intersection_results _result;
mutable Point_2<R> _intersection_point, _other_point;
};
@<do_intersect macro@>@(Ray_2@,Segment_2@)
CGAL_END_NAMESPACE
@<Ray_2_Segment_2_pair implementation@>
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Ray_2<R> &ray, const Segment_2<R>&seg)
{
typedef Ray_2_Segment_2_pair<R> is_t;
is_t ispair(&ray, &seg);
switch (ispair.intersection_type()) {
case is_t::NO:
default:
return Object();
case is_t::POINT: {
Point_2<R> pt;
ispair.intersection(pt);
return make_object(pt);
}
case is_t::SEGMENT: {
Segment_2<R> iseg;
ispair.intersection(iseg);
return make_object(iseg);
}
}
}
template <class R>
class Segment_2_Ray_2_pair: public Ray_2_Segment_2_pair<R> {
public:
Segment_2_Ray_2_pair(
Segment_2<R> const *seg,
Ray_2<R> const *ray) :
Ray_2_Segment_2_pair<R>(ray, seg) {}
};
@<do_intersect macro@>@(Segment_2@,Ray_2@)
template <class R>
inline Object
intersection(const Segment_2<R> &seg, const Ray_2<R> &ray)
{
return intersection(ray, seg);
}
CGAL_END_NAMESPACE
#endif
@}
@$@<Ray_2_Segment_2_pair implementation@>==@{
#include <CGAL/Line_2.h>
#include <CGAL/Line_2_Line_2_intersection.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Ray_2_Segment_2_pair<R>::Ray_2_Segment_2_pair()
{
_ray = 0;
_seg = 0;
_known = false;
}
template <class R>
Ray_2_Segment_2_pair<R>::Ray_2_Segment_2_pair(
Ray_2<R> const *ray, Segment_2<R> const *seg)
{
_ray = ray;
_seg = seg;
_known = false;
}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
typename Ray_2_Segment_2_pair<R>::Intersection_results
Ray_2_Segment_2_pair<R>::intersection_type() const
@<Ray_2_Segment_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
bool
Ray_2_Segment_2_pair<R>::intersection(Point_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != POINT)
return false;
result = _intersection_point;
return true;
}
template <class R>
bool
Ray_2_Segment_2_pair<R>::intersection(Segment_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != SEGMENT)
return false;
result = Segment_2<R>(_intersection_point, _other_point);
return true;
}
CGAL_END_NAMESPACE
@}
@$@<Ray_2_Segment_2_pair intersection_type body@>@M==@{@-
{
if (_known)
return _result;
// The non const this pointer is used to cast away const.
_known = true;
// if (!do_overlap(_ray->bbox(), _seg->bbox()))
// return NO;
const Line_2<R> &l1 = _ray->supporting_line();
const Line_2<R> &l2 = _seg->supporting_line();
Line_2_Line_2_pair<R> linepair(&l1, &l2);
switch ( linepair.intersection_type()) {
case Line_2_Line_2_pair<R>::NO:
_result = NO;
return _result;
case Line_2_Line_2_pair<R>::POINT:
linepair.intersection(_intersection_point);
_result = (_ray->collinear_has_on(_intersection_point)
&& _seg->collinear_has_on(_intersection_point) )
? POINT : NO;
return _result;
case Line_2_Line_2_pair<R>::LINE: {
@<Ray_2_Segment_2_pair collinear case@>
}
default:
CGAL_kernel_assertion(false); // should not be reached:
return _result;
}
}
@}
@C@<Collinear Case@>
We decide on a main direction (x or y) in which the segment changes
the fastest.
@$@<Ray_2_Segment_2_pair collinear case@>==@{@-
typedef typename R::RT RT;
const Point_2<R> &start1 = _seg->start();
const Point_2<R> &end1 = _seg->end();
const Point_2<R> &start2 = _ray->start();
const Point_2<R> *minpt, *maxpt;
Vector_2<R> diff1 = end1-start1;
if (CGAL_NTS abs(diff1.x()) > CGAL_NTS abs(diff1.y())) {
@<Ray_2_Segment_2_pair collinear case 2@>@(x@)
} else {
@<Ray_2_Segment_2_pair collinear case 2@>@(y@)
} @-
@}
The first parameter in the following macro should either be x or y.
The macro sorts the endpoints of the segment according to this
parameter. Then a check is made to see if there is an overlapping interval.
@$@<Ray_2_Segment_2_pair collinear case 2@>@(@1@)@M==@{@-
typedef typename R::FT FT;
if (start1.@1() < end1.@1()) {
minpt = &start1;
maxpt = &end1;
} else {
minpt = &end1;
maxpt = &start1;
}
if (_ray->direction().to_vector().@1() > FT(0)) {
if (maxpt->@1() < start2.@1()) {
_result = NO;
return _result;
}
if (maxpt->@1() == start2.@1()) {
_intersection_point = *maxpt;
_result = POINT;
return _result;
}
if (minpt->@1() < start2.@1()) {
_intersection_point = start2;
_other_point = *maxpt;
} else {
_intersection_point = _seg->start();
_other_point = _seg->end();
}
_result = SEGMENT;
return _result;
} else {
if (minpt->@1() > start2.@1()) {
_result = NO;
return _result;
}
if (minpt->@1() == start2.@1()) {
_intersection_point = *minpt;
_result = POINT;
return _result;
}
if (maxpt->@1() > start2.@1()) {
_intersection_point = start2;
_other_point = *maxpt;
} else {
_intersection_point = _seg->start();
_other_point = _seg->end();
}
_result = SEGMENT;
return _result;
}@-
@}
@B@<2D Ray Ray intersection@>
@O@<../include/CGAL/Ray_2_Ray_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Ray_2_Ray_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_RAY_2_RAY_2_INTERSECTION_H
#define CGAL_RAY_2_RAY_2_INTERSECTION_H
#include <CGAL/Ray_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/utils.h>
#include <CGAL/number_utils.h>
CGAL_BEGIN_NAMESPACE
template <class R>
class Ray_2_Ray_2_pair {
public:
enum Intersection_results {NO, POINT, SEGMENT, RAY};
Ray_2_Ray_2_pair() ;
Ray_2_Ray_2_pair(Ray_2<R> const *ray1,
Ray_2<R> const *ray2);
~Ray_2_Ray_2_pair() {}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
Intersection_results intersection_type() const;
#else
Intersection_results intersection_type() const
@<Ray_2_Ray_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
bool intersection(Point_2<R> &result) const;
bool intersection(Segment_2<R> &result) const;
bool intersection(Ray_2<R> &result) const;
protected:
Ray_2<R> const* _ray1;
Ray_2<R> const * _ray2;
mutable bool _known;
mutable Intersection_results _result;
mutable Point_2<R> _intersection_point, _other_point;
};
@<do_intersect macro@>@(Ray_2@,Ray_2@)
CGAL_END_NAMESPACE
@<Ray_2_Ray_2_pair implementation@>
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Ray_2<R> &ray1, const Ray_2<R>&ray2)
{
typedef Ray_2_Ray_2_pair<R> is_t;
is_t ispair(&ray1, &ray2);
switch (ispair.intersection_type()) {
case is_t::NO:
default:
return Object();
case is_t::POINT: {
Point_2<R> pt;
ispair.intersection(pt);
return make_object(pt);
}
case is_t::SEGMENT: {
Segment_2<R> iseg;
ispair.intersection(iseg);
return make_object(iseg);
}
case is_t::RAY: {
Ray_2<R> iray;
ispair.intersection(iray);
return make_object(iray);
}
}
}
CGAL_END_NAMESPACE
#endif
@}
@$@<Ray_2_Ray_2_pair implementation@>==@{
#include <CGAL/Line_2.h>
#include <CGAL/Line_2_Line_2_intersection.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Ray_2_Ray_2_pair<R>::Ray_2_Ray_2_pair()
{
_ray1 = 0;
_ray2 = 0;
_known = false;
}
template <class R>
Ray_2_Ray_2_pair<R>::Ray_2_Ray_2_pair(
Ray_2<R> const *ray1, Ray_2<R> const *ray2)
{
_ray1 = ray1;
_ray2 = ray2;
_known = false;
}
#ifndef CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
typename Ray_2_Ray_2_pair<R>::Intersection_results
Ray_2_Ray_2_pair<R>::intersection_type() const
@<Ray_2_Ray_2_pair intersection_type body@>
#endif // CGAL_CFG_RETURN_TYPE_BUG_2
template <class R>
bool
Ray_2_Ray_2_pair<R>::intersection(Point_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != POINT)
return false;
result = _intersection_point;
return true;
}
template <class R>
bool
Ray_2_Ray_2_pair<R>::intersection(Segment_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != SEGMENT)
return false;
result = Segment_2<R>(_ray1->start(), _ray2->start());
return true;
}
template <class R>
bool
Ray_2_Ray_2_pair<R>::intersection(Ray_2<R> &result) const
{
if (!_known)
intersection_type();
if (_result != RAY)
return false;
result = Ray_2<R>(_intersection_point, _ray1->direction());
return true;
}
CGAL_END_NAMESPACE
@}
@$@<Ray_2_Ray_2_pair intersection_type body@>@M==@{@-
{
if (_known)
return _result;
// The non const this pointer is used to cast away const.
_known = true;
// if (!do_overlap(_ray1->bbox(), _ray2->bbox()))
// return NO;
const Line_2<R> &l1 = _ray1->supporting_line();
const Line_2<R> &l2 = _ray2->supporting_line();
Line_2_Line_2_pair<R> linepair(&l1, &l2);
switch ( linepair.intersection_type()) {
case Line_2_Line_2_pair<R>::NO:
_result = NO;
return _result;
case Line_2_Line_2_pair<R>::POINT:
linepair.intersection(_intersection_point);
_result = (_ray1->collinear_has_on(_intersection_point)
&& _ray2->collinear_has_on(_intersection_point) )
? POINT : NO;
return _result;
case Line_2_Line_2_pair<R>::LINE:
@<Ray_2_Ray_2_pair collinear case@>
default:
CGAL_kernel_assertion(false); // should not be reached:
return _result;
}
}
@}
@C@<Collinear Case@>
We decide on a main direction (x or y) in which the segment changes
the fastest.
@$@<Ray_2_Ray_2_pair collinear case@>==@{@-
{
typedef typename R::RT RT;
const Vector_2<R> &dir1 = _ray1->direction().to_vector();
const Vector_2<R> &dir2 = _ray2->direction().to_vector();
if (CGAL_NTS abs(dir1.x()) > CGAL_NTS abs(dir1.y())) {
@<Ray_2_Ray_2_pair collinear case 2@>@(x@)
} else {
@<Ray_2_Ray_2_pair collinear case 2@>@(y@)
}
} @-
@}
The first parameter in the following macro should either be x or y.
The macro sorts the four endpoints of the two segments according to this
parameter. Then a check is made to see if there is an overlapping interval.
@$@<Ray_2_Ray_2_pair collinear case 2@>@(@1@)@M==@{@-
typedef typename R::FT FT;
if (dir1.@1() > FT(0)) {
if (dir2.@1() > FT(0)) {
_intersection_point =
(_ray1->start().@1() < _ray2->start().@1())
? _ray2->start() : _ray1->start();
_result = RAY;
return _result;
} else {
if (_ray1->start().@1() > _ray2->start().@1()) {
_result = NO;
return _result;
}
if (_ray1->start().@1() == _ray2->start().@1()) {
_intersection_point = _ray1->start();
_result = POINT;
return _result;
}
_result = SEGMENT;
return _result;
}
} else {
if (dir2.@1() < FT(0)) {
_intersection_point =
(_ray1->start().@1() > _ray2->start().@1())
? _ray2->start() : _ray1->start();
_result = RAY;
return _result;
} else {
if (_ray1->start().@1() < _ray2->start().@1()) {
_result = NO;
return _result;
}
if (_ray1->start().@1() == _ray2->start().@1()) {
_intersection_point = _ray1->start();
_result = POINT;
return _result;
}
_result = SEGMENT;
return _result;
}
}
@}
@B@<2D Point Line intersection@>
@O@<../include/CGAL/Line_2_Point_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Line_2_Point_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Point_2_Line_2_intersection.h>
@}
@O@<../include/CGAL/Point_2_Line_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Point_2_Line_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_POINT_2_LINE_2_INTERSECTION_H
#define CGAL_POINT_2_LINE_2_INTERSECTION_H
#include <CGAL/Line_2.h>
#include <CGAL/Point_2.h>
CGAL_BEGIN_NAMESPACE
template <class R>
inline bool
do_intersect(const Point_2<R> &pt, const Line_2<R> &line)
{
return line.has_on(pt);
}
CGAL_END_NAMESPACE
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Point_2<R> &pt, const Line_2<R> &line)
{
if (do_intersect(pt,line)) {
return make_object(pt);
}
return Object();
}
template <class R>
inline bool
do_intersect(const Line_2<R> &line, const Point_2<R> &pt)
{
return line.has_on(pt);
}
template <class R>
inline Object
intersection(const Line_2<R> &line, const Point_2<R> &pt)
{
if (do_intersect(pt,line)) {
return make_object(pt);
}
return Object();
}
CGAL_END_NAMESPACE
#endif
@}
@B@<2D Point Ray intersection@>
@O@<../include/CGAL/Ray_2_Point_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Ray_2_Point_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Point_2_Ray_2_intersection.h>
@}
@O@<../include/CGAL/Point_2_Ray_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Point_2_Ray_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_POINT_2_RAY_2_INTERSECTION_H
#define CGAL_POINT_2_RAY_2_INTERSECTION_H
#include <CGAL/Ray_2.h>
#include <CGAL/Point_2.h>
CGAL_BEGIN_NAMESPACE
template <class R>
inline bool
do_intersect(const Point_2<R> &pt, const Ray_2<R> &ray)
{
return ray.has_on(pt);
}
CGAL_END_NAMESPACE
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Point_2<R> &pt, const Ray_2<R> &ray)
{
if (do_intersect(pt,ray)) {
return make_object(pt);
}
return Object();
}
template <class R>
inline bool
do_intersect(const Ray_2<R> &ray, const Point_2<R> &pt)
{
return ray.has_on(pt);
}
template <class R>
inline Object
intersection(const Ray_2<R> &ray, const Point_2<R> &pt)
{
if (do_intersect(pt,ray)) {
return make_object(pt);
}
return Object();
}
CGAL_END_NAMESPACE
#endif
@}
@B@<2D Point Segment intersection@>
@O@<../include/CGAL/Segment_2_Point_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Segment_2_Point_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
MPI, Saarbruecken@)
#include <CGAL/Point_2_Segment_2_intersection.h>
@}
@O@<../include/CGAL/Point_2_Segment_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Point_2_Segment_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_POINT_2_SEGMENT_2_INTERSECTION_H
#define CGAL_POINT_2_SEGMENT_2_INTERSECTION_H
#include <CGAL/Segment_2.h>
#include <CGAL/Point_2.h>
CGAL_BEGIN_NAMESPACE
template <class R>
inline bool
do_intersect(const Point_2<R> &pt, const Segment_2<R> &seg)
{
return seg.has_on(pt);
}
CGAL_END_NAMESPACE
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Point_2<R> &pt, const Segment_2<R> &seg)
{
if (do_intersect(pt,seg)) {
return make_object(pt);
}
return Object();
}
template <class R>
inline bool
do_intersect(const Segment_2<R> &seg, const Point_2<R> &pt)
{
return seg.has_on(pt);
}
template <class R>
inline Object
intersection(const Segment_2<R> &seg, const Point_2<R> &pt)
{
if (do_intersect(pt,seg)) {
return make_object(pt);
}
return Object();
}
CGAL_END_NAMESPACE
#endif
@}
@B@<2D Point Point intersection@>
@O@<../include/CGAL/Point_2_Point_2_intersection.h@>==@{
@<cgal_heading@>@(@-
include/CGAL/Point_2_Point_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_POINT_2_POINT_2_INTERSECTION_H
#define CGAL_POINT_2_POINT_2_INTERSECTION_H
#include <CGAL/Point_2.h>
CGAL_BEGIN_NAMESPACE
template <class R>
inline bool
do_intersect(const Point_2<R> &pt1, const Point_2<R> &pt2)
{
return pt1 == pt2;
}
CGAL_END_NAMESPACE
#include <CGAL/Object.h>
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Point_2<R> &pt1, const Point_2<R> &pt2)
{
if (pt1 == pt2) {
return make_object(pt1);
}
return Object();
}
CGAL_END_NAMESPACE
#endif
@}
@B@<Packing intersections together@>
@O@<../include/CGAL/Bbox_2_intersection.h@>==@{@-
@<cgal_heading@>@(@-
include/CGAL/Bbox_2_intersection.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_BBOX_2_INTERSECTIONS_H
#define CGAL_BBOX_2_INTERSECTIONS_H
#include <CGAL/Bbox_2_Line_2_intersection.h>
#include <CGAL/Ray_2_Bbox_2_intersection.h>
#endif // CGAL_BBOX_2_INTERSECTIONS_H
@}
@O@<../include/CGAL/intersection_2_1.h@>==@{@-
@<cgal_heading@>@(@-
include/CGAL/intersection_2_1.h@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#ifndef CGAL_INTERSECTION_2_1_H
#define CGAL_INTERSECTION_2_1_H
#include <CGAL/Line_2_Line_2_intersection.h>
#include <CGAL/Segment_2_Line_2_intersection.h>
#include <CGAL/Segment_2_Segment_2_intersection.h>
#include <CGAL/Ray_2_Line_2_intersection.h>
#include <CGAL/Ray_2_Segment_2_intersection.h>
#include <CGAL/Ray_2_Ray_2_intersection.h>
#include <CGAL/Point_2_Line_2_intersection.h>
#include <CGAL/Point_2_Ray_2_intersection.h>
#include <CGAL/Point_2_Segment_2_intersection.h>
#include <CGAL/Point_2_Point_2_intersection.h>
#endif
@}
@O@<../src/Bbox_2_intersections.C@>==@{@-
@<cgal_heading@>@(@-
src/Bbox_2_intersections.C@,@-
intersection_2_1.fw@,@-
Geert-Jan Giezeman@,@-
Saarbruecken@)
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Bbox_2_Line_2_intersection.h>
#include <CGAL/Ray_2_Bbox_2_intersection.h>
typedef CGAL::Simple_cartesian<double> Rcart;
@<Bbox2_2 cartesian double Line_2 intersection@>
@<Bbox2_2 cartesian double Ray_2 intersection@>
@}