#ifdef WIN32
    #include <windows.h>
	#undef near
#endif
#include <math.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glut.h>

#define     MAX_NAME_LENGTH 8
#define     MAX_SUM_ASCI    4100        /* = (MAX_NAME_LENGTH**2 * 128)/2 = 4096 */


#define     pi          3.14159265358979323846264338327950288
#define     MAX_INTEGER 2147483647
#define     MAX_FLOAT   1.e32

#define     MAX_LINE_LENGTH 256
#define     NODES       1000000
#define     ELEMENTS    1000000
#define     MAX_LOADCASES  100000

/* intpol2.c, spline.c */
#define     PNTS  2000

/* from #include "f2c.h" */
#define abs(x) ((x) >= 0 ? (x) : -(x))
#define dabs(x) (double)abs(x)
#define smin(a,b) ((a) <= (b) ? (a) : (b))
#define smax(a,b) ((a) >= (b) ? (a) : (b))
#define dmin(a,b) (double)min(a,b)
#define dmax(a,b) (double)max(a,b)

typedef struct {
  unsigned char  model[MAX_LINE_LENGTH]; /* haeder model */
  int   n;         /* number of nodes */
  int   e;         /* number of elements  */
  int   f;         /* number of faces */
  int   g;         /* number of edges */
  int   l;         /* number of loadcases (Datasets) */
  int   b;         /* number of nodeBlocks */
  int   c;         /* number of 'cuts' over all nodeBlocks (block-to-block interfaces for isaac) */
  int   etype[100];/* number of elements of a certain type */
  int   nmax;      /* maximum nodenumber */
  int   nmin;      /* minimum nodenumber */
  int   emax;      /* maximum elemnumber */
  int   emin;      /* minimum elemnumber */
} Summen;

typedef struct {
  int   nr;              /*   node-nr (node[node-nr].nx        */
  int   indx;            /*   node-index (node[node-index].nr) */
  unsigned char  pflag;  /*   1 if used for display purposes   */
                         /*  -1 if the node is deleted         */
                         /*   0 default                        */
  double nx;              /*   coordinates                      */
  double ny;
  double nz;
} Nodes;

typedef struct {
  int nr;                /* external element number */
  int elem_nr;           /* internal element-index  */ 
  int type;              /* element type (1:Hexa8)  */
  int group;
  int mat;
  int attr;              /* -1:unstructured mesh */
                         /*  0:default           */
                         /*  1:reduced integration */
                         /*  2:incompatible modes */
  int nod[26];
  double **side;     /* side[Nr.][x|y|z]== normal vector */
} Elements;

typedef struct {
  int dim;                /* 2: surf, 3: body */
  int i,j,k;              /* block dimension in i,j,k direction */
  int *nod;
  int geo;                /* related surf/body */
  int bcface[6];          /* index of the line/face of the related surf/body */
  int neighbor[6];        /* adjacent surface/body index */
  int map[6][3];          /* relative orientation of the neighbor 1:i==i_neigh, 4:i==-i_neigh */
  int strt1[6][3]; 
  int end_1[6][3]; 
  int strt2[6][3]; 
  int end_2[6][3];
  unsigned char bctype[6][MAX_LINE_LENGTH];          /* bondary condition type */
 } NodeBlocks;

typedef struct {
  int nr;                /* element-face-nr in Abaqus Format  (-1 for shell elements) */
  int elem_nr;           /* reference to external element number  */ 
  int type;
  int group;
  int mat;
  int nod[10];
  double **side;          /* normal vector: side[Nr.][x|y|z] */
} Faces;


typedef struct {
  int nod[3];
  double ncol[3][3];
  int elem_nr;
  int group;
  int mat;
} CTri3;


typedef struct {
  unsigned char  **compName;
  unsigned char  **icname;
  unsigned char  name[MAX_LINE_LENGTH];
  unsigned char  dataset_name[MAX_LINE_LENGTH];
  unsigned char  dataset_text[MAX_LINE_LENGTH];
  unsigned char  analysis_name[MAX_LINE_LENGTH];
  float value;
  int analysis_type;
  int step_number;
  int ncomps;
  int irtype;
  int *ictype;
  int *icind1;
  int *icind2;
  int *iexist;
  float **dat;        /* node related data */
  float ***edat;      /* element related data */
  float *max;         /* maximum datum */
  float *min;         /* minimum datum */
  int *nmax;          /* node with maximum datum */
  int *nmin;          /* node with minimum datum */
} Datasets;


typedef struct {
  int p1;
  int p2;
} Edges;

typedef struct {
  double w;                     /* scalierung in den Einheitswuerfel==max(xyzmax) */
  double x;                     /* Mittelpunktsversatz der unscalierten Vektoren */
  double y;
  double z;
  double vmax, vmin;                            /* max,min Werte der values */
  double bmin, bmax;                            /* max,min Werte der Scala  */
  double xmax, xmin, ymax, ymin, zmax, zmin;    /* max==|max|Abstand eines Punktes vom Zentrum */
  int   nmax, nmin;                            /* nodes der max/min-Werte  */
} Scale;


typedef struct {
  unsigned char name[MAX_LINE_LENGTH];
  unsigned char flag;                  /* if the set is open: 'o' else: 'c' */
  unsigned char type;                  /* ordered entities:1 (seq) or not: 0 (set) */ 
  int anz_n;
  int anz_e;
  int anz_f;
  int anz_p;
  int anz_l;
  int anz_c;
  int anz_s;
  int anz_b;
  int anz_nurl;
  int anz_nurs;
  int anz_se;
  int *node;
  int *elem;
  int *face;
  int *pnt;
  int *line;
  int *lcmb;
  int *surf;
  int *body;
  int *nurl;
  int *nurs;
  int *set;
  int etyp;
  int eattr;       /* -1:unstructured mesh, 0:default, 1:reduced integration, 2:incompatible modes */
} Sets;

typedef struct {
  int nr;
  int *set;
} OpenSets;


/* compiles the actual displayed sets */
typedef struct {
  int nr;
  unsigned char type[MAX_NAME_LENGTH];
  int col;
} Psets;

/* sum of unsigned char of asci letters */
typedef struct {
  int  anza[MAX_SUM_ASCI];         /* nr of aliases stored */
  int  *aindx[MAX_SUM_ASCI];       /* alias indexes       */
  int  anzp[MAX_SUM_ASCI];         /* nr of points stored */
  int  *pindx[MAX_SUM_ASCI];       /* point indexes       */
  int  anzl[MAX_SUM_ASCI];         /* nr of lines stored  */
  int  *lindx[MAX_SUM_ASCI];       /* line indexes        */
  int  anzc[MAX_SUM_ASCI];         /* nr of lcmbs stored  */
  int  *cindx[MAX_SUM_ASCI];       /* lcmb indexes        */
  int  anzs[MAX_SUM_ASCI];         /* nr of surfs stored  */
  int  *sindx[MAX_SUM_ASCI];       /* surf indexes        */
  int  anzb[MAX_SUM_ASCI];         /* nr of bodys stored  */
  int  *bindx[MAX_SUM_ASCI];       /* body indexes        */
  int  anzS[MAX_SUM_ASCI];         /* nr of Nurs stored  */
  int  *Sindx[MAX_SUM_ASCI];       /* nurs indexes        */
  int  anzse[MAX_SUM_ASCI];        /* nr of sets stored  */
  int  *seindx[MAX_SUM_ASCI];      /* set indexes        */
} SumAsci;

typedef struct {
  unsigned char  model[MAX_LINE_LENGTH]; /* haeder model */
  int   alias;                           /* alias-names     */
  int   p;                               /* points */
  int   l;                               /* lines  */
  int   c;                               /* lcmbs  */
  int   s;                               /* surfs  */
  int   b;                               /* bodys  */
  int   nurl;                            /* nurbs lines     */
  int   nurs;                            /* nurbs surfaces  */
  int   sets;   
  int   psets;   
} SumGeo;

typedef struct{
  unsigned char   name[MAX_LINE_LENGTH];
  unsigned char   entitieName[MAX_LINE_LENGTH];
} Alias;


typedef struct {
  unsigned char  name[MAX_NAME_LENGTH];
  double px;     /* coordinates will be scaled during run-time, scalPoints() */
  double py;
  double pz;
  int   nn;
  int   *nod;
} Points;

typedef struct {
  unsigned char  name[MAX_NAME_LENGTH];
  unsigned char  typ;      /* straight:' ', arc:'a', spline:'s', nurbs:'n' */
  int   p1;
  int   p2;
  int   trk;      /* if arc: 3.pnt, if spline: setname, if nurbs: nurblname */
  int   div;
  double bias;
  int   nip;
  double *ip;
  int   fail;             /* if 1 then the meshing failed */
  int   nn;
  int   *nod;
  int   ne;
  int   *elem;
  int  etyp;
  int  eattr;       /* -1:unstructured mesh, 0:default, 1:reduced integration, 2:incompatible modes */
} Lines;

typedef struct {
  unsigned char  name[MAX_NAME_LENGTH];
  unsigned char  nl;
  unsigned char  *o;      /* l-orient +- */
  int   *l;               /* lines */
  int   p1;               /* starting point */
  int   p2;               /* end point */
  double cx;               /* CG, not used so far */
  double cy;
  double cz;
} Lcmb;

typedef struct {
  unsigned char  name[MAX_NAME_LENGTH];
  unsigned char  ori;     /* surface-orientation +- */
  int   sh;               /* embedded shape (nurs) */
  unsigned char   sho;    /* embedded shape (nurs) orientation  */
  int   nl;               /* corners (ether line or lcmb) */
  unsigned char  *typ;    /* type: l=line c=lcmb */
  unsigned char  *o;      /* l-orient +- */
  int   *l;               /* index of lines, lcmbs, also used to store the index of a substitute surf (last item) */
  int   *cp;              /* index of points at the junction between  lines, lcmbs, starting at the beginning of the first line */
  int   nc;               /* number of closed-line-loops (curves) */
  int   *c;               /* number of lines in each curve */
  double cx;               /* CG, in orient determined, not scaled during run! */
  double cy;
  double cz;
  int   fail;             /* if 1 then the meshing failed */
  int   nn;
  int   *nod;
  int   ne;
  int   *elem;
  int   etyp;
  int   eattr;       /* -1:unstructured mesh, 0:default, 1:reduced integration, 2:incompatible modes */
  int   patch;            /* number of trimming patch in the related nurbs */
  GLint   npgn;           /* size of feed-back-Buffer pgn */
  GLdouble *pgn;           /* stores poligons of the trimmed nurbs which defines the interiour */
} Gsur;

typedef struct {
  unsigned char  name[MAX_NAME_LENGTH];
  unsigned char  ori;     /* body-orientation +- */
  int   ns;               /* nr. of surfaces (currently must be 6 for meshing) */
  unsigned char  *o;      /* s-orient +- */
  int   *s;               /* surfaces */
  double cx;               /* CG, in orient determined, not scaled during run! */
  double cy;
  double cz;
  int   fail;             /* if 1 then the meshing failed */
  int   nn;
  int   *nod;
  int   ne;
  int   *elem;
  int   etyp;
  int  eattr;       /* -1:unstructured mesh, 0:default, 1:reduced integration, 2:incompatible modes */
} Gbod;

typedef struct {
  unsigned char  name[MAX_NAME_LENGTH];
  unsigned char  endFlag;
  GLUnurbsObj *Nurb;
  GLint   u_npnt;
  GLint   u_exp;
  GLint   u_nknt;
  GLfloat *uknt;
  GLint   u_stride;
  GLfloat *ctlarray;
  GLfloat *weight;
  GLenum  type;
  GLint   *ctlpnt;
} Nurbl;

typedef struct {
  unsigned char  name[MAX_NAME_LENGTH];
  unsigned char  endFlag;
  GLUnurbsObj *Nurb;
  GLint   u_npnt;
  GLint   u_exp;
  GLint   u_nknt;
  GLint   v_npnt;
  GLint   v_exp;
  GLint   v_nknt;
  GLfloat *uknt;
  GLfloat *vknt;
  GLint   u_stride;
  GLint   v_stride;
  GLfloat *ctlarray;
  GLenum  type;
  GLint   **ctlpnt;
  GLfloat **weight;

  /* additional values for rendering purposes */
  int ures, vres;    /* division per u or v */
  int patches;        /* number of trimming patches (separate surfaces)*/
  int *nc;             /* number of trimming curves */
  int **np;            /* number of points in each trimming curve */
  GLfloat ***uv;         /* u,v coordinates of the spline-points of the trimming curves */
  double ***xyz;        /* x,y,z coordinates of the spline-points of the trimming curves */
  double tx, ty, tz;   /* average position for the name-string */
  double *umax, *vmax;   /* max val for u,v, for rendering purposes */
} Nurbs;



typedef struct {
  double alpha, beta;
  int nadapt;
} Meshp;

typedef struct {
  unsigned char name[MAX_LINE_LENGTH];
  unsigned char bctype[MAX_LINE_LENGTH];
  int surfs;
  int *surf;
} Dunsbou;


void adjustMidsideNode(double *P1, double *P2, double *Pm);
int strsplt( unsigned char *rec_str, unsigned char breakchar, unsigned char ***ptr);
int strfind (unsigned char *as1, unsigned char *as2);
int readEdges( unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr );
int *innerFacesHe8(Elements *elems, int numElems, Faces **ptr);

void calcElemNorm_quad4(int i, int n1, int n2, int n3, int n4, int f, Nodes *node, Elements *elem );
void calcElemNorm_tri3(int i, int n1, int n2, int n3, int f, Nodes *node, Elements *elem );
void calcFaceNorm_quad4(int i, int n1, int n2, int n3, int n4, int f, Nodes *node, Faces *face);
void calcFaceNorm_tri3(int i, int n1, int n2, int n3, int f, Nodes *node, Faces *face );
void getElemNormalen( Elements *e_enqire, Nodes *node, int elems );
void getFaceNormalen( Faces *face, Nodes *node, int nr );


int renumberfrd( int firstelem, int firstnode, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr  );

void define_rgb(float v, float *r, float *g, float *b);
void text(double x, double y, double z,unsigned char *msg);
void scala_rgb( double dx, double dy, int divisions, double bmin, double bmax, double *col);
void scala_indx( double dx, double dy, int divisions, double bmin, double bmax, int offset, int col);
void scala_tex( double dx, double dy, int divisions, double bmin, double bmax, double scale, double *col);
int button(double dx, double dy, unsigned char *msg, double mx, double my);
void polymark ( int n, double *col_r, double *col_g, double *col_b, double *x,
		double *y, double *z );

double nullstelle(double xmin, double xmax, double funktion(double), double *result);
int  calcPrinc( double *s, double *p, double *a1, double *a2, double *a3, int sortFlag );
int calcPvector( double *s, double *p, double *a );
void stopClock(int zaeler);
void bsort (double *wert, double *wertsort, int *isort, int anzahl);
int *bsort2(double *wert, int anzahl, int n );
int *bsortf(double *wert, int anzahl, int n );
int *bsortfp(double *wert, int anzahl, int n );
int *bsorti( int *wert, int anzahl, int n );
int compare (unsigned char *str1, unsigned char *str2, int length);
int compareStrings (unsigned char *str1, unsigned char *str2);
int elemChecker(Summen *anz, Nodes *node, Elements *elem);
int frecord( FILE *handle1,  unsigned char *string);
void  getGeoDataTria( double *p1, double *p2, double *p3, double *Ix, double *Iy, double *Ixy,
                double *A, double *pcg);
int getrecord (int bufstart, int bufsize, unsigned char *inputdata, unsigned char *buffer);
int gl3grades( double a, double b, double c, double *x);
int AsplitA( double *pa1, double *pa2, double *pa3, double *pb1, double *pb2, double *pb3, double *ps1, double *ps2);
double AsplitL( double *b, double *eu, double *ev, double *eg );
double interpol(double *x, double *y, int nn, double x0);
double intpol2(double *x, double *y, int n, double x0, int *method );
double intpol3(double *x, double *y, int n, double x0, int *method );
double intpol(double *x, double *y, int n, double x0 );
int nearNodes(double *po, int *n, double *p, int *node, int *k, int *flag);
int iinsert(int **ipnt, int n, int x0 );
int ifind(int **ipnt, int n, int x0 );
int iremove(int **ipnt, int n, int x0 );
void linelength(double *x, double *y, double *z, int n, double *s );
int kbrecord( unsigned char *string);
int p3_finder(int anzahl_nodes, double *nx, double *nz, int *p);
int parser( unsigned char gkey, unsigned char *record );
int readfrd(unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr );
int read2frd(unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr );
int readFElt(unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr );
int readDuns(unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr, int elem_type );
int readIsaac(unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr, NodeBlocks **bptr, int elem_type,  double A, double B, double C );
int readGiff( unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr );
int readStl( unsigned char *datin, Summen *anz, Nodes **nptr, Elements **eptr, Datasets **lptr );
int rotiere(double *x, double *y, int n, double phi, double *xneu, double *yneu);
int srecord( unsigned char *handle1,  unsigned char *string);
double stof(unsigned char *string, int a, int b);
int stoi(unsigned char *string, int a, int b);
void stos(unsigned char *string, int a, int b, unsigned char *puffer);
int sins(unsigned char *string, int a, int b, unsigned char *puffer);
int sword( unsigned char *string, unsigned char *word);
double p_angle(double x, double y);
void v_add( double *A, double *B, double *C );
double v_betrag(double *a);
void  v_matmult(double *v, double *m);
double v_norm( double *A, double *C );
void v_prod( double *A, double *B, double *C );
void v_result( double *A, double *B, double *C );
int v_rot(double fi, double *p0, double *v, double *pin, double *pout);
void v_scal( double *A, double *B, double *C );
double v_sprod( double *a, double *b);
double v_angle( double *v0, double *v1 );
double v_angle_ref( double *v0, double *v1, double *en );
double v_distA( double *N0, double *N1, double *N2, double *N, double *vray);
int  v_rec2cyl( double *pr, int axis, int *csys, double *pc );
int v_sgg( double *p1, double *p2, double *e1s, double *e2s, double *ps);

void vl_add( double *A, double *B, double *C );
double vl_betrag(double *a);
void  vl_matmult(double *v, double *m);
double vl_norm( double *A, double *C );
void vl_prod( double *A, double *B, double *C );
void vl_result( double *A, double *B, double *C );
void vl_scal( double *A, double *B, double *C );
double vl_sprod( double *a, double *b);
double vl_angle( double *v0, double *v1, double *v2, double *scg, double *bcg );
void  m_copy(double *s, double *m);
void  m_print( double *m);

int m_prod(int *n,double *a,double *b,double *c);
int m_prodtr(int *n,double *a,double *b,double *c);

void  m_sub(double *ms, double *m, double *s);
int write2frd(unsigned char *datout, Summen *anz, Nodes *node, Elements *elem, Datasets *lcase );
int write2nas(unsigned char *datout, Summen *anz, Nodes *node, Elements *elem, Datasets *lcase );
int write2aba(unsigned char *datout, Summen *anz, Nodes *node, Elements *elem, Datasets *lcase, unsigned char **dat );
int write2ansys(unsigned char *datout, Summen *anz, Nodes *node, Elements *elem, Datasets *lcase );
int write2aster(unsigned char *datout, Summen *anz, Nodes *node, Elements *elem, Datasets *lcase );
int write2isaac( unsigned char *datout, Summen *anz, Nodes *node, Elements *elem, Datasets *lcase, NodeBlocks *nBlock );
int write2duns( unsigned char *datout, Summen *anz, Nodes *node, Elements *elem, Datasets *lcase, NodeBlocks *nBlock, int bouNr, Dunsbou *dunsbou );



void readStdCmap( Display **ptr_dpy, int *ptr_dpycells, Colormap *ptr_cmap, XColor **ptr_c,
                 unsigned long **ptr_pix, unsigned int *ptr_npixels, int anzCells );

int selectDisplayFacesHe8 (Elements *elems, int numElems, int **pfaces, int *);
int selectDisplayFacesHe20 (Elements *elems, int numElems, int **pfaces, int *);
int selectDisplayFacesTet4 (Elements *elems, int numElems, int **ptr, int *edges);
int selectDisplayFacesTet10 (Elements *elems, int numElems, int **ptr, int *edges);
int selectDisplayFacesPe6 (Elements *elems, int numElems, int **ptr, int *edges);
int selectDisplayFacesPe20 (Elements *elems, int numElems, int **ptr, int *edges);
int commonEdge3 (int *a, int *b);
int findCTri3Edges(Elements *elems, int numElems, int **edges);
double spline_int( int nc, double xneu, double **c );
void createSpline( int n, double **c);
int read2fbd( unsigned char *datin, SumGeo *anz, Points **pntptr, Lines **lineptr, Lcmb **lcmbptr, Gsur **surptr, Gbod **bodptr, Nurbs **nursptr, Sets *set );

int attachhe20_(double *co, int *nk, int *neigh, int *node, double *xi_loc__,double *et_loc__);
int attachhe8_(double *co, int *nk, int *neigh, int *node,double *xi_loc__,double *et_loc__);
int distattachhe20_(double *xi,double *et,double *pneigh,double *pnode,double *dist,double *p);
int distattachhe8_(double *xi,double * et, double *pneigh, double *pnode, double *dist, double *p);
int shapefhe20_(double *xi, double *et, double *coef);
int shapefhe8_(double *xi, double *et, double *coef);

int mesh2d(int *_nt, int _nb, int *npc, double **_pnt_u, double **_pnt_v, int **_pnt_flag, int **_tri3, double _alpha, double _beta, int _nadapt);






















