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

#include <vector>

#include "BlitzExtension/blitzConfig.h"

class gmafQuad;
class gmafPCCMQuad;

class gmafQuadVertex {
// ENUMS
public:
  enum { UPPER_LEFT = 0,
	 LOWER_LEFT = 1,
	 LOWER_RIGHT = 2,
	 UPPER_RIGHT = 3 };

private:
  struct QuadNeighbor {
    int quadidx;
    int corner;
    QuadNeighbor(int i, int c) { quadidx = i; corner = c; }
  };
// VARIABLES
/**@name Class Variables */
//@{
protected:
  /** 
      contain the neighbor quads of this vertex
  */
  vector<QuadNeighbor> mNeighborList; //CW

private:
  Vertex3D mTmpVertex;
//@}

// METHODS
/**@name Class Methods */
//@{
public:
  /**
     qidx : the index of the added quad
     c : the corner of the added quad
     br : the blend ratio for the added edge
  */    
  inline void addNeighbor(int qidx, int c) {
    QuadNeighbor qn(qidx,c);
    mNeighborList.push_back(qn);
  }

  /**
     Because these tree function will use the temp variable, 
     the caller function must copy/use the return vertex right
     away after calling these function.
   */
  const Vertex3D& sumAlphaVertices(vector<gmafQuad*>& qlist, 
					  int l = -1);
  const Vertex3D& sumGammaVertices(vector<gmafQuad*>& qlist, 
					  int l = -1);
  const Vertex3D& sumBetaVertices(vector<gmafQuad*>& qlist, 
					 int l = -1);

  inline int getValance() { return mNeighborList.size(); }

  void writeBackAlphaVertex(Vertex3D& v, vector<gmafQuad*>& qlist, 
				   int l = -1);
  void synchronizeBetaVertex(vector<gmafQuad*>& qlist, int l = -1);
  void writeBackPCCMAlphaVertex(Vertex3D& v,
				vector<gmafPCCMQuad*>& pccmqlist);

  /**
     Fllowing tree functions are only for PCCM. The rule of the index
     is based on PCCM paper.
   */
  void getPCCMQij(Vertex3D& q00,
		  VertexMatrix1D& q10,
		  VertexMatrix1D& q20,
		  VertexMatrix1D& q40,
		  vector<gmafPCCMQuad*>& pccmqlist);
  void setPCCMQij(const VertexMatrix1D& q10,
		  const VertexMatrix1D& q20,
		  const VertexMatrix1D& q11,
		  const VertexMatrix1D& dq20,
		  vector<gmafPCCMQuad*>& pccmqlist);
  void setPCCMQij(const VertexMatrix1D& q10,
		  const VertexMatrix1D& q20,
		  const VertexMatrix1D& q11,
		  const VertexMatrix1D& dq20,
		  const VertexMatrix1D& dq40,
		  vector<gmafPCCMQuad*>& pccmqlist);

  /**
     
   */
  void getVertices(VertexMatrix1D& q11, 
		   VertexMatrix1D& q21, //CCW
		   VertexMatrix1D& q22, //CCW
		   vector<gmafQuad*>& qlist,
		   int layer = -1);
  void getVertices(Vertex3D& q11, 
		   VertexMatrix1D& q21, //CCW
		   VertexMatrix1D& q22, //CCW
		   vector<gmafQuad*>& qlist,
		   int layer = -1);
  void setVertices(const Vertex3D& q11,
		   const VertexMatrix1D& q21, //CCW
		   const VertexMatrix1D& q22, //CCW
		   vector<gmafQuad*>& qlist,
		   int layer = -1);

  /**
     brout : the blend ratio from this vertex to its neighbor vertices 
     brin  : the blend ratio from the neighbor vertices to this vertex 
  */ 
  void getBlendRatios(Matrix1D& brout, 
		      Matrix1D& brin, 
		      vector<gmafQuad*>& qlist); // CCW
protected:
  
private:

};

#endif gmafQuadVertex_H
