// ****************************************************************************
//
//  $Id: cisReferenceSegment3D.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-04-01
//
//
//              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 _cisIndexSegment3D_h
#define _cisIndexSegment3D_h

#include "cisAbstractSegment3D.h"

// class cisIndexSegment3D
// Provides a concrete implementation for the cisAbstractSegment3D by storing
// a reference to a vertex container and indices of the vertices in that 
// container. The class is templated over the type of the container and
// the type of the index. The container must provide at least the 
// implementation of operator[](IndexType) const .
// Data in the container may change from outside, causing a cisIndexSegment3D
// to re-evaluate the segment attributes with the new vertex values. For
// convenience, we also provide the SetContainer method as an exception
// to the immutability rule. Thus if one stores a mesh and transforms the
// vertices, and one sometimes wants to store the transformed vertices into
// a new container, it is possible to make the cisIndexSegment3D use the new
// container with the same set of vertex indices.
template<class _Container, class _Index>
class cisEXPORT cisIndexSegment3D : public cisAbstractSegment3D
{
public:
	typedef cisAbstractSegment3D::ParametrizationType ParametrizationType;
	typedef cisAbstractSegment3D::AngleType AngleType;
	typedef cisAbstractSegment3D::LocalPointType LocalPointType;
	typedef cisAbstractSegment3D::LocalDirectionType LocalDirectionType;
	typedef cisAbstractSegment3D::GlobalPointType GlobalPointType;
	typedef cisAbstractSegment3D::GlobalDirectionType GlobalDirectionType;

	typedef _Container ContainerType;
	typedef _Index IndexType;

protected:
	const IndexType Vertices[NUM_VERTICES];
	const ContainerType * Container;

public:
	cisIndexSegment3D(const ContainerType * container, 
			  const IndexType & indexVertex0, 
			  const IndexType & indexVertex1)
	  {
	    Container = container;
	    Vertices[0] = indexVertex1;
	    Vertices[1] = indexVertex2;
	  }

	const ContainerType * GetContainer() const
	  {
	    return Container;
	  }

	const ContainerType * SetContainer(const ContainerType * newContainer)
	  {
	    const ContainerType * oldContainer = Container;
	    Container = newContainer;
	    return oldContainer;
	  }

	const IndexType & GetVertexIndex(unsigned int index) const
	  {
	    assert( (index >= 0) && (index < GetNumVertices() );
	    return Vertices[index];
	  }

	virtual const LocalPointType & GetVertex(unsigned int index) const
	  {
	    assert( (index >= 0) && (index < GetNumVertices()) );
	    return (*Container)[ Vertices[index] ];
	  }

	virtual const LocalPointType & GetVertex0() const
	  {
	    return (*Container)[ Vertices[0] ];
	  }

	virtual const LocalPointType & GetVertex1() const
	  {
	    return (*Container)[ Vertices[1] ];
	  }

	virtual ~cisIndexSegment3D()
	  {}
};

#endif

