cgal/Packages/Intersections_3/web/intersection_3.fw

885 lines
21 KiB
Plaintext

@! $RCSfile$
@! $Revision$
@! $Date$
@! Author: Geert-Jan Giezeman (geert@cs.ruu.nl)
@i cgal_util.fwi
@A@<Three dimensional intersection routines@>
Because there are a lot of intersection routines (quadratic in the number of
object types), those routines are split in several classes.
@B@<Class 1 intersection routines@>
@C@<Line Plane intersection@>
@$@<3D Line Plane intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane, const Line_3<R>&line);
template <class R>
inline
Object
intersection(const Line_3<R>&line, const Plane_3<R> &plane)
{
return intersection(plane,line);
}
template <class R>
bool
do_intersect(const Plane_3<R> &p2, const Line_3<R> &p1);
template <class R>
inline bool
do_intersect(
const Line_3<R> &p1,
const Plane_3<R> &p2)
{
return do_intersect(p2,p1);
}
CGAL_END_NAMESPACE
@}
@$@<3D Line Plane intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane, const Line_3<R>&line)
{
typedef typename R::RT RT;
const Point_3<R> &line_pt = line.point();
const Direction_3<R> &line_dir = line.direction();
RT num, den;
num = plane.a()*line_pt.hx() + plane.b()*line_pt.hy()
+ plane.c()*line_pt.hz() + plane.d()*line_pt.hw();
den = plane.a()*line_dir.dx() + plane.b()*line_dir.dy()
+ plane.c()*line_dir.dz();
if (den == RT(0)) {
if (num == RT(0)) {
// all line
return make_object(line);
} else {
// no intersection
return Object();
}
}
return make_object(Point_3<R>(
den*line_pt.hx()-num*line_dir.dx(),
den*line_pt.hy()-num*line_dir.dy(),
den*line_pt.hz()-num*line_dir.dz(),
line_pt.hw()*den));
}
template <class R>
bool
do_intersect(const Plane_3<R> &plane, const Line_3<R>&line)
{
typedef typename R::RT RT;
const Point_3<R> &line_pt = line.point();
const Direction_3<R> &line_dir = line.direction();
RT num, den;
den = plane.a()*line_dir.dx() + plane.b()*line_dir.dy()
+ plane.c()*line_dir.dz();
if (den != RT(0))
return true;
num = plane.a()*line_pt.hx() + plane.b()*line_pt.hy()
+ plane.c()*line_pt.hz() + plane.d()*line_pt.hw();
if (num == RT(0)) {
// all line
return true;
} else {
// no intersection
return false;
}
}
CGAL_END_NAMESPACE
@}
@C@<Segment Plane intersection@>
@$@<3D Segment Plane intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane, const Segment_3<R>&seg);
template <class R>
inline
Object
intersection(const Segment_3<R>&seg, const Plane_3<R> &plane)
{
return intersection(plane,seg);
}
template <class R>
bool
do_intersect(const Plane_3<R> &p1, const Segment_3<R> &p2);
template <class R>
inline bool
do_intersect(
const Segment_3<R> &p1,
const Plane_3<R> &p2)
{
return do_intersect(p2,p1);
}
CGAL_END_NAMESPACE
@}
@$@<3D Segment Plane intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane, const Segment_3<R>&seg)
{
const Point_3<R> &source = seg.source();
const Point_3<R> &target = seg.target();
Oriented_side source_side,target_side;
source_side = plane.oriented_side(source);
target_side = plane.oriented_side(target);
switch (source_side) {
case ON_ORIENTED_BOUNDARY:
if (target_side == ON_ORIENTED_BOUNDARY)
return make_object(seg);
else
return make_object(source);
case ON_POSITIVE_SIDE:
switch (target_side) {
case ON_ORIENTED_BOUNDARY:
return make_object(target);
case ON_POSITIVE_SIDE:
return Object();
case ON_NEGATIVE_SIDE:
return intersection(plane, seg.supporting_line());
}
case ON_NEGATIVE_SIDE:
switch (target_side) {
case ON_ORIENTED_BOUNDARY:
return make_object(target);
case ON_POSITIVE_SIDE:
return intersection(plane, seg.supporting_line());
case ON_NEGATIVE_SIDE:
return Object();
}
}
CGAL_kernel_assertion_msg(false, "Supposedly unreachable code.");
return Object();
}
template <class R>
bool
do_intersect(const Plane_3<R> &plane, const Segment_3<R>&seg)
{
const Point_3<R> &source = seg.source();
const Point_3<R> &target = seg.target();
Oriented_side source_side,target_side;
source_side = plane.oriented_side(source);
target_side = plane.oriented_side(target);
if ( source_side == target_side
&& target_side != ON_ORIENTED_BOUNDARY) {
return false;
}
return true;
}
CGAL_END_NAMESPACE
@}
@C@<Ray Plane intersection@>
@$@<3D Ray Plane intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane, const Ray_3<R>&ray);
template <class R>
inline
Object
intersection(const Ray_3<R>&ray, const Plane_3<R> &plane)
{
return intersection(plane,ray);
}
template <class R>
bool
do_intersect(const Plane_3<R> &p1, const Ray_3<R> &p2);
template <class R>
inline bool
do_intersect(
const Ray_3<R> &p1,
const Plane_3<R> &p2)
{
return do_intersect(p2,p1);
}
CGAL_END_NAMESPACE
@}
First we compute the intersection of the supporting line of the ray with
the plane.
@$@<3D Ray Plane intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane, const Ray_3<R>&ray)
{
const Object line_intersection =
intersection(plane, ray.supporting_line());
Point_3<R> isp;
if (assign(isp, line_intersection)) {
if (ray.collinear_has_on(isp))
return line_intersection;
else
return Object();
}
if (line_intersection.is_empty())
return line_intersection;
return make_object(ray);
}
template <class R>
bool
do_intersect(const Plane_3<R> &plane, const Ray_3<R>&ray)
{
const Object line_intersection =
intersection(plane, ray.supporting_line());
if (line_intersection.is_empty())
return false;
Point_3<R> isp;
if (assign(isp, line_intersection)) {
if (ray.collinear_has_on(isp))
return true;
else
return false;
}
return true;
}
CGAL_END_NAMESPACE
@}
@C@<Plane Plane intersection@>
@$@<3D Plane Plane intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane1, const Plane_3<R>&plane2);
template <class R>
inline bool
do_intersect(const Plane_3<R> &plane1, const Plane_3<R>&plane2)
{
return ! intersection(plane1, plane2).is_empty();
}
CGAL_END_NAMESPACE
@}
@$@<3D Plane Plane intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Plane_3<R> &plane1, const Plane_3<R>&plane2)
{
typedef typename R::RT RT;
const RT &a = plane1.a();
const RT &b = plane1.b();
const RT &c = plane1.c();
const RT &d = plane1.d();
const RT &p = plane2.a();
const RT &q = plane2.b();
const RT &r = plane2.c();
const RT &s = plane2.d();
const RT zero = RT(0);
RT det;
Point_3<R> is_pt;
Direction_3<R> is_dir;
det = a*q-p*b;
if (det != zero) {
is_pt = Point_3<R>(b*s-d*q, p*d-a*s, zero, det);
is_dir = Direction_3<R>(b*r-c*q, p*c-a*r, det);
return make_object(Line_3<R>(is_pt, is_dir));
}
det = a*r-p*c;
if (det != zero) {
is_pt = Point_3<R>(c*s-d*r, zero, p*d-a*s, det);
is_dir = Direction_3<R>(c*q-b*r, det, p*b-a*q);
return make_object(Line_3<R>(is_pt, is_dir));
}
det = b*r-c*q;
if (det != zero) {
is_pt = Point_3<R>(zero, c*s-d*r, d*q-b*s, det);
is_dir = Direction_3<R>(det, c*p-a*r, a*q-b*p);
return make_object(Line_3<R>(is_pt, is_dir));
}
// degenerate case
if (a!=zero || p!=zero) {
if (a*s == p*d)
return make_object(plane1);
else
return Object();
}
if (b!=zero || q!=zero) {
if (b*s == q*d)
return make_object(plane1);
else
return Object();
}
if (c!=zero || r!=zero) {
if (c*s == r*d)
return make_object(plane1);
else
return Object();
}
return make_object(plane1);
}
CGAL_END_NAMESPACE
@}
@C@<Line Box intersection@>
@$@<3D Line Box intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Line_3<R> &line,
const Bbox_3 &box) ;
template <class R>
inline Object
intersection(const Bbox_3 &box,
const Line_3<R> &line)
{
return intersection(line, box);
}
CGAL_END_NAMESPACE
@}
@$@<3D CD Line Box intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
extern Object
intersection_bl(const Bbox_3 &box,
double lx1, double ly1, double lz1,
double lx2, double ly2, double lz2,
bool min_infinite, bool max_infinite);
CGAL_END_NAMESPACE
@}
@D@<Implementation@>
Lines with a representation other than Cartesian double are transformed to
Cartesian double representation by transforming the coordinates of a point
of the line and of the direction.
@$@<3D Line Box intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Line_3<R> &line,
const Bbox_3 &box)
{
const Point_3<R> &linepoint = line.point();
const Direction_3<R> &linedir = line.direction();
return intersection_bl(box,
CGAL::to_double(linepoint.x()),
CGAL::to_double(linepoint.y()),
CGAL::to_double(linepoint.z()),
CGAL::to_double(linedir.dx()),
CGAL::to_double(linedir.dy()),
CGAL::to_double(linedir.dz()),
true, true
);
}
CGAL_END_NAMESPACE
@}
@$@<3D CD Line Box intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
Object
intersection_bl(const Bbox_3 &box,
double lpx, double lpy, double lpz,
double ldx, double ldy, double ldz,
bool min_infinite, bool max_infinite)
{
typedef Cartesian<double> R_cd;
Point_3<R_cd> ref_point(lpx,lpy, lpz);
Vector_3<R_cd> dir(ldx, ldy, ldz);
double seg_min = 0.0, seg_max = 1.0;
// first on x value
if (dir.x() == 0.0) {
if (ref_point.x() < box.xmin())
return Object();
if (ref_point.x() > box.xmax())
return Object();
} else {
double newmin, newmax;
if (dir.x() > 0.0) {
newmin = (box.xmin()-ref_point.x())/dir.x();
newmax = (box.xmax()-ref_point.x())/dir.x();
} else {
newmin = (box.xmax()-ref_point.x())/dir.x();
newmax = (box.xmin()-ref_point.x())/dir.x();
}
if (min_infinite) {
min_infinite = false;
seg_min = newmin;
} else {
if (newmin > seg_min)
seg_min = newmin;
}
if (max_infinite) {
max_infinite = false;
seg_max = newmax;
} else {
if (newmax < seg_max)
seg_max = newmax;
}
if (seg_max < seg_min)
return Object();
}
// now on y value
if (dir.y() == 0.0) {
if (ref_point.y() < box.ymin())
return Object();
if (ref_point.y() > box.ymax())
return Object();
} else {
double newmin, newmax;
if (dir.y() > 0.0) {
newmin = (box.ymin()-ref_point.y())/dir.y();
newmax = (box.ymax()-ref_point.y())/dir.y();
} else {
newmin = (box.ymax()-ref_point.y())/dir.y();
newmax = (box.ymin()-ref_point.y())/dir.y();
}
if (min_infinite) {
min_infinite = false;
seg_min = newmin;
} else {
if (newmin > seg_min)
seg_min = newmin;
}
if (max_infinite) {
max_infinite = false;
seg_max = newmax;
} else {
if (newmax < seg_max)
seg_max = newmax;
}
if (seg_max < seg_min)
return Object();
}
// now on z value
if (dir.z() == 0.0) {
if (ref_point.z() < box.zmin())
return Object();
if (ref_point.z() > box.zmax())
return Object();
} else {
double newmin, newmax;
if (dir.z() > 0.0) {
newmin = (box.zmin()-ref_point.z())/dir.z();
newmax = (box.zmax()-ref_point.z())/dir.z();
} else {
newmin = (box.zmax()-ref_point.z())/dir.z();
newmax = (box.zmin()-ref_point.z())/dir.z();
}
if (min_infinite) {
min_infinite = false;
seg_min = newmin;
} else {
if (newmin > seg_min)
seg_min = newmin;
}
if (max_infinite) {
max_infinite = false;
seg_max = newmax;
} else {
if (newmax < seg_max)
seg_max = newmax;
}
if (seg_max < seg_min)
return Object();
}
if (min_infinite || max_infinite) {
seg_max = 0.0;
CGAL_kernel_assertion_msg(true,
"Zero direction vector of line detected.");
}
if (seg_max == seg_min)
return make_object(ref_point + dir*seg_max);
return make_object(Segment_3<R_cd>(
ref_point + dir*seg_min, ref_point + dir*seg_max));
}
CGAL_END_NAMESPACE
@}
@C@<Ray Box intersection@>
@$@<3D Ray Box intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Ray_3<R> &ray,
const Bbox_3 &box) ;
template <class R>
inline Object
intersection(const Bbox_3 &box,
const Ray_3<R> &ray)
{
return intersection(ray, box);
}
CGAL_END_NAMESPACE
@}
@D@<Implementation@>
Rays with a representation other than Cartesian double are transformed to
Cartesian double representation by transforming the coordinates of a point
of the ray and of the direction.
@$@<3D Ray Box intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Ray_3<R> &ray,
const Bbox_3 &box)
{
const Point_3<R> &linepoint = ray.source();
const Direction_3<R> &linedir = ray.direction();
return intersection_bl(box,
CGAL::to_double(linepoint.x()),
CGAL::to_double(linepoint.y()),
CGAL::to_double(linepoint.z()),
CGAL::to_double(linedir.dx()),
CGAL::to_double(linedir.dy()),
CGAL::to_double(linedir.dz()),
false, true
);
}
CGAL_END_NAMESPACE
@}
@C@<Segment Box intersection@>
@$@<3D Segment Box intersection declarations@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Segment_3<R> &seg,
const Bbox_3 &box) ;
template <class R>
inline Object
intersection(const Bbox_3 &box,
const Segment_3<R> &seg)
{
return intersection(seg, box);
}
CGAL_END_NAMESPACE
@}
@D@<Implementation@>
Segments with a representation other than Cartesian double are transformed to
Cartesian double representation by transforming the coordinates of a point
of the segment and of the direction.
@$@<3D Segment Box intersection implementation@>==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Segment_3<R> &seg,
const Bbox_3 &box)
{
const Point_3<R> &linepoint = seg.source();
const Vector_3<R> &diffvec = seg.target()-linepoint;
return intersection_bl(box,
CGAL::to_double(linepoint.x()),
CGAL::to_double(linepoint.y()),
CGAL::to_double(linepoint.z()),
CGAL::to_double(diffvec.x()),
CGAL::to_double(diffvec.y()),
CGAL::to_double(diffvec.z()),
false, false
);
}
CGAL_END_NAMESPACE
@}
@C@<Isobox Line intersection@>
@$@<3D Isobox Line intersection declarations@>@Z==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Line_3<R> &line,
const Iso_box_3 &box) ;
template <class R>
inline Object
intersection(const Iso_box_3 &box,
const Line_3<R> &line)
{
return intersection(line, box);
}
CGAL_END_NAMESPACE
@}
@D@<Implementation@>
@$@<3D Isobox Line intersection implementation@>@Z==@{
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Line_3<R> &line,
const Iso_box_3 &box)
{
typedef Line_2<R> line_t;
typedef typename R::RT RT;
typedef typename R::FT FT;
bool all_values = true;
Point_3<R> const & _ref_point(line.point());
Vector_3<R> const & _dir(line.direction().vector());
Point_3<R> const & _iso_min(box.min());
Point_3<R> const & _iso_max(box.max());
int i;
for (i=0; i< _ref_point.dimension(); i++) {
if (_dir.homogeneous(i) == RT(0)) {
if (_ref_point.cartesian(i) < _isomin.cartesian(i)) {
ncthis->_result = NO;
return NO;
}
if (_ref_point.cartesian(i) > _isomax.cartesian(i)) {
ncthis->_result = NO;
return NO;
}
} else {
FT newmin, newmax;
if (_dir.homogeneous(i) > RT(0)) {
newmin = (_isomin.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_isomax.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
} else {
newmin = (_isomax.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_isomin.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
}
if (all_values) {
ncthis->_min = newmin;
ncthis->_max = newmax;
} else {
if (newmin > _min)
ncthis->_min = newmin;
if (newmax < _max)
ncthis->_max = newmax;
if (_max < _min) {
ncthis->_result = NO;
return NO;
}
}
all_values = false;
}
}
CGAL_kernel_assertion(!all_values);
if (_max == _min) {
ncthis->_result = POINT;
return POINT;
}
ncthis->_result = SEGMENT;
return SEGMENT;
}
CGAL_END_NAMESPACE
@}
@$@<declarations 1@>==@{
#ifndef CGAL_OBJECT_H
#include <CGAL/Object.h>
#endif // CGAL_OBJECT_H
#ifndef CGAL_BBOX_INTERSECTION_3_H
#include <CGAL/bbox_intersection_3.h>
#endif // CGAL_BBOX_INTERSECTION_3_H
@<3D Plane Plane intersection declarations@>
@<3D Line Plane intersection declarations@>
@<3D Ray Plane intersection declarations@>
@<3D Segment Plane intersection declarations@>
@<3D Line Box intersection declarations@>
@<3D Ray Box intersection declarations@>
@<3D Segment Box intersection declarations@>
@!@<3D Isobox Line intersection declarations@>
@}
@$@<outline definitions 1@>==@{
@<3D Plane Plane intersection implementation@>
@<3D Line Plane intersection implementation@>
@<3D Ray Plane intersection implementation@>
@<3D Segment Plane intersection implementation@>
@<3D Line Box intersection implementation@>
@<3D Ray Box intersection implementation@>
@<3D Segment Box intersection implementation@>
@!@<3D Isobox Line intersection implementation@>
@}
@O@<../include/CGAL/bbox_intersection_3.h@>==@{
@<cgal_heading@>@(include/CGAL/bbox_intersection_3.h@,@-
web/intersection_3.fw@,@-
Geert-Jan Giezeman <geert@@cs.ruu.nl>@,@-
Saarbruecken@)
#ifndef CGAL_BBOX_INTERSECTION_3_H
#define CGAL_BBOX_INTERSECTION_3_H
#ifndef CGAL_BBOX_3_H
#include <CGAL/Bbox_3.h>
#endif // CGAL_BBOX_3_H
#ifndef CGAL_OBJECT_H
#include <CGAL/Object.h>
#endif // CGAL_OBJECT_H
@<3D CD Line Box intersection declarations@>
#endif // CGAL_BBOX_INTERSECTION_3_H
@}
@O@<../include/CGAL/intersection_3_1.h@>==@{@-
@<cgal_heading@>@(include/CGAL/intersection_3_1.h@,@-
web/intersection_3.fw@,@-
Geert-Jan Giezeman <geert@@cs.ruu.nl>@,@-
Saarbruecken@)
#ifndef CGAL_INTERSECTION_3_1_H
#define CGAL_INTERSECTION_3_1_H
@<declarations 1@>
#ifdef CGAL_CFG_NO_AUTOMATIC_TEMPLATE_INCLUSION
#include <CGAL/intersection_3_1.C>
#endif
#endif // CGAL_INTERSECTION_3_1_H
@}
@O@<../include/CGAL/intersection_3_1.C@>==@{@-
@<cgal_heading@>@(include/CGAL/intersection_3_1.C@,@-
web/intersection_3.fw@,@-
Geert-Jan Giezeman <geert@@cs.ruu.nl>@,@-
Saarbruecken@)
@<outline definitions 1@>
@}
@B@<All intersections@>
The following header file includes all other header files that define
intersections. This is a convenience for people who don't want to
remember which intersection header file to include and don't mind the extra
compilation time.
@O@<../include/CGAL/intersection_3.h@>==@{@-
@<cgal_heading@>@(include/CGAL/intersection_3.h@,@-
web/intersection_3.fw@,@-
Geert-Jan Giezeman <geert@@cs.ruu.nl>@,@-
Saarbruecken@)
#ifndef CGAL_INTERSECTION_3_H
#define CGAL_INTERSECTION_3_H
#ifndef CGAL_INTERSECTION_3_1_H
#include <CGAL/intersection_3_1.h>
#endif // CGAL_INTERSECTION_3_1_H
#endif // CGAL_INTERSECTION_3_H
@}
@O@<../src/Bbox_3_intersections.C@>==@{@-
@<cgal_heading@>@(src/Bbox_3_intersections.C@,@-
web/intersection_3.fw@,@-
Geert-Jan Giezeman <geert@@cs.ruu.nl>@,@-
Saarbruecken@)
#ifndef CGAL_CARTESIAN_H
#include <CGAL/Cartesian.h>
#endif // CGAL_CARTESIAN_H
#ifndef CGAL_POINT_3_H
#include <CGAL/Point_3.h>
#endif // CGAL_POINT_3_H
#ifndef CGAL_BBOX_INTERSECTION_3_H
#include <CGAL/bbox_intersection_3.h>
#endif // CGAL_BBOX_INTERSECTION_3_H
@<3D CD Line Box intersection implementation@>
@}