/****************************************************************************
** GMAF - The Geometry Modeling Algorithms Framework
**
** Created : 03252000
**
** Copyright (C) 2000 by Le-Jeng Shiue.  All rights reserved.
**
****************************************************************************/
#include <assert.h>
#include <iostream>
#include <limits.h>

#include "gmafQuad.h"

#include "gmafConfig.h"
#include "CgalExtension/cgalConfig.h"
#include "BlitzExtension/blitzConfig.h"

#include "BlitzExtension/gmafMatrixCirculator.h"
#include "gmafSubQuadIterator.h"

using namespace blitz;

//                                     0   1   2   3
const int gmafQuad::mBRMap[4][4] = { {-1,  0, -1,  7}, //0
				     { 1, -1,  2, -1}, //1
				     {-1,  3, -1,  4}, //2
				     { 6, -1,  5, -1}};//3


gmafQuad::gmafQuad(const Facet* f) : gmafDataStructure() {
  // This facet MUST have exactly 4 edges
  assert(CGAL::circulator_size(f->facet_begin()) == 4);

  mpFacet = const_cast<Facet*> (f);

  VertexMatrix2D* quadMatrix = new VertexMatrix2D(4,4);
  VertexMatrix2D& qm = *quadMatrix;
  qm = 0;

  // Set the central region of Quad
#define Vx(c) ((((c)->vertex())->point()).x())
#define Vy(c) ((((c)->vertex())->point()).y())
#define Vz(c) ((((c)->vertex())->point()).z())

  Halfedge_around_facet_circulator hecir = mpFacet->facet_begin(); //CCW
  Halfedge_handle neighber;
  gmafMatrixCirculator<VertexMatrix2D> qmc00(qm, 0, 0); //CCW
  gmafMatrixCirculator<VertexMatrix2D> qmc11(qm, 1, 1); //CCW
  gmafMatrixCirculator<VertexMatrix2D> qmc01(qm, 0, 1); //CCW
  gmafMatrixCirculator<VertexMatrix2D> qmc02(qm, 0, 2); //CCW
  int valance;
  for (int i = 0; i < qmc11.size(); hecir++, i++) {
    // set the central vertices
    qmc11.current() = Vx(hecir), Vy(hecir), Vz(hecir);
    // set the vertices of its neighber edge 
    // Here I assume all facets are quadralaterals
    neighber = (hecir->opposite())->next();
    qmc02.current() = Vx(neighber), Vy(neighber), Vz(neighber); 
    neighber = neighber->next();
    qmc01.current() = Vx(neighber), Vy(neighber), Vz(neighber);

    valance = CGAL::circulator_size(hecir->vertex_begin());
    mCornerValance[i] = valance;
    if (valance == 4) {
      neighber = ((neighber->next())->opposite())->next();
      qmc00.current() = Vx(neighber), Vy(neighber), Vz(neighber);
    } else if (valance == 3) {
      //qmc00.current() = qmc01.current();
    } else {
      //qmc00.current() = numeric_limits<DOUBLE>::quiet_NaN();
    }
    qmc00.next(); qmc11.next(); qmc01.next(); qmc02.next();
  }

  mMipQuad.push_back(quadMatrix);
  mCurLayer = 0;
  mValid = true;

  // initialize the blend ratios
  for (int i = 0; i < 8; i++)
    mBlendRatio[i] = 0.0;
}


gmafQuad::~gmafQuad() {
  //Clean the mip matrix here !!
  for (int i = 0; i < mMipQuad.size(); i++)
    delete mMipQuad[i];
}

void gmafQuad::dump(int l) {
#ifdef _DEBUG
  /*
  assert(l <= mCurLayer); 
  int layer = l < 0  ? mCurLayer : l;
  VertexMatrix2D* pQM = mMipQuad[layer];
  std::cerr << "Quad  (Layer = " << layer << " : Valance = " << 
    mCornerValance[0] << " " << mCornerValance[1] << " " << 
    mCornerValance[2] << " " << mCornerValance[3] << std::endl;
  for (int i = 0; i < pQM->rows(); i++) {
    for (int j = 0; j < pQM->cols(); j++)
      std::cerr << (*pQM)(i,j);
    std::cerr << std::endl;
  }
*/
    
  /*
  Vertex3D* vd = pQM->data();
  DOUBLE* dd = vd->data();
  Matrix2D x = pQM->extractComponent(DOUBLE(), firstDim,  3);
  Matrix2D y = pQM->extractComponent(DOUBLE(), secondDim, 3);
  Matrix2D z = pQM->extractComponent(DOUBLE(), thirdDim,  3);

  std::cerr << "mQuadMatrix : " << *pQM << std::endl;
  std::cerr << "x : " << x << std::endl;
  std::cerr << "y : " << y << std::endl;
  std::cerr << "z : " << z << std::endl;

  std::cerr << "xyz : " << std::endl;
  for (int i = 0; i < pQM->rows(); i++) {
    for (int j = 0; j < pQM->cols(); j++) {
      std::cerr << "[" << (*vd)(0) << " " << (*vd)(1) << " " << (*vd)(2) << "] ";
      vd++;
    }
    std::cerr << std::endl;
  }

  std::cerr << "Quad  (Layer = " << layer << " : Valance = " << 
    mCornerValance[0] << " " << mCornerValance[1] << " " << 
    mCornerValance[2] << " " << mCornerValance[3] << std::endl;
  for (int i = 0; i < pQM->rows(); i++) {
    for (int j = 0; j < pQM->cols(); j++) {
      std::cerr << "[" << *dd++ << " " ;
      std::cerr << *dd++ << " ";
      std::cerr << *dd++ << "] ";
    }
    std::cerr << std::endl;
  }
  */
    
#endif _DEBUG

}
