/****************************************************************************
** GMAF - The Geometry Modeling Algorithms Framework
**
** Created : 04022000
**
** Copyright (C) 2000 by Le-Jeng Shiue.  All rights reserved.
**
****************************************************************************/
#ifndef gmafFacetVertexIterator_H
#define gmafFacetVertexIterator_H

#include "BlitzExtension/blitzConfig.h"
#include "gmafQuad.h"

/**
   gmafFacetVertexIterator:
   Ex. QuadArray = 1 2 3 4 5  (Assume 1,5 are valid corners) 
                   6 7 8 9 a
		   b c d e f
		   g h i j k
		   l m n o p
   This itr will traverse this quad in following order: 
   1 3 5 b d f n
*/
class gmafFacetVertexIterator {
// ENUMS
public:

// VARIABLES
/**@name Class Variables */
//@{
protected:
  gmafQuad* mpQuad; // the quad which this itr to traverse
  VertexMatrix2D mQM; // the blitz array which represent the quad
  VertexMatrix2D mMatrix; // only contains the needed entries

  VertexMatrix2D::iterator mCurItr;
  int mSize; // total number of the fcaet vertices
  int mW; // width of the quad
  int mH; // height of the quad
  int mCurPos;
  int mStartPos;
  int mEndPos;
  Vertex3D mCurVertex;
private:

//@}

// METHODS
/**@name Class Methods */
//@{
public:
  /**
     Constructor of gmafFacetVertexIterator
     it will traverse the 4 corners if they are valance 4
  */    
  gmafFacetVertexIterator(gmafQuad* q);
  /**
     Destructor of gmafFacetVertexIterator
  */
  virtual ~gmafFacetVertexIterator();
  
  inline virtual int size() const;
  inline virtual void restart();
  inline virtual bool valid() const;
  inline virtual void next();
  inline virtual Vertex3D& current() ; // return the facet value
  
protected:
  
private:
};

//---------------------------------------------------------
inline gmafFacetVertexIterator::gmafFacetVertexIterator(gmafQuad* q) 
  : mQM(q->getQuadArray()), 
  mMatrix(mQM(Range(0, mQM.rows()-1, 2), Range(0, mQM.cols()-1, 2))), 
  mCurItr(mMatrix.begin()) {
  
  mpQuad = q;
  
  mH = mMatrix.rows(); //1st dimension
  mW = mMatrix.cols(); //2rd dimension
  
  mSize = mH*mW;
  for (int c = 0; c < 4; c++)
    if (!mpQuad->isCornerValid(c)) mSize--;

  mStartPos = mpQuad->isCornerValid(gmafQuad::UPPER_LEFT) ? 0 : 1;
  mEndPos = mpQuad->isCornerValid(gmafQuad::LOWER_RIGHT) ? mW*mH : mW*mH-1;
  mCurPos = mStartPos;

  for (int i = 0; i < mStartPos; i++) ++mCurItr;
}

inline gmafFacetVertexIterator::~gmafFacetVertexIterator() {
}

inline int gmafFacetVertexIterator::size() const {
  return mSize; // the number of the facets
}

inline void gmafFacetVertexIterator::restart() {
  mCurPos = mStartPos;
  mCurItr = mMatrix.begin();
  for (int i = 0; i < mStartPos; i++) ++mCurItr;
}

inline bool gmafFacetVertexIterator::valid() const {
  return (mCurPos < mEndPos);
}

inline void gmafFacetVertexIterator::next() {
  if (mCurPos < mEndPos) {
    mCurPos++;
    ++mCurItr;
    if (mCurPos >= mEndPos) return;
    Position2D pos = mCurItr.position();
    while ((pos(0) == 0 && pos(1) == mW-1 && !mpQuad->isCornerValid(gmafQuad::UPPER_RIGHT) ) || //skip the upper-right corner if it's invalid
	   (pos(0) == mH-1 && pos(1) == 0 && !mpQuad->isCornerValid(gmafQuad::LOWER_LEFT) ) ) { //skip the lower-left corner if it's invalid
      mCurPos++;
      ++mCurItr;
      pos = mCurItr.position();
    }
  }
}

inline Vertex3D& gmafFacetVertexIterator::current() {
  return *mCurItr;
}

#endif gmafFacetVertexIterator_H

