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

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


/**
   It traverse the quad in c fasion order and return the subquads.
*/
class gmafSubQuadIterator {
// ENUMS
public:

// VARIABLES
/**@name Class Variables */
//@{
protected:
  gmafQuad* mpQuad;
  VertexMatrix2D mMatrix;
  VertexMatrix2D mCurSubQuad;
  VertexMatrix2D::iterator mCurItr;
  int mCurPos;
  int mEndPos;
  int mW;
  int mH;
private:

//@}

// METHODS
/**@name Class Methods */
//@{
public:
  /**
     Constructor of gmafSubQuadIterator
  */    
  gmafSubQuadIterator(gmafQuad* q);
  /**
     Destructor of gmafSubQuadIterator
  */    
  virtual ~gmafSubQuadIterator();
  
  inline virtual int size() const;
  inline virtual void restart();
  inline virtual bool valid() const;
  inline virtual void next();
  inline virtual const VertexMatrix2D& current() const;
  
protected:
  
private:
};

//---------------------------------------------------------
inline gmafSubQuadIterator::gmafSubQuadIterator(gmafQuad* q) 
  : mMatrix(q->getQuadArray()), mCurItr(mMatrix.begin()), mCurSubQuad() {
  mpQuad = q;
  mW = mMatrix.cols();
  mH = mMatrix.rows();
  mCurPos = 1;
  mEndPos = (mW-1)*(mH-1)-1;
  ++mCurItr; // skip (0,0)
}

inline gmafSubQuadIterator::~gmafSubQuadIterator() {
}

inline int gmafSubQuadIterator::size() const {
  return (mW-1)*(mH-1)-4;
}

inline void gmafSubQuadIterator::restart() {
  mCurPos = 1;
  mCurItr = mMatrix.begin();
  ++mCurItr; // skip (0,0)
}

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

inline void gmafSubQuadIterator::next() {
  if (mCurPos < mEndPos) { 
    mCurPos++;
    ++mCurItr;
    if (mCurPos == mW-2 || mCurPos == mEndPos-(mW-2)) {
      mCurPos++;
      ++mCurItr;
    }
  }
}

inline const VertexMatrix2D& gmafSubQuadIterator::current() const {
  gmafSubQuadIterator* me = (gmafSubQuadIterator*)this;
  blitz::TinyVector<int,2> idx = mCurItr.position();
  blitz::Range r1(idx(0), idx(0)+1);
  blitz::Range r2(idx(1), idx(1)+1);
  me->mCurSubQuad.reference(mMatrix(r1, r2));
  return mCurSubQuad;
}



#endif gmafSubQuadIterator_H

