/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkAutomaticTopologyMeshSource.txx,v $
  Language:  C++
  Date:      $Date: 2005/07/26 15:05:01 $
  Version:   $Revision: 1.19 $

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef _itkAutomaticTopologyMeshSource_txx
#define _itkAutomaticTopologyMeshSource_txx

// For debugging.
#include <iostream>
#include <algorithm>

#include "itkAutomaticTopologyMeshSource.h"
#include "itkNumericTraits.h"

namespace itk
{


template<class TOutputMesh>
AutomaticTopologyMeshSource<TOutputMesh>
::AutomaticTopologyMeshSource()
{
  m_OutputMesh = TOutputMesh::New();

  this->ProcessObject::SetNumberOfRequiredOutputs(1);
  this->ProcessObject::SetNthOutput(0, m_OutputMesh.GetPointer());

  this->ReleaseDataBeforeUpdateFlagOff(); // Prevents destruction of the current mesh output
}

template<class TOutputMesh>
AutomaticTopologyMeshSource<TOutputMesh>
::~AutomaticTopologyMeshSource()
{
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddPoint( const PointType& p0 )
{
  IdentifierType nextNewPointID = m_OutputMesh->GetNumberOfPoints();
  IdentifierType& pointIDPlusOne = m_PointsHashTable[ p0 ];
  IdentifierType pointID;
  if( pointIDPlusOne != 0 )
    {
    pointID = pointIDPlusOne - 1;
    }
  else
    {
    pointID = nextNewPointID;
    pointIDPlusOne = pointID + 1;
    m_OutputMesh->SetPoint( pointID, p0 );
    }
  return pointID;
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddPoint( const CoordinateType* p0)
{
  PointType newPoint;
  unsigned int i;
  for( i = 0; i < PointDimension; i++ )
    {
    newPoint[ i ] = p0[ i ];
    }
  return AddPoint( newPoint );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddPoint( CoordinateType x0, CoordinateType x1, CoordinateType x2,
            CoordinateType x3, CoordinateType x4, CoordinateType x5 )
{
  CoordinateType p0[] = { x0, x1, x2, x3, x4, x5 };
  PointType newPoint;
  unsigned int i;
  unsigned int end = ( PointDimension < 6 ? PointDimension : 6 );
  for( i = 0; i < end; i++ )
    {
    newPoint[ i ] = p0[ i ];
    }
  for( ; i < PointDimension; i++ )
    {
    newPoint[ i ] = 0;
    }
  return AddPoint( newPoint );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddVertex( const IdentifierArrayType& pointIDs )
{
  // pointIDs is an array with one element; this is for consistency.

  // m_PointsHashTable[ foo ] is set to 0 if foo is not found, but I
  // want the initial identifier to be 0.  
  IdentifierType* cellIDPlusOne = &m_CellsHashTable[ pointIDs ];
  IdentifierType cellID;
  
  if( *cellIDPlusOne != 0 )
    {
    cellID = *cellIDPlusOne - 1;
    }
  else
    {

    // Choose the ID and store it in its hash location (cellIDPlusOne)
    cellID = m_OutputMesh->GetNumberOfCells();
    *cellIDPlusOne = cellID + 1;

    // Construct the cell.
    CellAutoPointer newCell;
    newCell.TakeOwnership( new VertexCell );
    newCell->SetPointId( 0, pointIDs[0] );

    // Add the cell to the mesh.
    m_OutputMesh->SetCell( cellID, newCell ); 

    m_OutputMesh->SetBoundaryAssignment( 0, cellID, 0, cellID );

    }
  return cellID;
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddLine( const IdentifierArrayType& pointIDs )
{       

  // Check to see if the cell is already referenced in the hash table.
  IdentifierType* cellIDPlusOne = &m_CellsHashTable[ pointIDs ];
  IdentifierType cellID;

  if( *cellIDPlusOne != 0 )
    {
    cellID = *cellIDPlusOne - 1;
    }
  else
    {
    const IdentifierType pointIdsEnd = 2;

    // Construct the cell.
    CellAutoPointer newCell;
    newCell.TakeOwnership( new LineCell );

    // Add the points and vertices, keeping track of the vertex IDs.
    IdentifierArrayType vertexArray( pointIdsEnd );
    IdentifierType i;
    for( i = 0; i < pointIdsEnd; i++ )
      {
      IdentifierType pointID = pointIDs[i];
      vertexArray[i] = AddVertex( pointID );
      newCell->SetPointId( i, pointID );
      }

    // Choose the ID and store it in its hash location (cellIDPlusOne)
    cellID = m_OutputMesh->GetNumberOfCells();
    *cellIDPlusOne = cellID + 1;

    // Add the cell to the mesh.
    m_OutputMesh->SetCell( cellID, newCell ); 

    // Set the boundaries for the new cell.

    for( i = 0; i < pointIdsEnd; i++ )
      {
      IdentifierType boundaryID = vertexArray[i];
      m_OutputMesh->SetBoundaryAssignment( 0, cellID, i, boundaryID );
      }

    }

  return cellID;
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddTriangle( const IdentifierArrayType& pointIDs )
{

  // Check to see if the cell is already referenced in the hash table.
  IdentifierType* cellIDPlusOne = &m_CellsHashTable[ pointIDs ];
  IdentifierType cellID;

  if( *cellIDPlusOne != 0 )
    {
    cellID = *cellIDPlusOne - 1;
    }
  else
    {

    // Create and add a new cell.

    const IdentifierType pointIdsEnd = 3;
    const IdentifierType lineIdsEnd = 3;
    IdentifierType i;

    // Construct the cell.
    CellAutoPointer newCell;
    newCell.TakeOwnership( new TriangleCell );

    // Add the points and vertices, keeping track of the vertex IDs.
    IdentifierArrayType vertexArray( pointIdsEnd );
    for( i = 0; i < pointIdsEnd; i++ )
      {
      IdentifierType pointID = pointIDs[i];
      vertexArray[i] = AddVertex( pointID );
      newCell->SetPointId( i, pointID );
      }

    // Add the edges, keeping track of edge IDs.
    IdentifierArrayType lineArray( lineIdsEnd );
    for( i = 0; i < lineIdsEnd; i++ )
      {
      lineArray[i] = AddLine( pointIDs[i], pointIDs[ (i+1) % pointIdsEnd ] );
      }

    // Choose the ID and store it in its hash location (cellIDPlusOne)
    cellID = m_OutputMesh->GetNumberOfCells();
    *cellIDPlusOne = cellID + 1;

    // Add the cell to the mesh.
    m_OutputMesh->SetCell( cellID, newCell ); 

    // Set the boundaries for the new cell.

    for( i = 0; i < pointIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 0, cellID, i, vertexArray[i] );
      }

    for( i = 0; i < lineIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 1, cellID, i, lineArray[i] );
      }

    }

  return cellID;
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddQuadrilateral( const IdentifierArrayType& pointIDs )
{

  // Check to see if the cell is already referenced in the hash table.
  IdentifierType* cellIDPlusOne = &m_CellsHashTable[ pointIDs ];
  IdentifierType cellID;

  if( *cellIDPlusOne != 0 )
    {
    cellID = *cellIDPlusOne - 1;
    }
  else
    {

    // Create and add a new cell.

    const IdentifierType pointIdsEnd = 4;
    const IdentifierType lineIdsEnd = 4;
    IdentifierType i;

    // Construct the cell.
    CellAutoPointer newCell;
    newCell.TakeOwnership( new QuadrilateralCell );

    // Add the points and vertices, keeping track of the vertex IDs.
    IdentifierArrayType vertexArray( pointIdsEnd );
    for( i = 0; i < pointIdsEnd; i++ )
      {
      IdentifierType pointID = pointIDs[i];
      vertexArray[i] = AddVertex( pointID );
      newCell->SetPointId( i, pointID );
      }

    // Add the edges, keeping track of edge IDs.
    IdentifierArrayType lineArray( lineIdsEnd );
    lineArray[0] = AddLine( pointIDs[0], pointIDs[1] );
    lineArray[1] = AddLine( pointIDs[2], pointIDs[3] );
    lineArray[2] = AddLine( pointIDs[0], pointIDs[2] );
    lineArray[3] = AddLine( pointIDs[1], pointIDs[3] );

    // Choose the ID and store it in its hash location (cellIDPlusOne)
    cellID = m_OutputMesh->GetNumberOfCells();
    *cellIDPlusOne = cellID + 1;

    // Add the cell to the mesh.
    m_OutputMesh->SetCell( cellID, newCell ); 

    // Set the boundaries for the new cell.

    for( i = 0; i < pointIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 0, cellID, i, vertexArray[i] );
      }

    for( i = 0; i < lineIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 1, cellID, i, lineArray[i] );
      }

    }
  return cellID;
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddTetrahedron( const IdentifierArrayType& pointIDs )
{

  // Check to see if the cell is already referenced in the hash table.
  IdentifierType* cellIDPlusOne = &m_CellsHashTable[ pointIDs ];
  IdentifierType cellID;

  if( *cellIDPlusOne != 0 )
    {
    cellID = *cellIDPlusOne - 1;
    }
  else
    {

    // Create and add a new cell.

    const IdentifierType pointIdsEnd = 4;
    const IdentifierType lineIdsEnd = 6;
    const IdentifierType faceIdsEnd = 4;
    IdentifierType i;

    // Construct the cell.
    CellAutoPointer newCell;
    newCell.TakeOwnership( new TetrahedronCell );

    // Add the points and vertices, keeping track of the vertex IDs.
    IdentifierArrayType vertexArray( pointIdsEnd );
    for( i = 0; i < pointIdsEnd; i++ )
      {
      IdentifierType pointID = pointIDs[i];
      vertexArray[i] = AddVertex( pointID );
      newCell->SetPointId( i, pointID );
      }

    // Add the edges, keeping track of edge IDs.
    IdentifierArrayType lineArray( lineIdsEnd );
    lineArray[0] = AddLine( pointIDs[0], pointIDs[1] );
    lineArray[1] = AddLine( pointIDs[0], pointIDs[2] );
    lineArray[2] = AddLine( pointIDs[0], pointIDs[3] );
    lineArray[3] = AddLine( pointIDs[1], pointIDs[2] );
    lineArray[4] = AddLine( pointIDs[1], pointIDs[3] );
    lineArray[5] = AddLine( pointIDs[2], pointIDs[3] );

    // Add the faces, keeping track of face IDs.
    IdentifierArrayType faceArray( faceIdsEnd );
    faceArray[0] = AddTriangle( pointIDs[0], pointIDs[1], pointIDs[2] );
    faceArray[1] = AddTriangle( pointIDs[0], pointIDs[1], pointIDs[3] );
    faceArray[2] = AddTriangle( pointIDs[0], pointIDs[2], pointIDs[3] );
    faceArray[3] = AddTriangle( pointIDs[1], pointIDs[2], pointIDs[3] );

    // Choose the ID and store it in its hash location (cellIDPlusOne)
    cellID = m_OutputMesh->GetNumberOfCells();
    *cellIDPlusOne = cellID + 1;

    // Add the cell to the mesh.
    m_OutputMesh->SetCell( cellID, newCell ); 

    // Set the boundaries for the new cell.

    for( i = 0; i < pointIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 0, cellID, i, vertexArray[i] );
      }

    for( i = 0; i < lineIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 1, cellID, i, lineArray[i] );
      }

    for( i = 0; i < faceIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 2, cellID, i, faceArray[i] );
      }

    }

  return cellID;
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource<TOutputMesh>
::AddHexahedron( const IdentifierArrayType& pointIDs )
{

  // Check to see if the cell is already referenced in the hash table.
  IdentifierType* cellIDPlusOne = &m_CellsHashTable[ pointIDs ];
  IdentifierType cellID;

  if( *cellIDPlusOne != 0 )
    {
    cellID = *cellIDPlusOne - 1;
    }
  else
    {

    // Create and add a new cell.

    const IdentifierType pointIdsEnd = 8;
    const IdentifierType lineIdsEnd = 12;
    const IdentifierType faceIdsEnd = 6;
    IdentifierType i;

    // Construct the cell.
    CellAutoPointer newCell;
    newCell.TakeOwnership( new HexahedronCell );

    // Add the points and vertices, keeping track of the vertex IDs.
    IdentifierArrayType vertexArray( pointIdsEnd );
    for( i = 0; i < pointIdsEnd; i++ )
      {
      IdentifierType pointID = pointIDs[i];
      vertexArray[i] = AddVertex( pointID );
      newCell->SetPointId( i, pointID );
      }

    // Add the edges, keeping track of edge IDs.
    IdentifierArrayType lineArray( lineIdsEnd );
    lineArray[0]  = AddLine( pointIDs[0], pointIDs[1] );
    lineArray[1]  = AddLine( pointIDs[2], pointIDs[3] );
    lineArray[2]  = AddLine( pointIDs[4], pointIDs[5] );
    lineArray[3]  = AddLine( pointIDs[6], pointIDs[7] );
    lineArray[4]  = AddLine( pointIDs[0], pointIDs[2] );
    lineArray[5]  = AddLine( pointIDs[1], pointIDs[3] );
    lineArray[6]  = AddLine( pointIDs[4], pointIDs[6] );
    lineArray[7]  = AddLine( pointIDs[5], pointIDs[7] );
    lineArray[8]  = AddLine( pointIDs[0], pointIDs[4] );
    lineArray[9]  = AddLine( pointIDs[1], pointIDs[5] );
    lineArray[10] = AddLine( pointIDs[2], pointIDs[6] );
    lineArray[11] = AddLine( pointIDs[3], pointIDs[7] );

    // Add the faces, keeping track of face IDs.
    IdentifierArrayType faceArray( faceIdsEnd );
    faceArray[0] = AddQuadrilateral( pointIDs[0], pointIDs[1], pointIDs[2], pointIDs[3] );
    faceArray[1] = AddQuadrilateral( pointIDs[4], pointIDs[5], pointIDs[6], pointIDs[7] );
    faceArray[2] = AddQuadrilateral( pointIDs[0], pointIDs[1], pointIDs[4], pointIDs[5] );
    faceArray[3] = AddQuadrilateral( pointIDs[2], pointIDs[3], pointIDs[6], pointIDs[7] );
    faceArray[4] = AddQuadrilateral( pointIDs[0], pointIDs[2], pointIDs[4], pointIDs[6] );
    faceArray[5] = AddQuadrilateral( pointIDs[1], pointIDs[3], pointIDs[5], pointIDs[7] );

    // Choose the ID and store it in its hash location (cellIDPlusOne)
    cellID = m_OutputMesh->GetNumberOfCells();
    *cellIDPlusOne = cellID + 1;

    // Add the cell to the mesh.
    m_OutputMesh->SetCell( cellID, newCell ); 

    // Set the boundaries for the new cell.

    for( i = 0; i < pointIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 0, cellID, i, vertexArray[i] );
      }

    for( i = 0; i < lineIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 1, cellID, i, lineArray[i] );
      }

    for( i = 0; i < faceIdsEnd; i++ )
      {
      m_OutputMesh->SetBoundaryAssignment( 2, cellID, i, faceArray[i] );
      }

    }

  return cellID;
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddVertex( IdentifierType pointId0 )
{
  Array<IdentifierType> pointIDs( 1 );
  pointIDs[ 0 ] = pointId0;
  return AddVertex( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddLine( IdentifierType pointId0, IdentifierType pointId1 )
{
  Array<IdentifierType> pointIDs( 2 );
  pointIDs[ 0 ] = pointId0;
  pointIDs[ 1 ] = pointId1;
  return AddLine( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddTriangle( IdentifierType pointId0, IdentifierType pointId1,
               IdentifierType pointId2 )
{
  Array<IdentifierType> pointIDs( 3 );
  pointIDs[ 0 ] = pointId0;
  pointIDs[ 1 ] = pointId1;
  pointIDs[ 2 ] = pointId2;
  return AddTriangle( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddQuadrilateral( IdentifierType pointId0, IdentifierType pointId1,
                    IdentifierType pointId2, IdentifierType pointId3 )
{
  Array<IdentifierType> pointIDs( 4 );
  pointIDs[ 0 ] = pointId0;
  pointIDs[ 1 ] = pointId1;
  pointIDs[ 2 ] = pointId2;
  pointIDs[ 3 ] = pointId3;
  return AddQuadrilateral( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddTetrahedron( IdentifierType pointId0, IdentifierType pointId1,
                  IdentifierType pointId2, IdentifierType pointId3 )
{
  Array<IdentifierType> pointIDs( 4 );
  pointIDs[ 0 ] = pointId0;
  pointIDs[ 1 ] = pointId1;
  pointIDs[ 2 ] = pointId2;
  pointIDs[ 3 ] = pointId3;
  return AddTetrahedron( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddHexahedron( IdentifierType pointId0, IdentifierType pointId1,
                 IdentifierType pointId2, IdentifierType pointId3,
                 IdentifierType pointId4, IdentifierType pointId5,
                 IdentifierType pointId6, IdentifierType pointId7 )
{
  Array<IdentifierType> pointIDs( 8 );
  pointIDs[ 0 ] = pointId0;
  pointIDs[ 1 ] = pointId1;
  pointIDs[ 2 ] = pointId2;
  pointIDs[ 3 ] = pointId3;
  pointIDs[ 4 ] = pointId4;
  pointIDs[ 5 ] = pointId5;
  pointIDs[ 6 ] = pointId6;
  pointIDs[ 7 ] = pointId7;
  return AddHexahedron( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddVertex( const PointType& p0 )
{
  IdentifierType pointId = AddPoint( p0 );
  return AddVertex( pointId );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddLine( const PointType& p0, const PointType& p1 )
{
  Array<IdentifierType> pointIDs( 2 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  return AddLine( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddTriangle( const PointType& p0, const PointType& p1,
               const PointType& p2 )
{
  Array<IdentifierType> pointIDs( 3 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  return AddTriangle( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddQuadrilateral( const PointType& p0, const PointType& p1,
                    const PointType& p2, const PointType& p3 )
{
  Array<IdentifierType> pointIDs( 4 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  pointIDs[ 3 ] = AddPoint( p3 );
  return AddQuadrilateral( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddTetrahedron( const PointType& p0, const PointType& p1,
                  const PointType& p2, const PointType& p3 )
{
  Array<IdentifierType> pointIDs( 4 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  pointIDs[ 3 ] = AddPoint( p3 );
  return AddTetrahedron( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddHexahedron(
  const PointType& p0, const PointType& p1, const PointType& p2,
  const PointType& p3, const PointType& p4, const PointType& p5,
  const PointType& p6, const PointType& p7 )
{
  Array<IdentifierType> pointIDs( 8 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  pointIDs[ 3 ] = AddPoint( p3 );
  pointIDs[ 4 ] = AddPoint( p4 );
  pointIDs[ 5 ] = AddPoint( p5 );
  pointIDs[ 6 ] = AddPoint( p6 );
  pointIDs[ 7 ] = AddPoint( p7 );
  return AddHexahedron( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddVertex( const CoordinateType* p0)
{
  Array<IdentifierType> pointIDs( 1 );
  pointIDs[ 0 ] = AddPoint( p0 );
  return AddVertex( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddLine( const CoordinateType* p0,
           const CoordinateType* p1)
{
  Array<IdentifierType> pointIDs( 2 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  return AddLine( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddTriangle( const CoordinateType* p0,
               const CoordinateType* p1,
               const CoordinateType* p2 )
{
  Array<IdentifierType> pointIDs( 3 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  return AddTriangle( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddQuadrilateral( const CoordinateType* p0, 
                    const CoordinateType* p1,
                    const CoordinateType* p2,
                    const CoordinateType* p3 )
{
  Array<IdentifierType> pointIDs( 4 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  pointIDs[ 3 ] = AddPoint( p3 );
  return AddQuadrilateral( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddTetrahedron( const CoordinateType* p0,
                  const CoordinateType* p1,
                  const CoordinateType* p2,
                  const CoordinateType* p3 )
{
  Array<IdentifierType> pointIDs( 4 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  pointIDs[ 3 ] = AddPoint( p3 );
  return AddTetrahedron( pointIDs );
}

template<class TOutputMesh>
typename AutomaticTopologyMeshSource< TOutputMesh >::IdentifierType
AutomaticTopologyMeshSource< TOutputMesh >
::AddHexahedron( const CoordinateType* p0,
                 const CoordinateType* p1,
                 const CoordinateType* p2,
                 const CoordinateType* p3,
                 const CoordinateType* p4,
                 const CoordinateType* p5,
                 const CoordinateType* p6,
                 const CoordinateType* p7)
{
  Array<IdentifierType> pointIDs( 8 );
  pointIDs[ 0 ] = AddPoint( p0 );
  pointIDs[ 1 ] = AddPoint( p1 );
  pointIDs[ 2 ] = AddPoint( p2 );
  pointIDs[ 3 ] = AddPoint( p3 );
  pointIDs[ 4 ] = AddPoint( p4 );
  pointIDs[ 5 ] = AddPoint( p5 );
  pointIDs[ 6 ] = AddPoint( p6 );
  pointIDs[ 7 ] = AddPoint( p7 );
  return AddHexahedron( pointIDs );
}

} /** end namespace itk. */

#endif

