// make -f tst.mak
/*
 *
 * Copyright (C) 2015 CADCAM-Servies Franz Reiter (franz.reiter@cadcam.co.at)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 *
-----------------------------------------------------
TODO:
  ..

-----------------------------------------------------
Modifications:
  ..

-----------------------------------------------------
*/
/*!
\file  ../APP/tst.c
\brief plugin tests
\code
=====================================================
List_functions_start:
..
List_functions_end:
=====================================================

\endcode *//*----------------------------------------

make -f tst.mak
nmake -f tst.nmak


gCad_main
gCad_fini
tst_sel_CB


*/



#ifdef _MSC_VER
#include "../xa/MS_Def1.h"
#endif



#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>                         // for ...

#include <GL/gl.h>                     // GL_TRIANGLES


// #include <errno.h>
// #include <dlfcn.h>           // Unix: dlopen


#ifdef _MSC_VER
// die folgenden 2 Funktionen exportieren (werden vom Main gerufen):
__declspec(dllexport) int gCad_main ();
__declspec(dllexport) int gCad_fini ();
// nachfolgende externals werden aus dem Main-Exe imported:
#define extern __declspec(dllimport)
#endif



#include "../ut/ut_geo.h"              // Point ...
#include "../ut/ut_geo_const.h"        // UT3D_CCV_NUL
#include "../ut/ut_cast.h"             // INT_PTR
#include "../ut/ut_txt.h"              // fnam_del
#include "../ut/ut_txTab.h"            // TxtTab
#include "../ut/ut_os.h"               // OS_get_bas_dir ..
#include "../ut/ut_obj.h"              // UTO_stru_2_obj
#include "../ut/ut_TX.h"               // TX_Print
#include "../ut/ut_plg.h"              // UT3D_par1_parplg
#include "../ut/func_types.h"               // SYM_..
#include "../ut/ut_ox_base.h"          // OGX_SET_INDEX
#include "../ut/ut_memTab.h"           // MemTab_..
#include "../db/ut_DB.h"               // DB_get_..
#include "../gr/tess_su.h"             // TypTsuSur
#include "../gr/ut_GL.h"               // GL_get_Scale
#include "../gui/gui__.h"              // GUI_
#include "../xa/xa_msg.h"              // MSG_*
#include "../xa/xa_mem.h"              // memspc51, mem_cbuf1

#include "../ci/NC_apt.h"                 // T_BSP0

#include "../ut/ut_itmsh.h"            // MSHIG_EDGLN_.. typedef_MemTab.. Fac3
#include "../ut/ut_face.h"              // UFA
#include "../xa/xa_ato.h"              // ATO_getSpc_tmp__


// Externals aus ../ci/NC_Main.c:
extern double    APT_ModSiz;

// 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


// protos:
  int tst_sel_CB (int src, long dl_ind);
  int tst_key_CB (int key);



//=============================================================================
  int APT_decode_su_swp_cyl (ObjGX *ox1,
                             int aus_anz, int aus_typ[], double aus_tab[],
                             Memspc *wrkSpc) {
//=============================================================================
// create ox1 = sweep-surface-cylindric from axis + radius
// A = CYL axis radius ang0 ang1 length0 length1
// was APT_decode_s_cyl
// Output:
//   ox1      cylindric-
//   wrkSpc   memspace for necessary components of ox1


  int     irc, i1, ibp, typCov, typPath;
  long    dbi, sDbi, bDbi, indCov, indPath;
  double  rdc, dz, d1, d2;
  SurSwp  *sur1;
  Line    *ln1;
  Circ    *ci1;
  void    *datCov, *datPath;

  Point   *pp1, *pp2;
  Plane   pln1;

  ObjGX   *oxTab, oxSur;



  printf("APT_decode_su_swp_cyl %d\n",aus_anz);
  for(i1=0; i1<aus_anz; ++i1)
    { printf(" %d typ=%d tab=%f\n",i1,aus_typ[i1],aus_tab[i1]); }


  typCov  = Typ_CI;
  typPath = Typ_LN;



  // prepare memspc for sur1 ln1 ci1
  sur1 = UME_reserve (wrkSpc, sizeof(SurSwp));      // surface
  ln1 = UME_reserve (wrkSpc, sizeof(Line));      
  ci1 = UME_reserve (wrkSpc, sizeof(Circ));



  // decode Typ_goAxis --> pln & aus_typ[1],aus_tab[1]
  irc = APT_decode_goAxis (&pln1, &aus_typ[1], &aus_tab[1]);
  if(irc < 0) goto Error;
    UT3D_stru_dump (Typ_PLN, &pln1, " _su_swp_cyl-pln1");
    


  // decode Typ_goRadius --> rdc
  irc = APT_decode_goRadius (&rdc, 1, &aus_typ[2], &aus_tab[2], &pln1);
  if(irc < 0) goto Error;
    printf(" _su_swp_cyl-rdc %lf\n",rdc);



  //----------------------------------------------------------------
  // set contourelement cov (eg circle for pipe)
  // get u0,u1    start/end-parameters of path; for all types of contour 0-1

  // get Angle from value/Point
  if(aus_anz > 3)
    APT_dec_Ang_Obj (&d1, 0, &aus_typ[3], &aus_tab[3], &pln1);
  else
    d1 = 0.;

  // get Angle from value/Point
  if(aus_anz > 4)
    APT_dec_Ang_Obj (&d2, 0, &aus_typ[4], &aus_tab[4], &pln1);
  else
    d2 = RAD_360;

  if(fabs(d1-d2) < UT_TOL_pt) d2 += RAD_360;
    printf(" a1=%f a2=%f\n",d1,d2);


  // create ci1
  UT3D_ci_ptrd2vc2angr (ci1, &pln1.po, rdc, &pln1.vz, &pln1.vx, d1, d2);
    UT3D_stru_dump (Typ_CI, ci1, " ci1");

  // store circ in DB
  indCov = DB_StoreCirc (-1L, ci1);

  // create PRCV for bin.obj (if dynam.obj)
  PRCV_set_obj_dbi (typCov, ci1, 1, typCov, indCov);

  sur1->indCov = indCov; 
  sur1->typCov = Typ_CI;

  // make parameters u0,u1
  sur1->u0 = d1 / RAD_360;
  sur1->u1 = d2 / RAD_360;
  


  //----------------------------------------------------------------
  // set path (eg centerline for pipe)

  // get v0 = startpoint|startparameter height
  if(aus_anz > 5) {
    if(aus_typ[5] == Typ_Val) {
      // value = height above origin of axis
      d1 = aus_tab[5];

    } else if (aus_typ[5] == Typ_PT) {
      pp1 = DB_get_PT ((long)aus_tab[5]);
      d1 = UT3D_len_2pt (pp1, &pln1.po);
    }

  } else
    d1 = 0.;


  // get v1 = endpoint|endparameter height
  if(aus_anz > 6) {
    if(aus_typ[6] == Typ_Val) {
      // value = height above origin of axis
      d2 = aus_tab[6];

    } else if (aus_typ[6] == Typ_PT) {
      pp2 = DB_get_PT ((long)aus_tab[6]);
      d2 = UT3D_len_2pt (pp2, &pln1.po);
    }

  } else
    d2 = WC_ask_ModSiz()/5.;
    printf("  d1=%lf d2=%lf\n",d1,d2);


  // create line along pln1.dz d1-d2
  UT3D_pt_traptvclen (&ln1->p1, &pln1.po, &pln1.vz, d1);
  UT3D_pt_traptvclen (&ln1->p2, &pln1.po, &pln1.vz, d2);
    // UT3D_stru_dump (Typ_LN, ln1, "  ln1");
    // GR_Disp_ln (ln1, 9);

  indPath = DB_StoreLine (-1L, ln1);

  sur1->indPath = indPath; 
  sur1->typPath = typPath;

  sur1->v0 = 0.;
  sur1->v1 = 1.;


    // TESTBLOCK
    UT3D_stru_dump (Typ_SURSWP, sur1, " _su_swp_cyl-sur1" );
    printf(" - APT_decode_su_swp_cyl irc=%d\n",irc);
    // END TESTBLOCK


  // store surf in DB 
  OGX_SET_OBJ (&oxSur, Typ_SURSWP, Typ_SURSWP, 1, sur1);
  sDbi = -1L;
  irc = DB_StoreSur (&sDbi, &oxSur);
    printf(" sDbi=%ld irc=%d\n",sDbi,irc);
  if(irc < 0) goto Err_DB;
  


  //================================================================
  typCov  = sur1->typCov;
  indCov  = sur1->indCov;
  datCov  = ci1;

  typPath = sur1->typPath;
  indPath = sur1->indPath;
  datPath = ln1;




  //================================================================
  // create outer-boundary (CCV) for sweep-surf
  // see GL_sSym_srv

  // create CCV from <cvNr> DB-obj's
  // 1. curve = contour1 = contour fwd
  // 2. curve = path1 = path translated to endpoint of contour1
  // 3. curve = contour2 = contour bwd translated to endpoint of path1
  // 4. curve = path2 = path bwd translated to endpoint of contour2

  // U along X; V along Y
  //             oc2                      pte
  //  V1    x-----2------x               x
  //        |            |               |
  //    op2 3            1 op1           | path
  //        |            |               |
  //  V0    x-----0------x               x
  //        U0           U1               pts
  //      pt1   cov      pt2
  //----------------------------------------------------------------
{
  // was ?
  int       i1, cvNr;
  CurvBSpl  cvTab[4];
  CurvCCV   ccvTab[4];
  Point     pts, pte, pt1, pt2; // *pt3, *pt4;
  Vector    vc1;
  Line      ln1;
  void      *op1, *oc2, *op2;


  // get contour, get path
  // contour = ci1, path = ln1

    printf(" su_swp_cyl-bnd %d %ld %d %ld\n",typCov,indCov,typPath,indPath);



  //----------------------------------------------------------------
  // create trimmed-curve from contour

  // contour & its PRCV already in DB;

  // get trimmed-curve from dbo
  CVTRM__dbo (&ccvTab[0], typCov, indCov);
    // GR_Disp_obj (Typ_CVTRM, &ccvTab[0], 7, 0);


  //----------------------------------------------------------------
  // get pt1 = startpoint of contour
  UT3D_ptvcpar1_std_obj (&pt1, NULL, NULL, Ptyp_0, typCov, datCov);
    // GR_Disp_pt (&pt2, SYM_STAR_S, ATT_COL_BLUE);

  // get pt2 = endpoint of contour
  UT3D_ptvcpar1_std_obj (&pt2, NULL, NULL, Ptyp_1, typCov, datCov);
    // GR_Disp_pt (&pt2, SYM_STAR_S, ATT_COL_BLUE);

  // get pts = startpoint of path
  UT3D_ptvcpar1_std_obj (&pts, NULL, NULL, Ptyp_0, typPath, datPath);
    // GR_Disp_pt (&pts, SYM_STAR_S, ATT_COL_RED);

  // get pte = get endpoint of path1
  UT3D_ptvcpar1_std_obj (&pte, NULL, NULL, Ptyp_1, typPath, datPath);
    // GR_Disp_pt (&pte, SYM_STAR_S, ATT_COL_BLUE);

  // set vc1 = path-vector (pts -> pte)
  UT3D_vc_2pt (&vc1, &pts, &pte);

  // define transformation
  UTRA_def__ (1, Typ_VC, &vc1);

  // set pt4 = pt1 <- vc1
  // UTRA_app_obj (&pt4, Typ_PT, 1, &pt1, wrkSpc);

  // set pt3 = pt2 <- vc1
  // UTRA_app_obj (&pt3, Typ_PT, 1, &pt2, wrkSpc);

  // oc2 = translate contour  (pts -> pte)
  UTRA_app_obj (&oc2, typCov, 1, ci1, wrkSpc);
    UT3D_stru_dump (typCov, oc2, " oc2 ");
    // GR_Disp_obj (typCov, oc2, 7, 0);

  // op1 = translate path  (pts -> pt2)
  UT3D_vc_2pt (&vc1, &pts, &pt2);
  UTRA_def__ (1, Typ_VC, &vc1);
  UTRA_app_obj (&op1, typPath, 1, datPath, wrkSpc);
    // GR_Disp_obj (typPath, op1, 7, 0);

  // store op1 in DB
  dbi = DB_StoreLine (-1L, op1);

  // create PRCV for op1 / NOT for line

  // create trimmed-curve from op1
  CVTRM__obj (&ccvTab[1], typPath, op1, dbi);
    // GR_Disp_obj (Typ_CVTRM, &ccvTab[1], 7, 0);


  //----------------------------------------------------------------
  // store oc2 contour2 in DB
  dbi = DB_StoreCirc (-1L, oc2);

  // create PRCV for bin.obj (if dynam.obj)
  PRCV_set_obj_dbi (typCov, oc2, 1, typCov, dbi);

  // create trimmed-curve from contour2
  CVTRM__obj (&ccvTab[2], typCov, oc2, dbi);

  // reverse trimmed-curve from contour2 (same curve, different direction)
  CVTRM__rev (&ccvTab[2]);
    // GR_Disp_obj (Typ_CVTRM, &ccvTab[2], 7, 0);


  //----------------------------------------------------------------
  // op2 = translate path (pts -> pt1) and reverse
  UT3D_vc_2pt (&vc1, &pts, &pt1);
  UTRA_def__ (1, Typ_VC, &vc1);
  UTRA_app_obj (&op2, typPath, 1, datPath, wrkSpc);
    // GR_Disp_obj (typPath, op2, 7, 0);

  // store op1 in DB
  dbi = DB_StoreLine (-1L, op2);

  // create PRCV for op1 / NOT for line

  // create trimmed-curve from op1
  CVTRM__obj (&ccvTab[3], typPath, op2, dbi);

  // reverse trimmed-curve 
  CVTRM__rev (&ccvTab[3]);
    // GR_Disp_obj (Typ_CVTRM, &ccvTab[3], 7, 0);


  //----------------------------------------------------------------
  // store CCV from ccvTab in DB
  cvNr = 4;
  bDbi = DB_StoreCvCCV (-1L, ccvTab, cvNr);
    printf(" dbi-ccv=%ld\n",bDbi);


    // TESTBLOCK
    // PRCV_test_get (Typ_CV, bDbi);
    // END TESTBLOCK

}


  //================================================================
  // build surface
  // get space for 2 ox-records
  oxTab = UME_reserve (wrkSpc, sizeof(ObjGX) * 2);
  if(oxTab == NULL) return -1;

  // 1. record = supporting sbsp-surface
  OGX_SET_INDEX (&oxTab[0], Typ_SURSWP, sDbi);

  // add outer-boundary as second ox-record 
  OGX_SET_INDEX (&oxTab[1], Typ_CVTRM, bDbi);



  //----------------------------------------------------------------
  ox1->typ   = Typ_SURSUP;
  ox1->form  = Typ_ObjGX;
  ox1->siz   = 2;
  ox1->data  = oxTab;


    UT3D_stru_dump (Typ_SURSWP, sur1, "ex-APT_decode_su_swp_cyl\n");
    // UTO_dump_s_ (ox1, "n-decode_su_swp_cyl");
    // TSU_test_OB_1 (Typ_CVTRM, bDbi);


  return 0;


  //----------------------------------------------------------------
  Error:
  TX_Error(" Definition A=CYL not implemented");
  return -1;

  Err_DB:
    TX_Error("SwpSurfDefinition: DB-Error ****");
    goto Error;


}


//=========================================================
  int SUP_load__ (ContTab *cTab, int *cNr, int cMax,
                  Point *pTab, int pMax,
                  ObjGX *oxi) {
//=========================================================
// get outer and inner boundaries -> cTab/pTab
// Output:
//   cTab    contour (closed; last pt = first pt)
//   RC: 0 = OK;
//       1 = Aussenkontur klein (planar darstellen)
//       2 = Aussenkontur zu klein (gar nix darstellen)

// was SUP_load_c SUP_addBound
// ACHTUNG: bei Konus wird an Spitze ein zusaetzlicher Punkt mit
//          X=VAL_MAX eingefuegt !


  int    i1, i2, irc, ptNr, bTyp;
  long   ind, bDbi;
  Point  *pa;
  ObjGX  ox1, *oxTab, *oxp1;


  printf("SUP_load__ cMax=%d pMax=%d\n",cMax,pMax);
  UTO_dump_s_ (oxi, "SUP_load__");


  if(oxi->siz < 2)    {TX_Error("SUP_load__ E001"); return -1;}
  if(oxi->siz > cMax) {TX_Error("SUP_load__ E002"); return -1;}

  oxTab = oxi->data;
  *cNr = 0;


  //----------------------------------------------------------------
  // loop tru oxi
  for(i1=1; i1<oxi->siz; ++i1) {

    oxp1 = &oxTab[i1];
      printf("_load_c[%d] typ=%d form=%d\n",i1,oxp1->typ,oxp1->form);


    if(oxp1->typ == Typ_modUndef) {
      // outer-boundary==Typ_modUndef: planar; get outer-boundary of suppSur
      TX_Error("SUP_load__ TODO-1");
      return -1;
      // cTab[*cNr].use = 'P';  // planar
      // ptNr = 0;
      // goto L_b_nxt;
    }


    if(oxp1->form == Typ_Index) {
      OGX_GET_INDEX (&bTyp, &bDbi, oxp1);
    } else {
      TX_Error("**** SUP_load__ E003");
      return -1;
    }


    // get Polygon from polygonal representation; (was SUP_addBound)
    irc = PRCV_npt_dbo__ (&pa, &ptNr, bTyp, bDbi, WC_modact_ind);
    if(irc < 0) return -1;
      // GR_Disp_pTab (ptNr, pa, SYM_STAR_S, 2);  // return -1;


    // add points to contour
    memcpy(pTab, pa, ptNr * sizeof(Point));


    // store active record
    L_b_nxt:
    cTab[*cNr].iNr = ptNr;
    cTab[*cNr].pa  = pTab;
    pMax -= ptNr;

      // TESTBLOCK
      // printf(" SUP_load__-1 %d\n",ptNr);
      // GR_Disp_pTab (ptNr, pTab, SYM_STAR_S, 2);  // return -1;
      // END TESTBLOCK


    // prepare for next contour
    pTab = &pTab[ptNr];
    *cNr += 1;
  }


  // finished;  update cTab.pa (points to start of point-array);


  return 0;

}


//================================================================
  int TSU_tps_typ (int *sstyp, ObjGX *oxi) {
//================================================================
// get type of supporting-surface 
// ObjGX[0])=supporting-surface

  ObjGX    *oxp1, *oxTab;


  printf("TSU_tps_typ\n");

  // get suppSur (rec.0)
  oxTab = oxi->data;
  oxp1 = &oxTab[0];


  //----------------------------------------------------------------
  if(oxp1->typ != Typ_modUndef) goto L_1;
    // outer-boundary==Typ_modUndef: planar.
    *sstyp = Typ_PLN;

    goto L_exit;


  //----------------------------------------------------------------
  L_1:
    TX_Error("TSU_tps_typ TODO-1");
    return -1;


  //----------------------------------------------------------------
  L_exit:


  return 0;

}


//================================================================
  int TSU_draw_sSym (ContTab *cTab, int cNr, Point *pTab,
                     long dbi, int att) {
//================================================================
// display surfaceboundaries
// see GL_sSym_spl


  int    i1, ii, iNr;
  long   dli;
  ObjGX  oo, *cvTab;


  printf("TSU_draw_sSym %d\n",cNr);


  cvTab = (ObjGX*) MEM_alloc_tmp (cNr * sizeof(ObjGX));


  ii = 0;
  for(i1=0; i1<cNr; ++i1) {
    iNr = cTab[i1].iNr;
    cvTab[i1].typ  = Typ_PT;
    cvTab[i1].form = Typ_PT;
    cvTab[i1].siz  = iNr;
    cvTab[i1].data = &pTab[ii];
    ii += iNr;
  }


  oo.typ  = Typ_GL_CV;
  oo.form = Typ_ObjGX;
  oo.siz  = cNr;
  oo.data = cvTab;

  dli = DL_StoreObj (Typ_SUR, dbi, att);

  GL_Draw_obj (&dli, Typ_Att_Fac1, &oo);

  return 0;

}

static long TSU_dli;
static int  TSU_mode = 0;  // 0=draw, 1=store


//================================================================
  int TSU_DrawSurTPS (ObjGX *oxi, long dbi, int att) {
//================================================================
// Tesselate / Display getrimmte/gelochte Flaechen
// typ  = Typ_SUR
// form = Typ_ObjGX
// siz  = Anzahl von ObjGX in data
// data = (ObjGX[0])=supporting-surface
//        (ObjGX[1])=outer-boundary
//        (ObjGX[2-n])=inner-boundaries
// ACHTUNG: bei planaren Flaechen keine Stuetzflaeche. Errechnen !
//          ObjGX[0] ist in diesem Fall Aussenkontur ..
// was TSU_DrawSurT_ SUP_load_c ..
// TSU_DrawSurTP     Planare Flaeche; getrimmt, gelocht;


  int       i1, i2, irc, cNr, cMax, pMax, ptNr, sstyp;
  long      l1, l2;
  Point     *pTab;
  Vector    vc1;
  Plane     pl1;
  ContTab   *cTab;
  ObjGX     *oTab, *oxp1, *gSur;
  ColRGB    *col;



  // printf("============================================ \n");
  printf("TSU_DrawSurTPS dbi=%ld typ=%d form=%d siz=%d\n",dbi,
          oxi->typ,oxi->form,oxi->siz);


  //----------------------------------------------------------------
  // get space for points
  pTab = (void*) memspc501;
  pMax = sizeof(memspc501) / sizeof(Point);


  // prepare space for contours
  cTab = (ContTab*)memspc201;
  cMax = sizeof(memspc201) / sizeof(ContTab);


  // get type of supporting-surface (Typ_PLN ..)
  irc = TSU_tps_typ (&sstyp, oxi);
  if(irc < 0) return irc;


  // get outer and inner boundaries
  // Aussen- und Innenkonturen holen
  irc = SUP_load__ (cTab, &cNr, cMax, pTab, pMax, oxi);
    // printf(" _load_c %d\n",irc);
  if(irc < 0) return irc;


  // compute Z-Vektor for planar (normal-vector to outer-boundary)
  irc = UT3D_pl_pta (&pl1, cTab[0].iNr, pTab);
  if(irc < 0) return irc;
  vc1 = pl1.vz;


  // orient contours (outer-boundary CCW, inner-boundaries CW)
  SUP_orient (&vc1, cTab, cNr);


  // draw symbolic
  // if(TSU_sStyl > 0) {
    // return TSU_draw_sSym (cTab, cNr, pTab, dbi, att);
  // }


  // tesselate into gSur
  irc = TSU_tps_tess (&gSur, &vc1, cTab, cNr);
  if(irc < 0) return irc;


  // display | store gSur
  if(TSU_mode == 0) {    // 0=draw, 1=store
    TSU_dli = DL_StoreObj (Typ_SUR, dbi, att);
    GL_DrawSur (&TSU_dli, att, gSur);
  }



  // store as PRSU
    // TSU_store (gSur);



  return 0;

}

 
//======================================================================
  int TSU_tps_tess (ObjGX **gSur, Vector *vcz, ContTab *cTab, int cNr) {
//======================================================================


  int   i1;


  printf("TSU_tps_tess \n");


  L_tess:

  // Start tesselation , Pointer -> active surf. holen
  GLT_start__ (gSur);

  // activate new tesselation-patch
  i1 = GLT_spp_pp (vcz);
  if(i1) return -1;

/*
  // Default- oder Spezialfarbe ?
  if((col->color != 0) || (col->vtra != 0)) {
    GLT_spp_Col (col);
    // GLT_spp_Col (&GL_actCol);

  } else if (col->vtex != 0) {
    if(GL_actTex >= 0) GLT_spp_Tex (GL_actTex);

  // } else {   // alles 0   // alles 0
    // GLT_spp_Col (&GL_defCol);

  }
*/

  // tesselate planar patch
  i1 = GLT_spp__ (cTab, cNr, vcz);
  if(i1 < 0) goto L_err;


    // TESTBLOCK
    // tess_dump_f_ (*gSur, "ex TSU_tps_tess");
    UTO_dump_s_ (*gSur, "ex TSU_tps_tess");
    // END TESTBLOCK



  return 0;


  //----------------------------------------------------------------
    L_err:
    if(i1 == -10) {
      GLT_exit ();
      GLT_init__ ();
      goto L_tess;          // realloc
    }
    // TX_Error("GLT_spp_pp E001 %d",i1);
    printf("GLT_spp_pp E001 %d",i1);
    return i1;



}



//================================================================
//================================================================
 

// typedef_MemTab(void);
// typedef_MemTab(IndTab);
// typedef_MemTab(Line);
// typedef_MemTab(char);
// typedef_MemTab(int);
// typedef_MemTab(Point);
// static int TSU_mode=0;  // 0=draw; 1=store


// ex ../gr/ut_tess_su.c
#define TessDatSiz 256   // TessDat_SWP
// Typ_PLN   unused; 0
//// Typ_SURSWP TessDat_SWP


// tesselation-data for surfaces
// oxs      ObjGX of surface (support, boundaries)
// ssTyp    form of support-surface; Typ_PLN|Typ_SURSWP
// ssDbi    DB-index of support-surface
// ssDat    data of support-surface (was TSU_sbsp ..)
// p2Dgbx     startpoint of 2D-grid (u0,v0)
// p3Dgbx   startpoint of 3D-grid
// ipgbx    index of first gridBox-point in ipa
// tr_*     functions 3D to 2D and retour
// td       individual for surface-type;
//          TessDat_SWP if typ = Typ_SURSWP
typedef struct {ObjGX *oxs; int ssTyp; long ssDbi; void *ssDat;
                int (*tr_2D_3D)(); int (*tr_3D_2D)(); 
                GridBox gbx; Point *p2Dgbx, *p3Dgbx; int ipgbx;
                double rx, ry, dx, dy, tol;
                char td[TessDatSiz];}                                TessDat__;


typedef struct {long dbi; int mdli;
                MemTab(IndTab) fmt;
                MemTab(char)   pst;
                MemTab(int)    ipa;
                MemTab(Point)  pa3;
                MemTab(Point)  pa2;
                MemTab(IndTab) bnd;
                Vector         vcz;}                                 TessStru;


  int (*TSU_2D_3D_pt) (Point*, Point*, TessDat__*);
  int (*TSU_3D_2D_pt) (Point*, Point*, TessDat__*);

  // sbsp srbsp con srv sru sph tor
  int TSU_2D_3D_sbsp (Point *pt2, Point *pt3, TessDat__ *td1);
  int TSU_3D_2D_sbsp (Point *pt3, Point *pt2, TessDat__ *td1);




//================================================================
  int TSU_init_bsp (TessStru *ts1, TessDat__ *td1) {
//================================================================
// load 3D-outer- and inner-boundaries
// find 2D-range = 3D-parameter-range (uMin, uMax, vMin, vMax)
// find 2D-tolerance, parameter-offsets in u and v for grid
// create 2D-gridBox with all points according 2D-tolerance
// add 2D-points > pa2; indices > imt.
// create 3D-points for 2D-gridBox and add to > pa3;
// - all boundary-points -> 2D (3D-coords -> u,v-parameters)
// - set functions 3D->2D and 2D->3D.


// was SUP_load_c Tess_sur_bnd__ TSU_tr_init_


//------ old versions: -------------------------------------------
// TSU_DrawSurBsp GL_sSym_sbsp
//   UT3D_uvNr_sbsp // get optimale Anzahl von Punkten in U- und V-Richtung
//   UT3D_ptgrid_sbsp
//   GR_DrawTriaStrip

// TSU_init_rbsp
// TSU_DrawSurRBsp 
//   UT3D_uvNr_srbsp // get optimale Anzahl von Punkten in U- und V-Richtung
//   UT3D_ptgrid_srbsp  // get points

// Tess_sur_td__   // save tesselation-date for sweep with spine=cvBspl
// TessDat__ int (*tr_2D_3D)(); int (*tr_3D_2D)();
// td1->tr_2D_3D = Tess_tr_2D_3D_swp;  // transl.func 3D -> 2D
// td1->tr_3D_2D = Tess_tr_3D_2D_swp;  // transl.func 2D -> 3D

  int   irc;

  printf("TSU_init_bsp\n");

  // add ts1->bnd for each boundary in td1->oxs
  // 3D-points out to ts1->pa3
  // indexes to 3D-points out to ts1->ipa
  irc = TSU_init_bnd_3D (ts1, td1);
  if(irc < 0) return -1;



  //================================================================
  // compute grid of 3D-points; used for faster computations (eg UT3D_parsbsp_pt)
  // setup GridBox td1->gb3D;
  // find 2D-range = 3D-parameter-range (uMin, uMax, vMin, vMax)

  // see ../gr/tess_su.c:4668
  {
    int       irc, i1, i2, iu, iv, cycX, cycY, ptNr, pintNr;
    // int       pMaxNr;
    double    uMin, uMax, vMin, vMax, du, dv, tol2D, d1;
    long      ld;
    SurBSpl   *sbsp;
    Memspc    wrkSpc;

    sbsp = td1->ssDat;
    uMin = sbsp->kvTabU[0];
    uMax = sbsp->kvTabU[sbsp->ptUNr + sbsp->degU];
    vMin = sbsp->kvTabV[0];
    vMax = sbsp->kvTabV[sbsp->ptVNr + sbsp->degV];
      printf("uMin=%f uMax=%f  vMin=%f vMax=%f\n",uMin, uMax, vMin, vMax);

    // die optimale Anzahl von Punkten in U- und V-Richtung ermitteln
    // SUSbsp_ck_tol (&i1, &i2, TSU_sbsp);
    UME_init (&wrkSpc, memspc53, sizeof(memspc53));
    UT3D_uvNr_sbsp (&iu, &iv, sbsp, &wrkSpc);
    ptNr = iu * iv;
      printf("  ptNr=%d iu=%d iv=%d\n",ptNr,iu,iv);

    // die 2D-Toleranz TSU_tol2D setzen
    d1 = ((vMax-vMin)+(uMax-uMin)) / 2.;  // soll 2.!
    tol2D =  UT_DISP_cv * d1 / APT_ModSiz;
      printf(" d1=%f tol2D=%f\n",d1,tol2D);


/*
    // Init Speicherbereich fuer 3D-Gitterpunkte (dzt nur f Typ_SURBSP)
    pta = (Point*) memspc102;              // was memspc54 !!!
    pMaxNr = sizeof(memspc102) / sizeof(Point);

    if(ptNr > pMaxNr) {TX_Error("TSU_init_bsp E1"); return -1;}
      printf(" pMaxNr=%d\n",pMaxNr);

    // reduce nr of points if necessary:
    L_sbsp_L1:
    if(iu*iv > pMaxNr) {
      if((i1 > 4)&&(i2 > 4)) {
        d1 = i1; d1 *= 0.75; i1 = d1;
        d1 = i2; d1 *= 0.75; i2 = d1;
        // printf("  korr. iu=%d iv=%d\n",i1,i2);
        goto L_sbsp_L1;
      } else {
        TX_Error("TSU_tr_init_ E002");
        return -1;
      }
    }
*/

    // feststellen ob in X geschlossen // closed (cyclic) in X (U)
    cycX = UT3D_sbs_ck_cycX (sbsp);  // 0=not, 1=yes

    // feststellen ob in Y geschlossen  // closed (cyclic) in Y (V)
// TODO: cycY = ..

    // # of intersection-points
    // muss neu gemacht werden mit TSU_cycY und UT3D_sbs_ck_cycY
    pintNr = UT3D_sbs_ck_closed (sbsp);


    // make grid > outer-boundary
    // tol2D = 0.1;
    // uMin -= tol2D;   uMax += tol2D;
    // vMin -= tol2D;   vMax += tol2D;
      // printf("uMin=%f uMax=%f  vMin=%f vMax=%f\n",uMin, uMax, vMin, vMax);


    du = (uMax - uMin) / (iu-1);  // uOff
    dv = (vMax - vMin) / (iv-1);  // vOff
      printf(" du=%f dv=%f\n",du,dv);



    //----------------------------------------------------------------
    // create 3D-point-grid for quicker computations.
    // nur die Kontrollpunkte sind zuwenig, wenn zB ein kreisformiges Stuck
    // gegeben ist.

    // td1->ipgbx = startIndex in pa3
    td1->ipgbx = MEMTAB_IND (&ts1->pa3);

    // reserve space for ptNr points in pa3
    irc = MemTab_add (&ts1->pa3, &ld, NULL, ptNr, 1);
    if(irc < 0) return irc;

    // get startPosition for 3D-points
    td1->p3Dgbx = MEMTAB__ (&ts1->pa3, td1->ipgbx);

    // compute points of 3D-point-grid
    UME_init (&wrkSpc, memspc53, sizeof(memspc53));
    irc = UT3D_ptgrid_sbsp (td1->p3Dgbx, NULL, NULL, &du, &dv,
                            sbsp, iu, iv, &wrkSpc);
    if(irc < 0) return -1;

    // td1->gbx.p1 = td1->p3Dgbx;
    // td1->gbx.pMaxNr = ptNr;
    td1->gbx.dx = du;
    td1->gbx.dy = dv;
    td1->gbx.ix = iu;
    td1->gbx.iy = iv;
    td1->gbx.iz = 1;


    // add links to gridPoints in ipa
    // td1->ipgbx = index of 1. point in ts1->pa3
    TSU_init_ipa_add (ptNr, td1->ipgbx, ts1);


    // add status = 4 to pst for gridPoints
    TSU_init_pst_add (ptNr, ts1, 4);


      // TESTBLOCK
      printf("  du=%f dv=%f\n",du,dv);
      // display ?
      GR_Disp_pTab (ptNr, td1->p3Dgbx, SYM_STAR_S, 2);
      // END TESTBLOCK

 
    //================================================================
    // - set functions 3D->2D and 2D->3D.
    // using p3Dgbx (3D-gridbox), dx,dy ix,iy 
    td1->tr_2D_3D = TSU_2D_3D_sbsp;  // transl.func 3D -> 2D

    // - set functions 3D->2D and 2D->3D.
    td1->tr_3D_2D = TSU_3D_2D_sbsp;  // transl.func 2D -> 3D


    //================================================================
    // translate all 3D-points (of all boundaries and 3D-gridbox) into 2D-points 
    // boundaries in from ts1->bnd
    // 3D-points in from ts1->pa3
    // 2D-points out to ts1->pa2
    irc = TSU_init_bnd_2D (ts1, td1);
    if(irc < 0) return -1;


    //================================================================
    // set gbx.p1 = startpoint of 2D-gridbox (needed by GLU_tess__)
    td1->gbx.pMin = *(MEMTAB__ (&ts1->pa2, td1->ipgbx));


    //================================================================
    // set ts1->vcz for 2D (CCW)
    ts1->vcz = UT3D_VECTOR_Z;

  }


  return 0;

}


//================================================================
  int TSU_init_pst_add (int ptNr, TessStru *ts1, int bitVal) {
//================================================================
// add status = 2 to pst for gridPoints

  int     irc;
  char    c1;
  long    ld;

  printf("TSU_init_pst_add %d %d\n",ptNr,bitVal);

  c1 = bitVal;

  // add statuswords for the gridPoints
  // i1 = MEMTAB_IND (&ts1->pa2D);
  // i2 = MEMTAB_IND (&ts1->pst);
  // ii = i1 - i2;

    // printf(" 2D-ptNr=%d ptStatNr=%d %d\n",i1,i2,ii);
  if(ptNr > 0) {
    // add point-status
    irc = MemTab_add (&ts1->pst, &ld, &c1, ptNr, 4);
    if(irc < 0) return irc;
  }
    printf(" after-init_pst_add r.pa3=%d r.pst=%d\n",
            MEMTAB_IND(&ts1->pa3),MEMTAB_IND(&ts1->pst));


  return 0;

}


//================================================================
 int TSU_init_ipa_add (int ptNr, int ips, TessStru *ts1) {
//================================================================
// add links to gridPoints in ipa
// td1->ipgbx = index of 1. point in ts1->pa3
// returns startIndex in ipa
// TODO: replace with MemTabI_add_s


  int     irc, i1, *ia, iis, ip1, ii1;
  long    ld;

  printf("TSU_init_ipa_add ptNr=%d ips=%d\n",ptNr,ips);


  // iis = next free position in ipa
  iis = MEMTAB_IND (&ts1->ipa);
    printf(" iis=%d\n",iis);

  // reserve ptNr links in ipa
  irc = MemTab_add (&ts1->ipa, &ld, NULL, ptNr, 1);
  if(irc < 0) {TX_Error("TSU_init_ipa_add E1");return -1;}

  // add all links into ipa 
  ia = MEMTAB_DAT (&ts1->ipa);   // get int-table
  if(irc < 0) {TX_Error("TSU_init_ipa_add E2");return -1;}

  ip1 = ips;
  ii1 = iis;

  for(i1=0; i1<ptNr; ++i1) {
    ia[ii1] = ip1;
    ++ip1;
    ++ii1;
  }

     // MemTab_dump (&ts1->ipa, "ex-TSU_init_ipa_add-ipa");

  return iis;

}


//================================================================
  int TSU_init_bnd_3D (TessStru *ts1, TessDat__ *td1) {
//================================================================
// - add ts1->bnd for each boundary in oxi to ts1->pa3


  int    irc, i1, cNr, bTyp, ptNr, ips, ip1, cAct, cTyp, ii1, iis, *ia;
  long   bDbi, ld;
  char   c1;
  ObjGX  *oxa, *oxb;
  Point  *pa;
  IndTab cnt1;


  // get nr of contours
  cNr = td1->oxs->siz - 1;

  printf("TSU_init_bnd_3D cNr=%d\n",cNr);


  // get pa = datablock of points pa3
  pa = MEMTAB_DAT (&ts1->pa3);

  cAct = 1;
  cTyp = MSH_EDGLN_OB;

  oxa = td1->oxs->data;


  //----------------------------------------------------------------
  L_nxt_cnt:
  // get oxb = next boundary
  oxb = &oxa[cAct];

  // get bDbi = dbi for next boundary
  if(oxb->form == Typ_Index) {
    OGX_GET_INDEX (&bTyp, &bDbi, oxb);
  } else {
    TX_Error("TSU_init_bnd_3D E1");
    return -1;
  }
    printf(" bTyp=%d bDbi=%ld\n",bTyp,bDbi);


  //----------------------------------------------------------------
  // get 3D-points for DB-obj
  irc = PRCV_npt_dbo__ (&pa, &ptNr, bTyp, bDbi, WC_modact_ind);
  if(irc < 0) {TX_Error("TSU_init_bnd_3D E2");return -1;}
    // GR_Disp_pTab (ptNr, pa, SYM_STAR_S, 2);

  // get ips = next free position of points in pa3
  ips = MEMTAB_IND (&ts1->pa3);
    printf(" ptNr=%d ips=%d\n",ptNr,ips);

  // copy points -> ts1->pa3
  irc = MemTab_add (&ts1->pa3, &ld, pa, ptNr, 0);
  if(irc < 0) return irc;


    // TESTBLOCK
    // GR_Disp_pTab (ptNr, &ts1->pa3.data[ips], SYM_STAR_S, 2);
    // END TESTBLOCK


  //----------------------------------------------------------------
  // add all links into ipa 
  // ips = index of 1. point in ts1->pa3
  // returns iis = startPosition ipa
  iis = TSU_init_ipa_add (ptNr, ips, ts1);
  if(iis < 0) return -1;


  //----------------------------------------------------------------
  // add point-status 2 to pst
  c1 = 2;
  irc = MemTab_add (&ts1->pst, &ld, &c1, ptNr, 4);
  if(irc < 0) return irc;


  //----------------------------------------------------------------
  // add outer-boundary-record -> ts1->bnd
  cnt1.ibeg = iis;    // startindex in ipa
  cnt1.iNr  = ptNr;   // nr of points
  cnt1.typi = cTyp;   // MSH_EDGLN_OB|MSH_EDGLN_IB
  cnt1.aux  = 0;      // unused
  irc = MemTab_add (&ts1->bnd, &ld, &cnt1, 1, 0);
  if(irc < 0) return irc;

    // MemTab_dump (&ts1->bnd, "bnd-2");

  ++cAct;
  cTyp = MSH_EDGLN_IB;
  if(cAct < cNr) goto L_nxt_cnt;

    // TESTBLOCK
    MemTab_dump (&ts1->bnd, "ex-TSU_init_bnd_3D-bnd");
    // MemTab_dump (&ts1->ipa, "ex-TSU_init_bnd_3D-ipa");
    // MemTab_dump (&ts1->pst, "ex-TSU_init_bnd_3D-pst");
    // MemTab_dump (&ts1->pa3, "ex-TSU_init_bnd_3D-pa3");
    // END TESTBLOCK



  return 0;

}


//================================================================
  int TSU_init_tr_3D (TessStru *ts1, TessDat__ *td1) {
//================================================================
// translate 2D-points created in GLU_tess__ into 3D

  int    ii, i2, i3;
  Point  *pa3, *pa2;

  // get nr of 2D-points
  i2 = MEMTAB_IND (&ts1->pa2);
  // get nr of 3D-points
  i3 = MEMTAB_IND (&ts1->pa3);
    printf(" i2=%d i3=%d\n",i2,i3);


  if(i2 <= i3) return 0;

  pa3 = MEMTAB_DAT (&ts1->pa3);
  pa2 = MEMTAB_DAT (&ts1->pa2);

  for(ii=i3; ii<i2; ++ii) {
    (*td1->tr_3D_2D) (&pa3[ii], &pa2[ii], td1);
  }


  printf("******* TODO-TSU_test_tess_TPS-1 %d %d\n",i2,i3);

  return -1;

}

 
//================================================================
  int TSU_init_bnd_2D (TessStru *ts1, TessDat__ *td1) {
//================================================================
// translate 3D-points of all boundaries into 2D-points


  int    irc, i1, ptNr;
  long   ld;
  Point  *pa3, *pa2;

  printf("TSU_init_bnd_2D %d\n",ts1->pa3.rNr);

  // existing 3D-points
  pa3 = MEMTAB_DAT (&ts1->pa3);

  // get ptNr = nr of 3D-points
  ptNr = ts1->pa3.rNr;

  // reserve space for ptNr points in pa2
  irc = MemTab_add (&ts1->pa2, &ld, NULL, ptNr, 1);
  if(irc < 0) return irc;


  pa2 = MEMTAB_DAT (&ts1->pa2);
  for(i1=0; i1<ptNr; ++i1) {
    // TSU_2D_3D_sbsp (&pa2[i1], &pa3[i1], td1);
    (*td1->tr_2D_3D) (&pa2[i1], &pa3[i1], td1);
  }

/*
  // int    i1, i2, ils, ile, ipt, *ipa;
  // IndTab *cnt1;
  // ipa = MEMTAB_DAT (&ts1->ipa);
  // loop tru contours
  for(i1=0; i1<ts1->bnd.rNr; ++i1) {
    cnt1 = &ts1->bnd.data[i1];
    ils = cnt1->ibeg;
    ile = ils + cnt1->iNr;
    // loop tru all points
    for(i2=ils; i2<ile; ++i2) {
      ipt = ipa[i2];
      // TSU_2D_3D_sbsp (&pa2[ipt], &pa3[ipt]);
        GR_Disp_pt (&pa3[ipt], SYM_STAR_S, ATT_COL_RED);
    }
  }
*/

  return 0;

}


//================================================================
  int TSU_3D_2D_sbsp (Point *pt3, Point *pt2, TessDat__ *td1) {
//================================================================

  int       irc;
  Point     pt1;
  Memspc    wrkSpc;


  UT3D_stru_dump (Typ_PT, pt2,"TSU_3D_2D_sbsp");

  UME_init (&wrkSpc, memspc53, sizeof(memspc53));

  irc = UT3D_pt_evparsbsp (pt3, td1->ssDat, pt2->x, pt2->y, &wrkSpc);

  // UT3D_stru_dump(Typ_PT, pt3,"ex TSU_tr_3D_2D_sbsp");

  return irc;


}


//================================================================
  int TSU_2D_3D_sbsp (Point *pt2, Point *pt3, TessDat__ *td1) {
//================================================================
// was TSU_tr_2D_3D_sbsp
// was TSU_tr_init_ ../gr/tess_su.c:4668
 
  
static int    iu,iv;
static double du,dv;


  int     irc;
  Memspc  wrkSpc;

  UT3D_stru_dump (Typ_PT, pt3, "TSU_2D_3D_sbsp");
  // GR_Disp_pt (pt3, SYM_STAR_S, ATT_COL_RED);

  // get tempSpace
  UME_init (&wrkSpc, memspc53, sizeof(memspc53));

  irc = UT3D_parsbsp_pt (&pt2->x, &pt2->y, pt3,
                         td1->p3Dgbx,
                         td1->gbx.dx, td1->gbx.dy,
                         td1->gbx.ix, td1->gbx.iy,
                         td1->ssDat, &wrkSpc);
  if(irc < 0) return irc;

  pt2->z=0.;


    // TESTBLOCK
    UT3D_stru_dump (Typ_PT, pt2, " ex-TSU_2D_3D_sbsp");
    GR_Disp_pt (pt2, SYM_TRI_S, ATT_COL_GREEN);
    // END TESTBLOCK


  return 0;

}


//===================================================================
  int TSU_init_pln (TessStru *ts1, TessDat__ *td1) {
//===================================================================
/// \code
/// TSU_init_pln          get contours and normalvector for planar surface
/// td1->ssTyp = Typ_SURPLN
/// add all contourPoints -> ts1->pa2
/// add all indices -> ts1->bnd; one record for each boundary
/// get normalvector -> ts1->vcz
/// \endcode

// TODO: use TSU_init_bnd_3D (fills pa3; set pa2-pointer = pa3)


  int    irc, i1, cNr, cAct, ptNr, ips, iis, ip1, ii1, bTyp, cTyp, *ia;
  long   bDbi, ld;
  char   c1;
  Point  *pa;
  Plane  pl1;
  ObjGX  *oxa, *oxb;
  IndTab cnt1;


  oxa = td1->oxs->data;

  // get nr of contours
  cNr = td1->oxs->siz;


  printf("TSU_init_pln cNr=%d\n",cNr);

  // td1->gbx.p1 = NULL;  // no grid for planar

  cAct = 1;
  cTyp = MSH_EDGLN_OB;

  L_nxt_cnt:

  // get oxb = next boundary
  oxb = &oxa[cAct];


  // get bDbi = dbi for outer-boundary
  if(oxb->form == Typ_Index) {
    OGX_GET_INDEX (&bTyp, &bDbi, oxb);
  } else {
    TX_Error("TSU_init_pln E1");
    return -1;
  }
    printf("--- cAct=%d  bTyp=%d bDbi=%ld\n",cAct,bTyp,bDbi);


  // get points ..
  irc = PRCV_npt_dbo__ (&pa, &ptNr, bTyp, bDbi, WC_modact_ind);
  if(irc < 0) {TX_Error("TSU_init_pln E2");return -1;}
    // GR_Disp_pTab (ptNr, pa, SYM_STAR_S, 2);


  // get ips = next free position of points in pa2
  ips = MEMTAB_IND (&ts1->pa2);
    printf("    cAct=%d ptNr=%d ips=%d\n",cAct,ptNr,ips);


  // compute Z-Vektor for planar (normal-vector to boundary)
  // only for outer-boundary
  if(cTyp == MSH_EDGLN_OB) {
    irc = UT3D_pl_pta (&pl1, ptNr, pa);
    if(irc < 0) return irc;
    ts1->vcz = pl1.vz;
      UT3D_stru_dump (Typ_VC, &ts1->vcz, "  vcz");
  }

  // copy points -> pa2
  irc = MemTab_add (&ts1->pa2, &ld, pa, ptNr, 0);
  if(irc < 0) return irc;


  // add all links into ipa 
  iis = TSU_init_ipa_add (ptNr, ips, ts1);
  if(iis < 0) return -1;


  // add point-status 2 to pst
  c1 = 2;
  irc = MemTab_add (&ts1->pst, &ld, &c1, ptNr, 4);
  if(irc < 0) return irc;


  // add outer-boundary-record -> ts1->bnd
  cnt1.ibeg = iis;    // startindex in ipa
  cnt1.iNr  = ptNr;   // nr of points
  cnt1.typi = cTyp;   // MSH_EDGLN_OB|MSH_EDGLN_IB
  cnt1.aux  = 0;      // unused
  irc = MemTab_add (&ts1->bnd, &ld, &cnt1, 1, 0);
  if(irc < 0) return irc;

    // MemTab_dump (&ts1->bnd, "bnd-2");


  ++cAct;
  cTyp = MSH_EDGLN_IB;
  if(cAct < cNr) goto L_nxt_cnt;


    // TESTBLOCK
    // MemTab_dump (&ts1->bnd, "bnd-2");
    // MemTab_dump (&ts1->pst, "pst-1");
    // GR_Disp_pTab (ts1->pa2.rNr, ts1->pa2.data, SYM_STAR_S, 2);
    printf(" ex-TSU_init_pln-0\n");

    // END TESTBLOCK

  return 0;

}


//=================================================================
  int TSU_init__ (TessStru *ts1, TessDat__ *td1) {
//=================================================================
// get boundaries & tesselation-data
// was Tess_sur_bnd__

  int   irc, sTyp=0, bNr;
  // ObjGX *oxa;

  printf("TSU_init__ td1->ssTyp=%d\n",td1->ssTyp);



  //----------------------------------------------------------------
  switch (td1->ssTyp) {

    case Typ_SURPLN:  // Typ_modUndef:
      irc = TSU_init_pln (ts1, td1);
      if(irc < 0) return -1;
      // orient contours (outer-boundary CCW, inner-boundaries CW)
      // boundaries ts1->bnd
      irc = SUP_cvcnt_orient__ (&ts1->bnd, ts1->pa2.data, &ts1->vcz);
      if(irc < 0) return -1;
      break;

    case Typ_SURBSP: // Loft-Surface, B-Spline-Surface
      irc = TSU_init_bsp (ts1, td1);
      break;

    default:
      TX_Error("TSU_init__ NYI typ=%d",sTyp);
      return -1;
  }

  // if(irc < 1) return -1;

    // printf("ex Tess_sur_bnd__:\n");
    // printf(" tot.points=%d\n",MEMTAB_IND(&pa2));
    // printf(" tot.edges=%d\n",MEMTAB_IND(&eas1));
    // Test_dump_sur (&eas1, sba[is].suID);



  //----------------------------------------------------------------
  return irc;

}
 

//================================================================
  int TSU_stps_sur (ObjGX *ox_stps, long dbi, Memspc *wrkSpc) {
//================================================================
// get TPS-surface from any surface
// Input:
//   ox_sur       surface to handle
// Output:
//   ox_stps     trimmed-perforated-supported from ox_sur


  int     irc;
  long    dbob;
  ObjGX   *ox_sur, *oxTab;


  printf("TSU_stps_sur %ld\n",dbi);


  ox_sur = DB_GetSur (dbi, 1);
  if(!ox_sur->typ) return -1;
    UT3D_stru_dump (Typ_ObjGX, ox_sur, "TSU_stps_sur");



  //================================================================
  // Typ_SURTPS = already surface-trimmed-perforated-supported; OK.
  // see APT_decode_su_pln ..
  if((ox_sur->typ == Typ_SURTPS) ||
     (ox_sur->typ == Typ_SURBSP))   {
    *ox_stps = *ox_sur;
    return 0;
  }

  //================================================================
  // Typ_SURBSP = supportsurface untrimmed unperforated , B_Spline_Surf (SurBSpl)
  // create boundary ..  was TSU_DrawSurBsp GL_sSym_sbsp
  if(ox_sur->typ == Typ_SURBSP) {

    // get space for 2 ObjGX
    oxTab = UME_reserve (wrkSpc, sizeof(ObjGX) * 2);
    if(oxTab == NULL) return -1;

    // ox[0] = supporting-surface Typ_SURBSP (SurBSpl)
    OGX_SET_INDEX (&oxTab[0], Typ_SURBSP, dbi);

    // get outer-boundary CurvCCV = 4 x CurvBSpl
    irc = TSU_cv_sbsp (&dbob, ox_sur);
    if(irc < 0) return -1;
    OGX_SET_INDEX (&oxTab[1], Typ_CVTRM, dbob);
    // ox[1] = outer-boundary
    // oxTab[1] = .;

    ox_stps->typ    = Typ_SURTPS;
    ox_stps->form   = Typ_ObjGX;
    ox_stps->siz    = 2;
    ox_stps->data   = oxTab;
    return 0;
  }



  //================================================================
  TX_Error("TSU_stps_sur sur NYI form=%d",ox_sur->form);
  return -1;

}


//================================================================
  int TSU_cv_sbsp (long *dbi, ObjGX *ox_sbsp) {
//================================================================
// get outer-boundary CurvCCV = 4 x CurvBSpl
// Input:
//   sbsp      Typ_SURBSP SurBSpl


  UT3D_stru_dump (Typ_ObjGX, ox_sbsp, "TSU_stps_sur");


  L_err:
  TX_Error("TSU_cv_sbsp E001");
  return -1;

}

 
//================================================================
  int TSU_test_tess__ (long dbi, int att, Memspc *tbuf1) {
//================================================================
// TSU_test_tess__        testprog tesselation
// tesselate, display, save as binary-suface-file
// Input:
//   dbi         DB-Index of surface
//   att
//   tbuf1       for temporary usage
//
//

  int       irc;

#ifdef _MSC_VER
const MemTab(void) MEMTAB_NUL = { NULL, 0, 0, 0 }; //_MEMTAB_NUL;
  TessDat__ td1;
  TessStru  ts1;
  //
  td1.gbx = GRIDBOX_NUL;
  ts1.fmt = *((MemTab_IndTab*)&MEMTAB_NUL);    // IndTab
  ts1.pst = *((MemTab_char*)&MEMTAB_NUL);      // char
  ts1.ipa = *((MemTab_int*)&MEMTAB_NUL);       // int
  ts1.pa2 = *((MemTab_Point*)&MEMTAB_NUL);
  ts1.pa3 = *((MemTab_Point*)&MEMTAB_NUL);
  ts1.bnd = *((MemTab_IndTab*)&MEMTAB_NUL);    // IndTab
  ts1.vcz = UT3D_VECTOR_NUL;

#else
  // C99
  TessDat__ td1 = {.gbx = GRIDBOX_NUL};
  TessStru  ts1 = {.fmt = _MEMTAB_NUL,    // IndTab
                   .pst = _MEMTAB_NUL,    // char
                   .ipa = _MEMTAB_NUL,    // int
                   .pa2 = _MEMTAB_NUL,
                   .pa3 = _MEMTAB_NUL,
                   .bnd = _MEMTAB_NUL,    // IndTab
                   .vcz = UT3D_VECTOR_NUL};
#endif


  printf("============================================ \n");
  printf("TSU_test_tess__ dbi=%ld att=%d\n",dbi,att);


  // get surf out of DB 
  td1.oxs = DB_GetSur (dbi, 1);
  if(!td1.oxs->typ) return -1;
    UTO_dump_s_ (td1.oxs, "n-DB_GetSur");


  ts1.dbi  = dbi;
  ts1.mdli = WC_modact_ind;


  //----------------------------------------------------------------
  // get ssTyp = surfacetype of ObjGX; 
  // get ssDbi = dbi of support-surface; (not for planar)
  irc = UTO_surfTyp_sur (&td1.ssTyp, &td1.ssDbi, &td1.ssDat, td1.oxs);
  if(irc < 0) return -1;
    printf(" ssTyp=%d ssDbi=%ld\n",td1.ssTyp,td1.ssDbi);


  //----------------------------------------------------------------
  switch(td1.ssTyp) {

    //----- supportSurfaces ------------------------------------------
    // supportSurfaces are not trimmed, not perforated;
    // tesselate as stripes or fan manually
    case Typ_SURBSP:
      // supportSurface only; tesselate as stripes or fan manually
      irc = TSU_test_tess_SS_BSP__ (&ts1, &td1);
      break;

    case Typ_SURSWP:
      irc = TSU_test_tess_SS_SWP__ (&ts1, &td1, tbuf1);
      break;


    // case Typ_SURRBSP:
    // case Typ_SURRV:
// Typ_SURRV  (SurRev*) RevolvedSurface
    // case Typ_SURRU:
// Typ_SURRU  contour + contour|vector|point; (Ruled)
      break;


    //----- trimmed-supported-surfaces ------------------------------------------
    case Typ_SURPLN:
      // planar, with outer-boundary, opttinally holes, no supportSurface
      irc = TSU_test_tess_PLN__ (&ts1, &td1);
      break;

    case Typ_SURTPS:
      TX_Error("TODO TSU_test_tess__ Typ_SURTPS"); return -1;
      // TSU_test_tess_TPS
      // break;

    default:
      TX_Error("TSU_test_tess__ E1-%d",td1.ssTyp);
      return -1;
  }
  if(irc < 0) goto L_exit;


  //----------------------------------------------------------------
  // display or store
  L_disp:
  if(TSU_mode == 0) {
    TSU_dli = DL_StoreObj (Typ_SUR, dbi, att);
    // display tesselated faces (using fmt pmt ipa pta)
    GR_Draw_iSur (&TSU_dli, att, &ts1.fmt, &ts1.ipa, &ts1.pa3);

  } else {
    // iSur -> Sur
    Tess_bMsh_iMsh (&ts1.fmt, &ts1.ipa, &ts1.pa3);
    // TSU_store (gSur);
  }


  // save into file binary
  irc = TSU_wrf__ (&ts1);



  //----------------------------------------------------------------
  L_exit:

  MemTab_free (&ts1.bnd);
  MemTab_free (&ts1.pa3);
  MemTab_free (&ts1.pa2);
  MemTab_free (&ts1.ipa);
  MemTab_free (&ts1.pst);
  MemTab_free (&ts1.fmt);


  return irc;

}


//================================================================
  int TSU_test_tess_PLN__ (TessStru *ts1, TessDat__ *td1) {
//================================================================
// planar, with outer-boundary, optionally holes, no supportSurface
// was TSU_init_pln 

  int    irc, cNr, cAct, cTyp, bTyp, ptNr, ips, iis;
  long   bDbi, ld;
  char   c1;
  Point  *pa;
  Plane  pl1;
  ObjGX  *oxa, *oxb;
  IndTab cnt1;


  printf("TSU_test_tess_PLN__ td1->ssTyp=%d\n",td1->ssTyp);


  //----------------------------------------------------------------
  // add all boundies into ts1->pa3 and get normalvector -> ts1->vcz
  // add outer-boundary-records -> ts1->bnd
  // add all links into ts1->ipa

  oxa = td1->oxs->data;   // table of surface-objects (supp,OB,IB's)
  cNr = td1->oxs->siz;    // nr of contours
  cAct = 1;               // 1=OB
  cTyp = MSH_EDGLN_OB;

// TODO woher ptNr ?? (nr of points of all bounds) ?
    printf(" cNr=%d ptNr=%d\n",cNr,ptNr);

  // get space in pa3 and ipa and pst
  MemTab_ini (&ts1->bnd, sizeof(IndTab), Typ_IndTab, cNr);
  MemTab_ini (&ts1->pa3, sizeof(Point), Typ_PT, ptNr);
  MemTab_ini (&ts1->ipa, sizeof(int), Typ_Int4, ptNr * 2);
  MemTab_ini (&ts1->pst, sizeof(char), Typ_Int1, ptNr);



  L_nxt_cnt:
    // get oxb = next boundary
    oxb = &oxa[cAct];

    // get bDbi = dbi for outer-boundary
    if(oxb->form == Typ_Index) {
      OGX_GET_INDEX (&bTyp, &bDbi, oxb);
    } else {
      TX_Error("TSU_test_tess_PLN__ E1");
      return -1;
    }
      printf("--- cAct=%d  bTyp=%d bDbi=%ld\n",cAct,bTyp,bDbi);

    // get points ..
    irc = PRCV_npt_dbo__ (&pa, &ptNr, bTyp, bDbi, WC_modact_ind);
    if(irc < 0) {TX_Error("TSU_test_tess_PLN__ E2");return -1;}
      // GR_Disp_pTab (ptNr, pa, SYM_STAR_S, 2);


    // get ips = next free position of points in pa2
    ips = MEMTAB_IND (&ts1->pa3);
      printf("    cAct=%d ptNr=%d ips=%d\n",cAct,ptNr,ips);


    // compute Z-Vektor for planar (normal-vector to boundary)
    // only for outer-boundary
    if(cTyp == MSH_EDGLN_OB) {
      irc = UT3D_pl_pta (&pl1, ptNr, pa);
      if(irc < 0) return irc;
      ts1->vcz = pl1.vz;
        UT3D_stru_dump (Typ_VC, &ts1->vcz, "  vcz");
    }

    // copy points -> pa3
    irc = MemTab_add (&ts1->pa3, &ld, pa, ptNr, 0);
    if(irc < 0) return irc;


    // add all links into ipa 
    iis = TSU_init_ipa_add (ptNr, ips, ts1);
    if(iis < 0) return -1;


    // add point-status 2 to pst
    c1 = 2;
    irc = MemTab_add (&ts1->pst, &ld, &c1, ptNr, 4);
    if(irc < 0) return irc;


    // add outer-boundary-record -> ts1->bnd
    cnt1.ibeg = iis;    // startindex in ipa
    cnt1.iNr  = ptNr;   // nr of points
    cnt1.typi = cTyp;   // MSH_EDGLN_OB|MSH_EDGLN_IB
    cnt1.aux  = 0;      // unused
    irc = MemTab_add (&ts1->bnd, &ld, &cnt1, 1, 0);
    if(irc < 0) return irc;

      // MemTab_dump (&ts1->bnd, "bnd-2");


    ++cAct;
    cTyp = MSH_EDGLN_IB;
    if(cAct < cNr) goto L_nxt_cnt;


      // TESTBLOCK
      MemTab_dump (&ts1->bnd, "bnd-1");
      // MemTab_dump (&ts1->pst, "pst-1");
      // GR_Disp_pTab (ts1->pa2.rNr, ts1->pa2.data, SYM_STAR_S, 2);
      printf(" -TSU_init_pln-0\n");
      // END TESTBLOCK



  //----------------------------------------------------------------
  // orient contours (outer-boundary CCW, inner-boundaries CW)
  // boundaries ts1->bnd
  irc = SUP_cvcnt_orient__ (&ts1->bnd, ts1->pa3.data, &ts1->vcz);
  if(irc < 0) return -1;


  //----------------------------------------------------------------
  // tesselate, using GLU_tess__

  // get spc for fmt
  MemTab_ini (&ts1->fmt, sizeof(IndTab), Typ_IndTab, (ptNr/3) + 16);

  // vcz: only for planar; else NULL.
  irc = GLU_tess__ (&ts1->fmt, &ts1->pst, &ts1->ipa, &ts1->pa3, &ts1->bnd,
                    &td1->gbx, &ts1->vcz);
  if(irc) {
    TX_Print ("**** GLU_tess__ error %d A%ld", irc, ts1->dbi);
    return -1;
  }

  return 0;

}


//===========================================================================
  int TSU_test_tess_SS_SWP__ (TessStru *ts1, TessDat__ *td1, Memspc *tbuf1) {
//===========================================================================
// Typ_SURSWP (SurBSpl*) Sweep-Surface (eg Cylinder ..)
// tesselate as stripes or fan manually
// was ?
//   tbuf1       for temporary usage
    
#define P_SIZ 2000
  int      irc, bTyp, ptNr, bForm, bNr;
  long     bDbi;
  Point    *pa;
  CurvCCV  *bDat;


  printf("TSU_test_tess_SS_SWP__ td1->ssTyp=%d\n",td1->ssTyp);
    

  // get outer-boundary = second subObj of complex-obj oSur
  TSU_dboOB_oSur (&bTyp, &bDbi, td1->oxs);
    printf(" bTyp=%d bDbi=%ld\n",bTyp,bDbi);

  // get data for OB-link
  bForm = DB_GetObjDat ((void**)&bDat, &bNr, bTyp, bDbi);
  if(bForm != Typ_CVTRM) {TX_Error("TSU_test_tess_SS_SWP__ E1");return -1;}


  // boundary of Sweep is a CCV; get 1. and 3. subCurve
    UT3D_stru_dump (Typ_CVTRM, &bDat[0], " bDat[0]");
  // Input: dbTyp, dbi  of CCV;
  // Output: trimmedCurve.

  // get polygon of trimmedCurve.
  // irc = PRCV_npt_trmCv (&pa, &ptNr, &bDat[0]);
  // get space in pa for pSiz points
  pa = (Point*) MEM_alloc_tmp (P_SIZ * sizeof(Point));
  ptNr = 0;
  irc = UT3D_npt_obj (&ptNr, pa, P_SIZ, Typ_CVTRM, &bDat[0], 1, UT_DISP_cv, 2);
  if(irc < 0) return irc;
    GR_Disp_pTab (ptNr, pa, SYM_STAR_S, 2);
    GR_Disp_txi (pa, ptNr, ATT_COL_BLACK);

  irc = PRCV_npt_trmCv (&pa, &ptNr, &bDat[2]);
  if(irc < 0) return irc;
    GR_Disp_pTab (ptNr, pa, SYM_STAR_S, 2);
    GR_Disp_txi (pa, ptNr, 5);


/*
  // get boundary (bnd)
  irc = PRCV_npt_dbo__ (&pa, &ptNr, bTyp, bDbi, WC_modact_ind);
  if(irc < 0) {TX_Error("TSU_test_tess_SS_SWP__ E2");return -1;}
    GR_Disp_pTab (ptNr, pa, SYM_STAR_S, 2);


  // get space in pa3 and ipa and pst
  // MemTab_ini (&ts1->bnd, sizeof(IndTab), Typ_IndTab, cNr);
  // MemTab_ini (&ts1->pa3, sizeof(Point), Typ_PT, ptNr);
  // MemTab_ini (&ts1->ipa, sizeof(int), Typ_Int4, ptNr * 2);
  // MemTab_ini (&ts1->pst, sizeof(char), Typ_Int1, ptNr);




  //----------------------------------------------------------------
  // get faces (fmt)


  // tesseleate  2 stripes of points;
*/

  return -1;

}


//================================================================
  int TSU_test_tess_SS_BSP__ (TessStru *ts1, TessDat__ *td1) {
//================================================================
// Typ_SURBSP (SurBSpl*) B-Spline-Surface (Loft)
// tesselate as stripes or fan manually
// was ?

  printf("TSU_test_tess_SS_BSP__ td1->ssTyp=%d\n",td1->ssTyp);


  //----------------------------------------------------------------
  // if one of the curves is a point; make fan
  // was GR_DrawTriaFan
  // return TSU_test_tess_SS_BSP_f (ts1, td1);


  //----------------------------------------------------------------
  // 2 curves - make strip.
  // was TSU_DrawSurBsp
  return TSU_test_tess_SS_BSP_s (ts1, td1);

}


//================================================================
  int TSU_test_tess_SS_BSP_f (TessStru *ts1, TessDat__ *td1) {
//================================================================
// Typ_SURBSP (SurBSpl*) B-Spline-Surface (Loft) from curve + point
// tesselate as fan manually
// was TSU_DrawSurBsp

  printf("TSU_test_tess_SS_BSP_f td1->ssTyp=%d\n",td1->ssTyp);

  return -1;
}


//================================================================
  int TSU_test_tess_SS_BSP_s (TessStru *ts1, TessDat__ *td1) {
//================================================================
// Typ_SURBSP (SurBSpl*) B-Spline-Surface (Loft) from 2 curves
// tesselate as stripes manually
// was TSU_DrawSurBsp

  int       irc, iu, iv, ptNr;
  long      ld;
  double    du, dv;
  SurBSpl   *sbsp;
  Memspc    wrkSpc;


  printf("TSU_test_tess_SS_BSP_s td1->ssTyp=%d\n",td1->ssTyp);


  //----------------------------------------------------------------
  // symbolic:
  // was GL_sSym_sbsp


  //----------------------------------------------------------------
  // find 2D-tolerance, parameter-offsets in u and v
  // get parameter-offsets in u and v
  UME_init (&wrkSpc, memspc53, sizeof(memspc53));
  sbsp = td1->ssDat;
  // get nr of rows,columns for grid of points with tolerance < UT_DISP_cv
  UT3D_uvNr_sbsp (&iu, &iv, sbsp, &wrkSpc);
  ptNr = iu * iv;
    printf("  ptNr=%d iu=%d iv=%d\n",ptNr,iu,iv);

  td1->gbx.ix = iu;
  td1->gbx.iy = iv;


  //----------------------------------------------------------------
  // create 3D-gridBox with all points in pa3
  MemTab_ini (&ts1->pa3, sizeof(Point), Typ_PT, ptNr + 16);

  // td1->ipgbx = startIndex in pa3
  td1->ipgbx = MEMTAB_IND (&ts1->pa3);

  // reserve space for ptNr points in pa3
  irc = MemTab_add (&ts1->pa3, &ld, NULL, ptNr, 1);
  if(irc < 0) return irc;

  // get startPosition for 3D-points
  td1->p3Dgbx = MEMTAB__ (&ts1->pa3, td1->ipgbx);

  // create 3D-gridBox with all points
  UME_init (&wrkSpc, memspc53, sizeof(memspc53));
  irc = UT3D_ptgrid_sbsp (td1->p3Dgbx, NULL, NULL, &du, &dv,
                          sbsp, iu, iv, &wrkSpc);
  if(irc < 0) return -1;     

      // TESTBLOCK
      printf("  du=%f dv=%f iu=%d iv=%d\n",du,dv,iu,iv);
      // display ?
      // GR_Disp_pTab (ptNr, td1->p3Dgbx, SYM_STAR_S, 2);
      // END TESTBLOCK



  //----------------------------------------------------------------
  // create links in ipa

  // get memSpc for point-indextables
  MemTab_ini (&ts1->ipa, sizeof(int), Typ_Int4, ptNr * 6);

  // add links to gridPoints in ipa
  // td1->ipgbx = index of 1. point in ts1->pa3
  TSU_init_ipa_add (ptNr, td1->ipgbx, ts1);


      // TESTBLOCK
      MemTab_dump (&ts1->ipa, "ipa-1");
      // END TESTBLOCK


  //----------------------------------------------------------------
  // tesselate; create faces from gridpoints;

  // get memSpc for tesselated-faces
  MemTab_ini (&ts1->fmt, sizeof(IndTab), Typ_IndTab, ptNr / 3);


  // loop tru all rows, create stripes (GL_TRIANGLE_STRIP)
  TSU_tess_add_grid (ts1, td1);


  //----------------------------------------------------------------
  // display or store
  // was GR_DrawTriaStrip
// see GR_Draw_iSur

  return 0;

}


//=================================================================
  int TSU_tess_add_grid (TessStru *ts1, TessDat__ *td1) {
//=================================================================
// create faces from gridpoints;
// loop tru all rows, create stripes (GL_TRIANGLE_STRIP)
// see GL_Disp_ipatch TSU_ntria_bMsh_p


  int   i1, i2, ii, iu, iv, ip1, ip2, *ia;


  iu = td1->gbx.ix;
  iv = td1->gbx.iy;
  ia = MEMTAB_DAT (&ts1->ipa);   // get int-table

  printf("TSU_tess_add_grid %d %d\n",iu,iv);

  // set primary index into ipa
  ii = 0;
  ip2 = ia[ii];

  
  for(i1=1; i1<iv; ++i1) {
    ii += iu;
    // set ip1 = index startpoint of 1. row
    ip1 = ip2;
    // set ip2 = index startpoint of 2. row
    ip2 = ia[ii];
    // create / add GL_TRIANGLE_STRIP
    TSU_tess_add_iSTRIP (ip1, ip2, iu, ts1);
  }


    // TESTBLOCK
    // GR_Disp_iSur (att, &fmt, &ipa, &pas1);
    // END TESTBLOCK

  return 0;

}


//====================================================================
  int TSU_tess_add_iSTRIP (int ip1, int ip2, int iNr, TessStru *ts1) {
//====================================================================
// create / add GL_TRIANGLE_STRIP
// - add the indices to ts1->ipa
// - add a record to ts1->fmt
// Input:
//   iNr     nr-of-points-per-row
//   ip1     first index of row1 in ts1->ipa
//   ip2     first index of row2 in ts1->ipa
//
//
//    20-21-22-23
//    | /| /| /|
//    |/ |/ |/ |
//    10-11-12-13
//
// 20 10 21 11 22 12 23 13


// see GL_Disp_ipatch TSU_ntria_bMsh_p


  int    irc, ii, ie, fNr, pNr, ipTot, *ia, *ipa1, *ipa2;
  long   l1;
  IndTab fa;


  printf("TSU_tess_add_iSTRIP %d %d %d\n",ip1,ip2, iNr);

  // set fNr = nr of triangles from nr-of-points-per-row
  fNr = (iNr -1) * 2;
  // set ipTot = nr of indexes for strip
  ipTot = fNr + 2;
  // last index
    // printf(" fNr=%d ipTot=%d\n",fNr,ipTot);


  // get space for ipTot indices
  ia = (int*) MEM_alloc_tmp (ipTot * sizeof(int));

  // get startpoints of index-array for row1, row2
  ipa1 = MEMTAB__ (&ts1->ipa, ip1);
  ipa2 = MEMTAB__ (&ts1->ipa, ip2);
    // printf(" ipa1: ");for(ii=0;ii<iNr;++ii){printf("%d ",ipa1[ii]);}i
    // printf("\n");
    // printf("ipa2:");for(ii=0;ii<iNr;++ii){printf("%d ",ipa2[ii]);}
    // printf("\n");



  ii = 0;


  //----------------------------------------------------------------
  L_nxt:
    // populate indexarray ia
    ia[ii] = ipa2[0]; ++ii;
    ia[ii] = ipa1[0]; ++ii;
      // printf(" _iSTRIP-1 %d %d\n",ia[ii-2],ia[ii-1]);

    if(ii < ipTot) { 
      ++ipa1;
      ++ipa2;
      goto L_nxt;
    }


  //----------------------------------------------------------------
  // add the indices to ipa
  irc = MemTab_add (&ts1->ipa, &l1, ia, ipTot, 0);
  if(irc) {TX_Error("TSU_tess_add_iSTRIP E1");return -1;}


  // add a record to fmt
  fa.aux  = GL_TRIANGLE_STRIP;
  fa.typi = MSH_PATCH;
  fa.typd = 0;
  fa.ibeg = MEMTAB_IND (&ts1->ipa) - ipTot;
  fa.iNr  = ipTot;

  irc = MemTab_add (&ts1->fmt, &l1, &fa, 1, 0);
  if(irc < 0) {TX_Error("TSU_tess_add_iSTRIP E2");return -1;}

    // TESTBLOCK
    // MemTab_dump (&ts1->fmt, "fmt-2");
    // MemTab_dump (&ts1->ipa, "ipa-2");
    // GR_Disp_iSur (5, &ts1->fmt, &ts1->ipa, &ts1->pa3);
    // END TESTBLOCK


  return 0;

}
 

//================================================================
  int TSU_test_tess_TPS (long dbi, int att) {
//================================================================
// TODO: get gridpoints from support-surface <<<<<<<<<<<<<

// TSU_test_tess_TPS        testprog for GLU_tess__
// tesselate, display, save as binary-suface-file
// Input:
//   dbi         DB-Index of surface
//   att
//
//
//----------------------------------------------------------------
// Boundaries: bnd + ipa + pta;
//   bnd         one record in bnd = one boundary;
//   bnd.ibeg    index of first point in ipa; 
//   bnd.inr     nr of points of contour; last point must be same as first
//                last pointindex is (bnd.ibeg + bnd.inr - 1)
//   ipa         index into pta
//
//----------------------------------------------------------------
// Faces: fmt + ipa + pta + pst
//   fmt          one record in fmt = one patch;
//   fmt.ibeg     index of first point of patch in ipa;
//   fmt.inr      nr of points of patch;
//                last pointindex is (fmt.ibeg + fmt.inr - 1)
//   fmp.aux      GL_TRIANGLES|GL_TRIANGLE_STRIP|GL_TRIANGLE_FAN  (4-6)
//     typi=7 typd=70 stat=1 ?
//   
//   pst        boundary-flags for pmt-points
//                bitVal 8 point is used in fmt
//                bitVal 1 is in fmt and on boundary (added point)
//                bitVal 2 is used in bnd (is on primary boundary)
//                bitVal 4 is used in gridbox
//
//----------------------------------------------------------------
//  td1.gb3D    3D-point-grid in memspc102; for quicker computations.
//
// see GLU_tess__


  int    irc, ii, pNr, i1, i2;
  long   dli;
  double tol;

#ifdef _MSC_VER
// #define SFINIT(f,v) f = v
// TessDat__ td1 = {SFINIT(gbx, GRIDBOX_NUL)};
// #define _MEMTAB_NUL { NULL, 0, 0, 0 };
  TessDat__ td1;
  TessStru  ts1;
#
const MemTab(void) MEMTAB_NUL = { NULL, 0, 0, 0 }; //_MEMTAB_NUL;
  td1.gbx = GRIDBOX_NUL;
  ts1.fmt = *((MemTab_IndTab*)&MEMTAB_NUL);    // IndTab
  ts1.pst = *((MemTab_char*)&MEMTAB_NUL);      // char
  ts1.ipa = *((MemTab_int*)&MEMTAB_NUL);       // int
  ts1.pa2 = *((MemTab_Point*)&MEMTAB_NUL);
  ts1.pa3 = *((MemTab_Point*)&MEMTAB_NUL);
  ts1.bnd = *((MemTab_IndTab*)&MEMTAB_NUL);    // IndTab
  ts1.vcz = UT3D_VECTOR_NUL;
#else
  TessDat__ td1 = {.gbx = GRIDBOX_NUL};
  TessStru  ts1 = {.fmt = _MEMTAB_NUL,    // IndTab
                   .pst = _MEMTAB_NUL,    // char
                   .ipa = _MEMTAB_NUL,    // int
                   .pa2 = _MEMTAB_NUL,
                   .pa3 = _MEMTAB_NUL,
                   .bnd = _MEMTAB_NUL,    // IndTab
                   .vcz = UT3D_VECTOR_NUL};
#endif
 


  printf("============================================ \n");
  printf("TSU_test_tess_TPS dbi=%ld\n",dbi);

  // get surf out of DB 
  td1.oxs = DB_GetSur (dbi, 1);
  if(!td1.oxs->typ) return -1;
    UTO_dump_s_ (td1.oxs, "n-DB_GetSur");


  ts1.dbi  = dbi;
  ts1.mdli = WC_modact_ind;



  //----------------------------------------------------------------
  // get sTyp = surfacetype of ObjGX
  irc = UTO_surfTyp_sur (&td1.ssTyp, &td1.ssDbi, &td1.ssDat, td1.oxs);
  if(irc < 0) return -1;


  if(TSU_mode == 0) {  //0=disp; 1=store.
    td1.tol = UT_DISP_cv * 4;
  } else {
    td1.tol = UT_DISP_cv;
  }





  //----------------------------------------------------------------
  // estimate pNr = nr-of-points  for surface dbi / oxi
  pNr = TSU_ptNr_sur (Typ_ObjGX, td1.oxs, td1.tol);
  // Tess_ptNr_SURSWP
  pNr = 1000;
    printf(" pNr=%d\n",pNr);
// return -1;  // TEST ONLY

// &gb2D,



  //----------------------------------------------------------------
  // draw symbolic; done.
// TODO: att = ColRGB; extract TSU_sStyl ex ColRGB
  // col1 = COL_INT32(&att);   // col1 = (ColRGB*)&att;
// WAS IST WENN int 64 bits hat ?
    // // UT3D_stru_dump (Typ_Color, col1, "sur-col1");
  // TSU_sStyl = 0;            // 0=ON=shade; 1=OFF=symbolic
  // if(TSU_mode == 0)  {      // 0=draw; 1=store
    // if((APT_dispSOL == OFF) || (col1->vsym   == 1)) TSU_sStyl = 1;
  // }

  // if(TSU_sStyl > 0) return Tess_sSym__ (&td1, sTyp, sDat, att, dbi);



  //----------------------------------------------------------------
  // get memSpc for contours
  MemTab_ini (&ts1.bnd, sizeof(IndTab), Typ_IndTab, 100);

  // get memSpc for 2D-points - REALLOCATE NOT ALLOWED (OpenGL keeps pointers)
  MemTab_ini (&ts1.pa2, sizeof(Point), Typ_PT, pNr);

  // get memSpc for 3D-points
  if(td1.ssTyp != Typ_SURPLN)   // Planar is using pa2; not pa3
  MemTab_ini (&ts1.pa3, sizeof(Point), Typ_PT, pNr);

  // get memSpc for point-indextables
  MemTab_ini (&ts1.ipa, sizeof(int), Typ_Int4, pNr * 2);

  // get memSpc for point-flags
  MemTab_ini (&ts1.pst, sizeof(char), Typ_Int1, pNr);

  // get memSpc for tesselated-faces
  ii = pNr / 3;
  MemTab_ini (&ts1.fmt, sizeof(IndTab), Typ_IndTab, ii);


  //----------------------------------------------------------------
  // load 3D-outer- and inner-boundaries
  // find 2D-range = 3D-parameter-range (uMin, uMax, vMin, vMax)
  // find 2D-tolerance, parameter-offsets in u and v
  // create 2D-gridBox with all points according 2D-tolerance
  // add 2D-points > pa2; indices > imt.
  // create 3D-points for 2D-gridBox and add to > pa3;
  // was SUP_load_c Tess_sur_bnd__ TSU_tr_init_
  irc = TSU_init__ (&ts1, &td1);
    printf(" irc=%d\n",irc);
  if(irc < 0) goto L_exit;       // return -1;
    printf(" p2a-ind=%d\n",MEMTAB_IND (&ts1.pa2));

  // Testdisp. 3D-boundaries
  // GR_Disp_pTab (cTab[0].iNr, cTab[0].pa, SYM_STAR_S, 2);
  // for(i1=0; i1<cNr; ++i1)
  // GR_Disp_txi (&cTab[i1].pa[i2], i2, 0);



  //----------------------------------------------------------------
  // tesselate 2D; fill fmt, pst ..
  // vcz: only for planar; else NULL.
  L_tess:
  irc = GLU_tess__ (&ts1.fmt, &ts1.pst, &ts1.ipa, &ts1.pa2, &ts1.bnd,
                    &td1.gbx, &ts1.vcz);
  if(irc) {
    TX_Print ("**** GLU_tess__ error %d A%ld", irc, dbi);
      printf(" td1.ssTyp=%d\n",td1.ssTyp);
    goto L_exit;
  }

    // TESTBLOCK
    MemTab_dump (&ts1.fmt, "fmt-2");
    MemTab_dump (&ts1.ipa, "ipa-2");
    MemTab_dump (&ts1.pa2, "pa2-2");
    MemTab_dump (&ts1.pa3, "pa3-2");
    MemTab_dump (&ts1.pst, "pst-2");
    // GR_Disp_iSur (att, &ts1.fmt, &ts1.ipa, &ts1.pa2);
    // goto L_exit;
    // END TESTBLOCK



  //----------------------------------------------------------------
  // translate 2D-points created in GLU_tess__ into 3D
  // get 3D-points from 2D-points

  if(td1.ssTyp == Typ_SURPLN) {
    // planar: use pl2 for 3D.   
    ts1.pa3 = ts1.pa2;
    goto L_disp;
  }

  // translate 2D-points created in GLU_tess__ into 3D
  irc = TSU_init_tr_3D (&ts1, &td1);
  // if(irc < 0) goto L_exit;       // return -1;


/*
  // add all new points to p3D
  // make same nr of points for 2D and 3D
  i1 = MEMTAB_IND (&pta);
  i2 = MEMTAB_IND (&pas1); // nr of 3D-pts
  ii = i1 - i2;
  if(ii > 0) {
    irc = MemTab_add (&pas1, &ld, NULL, ii, 1);
    if(irc < 0) return irc;
  }
    // printf(" 2D-ptNr=%d 3D-ptNr=%d stat=%d\n",MEMTAB_IND(&pta),
           // MEMTAB_IND(&pas1), MEMTAB_IND(&pst));



  // get 3D-point from 2D-point
  i1 = MEMTAB_IND (&pta);
  pc1 = MEMTAB__ (&pst, 0);   // stat
  pa2 = MEMTAB__ (&pta, 0);    // 2D-pts
  pa3 = MEMTAB__ (&pas1, 0);    // 3D-pts


  // translate 3D <- 2D
  for(ii=0; ii<i1; ++ii) {
    // pst: 1=2D-val; 3=3D-val.
      // printf(" 2D_3D pas1[%d]=%d %d\n",ii,pc1[ii],BIT_GET(pc1[ii],4));
    // skip all unused points
    // test if 3D-coords already exist
    if(!(BIT_GET(pc1[ii],8))) continue;
    // translate 3D <- 2D ( Tess_tr_3D_2D_swp UT3D_pt_par_swp)
    td1.tr_3D_2D (&pa3[ii], &pa2[ii], td1.td);
  }
    // printf(" 2D-points: %d\n",i1);
    // printf(" 3D-points: %d\n",ii);
*/
    // Testdisp. 3D-faces
    // GR_Disp_iSur (att, &fmt, &ipa, &pas1);




  //----------------------------------------------------------------
  // display or store
  L_disp:
  if(TSU_mode == 0) {
    dli = DL_StoreObj (Typ_SUR, dbi, att);
    // display tesselated faces (using fmt pmt ipa pta)
    GR_Draw_iSur (&dli, att, &ts1.fmt, &ts1.ipa, &ts1.pa3);

  } else {
    // iSur -> Sur
    Tess_bMsh_iMsh (&ts1.fmt, &ts1.ipa, &ts1.pa3);
    // TSU_store (gSur);
  }


  // save into file binary
  TSU_wrf__ (&ts1);


  //----------------------------------------------------------------
  L_exit:

  MemTab_free (&ts1.bnd);
  if(td1.ssTyp != Typ_SURPLN)   // Planar is using pa2; not pa3
  MemTab_free (&ts1.pa3);
  MemTab_free (&ts1.pa2);
  MemTab_free (&ts1.ipa);
  MemTab_free (&ts1.pst);
  MemTab_free (&ts1.fmt);


  return irc;

}


//================================================================
  int TSU_ptNr_sur (int form, void *data, double tol) {
//================================================================
// estimate nr-of-points  for surface
// see also UT3D_ptNr_obj Tess_ptNr_SURSWP

  int   pNr;


printf("**** TODO TSU_ptNr_sur\n");
  UT3D_stru_dump (form, data, "TSU_ptNr_sur");


  // if(form == Typ_SURTPS) {
  // }









  pNr = 1000;

    printf(" ex-TSU_ptNr_sur\n");

  return pNr;

}


//================================================================
  int TSU_wrf__ (TessStru *ts1) {
//================================================================
// write mesh into file "[M<subModelNr>]A<surf#>.odat"
// Fileformat: recordNr's, recordSizes, MemTabs.
// see also PRCV_wrf__
 
  FILE      *fp1;
  char      ofid[128];
static char cTyp='A';


  printf("TSU_wrf__ %ld\n",ts1->dbi);



  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.odat",OS_get_tmp_dir(),cTyp,ts1->dbi);
  }
    printf(" ofid=|%s|\n",ofid);



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


  // write nr of records of fmt,pst,ipa,pta,bnd
  fwrite(&ts1->fmt.rNr, sizeof(int), 1, fp1);
  fwrite(&ts1->pst.rNr, sizeof(int), 1, fp1);
  fwrite(&ts1->ipa.rNr, sizeof(int), 1, fp1);
  fwrite(&ts1->pa3.rNr, sizeof(int), 1, fp1);
  fwrite(&ts1->pa2.rNr, sizeof(int), 1, fp1);
  fwrite(&ts1->bnd.rNr, sizeof(int), 1, fp1);

  // write size of records of fmt,pst,ipa,pta,bnd
  fwrite(&ts1->fmt.rSiz, sizeof(int), 1, fp1);
  fwrite(&ts1->pst.rSiz, sizeof(int), 1, fp1);
  fwrite(&ts1->ipa.rSiz, sizeof(int), 1, fp1);
  fwrite(&ts1->pa3.rSiz, sizeof(int), 1, fp1);
  fwrite(&ts1->pa2.rSiz, sizeof(int), 1, fp1);
  fwrite(&ts1->bnd.rSiz, sizeof(int), 1, fp1);


  // write fmt,pst,ipa,pta,bnd,vcz
  MemTab_wrf__ (&ts1->fmt, fp1);
  MemTab_wrf__ (&ts1->pst, fp1);
  MemTab_wrf__ (&ts1->ipa, fp1);
  MemTab_wrf__ (&ts1->pa3, fp1);
  MemTab_wrf__ (&ts1->pa2, fp1);
  MemTab_wrf__ (&ts1->bnd, fp1);
  fwrite(&ts1->vcz, sizeof(Vector), 1, fp1);

  fclose(fp1);



  return 0;

}


/*
//==============================================================================
  int TSU_sur_2Dgrid (double uMin, double vMin, TessStru *ts1, TessDat__ *td1) {
//==============================================================================
// compute all gridbox-points; add these points to ts1->pa2
// Input:
//   td1       get rx, ry (total range of 2D-space X and Y)
//             and dx, dy (minimum increment; same unit as total-range)
// Output:
//   pgb       pointer to gridbox
//
// Example rx,dx:  rx=RAD_360; dx=minAng from UT2D_angr_ciSec

// see TSU_tr_init_ Tess_sur_grd__


  int     irc, ips, ptNr;
  long    ld;
  Point   pt2Ds;


  ptNr = td1->gbx.ix * td1->gbx.iy;

  printf("TSU_sur_2Dgrid ptNr=%d\n",ptNr);
  UT3D_stru_dump (Typ_GridBox, &td1->gbx, " td1->gbx");


  // get index to next free 
  ips = MEMTAB_IND (&ts1->pa2);
    printf(" ips=%d\n",ips);

  // reserve space for ptNr points in pa3
  irc = MemTab_add (&ts1->pa2, &ld, NULL, ptNr, 1);
  if(irc < 0) return irc;

  // set startPosition (u0,v0) -> td1->gbx.p1
  pt2Ds.x = uMin;
  pt2Ds.y = vMin;
  pt2Ds.z = 0.;
  td1->gbx.p1 = &pt2Ds;

  // add points to ts1->pa2
  // Input from td1->gb2D: ix,iy,iz (nr of x-rows,y-rows,z-rows)
  //                       dx,dy,dz (row-offsets)
  //                       p1 (startPosition (u0,v0)
  ptNr = UT3D_grd_pta (&ts1->pa2, &td1->gbx);
  if(ptNr < 1) return -1;
    printf(" ptNr=%d\n",ptNr);

  // copy pointer to points -> gb.p1
  td1->gbx.p1 = MEMTAB__ (&ts1->pa2, ips);


      // TESTBLOCK
      GR_Disp_pTab (ptNr, td1->gbx.p1, SYM_STAR_S, 2);
      // END TESTBLOCK


  return 0;

}
*/


//================================================================
  int TSU_test_read (long dbiPln, long dbi) {
//================================================================
// read binary-suface-file, intersect
// see gis_ptab_save gis_etab_save UFA_fnb_dump__

 
  int      att;
  long     dli;
  TessStru ts1;


  printf("TSU_test_read dbi=%ld\n",dbi);

  // ts1 = read mesh for Surface <dbi>
  ts1.dbi  = dbi;
  ts1.mdli = WC_modact_ind;
  TSU_rdf__ (&ts1);


  // display
    // att = 5;
    // dli = DL_StoreObj (Typ_SUR, dbi, att);
    // GR_Draw_iSur (&dli, att, &ts1.fmt, &ts1.ipa, &ts1.pta);


  // test intersect
  TSU_test_intersect (dbiPln, &ts1);


  // if(ts1.ts1Spc)  free (ts1.ts1Spc);

  return 0;

}


//typedef_MemTab(Fac3);   ../ut/ut_face.h


//================================================================
  int TSU_test_intersect (long dbiPln, TessStru *ts1) {
//================================================================


  int          mSiz;
  Line         *lTab;
  Point        *pTab;
  Plane        *pl1;
  MemTab(Fac3) ifa = _MEMTAB_NUL;
  MemTab(Line) lna = _MEMTAB_NUL;


  printf("TSU_test_intersect \n");


  // ifa = get Indexed-faces from indexed-patches (fmt + ipa + pta)
  TSU_nfac_ipatch_ts1 (&ifa, ts1);


  // get plane
  pl1 = DB_get_PLN (dbiPln);


  // get space for (ifa->rNr) linesegments in lna
  mSiz = (ifa.rNr + 16) * sizeof(Line);      printf(" imSiz=%d\n",mSiz);
  lTab = (Line*) MEM_alloc_tmp (mSiz);
  MemTab_spc (&lna, lTab, mSiz, sizeof(Line), Typ_LN);


  // lna = intersect Indexed-faces ifa with plane pl1; eg S20=INT A20 R20
  pTab = ts1->pa3.data;
  INT_nln_nfac_pln (&lna, &ifa, pTab, pl1);


  MemTab_free (&ifa);


  return 0;

}


//================================================================
  int TSU_nfac_ipatch_ts1 (MemTab(Fac3) *ifa, TessStru *ts1) {
//================================================================
// get indexed-triangles from indexed-patches (fmt + ipa + pa3)
// see also TSU_ntria_bMsh_p

 
  int    irc, i1, i2, ii, fNr, *iTab;
  long   l1;
  IndTab *patAct;
  Fac3   *fTab;
  Point  *pTab;


  printf("TSU_nfac_ipatch_ts1 \n");

  pTab = ts1->pa3.data;
  iTab = ts1->ipa.data;

  // estimate nr of triangles (for memspc)
  fNr = TSU_facNr_ipatch (ts1);
    // printf(" fNr=%d\n",fNr);


  MemTab_ini (ifa, sizeof(Fac3), Typ_Fac3, 1000);

  // get space for fNr triangles
  // i1 = MEMTAB_IND (ifa);
  // fTab = MEMTAB__ (ifa,i1);
  irc = MemTab_add (ifa, &l1, NULL, fNr, 1);
  if(irc < 0) return irc;
    // MemTab_dump (ifa, "_facNr_ipatch-ifa-1");
  fTab = MEMTAB_DAT (ifa);



  // add indexed-triangles from patches
  // loop tru all patches of ts1
  ii = 0;
  for(i1=0; i1<ts1->fmt.rNr; ++i1) {

    // add triangles from patches
    patAct = MEMTAB__ (&ts1->fmt, i1);
      // printf(" glTyp=%d inr=%d\n",patAct->aux,patAct->iNr);

    i2 = ifa->rMax - ii; // max nr of faces
    irc = TSU_nfac_ipatch__ (&fTab[ii], &i2, patAct, iTab);
    if(irc < 0) return -1;
    ii += i2;
  }


    // TESTBLOCK
    // display indexed-triangles
    // MemTab_dump (ifa, "_facNr_ipatch-ifa-2");
    if(ii != ifa->rNr) printf("**** TSU_nfac_ipatch_ts1 E1\n");
    // MSH_test_disp_fb1
    for(i1=0;i1<ii;++i1) UFA_disp_fb1 (i1, fTab, pTab);
    // END TESTBLOCK



  return 0;

}


//================================================================
  int TSU_facNr_ipatch (TessStru *ts1) {
//================================================================
// get nr of triangles of indexed-patches using TessStru
// see UTRI_triaNr_patch

  int    i1, fNr;
  IndTab *patAct;


  // printf("TSU_facNr_ipatch \n");
  // MemTab_dump (&ts1->fmt, "_facNr_ipatch-fmt");


  fNr = 0;

  // loop tru all patches of ts1
  for(i1=0; i1<ts1->fmt.rNr; ++i1) {
 
    patAct = MEMTAB__ (&ts1->fmt, i1);
      // printf(" glTyp=%d inr=%d\n",patAct->aux,patAct->iNr);

    switch (patAct->aux) {

      case GL_TRIANGLES:
        fNr += patAct->iNr / 3;
        break;

      case GL_TRIANGLE_STRIP:
      case GL_FAC_PLANAR:
      case GL_TRIANGLE_FAN:
      case GL_QUAD_STRIP:
        fNr += patAct->iNr - 2;
        break;

      default:
        TX_Error("TSU_facNr_ipatch NYI typ=%d",patAct->aux);
        return -1;
    }

  }

    // printf("ex TSU_facNr_ipatch %d\n",fNr);
 

  return fNr;

}


//================================================================
  int TSU_rdf__ (TessStru *ts1) {
//================================================================
/// Input:
///   ts1->dbi
///   ts1->mdli
// see TSU_wrf__ PRCV_rdf__

  FILE      *fp1;
  long      bSiz;
  char      ofid[128];
  // void      *vp1;
  char      *vp1;
static char cTyp='A';

  printf("TSU_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.odat",OS_get_tmp_dir(),cTyp,ts1->dbi);
  }
    printf(" ofid=|%s|\n",ofid);


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

  // get nr-of-records of fmt,pst,ipa,pta,bnd
  fread(&ts1->fmt.rNr, sizeof(int), 1, fp1);
  fread(&ts1->pst.rNr, sizeof(int), 1, fp1);
  fread(&ts1->ipa.rNr, sizeof(int), 1, fp1);
  fread(&ts1->pa3.rNr, sizeof(int), 1, fp1);
  fread(&ts1->pa2.rNr, sizeof(int), 1, fp1);
  fread(&ts1->bnd.rNr, sizeof(int), 1, fp1);
    printf(" nr-of-records %d %d %d %d %d %d\n",ts1->fmt.rNr,ts1->pst.rNr,
            ts1->ipa.rNr,ts1->pa3.rNr,ts1->pa2.rNr,ts1->bnd.rNr);

  // get size-of-records of fmt,pst,ipa,pta,bnd
  fread(&ts1->fmt.rSiz, sizeof(int), 1, fp1);
  fread(&ts1->pst.rSiz, sizeof(int), 1, fp1);
  fread(&ts1->ipa.rSiz, sizeof(int), 1, fp1);
  fread(&ts1->pa3.rSiz, sizeof(int), 1, fp1);
  fread(&ts1->pa2.rSiz, sizeof(int), 1, fp1);
  fread(&ts1->bnd.rSiz, sizeof(int), 1, fp1);
    printf(" size-of-records %d %d %d %d %d %d\n",ts1->fmt.rSiz,ts1->pst.rSiz,
            ts1->ipa.rSiz,ts1->pa3.rSiz,ts1->pa2.rSiz,ts1->bnd.rSiz);


  // compute totalsize bSiz
  bSiz = 0L;
  bSiz += ts1->fmt.rNr * ts1->fmt.rSiz;
  bSiz += ts1->pst.rNr * ts1->pst.rSiz;
  bSiz += ts1->ipa.rNr * ts1->ipa.rSiz;
  bSiz += ts1->pa3.rNr * ts1->pa3.rSiz;
  bSiz += ts1->pa2.rNr * ts1->pa2.rSiz;
  bSiz += ts1->bnd.rNr * ts1->bnd.rSiz;
    printf(" bSiz=%ld\n",bSiz);


  // get memspc
  // ts1->ts1Spc = malloc(bSiz);


  // set data-space for fmt,pst,ipa,pta,bnd
  // vp1 = ts1->ts1Spc;
  ts1->fmt.data = (void*)vp1;
  ts1->fmt.rMax = ts1->fmt.rNr;

  vp1 += ts1->fmt.rNr * ts1->fmt.rSiz;

  ts1->pst.data = vp1;
  ts1->pst.rMax = ts1->pst.rNr;

  vp1 += ts1->pst.rNr * ts1->pst.rSiz;

  ts1->ipa.data = (void*)vp1;
  ts1->ipa.rMax = ts1->ipa.rNr;

  vp1 += ts1->ipa.rNr * ts1->ipa.rSiz;

  ts1->pa3.data = (void*)vp1;
  ts1->pa3.rMax = ts1->pa3.rNr;

  vp1 += ts1->pa3.rNr * ts1->pa3.rSiz;

  ts1->pa2.data = (void*)vp1;
  ts1->pa2.rMax = ts1->pa2.rNr;

  vp1 += ts1->pa2.rNr * ts1->pa2.rSiz;

  ts1->bnd.data = (void*)vp1;
  ts1->bnd.rMax = ts1->bnd.rNr;



  // get data
  MemTab_rdf__ (&ts1->fmt, fp1);
  MemTab_rdf__ (&ts1->pst, fp1);
  MemTab_rdf__ (&ts1->ipa, fp1);
  MemTab_rdf__ (&ts1->pa3, fp1);
  MemTab_rdf__ (&ts1->pa2, fp1);
  MemTab_rdf__ (&ts1->bnd, fp1);


  fclose(fp1);




  return 0;

}

/*
// get next esn; 1 -> 2; 2 -> 3; 3 -> 1.
int UFA_esn_nxt (int);
#define UFA_esn_nxt(esn) ((esn) > 2 ? 1 : esn + 1)
// get previous esn; 1 -> 3; 2 -> 1; 3 -> 2.
int UFA_esn_prv (int);
#define UFA_esn_prv(esn) ((esn) < 2 ? 3 : esn - 1)
*/

// get previous and next edge-sequence-nr; eg es=2 gives ep=1 and en=3
// void UFA_2esn_prvnxt (int *ep, int *en, int es);
// #define UFA_2esn_prvnxt(ep,en,es)\
 // {if(es<2){*ep=3;*en=2;}else if(es<3){*ep=1;*en=3;}else{*ep=2;*en=1;}}
// //   es=1                       es=2                    es=3


//================================================================
  int tst_surfaces (int ii) {
//================================================================
// general test ..
// retcod   0 exit and unload
//          1 do not unload
 

  int       irc, i1, i2, iNr, oNr, typ;
  double    d1, d2, d3;
  char      s1[400], *p1;
  int       triSiz, triNr, surSiz, surNr;
  int       sTyp[10];
  long      sTab[10], l1, dbi;
  ObjGX     *oTab=NULL, ox1;
  Triangle  *triTab;
  TypTsuSur *surTab;
  // Point2    p20={-4.03350,-65.62150}; // 1691
  // Point2    p21={-4.03750,-65.63950}; // 2138
  // Point2    p22={-2.46750,-65.68750}; // 1694
  // Point2    p23={9.55,50.6};
  // Point     p30={147.802,  -53.896,    0.000};
  // Point     p32={80., -50., 0.}, p33={50., 50., 0.};
  // Point     p32={50., -50., 0.}, p33={80., 50., 0.};
  // Point     p32={85., -50., 0.}, p33={115., 50., 0.};
  // Point     p32={80., -50., 0.}, p33={80., 50., 0.};      // NORMAL
  // Point     p32={0., 10., 0.}, p33={100., 10., 0.};         // PARALL
  // Point     p32={50., 0., 0.}, p33={120., 0., 0.};         // PARALL
  Point     p34, *pa;
  Vector2   v21={10., 0.};
  Vector2   v22={-15., 5.};
  Vector    v30={1., 0., 0.};
  // Vector    v32={1., 1., .0};
  // Vector    v32={0.866,    0.500, 0.};    // 30 deg
  // Vector    v32={0.707,    0.707, 0.};    // 45 deg
  Vector    v31={+0.500,   -0.866, 0.};    // 60 deg
  // Vector    v32={1.0,    1.72, 0.};    // 60 deg
  // Vector    v32={0.,    1., 0.};    // 90 deg
  // Vector    v32={-0.500,    0.866, 0.};    // 120 deg
  // Vector    v32={-0.707,    0.707, 0.};    // 135 deg
  // Vector    v32={-0.866,    0.500, 0.};    // 150 deg
  // Vector    v32={0., -1., 0.};  // 180 deg
  Vector    v32={0., 0., -1.};  // 180 deg
  Vector    vab, vcd;
  //               55.814,   76.822,    0.000,    // p1
  //             -155.238,  -50.440,    0.000,    // p2
  CurvElli  el1={ 200.000,    0.000,    0.000,    // p1
                   55.814,   76.822,    0.000,    // p2
                    0.000,    0.000,    0.000,    // pc
                    0.000,    0.000,    1.000,    // vz
                  200.000,    0.000,    0.000,    // va
                    0.000,   80.000,    0.000,    // vb
                   (short)0, (char)0, (char)0, (char)0 };  // srot,clo,uu1,uu2
  void      *obj;

  // FILE *fp;
  // int state = GL2PS_OVERFLOW, buffsize = 0, format, sort, opts, icol;
  // char ext[32], fNam[256];
  // GLint viewport[4];
  char fNam[256];


  //----------------------------------------------------------------
  {
    ObjGX ox1, ox_tps;
    int aus_typ[10], ausNr, iatt;
    long dbiSur, dbiPln;
    double aus_tab[10];
    Memspc wrkSpcT2, wrkSpcT1, wrkSpcP;
    ObjAto    ato1;

    // for obj's to store in DB (cpTab und wTab for curves ..)
    UME_init (&wrkSpcP, memspc501, sizeof(memspc501));
    // temp. obj's
    UME_init (&wrkSpcT1, memspc201, sizeof(memspc201));
    UME_init (&wrkSpcT2, mem_cbuf1, mem_cbuf1_SIZ); // 200000 b

    ATO_getSpc_tmp__ (&ato1, 12);


//----------------------------------------------------------------
// sweep-surf-cylindric;
    strcpy(s1,"CYL R(L23) 160 0 180 P31 P(L23 MOD(2))");
    ATO_ato_srcLn__ (&ato1, s1);
    irc = APT_decode_su_swp_cyl (&ox1, ato1.nr, ato1.typ, ato1.val, &wrkSpcP);
    if(irc < 0) return irc;
    dbiPln = 23L;
    goto L_start;


//----------------------------------------------------------------
// planar-surface Circ (test_sur_pln1.gcad):   replacing:
// APT_decode_spl    // Standardflaechen (planar, Conic, Torus
// NEW: store planar-surface as TPS-surface !
    // A20=C20 C21
    aus_typ[0] = Typ_CI;       aus_tab[0] = 20.;     ausNr = 1;
    aus_typ[1] = Typ_CI;       aus_tab[1] = 21.;     ausNr = 2;
    APT_decode_su_pln (&ox1, ausNr, aus_typ, aus_tab, &wrkSpcP);
    dbiPln = 20L;
    // goto L_start;



//----------------------------------------------------------------
// planar-surface polygon (test_sur_pln1.gcad):   replacing:
// APT_decode_spl    // Standardflaechen (planar, Conic, Torus
// NEW: store planar-surface as TPS-surface !
    // create ox1 = surf-planar
    aus_typ[0] = Typ_CV;       aus_tab[0] = 20.;     ausNr = 1;
    aus_typ[1] = Typ_CV;       aus_tab[1] = 21.;     ausNr = 2;
    APT_decode_su_pln (&ox1, ausNr, aus_typ, aus_tab, &wrkSpcP);
    dbiPln = 21L;
    // goto L_start;


//----------------------------------------------------------------
// planar-surface CCV (test_sur_pln1.gcad):   replacing:
// APT_decode_spl    // Standardflaechen (planar, Conic, Torus
// NEW: store planar-surface as TPS-surface !
    // create ox1 = surf-planar
    aus_typ[0] = Typ_CV;       aus_tab[0] = 23.;     ausNr = 1;
    // aus_typ[1] = Typ_CI;       aus_tab[1] = 23.;     ausNr = 2;
    APT_decode_su_pln (&ox1, ausNr, aus_typ, aus_tab, &wrkSpcP);
    dbiPln = 22L;
    // goto L_start;


//----------------------------------------------------------------
// B-Spline-Surface = support-surface  from curves along surface
// automatic created outer-boundary (
// was APT_decode_sbsp
// A20=BSP U(S21 S22 S23)
// Output  ox1->data:
//   ObjGX[0] supporting-surface (CON/TOR/SRU/SRV/SBS/Undef)
//   ObjGX[1] outer-boundary (CCV)
    aus_typ[0] = Typ_cmdNCsub; aus_tab[0] = T_BSP0;  ausNr = 1;
    aus_typ[1] = Typ_Group;    aus_tab[1] = 3;       ausNr = 1;
    aus_typ[2] = Typ_CV;       aus_tab[2] = 30.;     ausNr = 1;
    aus_typ[3] = Typ_CV;       aus_tab[3] = 31.;     ausNr = 2;
    aus_typ[4] = Typ_CV;       aus_tab[4] = 32.;     ausNr = 5;
    irc = APT_decode_sbsp_2 (&ox1, ausNr, aus_typ, aus_tab,
                             &wrkSpcP, &wrkSpcT1, &wrkSpcT2);
    dbiPln = 23L;
    if(irc < 0) return irc;


    //----------------------------------------------------------------
    // store as dyn-sur
    L_start:
    dbiSur = 20L;
    DB_StoreSur (&dbiSur, &ox1);   printf(" dbiSur=%ld\n",dbiSur);
      // GR_Disp_dbo (Typ_SUR, dbi, 9, 0);

// /*
    //------- old version: -------------------------------------------
//     // get surf out of DB 
//     oxp = DB_GetSur (dbiSur, 1);
//     if(!oxp->typ) return -1;
//     // UTO_dump_s_ (oxp, "n-DB_GetSur");
//     // tesselate & display
//     TSU_DrawSurTPS (oxp, dbiSur, 5);
// GR_DrawSur
//   UT_hatch__
//   TSU_DrawSurMsh     untrimmed unperforated Mesh
//   TSU_DrawSurBsp     untrimmed unperforated BSP-Sur
//   TSU_DrawSurRBsp
//   TSU_DrawRCIR       fan
//   GR_DrawStrip       stripe
//   Tess_sur__       sweep-surface
//   TSU_DrawSurT_
//     TSU_DrawSurTRU   ungetrimmte/ungelochte Ruled Flaeche
//     TSU_DrawSurTRV   ungetrimmte/ungelochte Revolved Flaeche
//     TSU_DrawSurTS    ungetrimmte/ungelochte Planare Flaeche
//     TSU_DrawSurTP    ungetrimmte/ungelochte Planare Flaeche
//     TSU_DrawSurTC    getrimmte/gelochte Complex-Flaeche
//   GL_sSym_sbsp
//   GL_sSym_srv
//   GL_sSym_spl        ungetrimmte/ungelochte Planare Flaeche
//   GL_sSym_spl        trimmed/punched surf
// 
//   SUP_load_c         load contours for TSU_DrawSurTC
// */

// /*
//     //------- new version: -------------------------------------------
//     // get ox_tps = TPS-surface from any surface
//     dbiSur = 20L;
//     irc = TSU_stps_sur (&ox_tps, dbiSur, &wrkSpcT1);
//     if(irc < 0) return irc;
// */


    //================================================================
    // TPS-surface: tesselate, display, save as binary-surface-file
    iatt = 5;
    UME_init (&wrkSpcT1, memspc201, sizeof(memspc201));
    irc = TSU_test_tess__ (dbiSur, iatt, &wrkSpcT1);
    if(irc < 0) return irc;


    // read binary-suface-file, intersect
    // TSU_test_read (dbiPln, dbiSur);


    // test outer-boundary of sur <dbiSur>
    TSU_test_OB__ (dbiSur);
  }



//================================================================
// /*
//   {
//     // Point    pt1={-98.320, -134.421,    0.000};  // C20
//     // Point    pt2={00.00, 100.000,    0.000};     // C21
//     Point   pb1, pb2;
//     CurvRBSpl *obj;
//     dbi = 12L;
// #define oaSIZ 10
//     ObjDB   parTab[oaSIZ];
// 
//     typ = DB_GetObjDat (&obj, &oNr, Typ_CV, dbi);
//       printf(" typ=%d\n",typ);
//     // UT3D_box_ini0 (&pb1, &pb2);
//     // UT3D_box_ln (&pb1, &pb2, (Line*)obj);
//     // cv1 = *(CurvPoly*)obj;
//     // cv1.v0  = 248.039;
//     // cv1.v1  = 24.558;
//     // cv1.dir = 1;
//     // UPLG_2par_iseg (&d1, &d2, 0, &cv1);
//     // UPLG_2par_iseg (&d1, &d2, 1, &cv1);
//     // UPLG_2par_iseg (&d1, &d2, 2, &cv1);
//     // d1 = 280.;
//     // d2 = 360.; 
//     // CVTRM__plg_2par (&cv1, &d1, &d2, dbi, (CurvPoly*)obj);
//     // i1=0;
//     // OPAR_get_src (&i1, parTab, oaSIZ, Typ_LN, 24L);
//     UT3D_ptNr_rbsp (&i1, obj, UT_DISP_cv);
//   }
// */
  //----------------------------------------------------------------
  // {
    // int      ptNr;
    // CurvBSpl cv1;
    // Point    pta[100];
    // typ = DB_GetObjDat (&obj, &oNr, Typ_CV, 20L);
    // cv1 = *(CurvBSpl*)obj;
    // cv1.v0 = 0.984481;
    // cv1.v1 = 1.;
    // UT3D_stru_dump (typ, &cv1, " cv1 ");
    // irc = UT3D_pta_bsp  (&ptNr, pta, &cv1, 100, UT_DISP_cv);
      // printf(" irc=%d ptNr=%d\n",irc,ptNr);
    // UT3D_nstru_dump (Typ_PT, ptNr, pta, "pta");
    // GR_Disp_pt (&pt1, SYM_STAR_S, ATT_COL_RED);

  // }
  //----------------------------------------------------------------
  {
  // CNTF_test__ ();
  // PRCV_test__ ();
  // i1 = UT___ptNr_ell (&el1, UT_DISP_cv);
  // i1 = 10;
  // pa = (Point*) MEM_alloc_tmp (i1 * sizeof(Point));
  // _npt_ell (i1, pa, &el1);
  // UT3D_npt_ell (i1, pa, &el1);
    // GR_Disp_cv (pa, i1, 8);

    // GR_Disp_ln2 (&p32,&p33,5);
    // irc =   _pt_int2pt2pt_lim(&p34, &d1,&d2, &p30,&p31,&p32,&p33,UT_TOL_pt);
    // printf(" irc=%d\n",irc);


    //----------------------------------------------------------------
    // PRCV_test__ ();
    return 1;
  }

  // test message
  // MSG_STD_ERR (func_not_impl, "E001 - %d",4);
  // return 0;

/*
  {
  int    sx, sy, dx, dy, typ, oNr;
  long   dbi, dli;
  double dsx, dsy, dsz;
  Point  p1, p2;

    dbi = 1L;
    dli = 0L;

    // get data for note l1
    typ = DB_GetObjDat (&obj, &oNr, Typ_Note, dbi);
      UT3D_stru_dump (typ, obj, " N1 ");

    // DL_txtgetInfo (&typ, &p1, &sx, &sy, &dx, &dy, dli);
    irc = GR_img_get_dbi (&typ, &p1, &sx, &sy, &dx, &dy, dbi);

      UT3D_stru_dump (Typ_PT, &p1, "p1");
      printf(" sx=%d sy=%d\n",sx,sy);
      GR_Disp_pt (&p1, SYM_STAR_S, ATT_COL_RED);


    // change Textpoint --> Screencoords
    GL_Uk2Sk (&dsx, &dsy, &dsz, p1.x, p1.y, p1.z);
      // printf(" LU(ScrCoords) dsx=%f dsy=%f dsz=%f\n",dsx,dsy,dsz);

    dsx += sx + dx;
    dsy += sy + dy;

    // change RO --> UserCoords
    GL_Sk2Uk (&p2.x, &p2.y, &p2.z,  dsx, dsy, dsz);
      GR_Disp_pt (&p2, SYM_STAR_S, ATT_COL_RED);
      // UT3D_stru_dump(Typ_PT, &p2, " RO=");

    // use RO
    // UT3D_box_extend (pb1, pb2, &p2);   ++pNr;


  } return 0;
*/

  //----------------------------------------------------------------
  // testdll__ (); return 0;
  goto L_test_func;
  goto L_test_ReScale;
  goto L_test_tess1;

{

  Point    pb1, pb2, pOri;
  Memspc   impSpc;


  // strcpy (fNam, "/mnt/serv1/Devel/GITHUB/gcad3d/gCAD3D/tmp/SERV_VR1_nor_frac_graphics_model_9.tess");
  // strcpy (fNam, "/mnt/serv1/Devel/GITHUB/gcad3d/gCAD3D/tmp/Data_warner1.tess");
  strcpy (fNam, "/mnt/serv1/Devel/GITHUB/gcad3d/gCAD3D/tmp/Data_samp_anilin.tess");
  // strcpy (fNam, "/mnt/serv1/Devel/GITHUB/gcad3d/gCAD3D/tmp/Data_Haus1.tess");
  // strcpy (fNam, "/mnt/serv1/Devel/GITHUB/gcad3d/gCAD3D/tmp/Data_unknown.tess");


  // load tess-model from file
  if(OS_checkFilExist (fNam, 1) == 0) return -1;
  TSU_imp_tess (&impSpc, fNam);

  // // find box of tess-model in memory
  // tess_box_get (&pb1, &pb2, &impSpc);

  // // get origin from box of tess-model
  // tess_origin_box (&pOri, &pb1, &pb2);

  // // subract origin of tess-model in memory
  // tess_origin_set__ (&impSpc, &pOri);

  // analyze tess-model
  tess_analyz__ (&impSpc);
  // tess_res_CB__ (&impSpc, DXFW_tess_CB);

  UME_free (&impSpc);

  return 1;

}


/*
  TX_Print ("XXXXXXXXXXXXX q=Quit, l=reLoad; u=unLoad;  tst__ %d\n",ii);
  printf("CXXXXXXXXXXXXXXXXXXXXXXXX  tst__ %d\n",ii);
    printf(" dll1=%p\n",dll1);
    printf(" UT3D_VECTOR_Y = %f %f %f\n",
           UT3D_VECTOR_Y.dx, UT3D_VECTOR_Y.dy, UT3D_VECTOR_Y.dz);


  // if(ii == 1) {
    // UI_PRI__ (FUNC_UNLOAD);
    // // i1 = _OS_dll__ (&dll1,  2, NULL); // unload
    // return 0;
  // }
// 
  // UI_PRI__ (FUNC_EXEC); // 0=start, 2=unload


  return 1;
  // do not yet unload (gui is active)
*/


//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// xa_print__.mak ../xa/print__.c
// xa_print_pdf.mak
// ../exp/print_pdf.c  int PRI_PDF__ (char* fnam)
  // i1 = OS_dll_do ("xa_print__", "PRI__", "abc");

  // i1 = OS_ck_SW_is_installed ("ps2pdf");
  // printf(" ps2pdf = %d\n",i1);
  // GUI_printer__ ("C:\Users\freiter\AppData\Roaming\gCAD3D\tmp\print.eps");
  // GUI_printer__ ("/mnt/serv1/Devel/GITHUB/gcad3d/gCAD3D/tmp/print.eps");


/*
//XXXXXX GL2PS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // see GL_Feedback
  // pdf svg tex eps
  sprintf(fNam, "%s.eps", "test");
  gl2ps_print3 (fNam, AP_mod_fnam, "gCAD3D", GL_Redraw);
    // GL_Redraw (); // display();   // redraw
*/



//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/*
  sprintf(s1, "%swin.bmp",OS_get_tmp_dir());
  sprintf(s2, "%swin.jpg",OS_get_tmp_dir());

  // create BMP-file of active OpenGL-window
  bmp_save__ (s1);
  // create JPG-file from BMP-file
  OS_jpg_bmp (s2, s1);
*/


//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/*
  // AP_print__ (); // test feedbackbuffer - out -> <tempDir>/print.tmp

  // AP_print_work3 ();
  // AP_print_psv3 (1, "0,0", "1", "2");
*/

  AP_print_work2 ();
  AP_print_psv2 (1, "0,0", "1", "2");
  // system("v /mnt/serv1/Devel/GITHUB/gcad3d/gCAD3D/tmp/print.eps");
return 0;



//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // irc = UT3D_pt_int2pt2pt_lim (&p34, NULL, NULL, &p30, &p31, &p32, &p33, 0.05);
  // printf(" irc=%d\n",irc);
  // UT3D_stru_dump (Typ_PT, &p34, "p34");

  // tst_tst_1 (&v31, &v32);

  // UT3D_vc_perp2vc (&v33, &v31, &v32);
  // UT3D_stru_dump (Typ_VC, &v33, "v33");

  // d1 = UT3D_angr_3vcn_CCW (&v33, &v31, &v32);
  // printf(" d1=%f %f\n",d1, UT_DEGREES(d1));

  // TX_Print(" plugin tst start ..");





//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  L_test_func:    printf("L_test_func: \n");
    {
      double d1;
      Point  pt1={-2985.076, 6834.254,    0.0};     // 0.09
      // Point  pt2={-2174.711, 9139.990,    0.0};     // 0.37
      // Point  pt2={3253.244, 9056.007,    0.000};
      // Point  pt2={-4834.796, 2087.975,   0.0};
      // Point  pt2={-4834.796, 2087.975,   0.0};
      // Point  pt2={-4834.796, 2087.975,   0.0};
      Point  pt2={-4834.796, 2087.975,   0.0};
      Circ   *ci1;
      ObjAto ato1;
      char   s1[256];

      // ci1 = DB_get_CI (21L);

      // ATO_getSpc__ (&ato1);
      strcpy(s1, "DISP_PT OFF");
      // ATO_wTab_str (&ato1, s1);
      printf("***** tst__ E- ATO_wTab_str\n");

    }
    return 0;



//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  L_test_ReScale:    printf("L_test_ReScale: \n");
    {
      Point  pb1, pb2;

      // get box of active model
      UT3D_box_mdl__ (&pb1, &pb2, -1);

      // view box
      DL_ReScale_box (&pb1, &pb2);

    }
    return 0;


//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  L_test_tess1:    printf("L_test_tess1: \n");


  sTyp[0] = Typ_SUR;
  // sTyp[0] = Typ_SOL;
  sTab[0] = 20L;

  TSU_tess_sTab (&oTab, sTyp, sTab, 1);

  // init
  ox1.typ = TYP_FuncInit;
  tess_analyz_CB (&ox1);


  // resolv all obj's, call tess_analyz_CB
  tess_res_CB__ (&oTab, tess_analyz_CB);


  // exit
  ox1.typ = TYP_FuncExit;
  tess_analyz_CB (&ox1);


/*
  // space for triangles --> triTab  (12bytes/Tria)
  triTab = (Triangle*)memspc501;
  triSiz = sizeof(memspc501) / sizeof(Triangle);
    printf(" triSiz=%d\n",triSiz);

  surTab = (TypTsuSur*)memspc51;
  surSiz = sizeof(memspc51) / sizeof(TypTsuSur);
    printf(" surSiz=%d\n",surSiz);

  // get triangles from spc1 --> triTab
  // (triangles are pointers into tesselated data !)
  surNr = surSiz;
  triNr = triSiz;
  irc = TSU_ntria_bMsh__ (surTab, &surNr, surSiz, triTab, &triNr, triSiz, oTab);
    printf(" _tsu2tria__ irc=%d surNr=%d triNr=%d\n",irc,surNr,triNr);

    // dump_Triangle
    // for(ii=0;ii<triNr;++ii) UT3D_stru_dump (Typ_Tria,&triTab[ii],"tria");
*/


  // free tesselated data
  TSU_free ();



  return 0;

}


//=========================================================
  int gCad_fini () {
//=========================================================
// dll being unloaded - reset Input, kill all open windows !!!

  printf("gCad_fini tst \n");

  TX_Print("---<<<<<< exit tst__ <<<<<<<---\n");

  // tst_ogl_reset ();
  // VcSel_exit ();

  AP_User_reset ();

  return 0;

}



//=========================================================
  int tst_sel_CB (int src, long dl_ind) {
//=========================================================
// userselection callback

  int   irc, typ;
  long  dbi;
  // char  so[512];
  char  *so;
  // ObjGX o1;


  printf("tst_sel_CB src=%d ind=%ld\n",src,dl_ind);

  return 0;

}


//=========================================================
  int tst_key_CB (int key) {
//=========================================================
// userKeyin callback


  printf("tst_key_CB %d\n",key);

  switch (key) {

    case GUI_KeyEsc:
    case 'q':
      // DL_hili_off (-1L);         //  -1 = unhilite all
      // DL_Redraw ();               // Redraw DispList
      gCad_fini ();
      // PED_CB1 (NULL, "Exit");
      break;

    case 'l':
      tst__ (0);
      break;

    case 'u':
      tst__ (1);
      break;

    case 't':
      printf(" GUI_Win_exist=%d\n",GUI_Win_exist ("Export/Print"));

      break;

  }

  return 0;

}


//================================================================
//================================================================
// PRCV ../ut/ut_prcv.c
//================================================================
//================================================================


/*
static int  PRCV_stat = -1;
static FILE *PRCV_fp   = NULL;
static int  PRCV_typ  = 0;
static long PRCV_dbi  = -1L;
static int  PRCV_mdli = 0;
static CurvPrcv PRCV_hdr;
*/


/* UNUSED
//================================================================
  int PRCV_get_dbo_0 (int *ptNr, int typ, long dbi, int mdli) {
//================================================================
// open and get first record of curve bDbi
// replace PRCV_rdf__
// TODO: *ptNr is total nr of points; for trimmed-curves not correkt !
// Input:
//   typ      type of DB-obj
//   dbi      DB-index
//   mdli     model-index
// Output:
//   ptNr     nr of points for DB-obj


  int      irc, i1, form, oNr;
  CurvCCV  *ccv1;
  char     ofid[128], cTyp;
  void     *obj;
  // FILE     *fp1;


  printf("PRCV_get_dbo_0 typ=%d dbi=%ld\n",typ,dbi);


  if((typ == PRCV_typ)&&(dbi == PRCV_dbi)&&(mdli == PRCV_mdli)) {
    // file alreaddy open; rewind; goto read
    rewind (PRCV_fp);

  } else {
    if(PRCV_fp) {
      fclose (PRCV_fp);
      PRCV_fp = NULL;
    }
  }


  // test for CCV (must resolv)
  if(typ != Typ_CV) goto L_get_basCv;




  //================================================================
  // resolv (group of) trimmed-curve(s)
  form = DB_GetObjDat (&obj, &oNr, typ, dbi);
    printf(" form=%d oNr=%d\n",form,oNr);
  if(form != Typ_CVTRM) goto L_get_basCv;


  for(i1=0; i1<oNr; ++i1) {

    // ccv1 = next trimmedCurve
    ccv1 = &((CurvCCV*)obj)[i1];
       printf("--------------------- CCV [%d] \n",i1);
       UT3D_stru_dump (Typ_CVTRM, ccv1, " ccv[%d]: ",i1);

    //----------------------------------------------------------------
    // add line
    if(ccv1->typ != Typ_LN) goto L_add_trCv;
    // get line from CCV and add it to output
    *ptNr += 2; //PRCV_get_dbo_add_ln (prc1, ccv1);
    goto L_cont;

    //----------------------------------------------------------------
    L_add_trCv:    // add trimmed curve
      // get PRCV of ccv1 from par ps to par pe to prc1
      // irc = PRCV_get_dbo_add_tc (prc1, ccv1);
      irc = PRCV_get_dbo_0 (ptNr, ccv1->typ, ccv1->dbi, mdli);
      if(irc < 0) return -1;

    L_cont:
      // TESTBLOCK
      printf(" -PRCV_get_dbo_0-L_cont: %d\n",*ptNr);
      // PRCV_dump__ (2, prc1, "nach ccv");
      // END TESTBLOCK
      continue;
  }

  goto L_exit;





  //================================================================
  // resolv basecurve - not yet trimmed; Circ, polygon, Ellipse, ..
  L_get_basCv:

  if(ccv1->typ == Typ_LN) {
    *ptNr += 2; // no PRCV for lines
    goto L_exit;
  }


  PRCV_typ = typ;
  PRCV_dbi = dbi;
  PRCV_mdli = mdli;

  if(PRCV_fp) goto L_read;


  // create filename for PRCV
  cTyp = AP_typChar_typ (PRCV_typ);  // 'S' | 'C'
  if(PRCV_mdli >= 0) {           // 0-n = sind in Submodel; -1=main
    sprintf(ofid,"%sM%d_%c%ld.odat",OS_get_tmp_dir(),cTyp,PRCV_mdli,PRCV_dbi);
  } else {
    sprintf(ofid,"%s%c%ld.odat",OS_get_tmp_dir(),cTyp,PRCV_dbi);
  }
    printf(" ofid=|%s|\n",ofid);


  // open
  if((PRCV_fp=fopen(ofid,"rb")) == NULL) {
    printf("**** PRCV_get_dbo_0 I001 |%s|\n",ofid);
    return -1;
  }


  // read 1. record
  L_read:
  fread(&PRCV_hdr, sizeof(CurvPrcv), 1, PRCV_fp);
    UT3D_stru_dump (Typ_PRCV, &PRCV_hdr, "_get_dbo_0");


  *ptNr += PRCV_hdr.ptNr;


  //================================================================
  L_exit:
  // fclose(fp1);
  PRCV_stat = 0;


    // TESTBLOCK
    printf("ex-PRCV_get_dbo_0 ptNr=%d\n",*ptNr);
    // END TESTBLOCK


  return 0;

}


//================================================================
  int PRCV_get_dbo_1 (Point *pa) {
//================================================================
// get Polygon from polygonal representation; (was SUP_addBound)
// must be called after PRCV_get_dbo_0

  
  if(PRCV_stat != 0) {printf("**** PRCV_get_dbo_1 E1\n");return -1;}



  fread(pa, sizeof(Point), PRCV_hdr.ptNr, PRCV_fp);
  // fread(prc->npar, sizeof(double), PRCV_hdr.ptNr, PRCV_fp);
  // fread(prc->nipt, sizeof(long), PRCV_hdr.ptNr, PRCV_fp);

  PRCV_stat = 1;


  return 0;

}
*/



//================================================================
//================================================================
// SUP  ../ut/ut_surstd.c
//================================================================
//================================================================


//================================================================
 int SUP_cvcnt_orient__ (MemTab(IndTab) *ncnt, Point *pTab, Vector *vcz) {
//================================================================
// was SUP_orient
 
  int    i1, idir, ipa, iNr, cNr, plMain;
  IndTab *iTab;
  Point  *pta;


  MemTab_dump (ncnt, " SUP_cvcnt_orient__");
  // UT3D_stru_dump (Typ_VC, vcz, " vcz");

  cNr = ncnt->rNr;

  // get main-BackPlaneNr
  plMain = UT3D_bp_vcz (vcz); // Berechnungsebene definieren
    // printf(" plMain=%d\n",plMain);



  for(i1=0; i1<cNr; ++i1) {

    iTab = MEMTAB__ (ncnt, i1);
      // UT3D_stru_dump (Typ_IndTab, iTab, " iTab[%d]",i1);

    iNr = iTab->iNr - 1;  // Anzahl Punkte ohne den letzten == ersten Punkt !
    // ipa = cTab[i1].ipa;
    pta = &pTab[iTab->ibeg];

    // // wenn keine Kontur vorhanden:
    // if(pta == NULL) continue;

    // get direction
    idir = UT3D_sr_polc (iNr, pta, vcz, plMain);
      // printf(" cnt %d dir %d\n",i1,idir);

    // all boundaries must be CCW
      if(idir < 0) {
          // printf(" ++++inv con %d\n",i1);
        UT3D_cv_inv (iNr+1, pta);
      }
  }


  return 0;

}


//================================================================
//================================================================
// ../ut/ut_memTab.c
//================================================================
//================================================================


//================================================================
  int MemTab_wrf__ (MemTab *mt, FILE *fp1) {
//================================================================
 

  // MemTab_dump (mt, "MemTab_wrf__");


  fwrite(mt, sizeof(MemTab), 1, fp1);

  fwrite(mt->data, mt->rSiz, mt->rNr, fp1);

  return 0;

}


//================================================================
  int MemTab_rdf__ (MemTab *mt, FILE *fp1) {
//================================================================
// read MemTab; dada-space must have enough space !
    
  void   *datSpc;
  int    rMaxNr;


  // keep datSpc (allready malloced)
  datSpc = mt->data;
  rMaxNr = mt->rMax;

  fread(mt, sizeof(MemTab), 1, fp1);

  if(mt->rNr > rMaxNr) {TX_Error("MemTab_rdf__ EOM"); return -1;}

  // reset datSpc (allready malloced)
  mt->data = datSpc;
  mt->rMax = rMaxNr;


  fread(mt->data, mt->rSiz, mt->rNr, fp1);
    // MemTab_dump (mt, "MemTab_rdf__");


  return 0;

}


//================================================================
  int TSU_test_OB__ (long dbiSur) {
//================================================================
// test outer-boundary of sur <dbiSur>
// surface also must create a dynamic boundary;



  int     irc, i1, typOB, OBnr, OBform, OBrSiz, ptNr;
  long    dbiOB;
  char    *data;
  ObjGX   *oSur;
  void    *OBdat;
  Point   *pta;


  printf("TSU_test_OB__ %ld\n",dbiSur);



  // get oxSur = complex-obj of surface <dbiSur>
  // get data for dbo
  oSur = DB_GetSur (dbiSur, 1);
  if(oSur->form != Typ_ObjGX) return -1;
  if(oSur->siz < 2) return -1;
    printf(" form=%d siz=%d\n",oSur->form,oSur->siz);
    UT3D_stru_dump (Typ_ObjGX, oSur, " oSur");



  // outer-boundary = second subObj of complex-obj oSur
  // irc = TSU_oOB_oSur (&OBform, &OBdat, &OBnr, oSur);
  irc = TSU_dboOB_oSur (&typOB, &dbiOB, oSur);
  if(irc < 0) return -1;


  //----------------------------------------------------------------
  // get PRCV-polygon for OB
  PRCV_npt_dbo__ (&pta, &ptNr, typOB, dbiOB, WC_modact_ind);
    // GR_Disp_cv (pta, ptNr, 8);

  return TSU_test_OB_1 (typOB, dbiOB);

}


//================================================================
  int TSU_test_OB_1 (int typOB, long dbiOB) {
//================================================================

  int     i1, OBform, OBnr, OBrSiz;
  char    *data;
  void    *OBdat;


  // get data for OB-link
  OBform = DB_GetObjDat (&OBdat, &OBnr, typOB, dbiOB);
  if(OBform < 0) return -1;
    printf(" OBform=%d OBnr=%d\n",OBform,OBnr);
    UT3D_nstru_dump (OBform, OBnr, OBdat, "  _OB-dat");


  OBrSiz = UTO_siz_stru (OBform);
    printf(" OBform=%d OBnr=%d OBrSiz=%d\n",OBform,OBnr,OBrSiz);

  // loop tru and display boundary-obj
  data = (char*)OBdat;
  for(i1=0; i1<OBnr; ++i1) {
      UT3D_stru_dump (OBform, (void*)data, " _OB_1-%d",i1);
      // display boundary-obj
      GR_Disp_obj (OBform, (void*)data, 8, 0);
    data += OBrSiz;
  }


  return 0;

}


//===================================================================
  int TSU_dboOB_oSur (int *obTyp, long *obDbi, ObjGX *oxSur) {
//===================================================================
// get outer-boundary = second subObj of complex-obj oSur
// get form, nr and data of OB
// Input:
//   oxSur is top-obj of a surface; its data is a group of DB-links (typ ObjGX);
//         1.=supportSurf, second = outer-boundary ..
// Output:
//   form  type of objects in data
//   data  objects of outer-boundary
//   oNr   nr of objects in data
 

  int     irc;
  ObjGX   *oTab, *oxOB;
  void    *odOB;


  // get oxOB = outer-boundary = second obj
  oTab = oxSur->data;
  oxOB = &oTab[1];
    UT3D_stru_dump (Typ_ObjGX, oxOB, " oxOB");

  // obj must be a link
  if(oxOB->form != Typ_Index) {TX_Error("TSU_oOB_oSur E1");return -1;}

  // resolv link
  OGX_GET_INDEX (obTyp, obDbi, oxOB);
    printf(" obTyp=%d obDbi=%ld\n",*obTyp,*obDbi);


  // // oxOB must be a CCV (Typ_CVTRM)|CI|CV
  // if(oxOB->typ != Typ_CVTRM) {
    // TX_Error("TSU_oOB_oSur E2");
    // return -1;
  // }


  // // Link to CCV:
  // // OB must be a DB-link; get data of DB-link
  // return DB_GetLinkDat (form, data, oNr, oxOB);

}

//================================================================
  int DB_GetLinkDat (int *form, void **lDat, int *lNr, ObjGX *ol) {
//================================================================
// get data of DB-link ol

  int  irc, lTyp;
  long lDbi;
  
  if(ol->form != Typ_Index) return -1;

  // resolv link
  OGX_GET_INDEX (&lTyp, &lDbi, ol);
    // printf(" lTyp=%d lDbi=%ld\n",lTyp,lDbi);

  *form = DB_GetObjDat (lDat, lNr, lTyp, lDbi);
  if(*form < 0) return -1;

    printf(" form=%d oNr=%d\n",*form,*lNr);
    UT3D_nstru_dump (*form, *lNr, *lDat, "  _GetLinkDat");

  return 0;

}


//======== EOF =========
