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

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

#include "gmafFacetValueIterator.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 : (ref. to sabin rules -- see Siggraph proceedings 99, page 62)
   f2673 : ...
   f3784 : ...
   f59a6 :
   f6ab7 :
   f7bc8 :
   faefb :
*/
class gmafCCSFacetValueIterator : public gmafFacetValueIterator {
// ENUMS
public:

// VARIABLES
/**@name Class Variables */
//@{
protected:
private:
  int mLayer;
//@}

// METHODS
/**@name Class Methods */
//@{
public:
  /**
     Constructor of gmafCCSFacetValueIterator
     it will traverse the 4 corners if they are valance 4
  */    
  gmafCCSFacetValueIterator(gmafQuad* q);
  /**
     Destructor of gmafCCSFacetValueIterator
  */
  virtual ~gmafCCSFacetValueIterator();
  
  inline virtual const Vertex3D& current() const; // return the facet value
  
protected:
  
private:
  // if return -1, it's not adjacent to any corner
  // if return 0,1,2,3, c will contain the corner vertex
  inline int adjacentCorner(Position2D& pos, Vertex3D& c) const;
};

//---------------------------------------------------------
inline gmafCCSFacetValueIterator::gmafCCSFacetValueIterator(gmafQuad* q) 
  : gmafFacetValueIterator(q) {
  mLayer = q->getCurLayerIdx();
}

inline gmafCCSFacetValueIterator::~gmafCCSFacetValueIterator() {
}

inline int gmafCCSFacetValueIterator::
adjacentCorner(Position2D& pos, Vertex3D& c) const {
  if ((pos(0) == 0 && pos(1) == 1) ||
      (pos(0) == 1 && (pos(1) == 0 || pos(1) == 1))) 
    { c = mMatrix(1,1); return 0; }// ul 
  else if ((pos(0) == mH-3 && (pos(1) == 0 || pos(1) == 1)) ||
	   (pos(0) == mH-2 && pos(1) == 1)) 
    { c = mMatrix(mH-2, 1);  return 1; }// ll
  else if ((pos(0) == mH-3 && (pos(1) == mW-3 || pos(1) == mW-2)) || 
	   (pos(0) == mH-2 && pos(1) == mW-3))
    { c = mMatrix(mH-2, mW-2);  return 2; }// lr
  else if ((pos(0) == 0 && pos(1) == mW-3) ||
	   (pos(0) == 1 && (pos(1) == mW-3 || pos(1) == mW-2))) 
    { c = mMatrix(1, mW-2);  return 3; }// ur
  else return -1;
}

inline const Vertex3D& gmafCCSFacetValueIterator::current() const {
  const static double Wn[8] = {
    0, 0, 0, 1.236068 , 1.0 , 0.7185  , 0.5223333 , 0.391842565
  };
  gmafCCSFacetValueIterator* me = (gmafCCSFacetValueIterator*)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);
  Vertex3D corner;
  int c = adjacentCorner(pos, corner);
  if (c != -1 && mpQuad->getCornerValance(c) != 4) {
    double w = Wn[mpQuad->getCornerValance(c)];
    me->mCurValue -= corner; 
    me->mCurValue += (w*corner);
    me->mCurValue /= (3+w);
  } else me->mCurValue /= 4;
  return mCurValue;
}

#endif gmafCCSFacetValueIterator_H

