/* $NoKeywords: $ */
/*
//
// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
// McNeel & Associates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//				
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
*/

#if !defined(ON_INTERSECT_INC_)
#define ON_INTERSECT_INC_

// These simple intersectors are fast and detect transverse intersections.
// If the intersection is not a simple transverse case, then they
// return false and you will have to use one of the slower but fancier
// models.


/*
Description:
  Intersect two lines.
Parameters:
  lineA - [in]
  lineB - [in]
  double* a - [out]
  double* b - [out] The shortest distance between the lines is the
                   chord from lineA.PointAt(*a) to lineB.PointAt(*b).
  tolerance - [in] If > 0.0, then an intersection is reported only
                   if the distance between the points is <= tolerance.
                   If <= 0.0, then the closest point between the lines
                   is reported.
  bIntersectSegments - [in] if true, the input lines are treated
                           as finite segments.  If false, the
                           input lines are treated as infinite lines.
Returns:
  True if a closest point can be calculated and the result passes
  the tolerance parameter test.
See Also:
  ON_Intersect( const ON_Line& lineA, const ON_Line& line B)
Remarks:
  If the lines are exactly parallel, meaning the system of equations
  used to find a and b has no numerical solution, then false is returned.
  If the lines are nearly parallel, which is often numerically true
  even if you think the lines look exactly parallel, then the
  closest points are found and true is returned.  So, if you
  care about weeding out "parallel" lines, then you need to
  do something like the following.

          bool rc = ON_IntersectLineLine(lineA,lineB,
                                         &a,&b,
                                         tolerance,
                                         bIntersectSegments);
          if (rc)
          {
            double angle_tolerance_radians = 0.5*ON_PI/180.0; // or whatever
            double parallel_tol = cos(angle_tolerance_radians);
            if ( fabs(lineA.Tangent()*lineB.Tangent()) >= parallel_tol )
            {
              ... do whatever you think is appropriate
            }
          }
*/
ON_DECL
bool ON_IntersectLineLine(
          const ON_Line& lineA, 
          const ON_Line& lineB, 
          double* a,
          double* b,
          double tolerance,
          bool bIntersectSegments
          );

/*
Description:
  Find the closest point between two infinte lines.
Parameters:
  lineA - [in]
  lineB - [in]
  double* a - [out]
  double* b - [out] The shortest distance between the lines is the
                   chord from lineA.PointAt(*a) to lineB.PointAt(*b).
Returns:
  True if points are found and false if the lines are numerically parallel.
  Numerically parallel means the 2x2 matrix

            AoA  -AoB
           -AoB   BoB

 is numerically singluar, where A = lineA.to-lineA.from 
 and B = lineB.to-lineB.from.
See Also:
  ON_IntersectLineLine
*/
ON_DECL
bool ON_Intersect(
          const ON_Line& lineA, 
          const ON_Line& lineB, 
          double* a,
          double* b
          );

ON_DECL
bool ON_Intersect( // Returns false unless intersection is a single point
                   // If returned parameter is < 0 or > 1, then the line
                   // segment between line.m_point[0] and line.m_point[1]
                   // does not intersect the plane
          const ON_Line&, 
          const ON_Plane&, 
          double* // parameter on line
          );

/*
Parameters:
  line - [in]
  plane_equation - [in]
  line_parameter - [out]
    If the returned parameter is < 0 or > 1, then the
    line segment between line.from and line.to
    does not intersect the plane.
Returns:
  true if the interesection is a singe point.
  and false otherwise.
  If returned parameter is < 0 or > 1, then the line
  segment between line.m_point[0] and line.m_point[1]
  does not intersect the plane
*/
ON_DECL
bool ON_Intersect(
          const ON_Line& line, 
          const ON_PlaneEquation& plane_equation, 
          double* line_parameter
          );

ON_DECL
bool ON_Intersect( const ON_Plane&, 
                  const ON_Plane&, 
                   ON_Line& // intersection line is returned here
                   );

ON_DECL
bool ON_Intersect( const ON_Plane&, 
                  const ON_Plane&, 
                  const ON_Plane&,
                  ON_3dPoint& // intersection point is returned here
                  );

/*
Description:
  Intersect a plane and a sphere.
Parameters:
  plane - [in]
  sphere - [in]
  circle - [out]
Returns:
  0: no intersection
    circle radius = 0 and circle origin = point on the plane
    closest to the sphere.
  1: intersection is a single point
    circle radius = 0;
  2: intersection is a circle
    circle radius > 0.
*/
ON_DECL
int ON_Intersect(
          const ON_Plane& plane, 
          const ON_Sphere& sphere,
          ON_Circle& circle
          );

ON_DECL
int ON_Intersect( // returns 0 = no intersections, 
                  // 1 = one intersection, 
                  // 2 = 2 intersections
                  // If 0 is returned, first point is point 
                  // on line closest to sphere and 2nd point is the point
                  // on the sphere closest to the line.
                  // If 1 is returned, first point is obtained by evaluating
                  // the line and the second point is obtained by evaluating
                  // the sphere.
                 const ON_Line&, const ON_Sphere&,
                  ON_3dPoint&, ON_3dPoint& // intersection point(s) returned here
                  );

ON_DECL
int ON_Intersect( // returns 0 = no intersections, 
                  // 1 = one intersection, 
                  // 2 = 2 intersections
                  // 3 = line lies on cylinder
                  // If 0 is returned, first point is point 
                  // on line closest to cylinder and 2nd point is the point
                  // on the sphere closest to the line.
                  // If 1 is returned, first point is obtained by evaluating
                  // the line and the second point is obtained by evaluating
                  // the sphere.
                  const ON_Line&, const ON_Cylinder&,
                  ON_3dPoint&, ON_3dPoint& // intersection point(s) returned here
                  );

/*
Description:
  Intersect an infinite line and an axis aligned bounding box.
Parameters:
  bbox - [in]
  line - [in]
  tolerance - [in]  If tolerance > 0.0, then the intersection is
                   performed against a box that has each side
                   moved out by tolerance.
  line_parameters - [out] 
    Pass null if you do not need the parameters.
    If true is returned and line.from != line.to,
    then the chord from line.PointAt(line_parameters[0])
    to line.PointAt(line_parameters[1]) is the intersection.
    If true is returned and line.from = line.to, then line.from
    is in the box and the interval (0.0,0.0) is returned.
    If false is returned, the input value of line_parameters
    is not changed.
Returns:
  True if the line intersects the box and false otherwise.
*/
ON_DECL
bool ON_Intersect( const ON_BoundingBox& bbox, 
                   const ON_Line& line, 
                   double tolerance,
                   ON_Interval* line_parameters
                   );

/*
Description:
  Intersect two spheres using exact calculations.
Parameters:
  sphere0 - [in]
  sphere1 - [in]
  circle - [out] If intersection is a point, then that point will be the center, radius 0.
Returns:
  0 if no intersection,
  1 if a single point,
  2 if a circle,
  3 if the spheres are the same.
*/
ON_DECL
int ON_Intersect( const ON_Sphere& sphere0, 
                  const ON_Sphere& sphere1, 
                  ON_Circle& circle
                 );
#endif
