#pragma once
#include "MCEGenerateFace.h"
typedef enum{CRYSTALS_FOU_FILE, GSAS_GRD_FILE, XD_GRD2D_FILE, XD_GRD3D_FILE, GSAS_FOB_FILE, THREE_D, XPLOR_TYPE, SHRINK_TYPE} Map_type;
typedef enum {nX,nY,nZ, nCustom} n_contour_direction;
typedef enum {SHRINK_ORIGIN_FIRST_ATOM, SHRINK_ORIGIN_FIRST_ATOM_CENTRAL, SHRINK_ORIGIN_MASS_CENTRAL} shrink_map_origin_type;
#define MAX_OPTIMAL_VOXEL_DIEMENSION 400
#include <vector>
#include <map>
#include "ColorSupport.h"
#include "VoxelMap2D.h"
class VoxelMap
{
public:
VoxelMap();
~VoxelMap(void);
void SaveToFile(CArchive *ar);
void LoadValues(map<CString,CString> params);
bool MemoryForVoxel();
bool MemoryFor3DLineMaps();
bool AddMemoryForLineMaps();
void generateMapEdges();
//Set map_minimum/maximum, layer_limits, layer_visibility (true)
//limits[0] = <0,1>
void SetLayerLimitsFromVoxel(float limits[3]);
float SetLayerLimitFromVoxelValue(float value);
void SetLayerLimitsFromOtherMap(float other_map_limits[3]);
void SetColors(float colors[3][3], float msh[2][3]);
bool GenerateFace(int reverse);
bool Generate3DLineMaps();
bool Generate2DMaps();
static float CalcDeterminant(float m[3][3]);
VoxelMap *ShrinkMap(MY_XYZ A, MY_XYZ B, MY_XYZ C, MY_XYZ dimensions, float resolution, shrink_map_origin_type origin_set);
MY_XYZ sumVectors(MY_XYZ A, MY_XYZ B, MY_XYZ C);
MY_XYZ MultipleVectByScalar(MY_XYZ A, float s);
static float getVectorSize(MY_XYZ A);
static MY_XYZ getVector(MY_XYZ A, MY_XYZ B);
static float getVectorsVolume(MY_XYZ A, MY_XYZ B, MY_XYZ C);
static void setVectorSize(MY_XYZ &A, float size);
static float VectorDotProduct(MY_XYZ A, MY_XYZ B);
void Coord3DfToInd(float &x, float &y, float &z, Map_type m_type);
MY_XYZ IndToCoord3Df(float x, float y, float z, Map_type m_type);
//get intensity from the map in 3Df system
//if x, y or z are out of the map's limits (of course after Coord3DfToInd) it returns false;
bool getIntensity3Df(float x, float y, float z, float &intensity);
bool getIntensityInd(float x, float y, float z, float &intensity);
//JANA2006 does not write the complete map of the unit cell. Instead of filling the space from 0 to 1, it fills just from 0 to 1-step.
//This procedure allows to add one more row in selected direction
void complete_map_in_direction(n_contour_direction dir);
static float Angle(MY_XYZ A, MY_XYZ B, MY_XYZ C);
void InvertMatrix(float m[3][3], float mi[3][3]);
float Distance(float Ax, float Ay, float Az, float Bx, float By, float Bz);
float getSurfaceArea(float isolevel);
float getVolume(float isolevel, bool smaller);
float getVolumeOfSingleVoxel();
//get Arithmetic Mean x = 1/n * (sum(xi))
float getMean();
float getSigma();
vector<vector<vector<float>>> Voxel;
VoxelMap2D m_2D_map;
Map_type mType;
AxDescStruct AxisParam[3];
float layer_limits[3];
bool layer_visibility[3];
float layer_color[3][3];//[n][r, g, b]
int Lines, Columns, Sections;
float map_maximum, map_minimum;
int map_2D_level;
grid_struct grids;
all_triangles_struct triangles;
CMCEGenerateFace * mpFace;
bool isFaceReady;
LineMeshStruct LineMap3D;
n_contour_direction LineMap2D_direction;
float MatrixFtC[3][4];//3x3 rot, 3x1 trans
float MatrixCtF[3][4];//3x3 rot, 3x1 trans
float m_2D_map_rect[4][3];
float m_3D_map_edges[8][3];
bool bTransparentSurface;
float fTransparencyLevel;
bool bMap_surface;
bool isPeriodic;
float m_mean;
float m_sigma;
//three basic vectors (they are norm vectors!)
private:
void VoxelDirectionalContour(n_contour_direction direction,LineMeshStruct *pM);
//if x, y or z are out of the map's limits it moves them into the map area. If the map is not periodic, it returns false;
bool Move_to_map3Df(float &x, float &y, float &z);
bool Move_to_mapInd(float &x, float &y, float &z);
};