// ****************************************************************************
//
//  $Id: cisLine3D.h,v 1.1.1.1 2001/09/27 20:12:22 anton Exp $
//
//  Description:
//		
//
//  Usage:
//		
//
//  See Also:
//		
//
//  Author(s):	Ofri Sadowsky
//  Created on: 2003-03-24
//
//
//              Developed by the Engineering Research Center for
//          Computer-Integrated Surgical Systems & Technology (CISST)
//
//               Copyright(c) 2001, The Johns Hopkins University
//                          All Rights Reserved.
//
//  Experimental Software - Not certified for clinical use.
//  For use only by CISST sponsored research projects.  For use outside of
//  CISST, please contact Dr. Russell Taylor, CISST Director, at rht@cs.jhu.edu
//  or Dr. Gabor Fichtinger, CISST Engineering Director, at gabor@cs.jhu.edu.
//  
// ****************************************************************************

#ifndef _cisLine3D_h
#define _cisLine3D_h

#include "cisGeomObj3DCommon.h"
#include "cisVecs.h"

/** class cisLine3D
 * defines a line in 3D space, and provides operations with the line.
 * A line in 3D space is defined uniquely by a direction vector with a positive
 * last-nonzero coordinate, and the point closest to the origin.
 * it is important to define a line uniquely so that comparisons and operations
 * will have consistent results.
 *
 * Note 1: The direction vector is normalized, except for the case of zero direction.
 *   We allow the last case in order to be able to represent degenerate cases, such
 *   as projecting a line on a perpendicular plane.
 *
 * Note 2: since a Line object is always in unique representation, it cannot be 
 *   implemented with virtual point and direction. That is, cisLine3D has a constructor,
 *   GetPoint() and GetDirection() all implemented.
 */
class cisEXPORT cisLine3D
{
public:
	// The type used for local parametrization of points on the line
	typedef cisScalar ParametrizationType;

	// Type of angles
	typedef double AngleType;

	// The type that represents a point on the line
	typedef cisVec3 LocalPointType;

	// The type that represents the direction of the line
	typedef cisVec3 LocalDirectionType;

	// The type that represents any point in space
	typedef cisVec3 GlobalPointType;

	// The type that represents any direction in space
	typedef cisVec3 GlobalDirectionType;

	// Type of this class
	typedef cisLine3D SelfType;


	// some conditional compilation definition, to simplify future testing
#define cisLine3D_with_angles 0
#define cisLine3D_mutable 0

protected:
	// The closest point to the origin on the line
	LocalPointType Point;
	
	// The last-nonzero-positive direction of the line
	LocalDirectionType Dir;

public:
	
	// default ctor -- initialize a zero-value line. Only allowed with
	// cisLine3_mutable set
#if cisLine3D_mutable
	cisLine3D();
#endif
	
	// parametrized ctor -- initialize a line by point and direction
	cisLine3D(const GlobalPointType & pt, const GlobalDirectionType & dir);

	const LocalPointType & GetPoint() const;

	const LocalDirectionType & GetDirection() const;

#if !cisLine3D_mutable
private:
#endif
	// assign new values to the line.
	void Set(const GlobalPointType & pt, const GlobalDirectionType & dir);
#if !cisLine3D_mutable
public:
#endif


	
	/***
	 * Point to this-line relations
	 ***/

	// evaluate a point on the line parametrized by a scalar.
	LocalPointType EvalAt(ParametrizationType param) const;

	// Get the line parameter value for the projection of a given point.
	// When the given point is on this line, the method evaluates the exact parameter
	// of the point.
	ParametrizationType ProjectPointLocal(const GlobalPointType & pt) const;

	// return the projection of a given point on this line
	LocalPointType ProjectPoint(const GlobalPointType & pt) const;

	cisScalar DistanceSquareToPoint(const GlobalPointType & pt) const;
	cisScalar DistanceToPoint(const GlobalPointType & pt) const;

	bool IsMember(const GlobalPointType & pt, cisScalar tolerance) const;

	/***
	 * Vector to this-line relations
	 ***/

	AngleType AngleWithVector(const GlobalDirectionType & v) const;

	/***
	 * Line to this-line relations
	 ***/

	static const cisScalar DefaultTolerance;

	// compute unsigned angle between two lines. As both line directions lie in the first
	// octant, the angle is between 0..(pi/2)
	AngleType AngleWithLine(const SelfType & other) const;

	// Decide if this line is parallel to the other, up to a given tolerance.
	// The default tolerance is: cos(theta) <= 1.e-8  , which is less than 0.1deg
	bool IsParallelTo(const SelfType & other, 
		cisScalar tolerance = DefaultTolerance) const;

	// return the point on this line closest to the other line.
	LocalPointType ClosestPointTo(const SelfType & other) const;

	bool operator == (const SelfType & L2) const;
	
	bool operator != (const SelfType & L2) const;

	/***
	 * Segment to this-line relations
	 ***/

	LocalPointType ClosestPointTo(const cisSegment3D & segment) const;

#if cisLine3D_with_angles
#if cisLine3D_mutable
	// assign new values to the line from angles and distances. as a line has 2DOF,
	// this completely defines a line, though the order of applying rotation angles and
	// translations may be arbitrary. The final values are guaranteed to be the unique
	// representation of a line.
	void SetFromAnglesDists(cisScalar angleY, cisScalar angleZ, cisScalar distY, cisScalar distZ);
#endif
	// A very obscure function.
	void GetAngleDists(cisScalar& angleY, cisScalar& angleZ, cisScalar& distY, cisScalar& distZ);
#endif
	
	
};


#define _cisLine3D_inl_h
#include "cisLine3D-inl.h"
#undef _cisLine3D_inl_h


#endif // CIS_GeomObj_Line3D_HPP

// ****************************************************************************
//                              Change History
// ****************************************************************************
//
//  $Log: cisLine3D.h,v $
//  Revision 1.1.1.1  2001/09/27 20:12:22  anton
//  Creation of new repository for CIS 2.
//
//
//  Older:
//
//  Revision 1.2  2001/04/26 15:30:19  anton
//  Include CISGeomObjExport.hpp and added EXPORT_xxx macros
//
//  Revision 1.1  2001/03/26 19:32:05  anton
//  Import of GeomObj within CIS from Andy Bzostek code with some formating and cleaning.  Add some -inl.hpp files.
//
//
// ****************************************************************************


