cgal/Packages/Intersections_3/include/CGAL/intersection_3_1.C

582 lines
16 KiB
C

// ============================================================================
//
// Copyright (c) 1997 The CGAL Consortium
//
// This software and related documentation is part of an INTERNAL release
// of the Computational Geometry Algorithms Library (CGAL). It is not
// intended for general use.
//
// ----------------------------------------------------------------------------
//
// release : $CGAL_Revision: $
// release_date : $CGAL_Date: $
//
// file : include/CGAL/intersection_3_1.C
// source : web/intersection_3.fw
// author(s) : Geert-Jan Giezeman <geert@cs.uu.nl>
//
// coordinator : Saarbruecken
//
// ============================================================================
#include <CGAL/wmult.h>
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
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() + wmult((R*)0, 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(),
wmult((R*)0, den, line_pt.hw())));
}
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() + wmult((R*)0, plane.d(), line_pt.hw());
if (num == RT(0)) {
// all line
return true;
} else {
// no intersection
return false;
}
}
CGAL_END_NAMESPACE
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
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
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
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
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
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Line_3<R> &line,
const Iso_cuboid_3<R> &box)
{
typedef typename R::RT RT;
typedef typename R::FT FT;
bool all_values = true;
FT _min, _max;
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) < _iso_min.cartesian(i)) {
return Object();
}
if (_ref_point.cartesian(i) > _iso_max.cartesian(i)) {
return Object();
}
} else {
FT newmin, newmax;
if (_dir.homogeneous(i) > RT(0)) {
newmin = (_iso_min.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_iso_max.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
} else {
newmin = (_iso_max.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_iso_min.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
}
if (all_values) {
_min = newmin;
_max = newmax;
} else {
if (newmin > _min)
_min = newmin;
if (newmax < _max)
_max = newmax;
if (_max < _min) {
return Object();
}
}
all_values = false;
}
}
CGAL_kernel_assertion(!all_values);
if (_max == _min) {
return make_object(Point_3<R>(_ref_point + _dir * _min ));
}
return make_object(
Segment_3<R>(_ref_point + _dir*_min, _ref_point + _dir*_max));
}
CGAL_END_NAMESPACE
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Ray_3<R> &ray,
const Iso_cuboid_3<R> &box)
{
typedef typename R::RT RT;
typedef typename R::FT FT;
bool all_values = true;
FT _min= FT(0), _max;
Point_3<R> const & _ref_point=ray.source();
Vector_3<R> const & _dir=ray.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) < _iso_min.cartesian(i)) {
return Object();
}
if (_ref_point.cartesian(i) > _iso_max.cartesian(i)) {
return Object();
}
} else {
FT newmin, newmax;
if (_dir.homogeneous(i) > RT(0)) {
newmin = (_iso_min.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_iso_max.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
} else {
newmin = (_iso_max.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_iso_min.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
}
if (all_values) {
_max = newmax;
} else {
if (newmax < _max)
_max = newmax;
}
if (newmin > _min)
_min = newmin;
if (_max < _min)
return Object();
all_values = false;
}
}
CGAL_kernel_assertion(!all_values);
if (_max == _min) {
return make_object(Point_3<R>(_ref_point + _dir * _min ));
}
return make_object(
Segment_3<R>(_ref_point + _dir*_min, _ref_point + _dir*_max));
}
CGAL_END_NAMESPACE
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(const Segment_3<R> &seg,
const Iso_cuboid_3<R> &box)
{
typedef typename R::RT RT;
typedef typename R::FT FT;
FT _min= FT(0), _max;
Point_3<R> const & _ref_point=seg.source();
Vector_3<R> const & _dir=seg.direction().vector();
Point_3<R> const & _iso_min=box.min();
Point_3<R> const & _iso_max=box.max();
int main_dir =
(CGAL_NTS abs(_dir.x()) > CGAL_NTS abs(_dir.y()) )
? (CGAL_NTS abs(_dir.x()) > CGAL_NTS abs(_dir.z()) ? 0 : 2)
: (CGAL_NTS abs(_dir.y()) > CGAL_NTS abs(_dir.z()) ? 1 : 2);
_max = (seg.target().cartesian(main_dir)-_ref_point.cartesian(main_dir)) /
_dir.cartesian(main_dir);
int i;
for (i=0; i< _ref_point.dimension(); i++) {
if (_dir.homogeneous(i) == RT(0)) {
if (_ref_point.cartesian(i) < _iso_min.cartesian(i)) {
return Object();
}
if (_ref_point.cartesian(i) > _iso_max.cartesian(i)) {
return Object();
}
} else {
FT newmin, newmax;
if (_dir.homogeneous(i) > RT(0)) {
newmin = (_iso_min.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_iso_max.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
} else {
newmin = (_iso_max.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
newmax = (_iso_min.cartesian(i) - _ref_point.cartesian(i)) /
_dir.cartesian(i);
}
if (newmax < _max)
_max = newmax;
if (newmin > _min)
_min = newmin;
if (_max < _min)
return Object();
}
}
if (_max == _min) {
return make_object(Point_3<R>(_ref_point + _dir * _min ));
}
return make_object(
Segment_3<R>(_ref_point + _dir*_min, _ref_point + _dir*_max));
}
CGAL_END_NAMESPACE
CGAL_BEGIN_NAMESPACE
template <class R>
Object
intersection(
const Iso_cuboid_3<R> &icub1,
const Iso_cuboid_3<R> &icub2)
{
Point_3<R> min_points[2];
Point_3<R> max_points[2];
min_points[0] = icub1.min();
min_points[1] = icub2.min();
max_points[0] = icub1.max();
max_points[1] = icub2.max();
typedef typename R::FT FT;
const int DIM = 3;
int min_idx[DIM];
int max_idx[DIM];
Point_3<R> newmin;
Point_3<R> newmax;
for (int dim = 0; dim < DIM; ++dim) {
min_idx[dim] =
min_points[0].cartesian(dim) >= min_points[1].cartesian(dim) ? 0 : 1;
max_idx[dim] =
max_points[0].cartesian(dim) <= max_points[1].cartesian(dim) ? 0 : 1;
if (min_idx[dim] != max_idx[dim]
&& max_points[max_idx[dim]].cartesian(dim)
< min_points[min_idx[dim]].cartesian(dim))
return Object();
}
if (min_idx[0] == min_idx[1] && min_idx[0] == min_idx[2]) {
newmin = min_points[min_idx[0]];
} else {
newmin = Point_3<R>(
min_idx[0] == 0
? wmult((R*)0, min_points[0].hx(), min_points[1].hw())
: wmult((R*)0, min_points[1].hx(), min_points[0].hw())
,
min_idx[1] == 0
? wmult((R*)0, min_points[0].hy(), min_points[1].hw())
: wmult((R*)0, min_points[1].hy(), min_points[0].hw())
,
min_idx[2] == 0
? wmult((R*)0, min_points[0].hz(), min_points[1].hw())
: wmult((R*)0, min_points[1].hz(), min_points[0].hw())
,
wmult((R*)0, min_points[0].hw(), min_points[1].hw()) );
}
if (max_idx[0] == max_idx[1] && max_idx[0] == max_idx[2]) {
newmax = max_points[max_idx[0]];
} else {
newmax = Point_3<R>(
max_idx[0] == 0
? wmult((R*)0, max_points[0].hx(), max_points[1].hw())
: wmult((R*)0, max_points[1].hx(), max_points[0].hw())
,
max_idx[1] == 0
? wmult((R*)0, max_points[0].hy(), max_points[1].hw())
: wmult((R*)0, max_points[1].hy(), max_points[0].hw())
,
max_idx[2] == 0
? wmult((R*)0, max_points[0].hz(), max_points[1].hw())
: wmult((R*)0, max_points[1].hz(), max_points[0].hw())
,
wmult((R*)0, max_points[0].hw(), max_points[1].hw()) );
}
Object result = make_object(Iso_cuboid_3<R>(newmin, newmax));
return result;
}
CGAL_END_NAMESPACE