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

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

/**
   gmafFacetValueIterator: It will calculate the value of the facet by 
   CC subdivision rule.
   Ex. QuadArray = 1 2 3 4 (Assume 1,4 are valid corners)
                   5 6 7 8
		   9 a b c
		   d e f g
   This itr will traverse this quad in following order: 
   f1562 : (v1+v5+v6+v2)/4
   f2673 : ...
   f3784 : ...
   f59a6 :
   f6ab7 :
   f7bc8 :
   faefb :
*/
class gmafFacetValueIterator {
// ENUMS
public:

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

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

//@}

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

//---------------------------------------------------------
inline gmafFacetValueIterator::gmafFacetValueIterator(gmafQuad* q) 
  : mMatrix(q->getQuadArray()), mCurItr(mMatrix.begin()) {
  mpQuad = q;

  mW = mMatrix.cols();
  mH = mMatrix.rows();
  mSize = (mW-1)*(mH-1)-4;
  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-1)-1 : mW*(mH-1)-2;
  mCurPos = mStartPos;

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

inline gmafFacetValueIterator::~gmafFacetValueIterator() {
}

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

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

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

inline void gmafFacetValueIterator::next() {
  if (mCurPos < mEndPos) {
    mCurPos++;
    ++mCurItr;
    if (mCurPos >= mEndPos) return;
    blitz::TinyVector<int,2> pos = mCurItr.position();
    // it will not traverse to the last row of the 
    // vertices (because mEndSubQuadPos)
    while (pos(1) == mW-1 || // skip the last col 
	   (pos(0) == 0 && pos(1) == mW-2 && !mpQuad->isCornerValid(gmafQuad::UPPER_RIGHT) ) || //skip the upper-right corner if it's invalid
	   (pos(0) == mH-2 && pos(1) == 0 && !mpQuad->isCornerValid(gmafQuad::LOWER_LEFT) ) ) { //skip the lower-left corner if it's invalid
      mCurPos++;
      ++mCurItr;
      pos = mCurItr.position();
    }
  }
}

inline const Vertex3D& gmafFacetValueIterator::current() const {
  gmafFacetValueIterator* me = (gmafFacetValueIterator*)this;
  Position2D pos = mCurItr.position();
  Range r1(pos(0), pos(0)+1);
  Range r2(pos(1), pos(1)+1);
  VertexMatrix2D r = mMatrix(r1, r2);

  me->mCurValue = (r(0,0) + r(0,1) + r(1,0) + r(1,1)) / 4;
  
  return mCurValue;
}

#endif gmafFacetValueIterator_H

