@! $RCSfile$ @! $Revision$ @! $Date$ @! Author: Geert-Jan Giezeman (geert@cs.ruu.nl) @i cgal_util.fwi @A@ Because there are a lot of intersection routines (quadratic in the number of object types), those routines are split in several classes. @B@ @C@ @$@<3D Line Plane intersection declarations@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Plane_3 &plane, const Line_3&line); template inline Object intersection(const Line_3&line, const Plane_3 &plane) { return intersection(plane,line); } template bool do_intersect(const Plane_3 &p2, const Line_3 &p1); template inline bool do_intersect( const Line_3 &p1, const Plane_3 &p2) { return do_intersect(p2,p1); } CGAL_END_NAMESPACE @} @$@<3D Line Plane intersection implementation@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Plane_3 &plane, const Line_3&line) { typedef typename R::RT RT; const Point_3 &line_pt = line.point(); const Direction_3 &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( 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 bool do_intersect(const Plane_3 &plane, const Line_3&line) { typedef typename R::RT RT; const Point_3 &line_pt = line.point(); const Direction_3 &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@ @$@<3D Segment Plane intersection declarations@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Plane_3 &plane, const Segment_3&seg); template inline Object intersection(const Segment_3&seg, const Plane_3 &plane) { return intersection(plane,seg); } template bool do_intersect(const Plane_3 &p1, const Segment_3 &p2); template inline bool do_intersect( const Segment_3 &p1, const Plane_3 &p2) { return do_intersect(p2,p1); } CGAL_END_NAMESPACE @} @$@<3D Segment Plane intersection implementation@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Plane_3 &plane, const Segment_3&seg) { const Point_3 &source = seg.source(); const Point_3 &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 bool do_intersect(const Plane_3 &plane, const Segment_3&seg) { const Point_3 &source = seg.source(); const Point_3 &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@ @$@<3D Ray Plane intersection declarations@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Plane_3 &plane, const Ray_3&ray); template inline Object intersection(const Ray_3&ray, const Plane_3 &plane) { return intersection(plane,ray); } template bool do_intersect(const Plane_3 &p1, const Ray_3 &p2); template inline bool do_intersect( const Ray_3 &p1, const Plane_3 &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 Object intersection(const Plane_3 &plane, const Ray_3&ray) { const Object line_intersection = intersection(plane, ray.supporting_line()); Point_3 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 bool do_intersect(const Plane_3 &plane, const Ray_3&ray) { const Object line_intersection = intersection(plane, ray.supporting_line()); if (line_intersection.is_empty()) return false; Point_3 isp; if (assign(isp, line_intersection)) { if (ray.collinear_has_on(isp)) return true; else return false; } return true; } CGAL_END_NAMESPACE @} @C@ @$@<3D Plane Plane intersection declarations@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Plane_3 &plane1, const Plane_3&plane2); template inline bool do_intersect(const Plane_3 &plane1, const Plane_3&plane2) { return ! intersection(plane1, plane2).is_empty(); } CGAL_END_NAMESPACE @} @$@<3D Plane Plane intersection implementation@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Plane_3 &plane1, const Plane_3&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 is_pt; Direction_3 is_dir; det = a*q-p*b; if (det != zero) { is_pt = Point_3(b*s-d*q, p*d-a*s, zero, det); is_dir = Direction_3(b*r-c*q, p*c-a*r, det); return make_object(Line_3(is_pt, is_dir)); } det = a*r-p*c; if (det != zero) { is_pt = Point_3(c*s-d*r, zero, p*d-a*s, det); is_dir = Direction_3(c*q-b*r, det, p*b-a*q); return make_object(Line_3(is_pt, is_dir)); } det = b*r-c*q; if (det != zero) { is_pt = Point_3(zero, c*s-d*r, d*q-b*s, det); is_dir = Direction_3(det, c*p-a*r, a*q-b*p); return make_object(Line_3(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@ @$@<3D Line Box intersection declarations@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Line_3 &line, const Bbox_3 &box) ; template inline Object intersection(const Bbox_3 &box, const Line_3 &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@ 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 Object intersection(const Line_3 &line, const Bbox_3 &box) { const Point_3 &linepoint = line.point(); const Direction_3 &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 R_cd; Point_3 ref_point(lpx,lpy, lpz); Vector_3 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( ref_point + dir*seg_min, ref_point + dir*seg_max)); } CGAL_END_NAMESPACE @} @C@ @$@<3D Ray Box intersection declarations@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Ray_3 &ray, const Bbox_3 &box) ; template inline Object intersection(const Bbox_3 &box, const Ray_3 &ray) { return intersection(ray, box); } CGAL_END_NAMESPACE @} @D@ 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 Object intersection(const Ray_3 &ray, const Bbox_3 &box) { const Point_3 &linepoint = ray.source(); const Direction_3 &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@ @$@<3D Segment Box intersection declarations@>==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Segment_3 &seg, const Bbox_3 &box) ; template inline Object intersection(const Bbox_3 &box, const Segment_3 &seg) { return intersection(seg, box); } CGAL_END_NAMESPACE @} @D@ 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 Object intersection(const Segment_3 &seg, const Bbox_3 &box) { const Point_3 &linepoint = seg.source(); const Vector_3 &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@ @$@<3D Isobox Line intersection declarations@>@Z==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Line_3 &line, const Iso_box_3 &box) ; template inline Object intersection(const Iso_box_3 &box, const Line_3 &line) { return intersection(line, box); } CGAL_END_NAMESPACE @} @D@ @$@<3D Isobox Line intersection implementation@>@Z==@{ CGAL_BEGIN_NAMESPACE template Object intersection(const Line_3 &line, const Iso_box_3 &box) { typedef Line_2 line_t; typedef typename R::RT RT; typedef typename R::FT FT; bool all_values = true; Point_3 const & _ref_point(line.point()); Vector_3 const & _dir(line.direction().vector()); Point_3 const & _iso_min(box.min()); Point_3 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 @} @$@==@{ #include #include @<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@> @} @$@==@{ @<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@>==@{ @@(include/CGAL/bbox_intersection_3.h@,@- web/intersection_3.fw@,@- Geert-Jan Giezeman @,@- Saarbruecken@) #ifndef CGAL_BBOX_INTERSECTION_3_H #define CGAL_BBOX_INTERSECTION_3_H #include #include @<3D CD Line Box intersection declarations@> #endif // CGAL_BBOX_INTERSECTION_3_H @} @O@<../include/CGAL/intersection_3_1.h@>==@{@- @@(include/CGAL/intersection_3_1.h@,@- web/intersection_3.fw@,@- Geert-Jan Giezeman @,@- Saarbruecken@) #ifndef CGAL_INTERSECTION_3_1_H #define CGAL_INTERSECTION_3_1_H @ #ifdef CGAL_CFG_NO_AUTOMATIC_TEMPLATE_INCLUSION #include #endif #endif // CGAL_INTERSECTION_3_1_H @} @O@<../include/CGAL/intersection_3_1.C@>==@{@- @@(include/CGAL/intersection_3_1.C@,@- web/intersection_3.fw@,@- Geert-Jan Giezeman @,@- Saarbruecken@) @ @} @B@ 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@>==@{@- @@(include/CGAL/intersection_3.h@,@- web/intersection_3.fw@,@- Geert-Jan Giezeman @,@- Saarbruecken@) #ifndef CGAL_INTERSECTION_3_H #define CGAL_INTERSECTION_3_H #include #endif // CGAL_INTERSECTION_3_H @} @O@<../src/Bbox_3_intersections.C@>==@{@- @@(src/Bbox_3_intersections.C@,@- web/intersection_3.fw@,@- Geert-Jan Giezeman @,@- Saarbruecken@) #include #include #include @<3D CD Line Box intersection implementation@> @}