/*
	File: marching_cubes_33.h
	Programed by: David Vega    - dvega@uc.edu.ve
                 Javier Abache - jabache@uc.edu.ve
	March 2012
	updated by David Vega
	December 2014
*/
#ifndef marching_cubes_33_h
#define marching_cubes_33_h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/*
GRD_data_type is the variable type for the grid data, by default it is float,
you can use unsigned char, unsigned short int, int, etc...
*/
//#ifndef GRD_data_type
//#define GRD_data_type float
//#endif
// moved to marching_cubes_33.c

#include "MC33_LookUpTable.h"

/*
The structure _GRD contain a function F[][][] evaluated at a grid of regularly
spaced points. N[] is the number of intervals in each dimension, so the number
of points is N[] + 1, and the grid contain (N[2] + 1)*(N[1] + 1)*(N[0] + 1)
points. L[] is the grid size in each dimension. r0[] are the coordinates of
the first grid point. d[] is the distance between adjacent points in each
dimension (can be different for each dimension), nonortho has a value of 1 when
the grid is inclined else 0. _A and A_ are the matrices that transform from
inclined to orthogonal coordinates and vice versa, respectively. If the grid is
periodic (is infinitely repeated along each dimension) the flag periodic must
be 1, else 0.

In this program, if _ORTHO_GRD is defined, then nonortho, _A and A_ can be
removed from this structure, and only works with orthogonal grids. periodic
and L[] are not used here and also can be removed.
*/

#ifndef MC33_util_grd_c
#ifndef LAGRANGE3D4GRD_H
typedef struct
{
	GRD_data_type ***F;
	int N[3];
	float L[3], Ang[3];//not necesary
	double r0[3], d[3];
#ifndef _ORTHO_GRD
	int nonortho; //necessary if _ORTHO_GRD is not defined
	double _A[3][3], A_[3][3]; //necessary if _ORTHO_GRD is not defined
#endif
	int periodic;//not necesary
	char title[128];//not necesary
} _GRD;
#endif
#endif

//#define MC_Normal_neg //when defined front and back surface are interchanged.

/*The struct surface (pointed by S) contains the data of a isosurface. The
isovalue is S->ISO, the number of surface points is S->nV + 1, and the number
of triangles is S->nT + 1. The coordinates of the points are stored in the
array V[][dim2][3]. The coordinates of the surface point number n are obtained
using V[n/S->dim2][n%S->dim2][]. N[][dim2][3] is the array that contains the
normal vectors calculated at the surface points. color[][dim2] contains the
color index of each point. T[][dim2][3] is the array that contains the set of
three points (vertexes) indices that form each triangle.*/
typedef struct
{
	float ISO;
	int dim2;
	int nV, nT;
	int (**T)[3];
	float (**V)[3];
	float (**N)[3];
	int **color;
} surface;

/*_MC_DVE is the second dimension of the struct surface arrays (its value is
equal to the struct surface member dim2). _MC_A is a mask (n&_MC_A is equivalent
to n%_MC_DVE). _MC_DVE and _MC_A are calculated using _MC_N, n>>_MC_N is
equivalent to n/_MC_DVE.*/
int _MC_N = 12;
int _MC_A = 0;
int _MC_DVE;

int DefaultColorMC = 0xff5c5c5c;//gray RGB color as unsigned char [3]

/*
error_mem() must be defined. this function is called when a memory allocation
error occurs in store_point_normal and store_triangle functions.
*/
void error_mem();

/******************************************************************
Save all the surface *S data (in binary format) to a "filename" file. The
return value is 0 if the call succeeds, else -1.
*/
int write_bin_s(char *filename, surface *S);

/******************************************************************
read (from a "filename" file) the surface data stored in binary format. The
return value is a surface pointer if the call succeeds, else NULL.
*/
surface* read_bin_s(char *filename);

/******************************************************************
Save all the surface *S data (in plain text format) to a "filename" file. The
return value is 0 if the call succeeds, else -1.
*/
int write_txt_s(char* filename, surface *S);

/******************************************************************
Calculate the isosurface with isovalue equal to iso, using a grd grid. the dimsn
value is used to calculate the dim2 value of the surface struture. The return
value is a surface pointer.
*/
surface* calculate_isosurface(_GRD* grd, float iso, int dimsn = _MC_N);

/******************************************************************
Freeing the allocated memory for the surface *S data
*/
void free_surface_memory(surface* &S);
#endif
