/* test_MSH2D
2D - tesselateion with outer-boundary, holes and a rectangular grid.

Input:
- outer-boundary and inner boundaries as indexed 2D-points
- tesselation-grid
Output:
- faces
- list of additional created gridpoints

=====================================================
List_functions_start:

test_MSH2D__         test MSH2D_ funcs
test_MSH2D_ini       define all inputs for tesselation
test_MSH2D_memspc    get necessary memspc for faces (fac, fnb)
test_MSH_wrf__       store binary-mesh into file
test_MSH_rdf__       load binary-mesh from file
test_MSH2D_tr_2D_3D  translate 3D-point -> 2D
test_MSH2D_tr_3D_2D  translate 2D-point -> 3D

List_functions_end:
=====================================================

Testmodels:
test_msh2d_1.gcad  <<<<<
test_msh2d_2.gcad



see tst_gl2
*/


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

#include "../ut/ut_geo.h"              // Point ...
#include "../ut/ut_geo_const.h"        // UT3D_CCV_NUL
#include "../ut/ut_memTab.h"           // MemTab_..
#include "../ut/ut_itmsh.h"            // MSHIG_EDGLN_.. typedef_MemTab.. Fac3
#include "../ut/ut_face.h"              // UFA
#include "../ut/msh2d.h"               // TessStru
#include "../ut/ut_os.h"               // OS_get_bas_dir ..

#include "../xa/xa_msg.h"              // MSG_*


// Externals aus ../xa/xa.c:
// extern char      AP_mod_fnam[128];
// extern Plane     WC_sur_act;            // die aktive Plane
extern int       WC_modact_ind;         // -1=primary Model is active;
                                        // else subModel is being created




  int test_MSH2D_tr_2D_3D (Point2 *pt2, Point *pt3, void *data);
  int test_MSH2D_tr_3D_2D (Point *pt2, Point2 *pt3, void *data);


//=========================================================
  int gCad_fini () {
//=========================================================

  AP_User_reset ();

  return 0;

}


//=========================================================
  int gCad_main () {
//=========================================================


  TX_Print(">>>>>>>>> gCad_main test_MSH2D__ <<<<<<<<<<\n");

  AP_debug__ ("test_MSH2D__");

  test_MSH2D__ ();

  DL_Redraw ();

  gCad_fini ();

  return 0;

}


//================================================================
  int test_MSH2D__ () {
//================================================================
// test 2D-tesselation-func MSH2D_tess__



// default nr of points for a single surf
#define MSH2D_NR_PTS 1000

// default nr of contours for a single surf
#define MSH2D_NR_CNTS 50

static MSH2D_STRU (tessDat);            // define MSH2D_STRU in ../ut/msh2d.h

  int          irc, i1, i2, ii, ptNr, mode, *ia;
  char         *pstat;
  long         l1;
  Point2       *pa2;
  Point        *pa3;
  Vec3f        vcf1;



  //================================================================
  // init memspace for tab, ipa, p2a; (only at programstart; keep this
  // space static for next surface ..)
  MSH2D_memspc_init (&tessDat, MSH2D_NR_PTS);




  //================================================================
  // query necessary memspc for points
  ptNr = MSH2D_NR_PTS;        printf(" ptNr=%d\n",ptNr);

  // get memspace for tab, ipa, p2a;
  MemTab_add (&tessDat.tab, &l1, NULL, ptNr / 2, 2);
  MemTab_add (&tessDat.ipa, &l1, NULL, ptNr * 2, 2);
  MemTab_add (&tessDat.pa2, &l1, NULL, ptNr, 2);
  MemTab_add (&tessDat.pa3, &l1, NULL, ptNr, 2);
  MemTab_add (&tessDat.vc3, &l1, NULL, ptNr, 2);
  MemTab_add (&tessDat.fac, &l1, NULL, ptNr * 4, 2);
  MemTab_add (&tessDat.fnb, &l1, NULL, ptNr * 4, 2);



  //================================================================
  mode = 0; // 0 = create support-surface only;
            //     save to file
  // mode = 1; // 1 = load support-surface from file; 
            //     add contours 
  // mode = 2; // 2 = support-surface and contours


  //================================================================
  // load binary-mesh from file
  if(mode == 1) {
    irc = test_MSH_rdf__ (&tessDat, 1L);
    if(irc < 0) return irc;
      // TESTBLOCK
      // MemTab_dump (&tessDat.pa3, ".pa3-0");
      // return -99;
      // END TESTBLOCK
  }


  //================================================================
  // get input into tessDat for support-surface or bounded-surface:
  // add gridbox or boundaries or both
  // For surfaces - support-surface not already loaded:
  //   - add gridbox into tessDat.gbx (uMin, uMax, vMin, vMax, uNr, vNr)
  // For bounded-surface:
  //   - add boundaries (outer (OB) and/or inner (IB))
  //     - boundarypoints with indextables
  //   - change all 3D-boundaryPoints -> 2D-boundaryPoints
  irc = test_MSH2D_ini (&tessDat, mode);
  if(irc < 0) return irc;


  //================================================================
  // // get necessary memspc for faces (fac, fnb)
  // irc = test_MSH2D_memspc (&tessDat);
  // if(irc < 0) return irc;


  // tesselate
  // if(mode == 0)
  irc = MSH2D_tess__ (&tessDat,
                      0,             // 0=keep unused gridpoints, 1=delete
                      0);            // 0=do-NOT-optimize; 1=optimize.


    // TESTBLOCK
    // printf("-------------------------------------------------- \n");
    printf("ex-_tess__-irc=%d pNr=%d\n",irc,MEMTAB_IND (&tessDat.pa2));
    MemTab_dump (&tessDat.tab, ".tab-t");
    // MemTab_dump (&tessDat.pa2, ".pa2-t");
    // MemTab_dump (&tessDat.fac, ".fac-t");
    // MemTab_dump (&tessDat.fnb, ".fnb-t");
    // UT3D_stru_dump (Typ_GridBox, &tessDat.gbx, ".gbx-t");
    // MSH2D_view_nfac (&tessDat, "pnbvf", 0, -1, "---");
    // MSH2D_dump_tab ();
    // END TESTBLOCK

  if(irc < -90) return irc;


  //================================================================
  // get 3D-points and 3D-vectors for new created 2D-gridpoints
  //   (must set pa2-Nr == pa3-Nr)
  // get list of all 2D-gridpoints. ii=ptNr; ia=list-of-pointIndexes
    // not for 1 = create boundaries onto existing support-surface
    //   no new points out of tess)
  if(mode != 1) {
    // get ia=list-gridpoints and status
    MSH2D_pgb_get (&ii, &ia, &pstat);
    // get data-blocks for points
    pa2 = MEMTAB_DAT (&tessDat.pa2);
    pa3 = MEMTAB_DAT (&tessDat.pa3);
    //
    GL_att_pt (ATT_PT_YELLOW);
    for(i1=0; i1<ii; ++i1) {
      if(pstat[i1] == 0) continue;          // skip stat=0 (point unused)
      i2 = ia[i1];                          // get index into pa2 & pa3 & vc3
      // get 3D-point from 2D-point
      test_MSH2D_tr_3D_2D (&pa3[i2], &pa2[i2], NULL);
      // get 3D-vector for 2D-gridpoint ..
      // test_MSH2D_vc_pt (&vc3[i2], &pa3[i2], NULL);
    }
  }

    // TESTBLOCK
    // UFA_view_nifac (&tessDat, -1L, Typ_SUR);
    vcf1.dx = 0.;
    vcf1.dy = 0.;
    vcf1.dz = 1.;
    MemTab_add (&tessDat.vc3, &l1, &vcf1, 1, 0);
      // MemTab_dump (&tessDat.vc3, "tessDat.vc3");
    UFA_view_nifac (MEMTAB_IND (&tessDat.fac),
                    MEMTAB_DAT (&tessDat.fac),
                    MEMTAB_DAT (&tessDat.ipa),
                    MEMTAB_DAT (&tessDat.pa3),
                    MEMTAB_DAT (&tessDat.vc3), -1L, Typ_PLN);
    // END TESTBLOCK


  //================================================================
  // store binary-mesh into file
  if(mode == 0) irc = test_MSH_wrf__ (&tessDat, 1L);
  // else          irc = test_MSH_rdf__ (&tessDat, 1L);


  //================================================================
  L_exit:

  // free or reset memspaces:
  // DO NOT FREE tessDat.fac AS LONG OPENGL IS USING IT !!
  MSH2D_memspc_exit (&tessDat);


  return 0;


}



//================================================================
  int test_MSH2D_ini (TessStru *ts1, int mode) {
//================================================================
// define all inputs for tesselation.
// mode    0 = support-surface only;
//         1 = contours only;
//         2 = support-surface + contours
// OB=S21, IB=S22,S23
// load outer-boundary and inner-boundaries as indexed 2D-points
// load tesselation-grid

// see TSU_test_tess__

  int   oTyp1, oNr, oTyp2, oTyp3;
  void  *o1, *o2, *o3;

  int       irc, i1, ii, cNr, ptNr;
  IndTab    it1;
  MemTab(Fac3) *fa;

  
  printf("test_MSH2D_ini %d\n",mode);


  //================================================================
  // set 2D-tolerance
  ts1->tol = 0.005;
  // ts1->tol = 0.0005;


  //================================================================
  // mode:
  // 0 = support-surface only;  set grid, not boundaries
  // 1 = load support-surface from file; do not set grid|planar; set contours
  // 2 = set grid|planar; set contours
  if(mode == 1) goto L_boundaries;
  // define support-surface. If no OB comes, this is OB !
  // define gridbox for support-surface (tile)
  // define gridbox gbx from (uMin, uMax, vMin, vMax, uNr, vNr)
  // uNr, vNr    nr of faces between Min-Max;
  // min, max-VALUES are 2D !

  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,    1,    1);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,    2,    2);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,    3,    3);
  MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,    4,    4);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,    6,    6);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,    8,    8);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,   10,   10);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,   15,   15);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,   20,   20);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,   25,   25);

  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,    3,    6);
  // MSH2D_tess_grid (&ts1->gbx, 0.,   1.,   0.,   1.,   25,   10);

  // define planar-surface (unlimited planar support-surface)
  // MSH2D_tess_pln (&ts1->gbx);

  if(mode == 0) return 0;


  //================================================================
  L_boundaries:    // mode 1 & 2
  // load OB, IBs, grid into a TessStru
  // Model: test_msh2d_1

  MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 21L, MSH_EDGLN_OB);
  // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 21L, MSH_EDGLN_IB);

  MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 22L, MSH_EDGLN_IB);
  MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 23L, MSH_EDGLN_IB);

  // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 22L, MSH_EDGLN_OB);    // oben
  // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 23L, MSH_EDGLN_OB);    // oben

  // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 24L, MSH_EDGLN_OB);
  // // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 24L, MSH_EDGLN_IB);

  // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 25L, MSH_EDGLN_OB);

  // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 26L, MSH_EDGLN_OB);
  // MSH2D_bnd_3D_add_dbo (ts1, Typ_CV, 26L, MSH_EDGLN_IB);


  //----------------------------------------------------------------
  // change all 3D-boundaryPoints -> 2D-boundaryPoints
  MSH2D_bnd_2D_3D (ts1, test_MSH2D_tr_2D_3D);

  return irc;

}
 

//================================================================
  int test_MSH2D_memspc (TessStru *ts1) {
//================================================================
// get necessary memspc for faces (fac, fnb)

  int   irc, fNr;
  long  l1;


  // query additional necessary memspc for faces (fac, fnb) for gridbox
  fNr = MSH2D_facNrMax (ts1);
    // fNr = MSH2D_NR_PTS * 4;   // see UFA_fNr_max

  // prepare necessary memspc for faces
  irc = MemTab_add (&ts1->fac, &l1, NULL, fNr, 2);
  if(irc < 1) return irc;
  irc = MemTab_add (&ts1->fnb, &l1, NULL, fNr, 2);
  if(irc < 1) return irc;


  return 0;

}


//================================================================
  int test_MSH_wrf__ (TessStru *ts1, long dbi) {
//================================================================
// store binary-mesh into file
// see MSHIG_wrf__ TSU_wrf__ Tess_fbsav_e Tess_fbget_e PRCV_wrf__
//   gis_etab_save gis_ptab_save MSHIG_load_sur

static char cTyp='A';   // surf

  FILE      *fp1;
  char      ofid[128];


  // get filename; see MSHIG_fnam TSU_wrf__
  sprintf(ofid,"%s%c%ld.myodat",OS_get_tmp_dir(),cTyp,dbi);


  printf("test_MSH_wrf__ |%s|\n",ofid);
  UT3D_stru_dump (Typ_MemTab, &ts1->tab, ".tab-wrf");
  UT3D_stru_dump (Typ_MemTab, &ts1->ipa, ".ipa-wrf");
  UT3D_stru_dump (Typ_MemTab, &ts1->pa3, ".pa3-wrf");
  UT3D_stru_dump (Typ_MemTab, &ts1->pa2, ".pa2-wrf");
  UT3D_stru_dump (Typ_MemTab, &ts1->fac, ".fac-wrf");
  UT3D_stru_dump (Typ_MemTab, &ts1->fnb, ".fnb-wrf");
  UT3D_stru_dump (Typ_GridBox, &ts1->gbx, ".gbx-wrf");
  printf(" tol=%f\n",ts1->tol);


  if((fp1=fopen(ofid,"wb")) == NULL) {
    TX_Print("test_MSH_wrf__ E001 |%s|",ofid);
    return -1;
  }

    MemTab_dump (&ts1->tab, ".tab-rdf");


  // write tab,pst,ipa,pa..
  MemTab_wrf (fp1, &ts1->tab);
  MemTab_wrf (fp1, &ts1->ipa);
  MemTab_wrf (fp1, &ts1->pa3);
  MemTab_wrf (fp1, &ts1->pa2);
  MemTab_wrf (fp1, &ts1->vc3);
  MemTab_wrf (fp1, &ts1->fac);
  MemTab_wrf (fp1, &ts1->fnb);

  // write gbx, tol
  fwrite(&ts1->gbx, sizeof(GridBox), 1, fp1);
  fwrite(&ts1->tol, sizeof(double), 1, fp1);

  fclose(fp1);



  return 0;

}
 

//================================================================
  int test_MSH_rdf__ (TessStru *ts1, long dbi) {
//================================================================
// load binary-mesh from file
// see TSU_rdf__
// MSHIG_wrf__ TSU_wrf__ Tess_fbsav_e Tess_fbget_e PRCV_wrf__
//   gis_etab_save gis_ptab_save MSHIG_load_sur
// see TSU_rdf__ ..

static char cTyp='A';   // surf

  FILE      *fp1;
  char      ofid[128];
    

  printf("test_MSH_rdf__ \n");


  // if(ts1->mdli >= 0) {           // 0-n = sind in Submodel; -1=main
    // sprintf(ofid,"%sM%d_%c%ld.odat",OS_get_tmp_dir(),cTyp,ts1->mdli,ts1->dbi);
  // } else {
    sprintf(ofid,"%s%c%ld.myodat",OS_get_tmp_dir(),cTyp,dbi);
  // }
    printf(" ofid=|%s|\n",ofid);


  if((fp1=fopen(ofid,"rb")) == NULL) {
    // TX_Print("test_MSH_rdf__ E001 |%s|",ofid);
    MSG_STD_ERR (ERR_file_open, "'%s'", ofid);
    return -1;
  }


  // get data
  MemTab_rdf (fp1, &ts1->tab);
  MemTab_rdf (fp1, &ts1->ipa);
  MemTab_rdf (fp1, &ts1->pa3);
  MemTab_rdf (fp1, &ts1->pa2);
  MemTab_rdf (fp1, &ts1->vc3);
  MemTab_rdf (fp1, &ts1->fac);
  MemTab_rdf (fp1, &ts1->fnb);

  fread(&ts1->gbx, sizeof(GridBox), 1, fp1);
  fread(&ts1->tol, sizeof(double), 1, fp1);

  fclose(fp1);


    // TESTBLOCK
    UT3D_stru_dump (Typ_MemTab, &ts1->tab, ".tab-rdf");
    UT3D_stru_dump (Typ_MemTab, &ts1->ipa, ".ipa-rdf");
    UT3D_stru_dump (Typ_MemTab, &ts1->pa3, ".pa3-rdf");
    UT3D_stru_dump (Typ_MemTab, &ts1->pa2, ".pa2-rdf");
    UT3D_stru_dump (Typ_MemTab, &ts1->fac, ".fac-rdf");
    UT3D_stru_dump (Typ_MemTab, &ts1->fnb, ".fnb-rdf");
    UT3D_stru_dump (Typ_GridBox, &ts1->gbx, ".gbx-rdf");
    printf(" tol=%f\n",ts1->tol);
    MemTab_dump (&ts1->tab, ".tab-rdf");
    // END TESTBLOCK


  return 0;

}


//================================================================
  int test_MSH2D_tr_2D_3D (Point2 *pt2, Point *pt3, void *data) {
//================================================================
 
  pt2->x = pt3->x;
  pt2->y = pt3->y;

  return 0;

}


//================================================================
  int test_MSH2D_tr_3D_2D (Point *pt3, Point2 *pt2, void *data) {
//================================================================

  pt3->x = pt2->x;
  pt3->y = pt2->y;
  pt3->z = 0.;

  return 0;

}

// EOF
