/* --------------------------------------------------------------------  */
/*                          CALCULIX                                     */
/*                   - GRAPHICAL INTERFACE -                             */
/*                                                                       */
/*     A 3-dimensional pre- and post-processor for finite elements       */
/*              Copyright (C) 1996 Klaus Wittig                          */
/*                                                                       */
/*     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; version 2 of           */
/*     the License.                                                      */
/*                                                                       */
/*     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.                      */
/*                                                                       */
/*     You should have received a copy of the GNU General Public License */
/*     along with this program; if not, write to the Free Software       */
/*     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.         */
/* --------------------------------------------------------------------  */



#include <cgx.h>


#define     TEST            0   /* debugging */

// so close must a point lie to an ambiguous edge to be considered as ambiguous 
#define TOL_AMBIG  1.e-2

extern Display       *dpy;
extern int           dpycells;
extern Colormap      cmap;
extern XColor        *xcolor;
extern unsigned long *pixels_return;
extern unsigned int  npixels;

extern GLfloat entity_r[SET_COLS];                     /* predefined colors of entities */
extern GLfloat entity_g[SET_COLS];
extern GLfloat entity_b[SET_COLS];

extern int   w0, w1;                                      /* Fenster identifier  */
extern int   activWindow;                                 /* das aktuelle Fenster */

extern int   width_w1, height_w1;
extern double trackbsize;                                  /* TRACKBALLSIZE */
extern double curquat[4];                                  /* Matrix aus Trackball */
extern double lastquat[4];                                 /* letzte Matrix aus Trackball*/

extern double     gtol;
extern Scale     scale[1];
extern int   steps;                                  /* Schrittweite der Farbscala */
extern int   offset, maxIndex;                       /* offset+steps-1 = maxIndex */
extern double dtx, dty, drx, dry, drz, ds;            /* Verschiebungen */
extern double centerPnt[3];                           /* Rotationszentrum */
extern double centerNode;               
extern double dx ,dy;                                 /* Mauskoordinaten im bereich +-1*/
extern int   xpixels ,ypixels;                       /* Mauskoordinaten in pixel, links unten 0,0 */
extern GLint   gl_max_eval_order;                         /* max order of NURBS */
extern GLdouble R[4][4];                                   /* Rotationsmatrix */
extern GLdouble dR[4][4];                                  /* dR= R-Rmem fuer center */
extern GLdouble Rmem[4][4];
extern double v[4];                                        /* drehkorrekturen fuer centerPkt */
extern double vmem[4];                                     /* kor. bis auswahl eines neuen drehpkts */
extern unsigned char  zoomFlag;                     /* (1) zoomModus */
extern unsigned char  centerFlag;                   /* (1) search centerPnt */
extern unsigned char  printFlag;                    /* printf 1:on 0:off */
extern unsigned char  fillSurfFlag;                 /* 1: generate triangles for surface-rendering and projection */

extern unsigned char  mode[2];                        /* pickmode */
extern unsigned char  pickfunc[MAX_LINE_LENGTH];                     /* pickfunc either "qenq" "qadd" "qrem"   */

extern int  pick_zmin;                         /* kleinster z-wert der gepickten items */
extern unsigned char pickname[MAX_LINE_LENGTH];                     /* name of the picked item   */
extern unsigned char  setname[MAX_LINE_LENGTH];                     /* setname-buffer for pick() */

extern int     num_etype[13];

extern Scale     scale[1];
extern double     *value_n;
extern Elements  *e_enqire;     /* elem-array by elem-number instead of elem[index]... */
extern Summen    anz[1];
extern Edges     *edge;
extern Nodes     *node;
extern Nodes     *n_anim;
extern Datasets *lcase;

extern Alias     *alias;
extern Sets      *set;
extern Psets     *pset;
extern Points    *point;
extern Lines     *line;
extern Lcmb      *lcmb;
extern Gsur      *surf;
extern Gbod      *body;
extern Nurbl     *nurbl;
extern Nurbs     *nurbs;
extern SumGeo    anzGeo[1];
extern SumAsci   sumAsci[1];

extern int       num_olc;

extern int       offset;
extern SpecialSet specialset[1];




/*---------------------------------------------------------*/
/* Liste aller unterstuetzten Funktionen                   */
/*---------------------------------------------------------*/
void help( void )
{
  printf ("\nKnown commands and syntax: \n");
  printf (" '..':   Keyword (either uppercase or lowercase)\n");
  printf (" <..>:   Parameter (case-sensitive)\n");
  printf (" [..]:   combination of parameters or optional parameter \n");
  printf (" (..):   Remark \n");
  printf (" |   :   OR \n");
  printf (" &   :   AND \n");
  printf (" -   :   from-to \n");
  printf ("   'area' <set> \n");
  printf ("   'asgn' 'n'|'e'|'p'|'l'|'c'|'s'|'b'|'S'|'L'|'se'|'alpha'|'beta'|'nadapt' <value>\n");
  printf ("   'bia'  [<set> [<bias>]|['mult'|'div' <factor>]] | [<line> <bias>]\n");
  printf ("   'body' <name|!> [<surf1> <surf2>]|[<surf1> <surf2> <surf3> <surf4> <surf5> <surf6>]\n");
  printf ("   'call' <parameters> \n");
  printf ("   'comp' <set> 'u'|'d'|'e'\n");
  printf ("   'copy' <set> <new_set> ['scal' <fx> <fy> <fz> [<pnt>]]|['tra' <dx> <dy> <dz>]|['rot' <p1> <p2> <alfa>]|['rad' 'x'|'y'|'z'|'p'<PNT> <dr>]|['mir' <P1> <P2>]\n");
  printf ("   'corrad' <set>\n");
  printf ("   'del'  ['p'|'l'|'s'|'b'|'S'|'L'|'se' <entity>]|['mesh']|['pic']\n");
  printf ("   'div'  [<set> ['auto' <node-dist> <angle>]|[<div>]|['mult'|'div' <factor-div> [<factor-bias>]]] | [<line> <div>\n");
  printf ("   'elem' <nr> <firstNode>-<lastNode> 'be2'|'be3'|'tr3'|'tr6'|'qu4'|'qu8'|'he8'|'he20'\n");
  printf ("   'elty' <set> 'be2'|'be3'|'tr3'|'tr3u'|'tr6'|'qu4'|'qu8'|'he8'|'he8r'|'he8i'|'he20'|'he20r'\n");
  printf ("   'exit' \n");
  printf ("   'frame' \n");
  printf ("   'gbod' <name|!> 'NORM' ['+|-' <surf>] .. (5-7 surfaces) \n");
  printf ("   'glue' <set> <tol> ['equ']\n");
  printf ("   'gonly' 'on'|'off' \n");
  printf ("   'graph' [<amplitude> 'amp']|[<material> 'mat']|[<set> 'nr'|'time'|'descr'] \n");
  printf ("   'gsur' <name|!> '+|-' 'BLEND|<nurbs>' ['+|-' <line|lcmb>] .. (3-5 lines) \n");  
  printf ("   'gtol' <geometric-tol> \n");
  printf ("   'help' \n");
  printf ("   'hcpy' ['ps'|'xwd'|'gif'|'png']|[make [ls]]|[clean] (def:xwd)\n");
  printf ("   'lc' <1.Dataset-Nr> <2.Dataset-Nr> <3.Dataset-Nr> ['a']|['e' <entity-nr> (up to 4 for vector-plots)] \n");
  printf ("   'lcmb' <name|!> ['+|-' <line> '+|-' <line> ..(up to 14 lines)]|['ADD' '+|-' <line> '+|-' <line>..(up to 14 lines)] \n");
  printf ("   'length' <set>\n");
  printf ("   'line' <name|!> <p1> <p2> <cp|seq> <div> \n");
  printf ("   'mata' <matNr> <set> \n");
  printf ("   'mats' \n");
  printf ("   'max' <value> \n");
  printf ("   'merg' 'n'|'e'|'p'|'l'|'c'|'s'|'b'|'S'|'L'|'se' <set> <gtol> 'nolock' \n");
  printf ("   'mesh' <set> ['fast' |& 'block' |& 'lonly' |& 'nolength' |& 'noangle' |& 'length' |& 'angle']\n");
  printf ("   'mids <set> ['lin']\n");
  printf ("   'min' <value> \n");
  printf ("   'minus' 'n'|'e'|'p'|'l'|'s'|'b'|'S'|'L' <set> \n");
  printf ("   'move' <set> ['scal' <fx> [<fy> <fz>] [<pnt>]]|['tra' <dx> <dy> <dz>]|['rot' <p1> <p2> <alfa>]|['rad' 'x'|'y'|'z'|'p'<pnt> <dr>]|['mir' <P1> <P2>] \n");
  printf ("   'movi' [delay <sec>]|[start]|[stop]|[make <nr> <nr> <prolog.gif>]|[clean] \n");
  printf ("   'msg' 'on|off' \n");
  printf ("   'node' <nr> <x> <y> <z> \n");
  printf ("   'nurl'  <name|!> ['DEFINE' ['COMPACT'] <pstart> <pend> <deg> <npnt> <nknt> <div>]|['CONTROL' <index> [<pnt>|<x y z>] <weight>]|['KNOT' <index> <value>]|['END']\n");
  printf ("   'nurs' [<name|!> ['DEFINE' ['COMPACT'] <u.deg> <v.deg> <u.npnt> <v.npnt> <u.nknt> <v.nknt>]|['CONTROL' <u.indx> <v.indx> [<pnt>|<x y z>] <weight>]|['KNOT' <u.indx> <v.indx> <value>]|['END']] | [ <!> <setname(containing surfaces)>]\n");
  printf ("   'ori' <set>\n");
  printf ("   'plot' 'n'|'e'|'f'|'p'|'l'|'s'|'b'|'S'|'L'&'a'|'d'|'v' <set> 'w'|'k'|'r'|'g'|'b'|'y'|'m'|'i'\n");
  printf ("   'plus' 'n'|'e'|'f'|'p'|'l'|'s'|'b'|'S'|'L'&'a'|'d'|'v' <set> 'w'|'k'|'r'|'g'|'b'|'y'|'m'|'i'\n");
  printf ("   'pnt' <name|!> [<x> <y> <z>]|[<L1> <ratio> <times>]|[<P1> <P2> <ratio> <times>]|[<setname(containing nodes)>]\n");
  printf ("   'prnt' ['amp' <RETURN|amplitude>]|['mat' <RETURN|material>]|['se' <RETURN|set>]|['n'|'e'|'f'|'p'|'l'|'s'|'b'|'S'|'L' <entity>]\n");
  printf ("   'proj' <set> <set> ['rad' 'x'|'y'|'z' <offset>]|['tra' <x> <y> <z> <offset>]|['rot' <p1> <p2> <offset>]|['nor' <offset>]\n"); 
  printf ("   'qadd' <set> RETURN 'w'|'a'|'i'|'r'|'n'|'e'|'f'|'p'|'l'|'s'|'b'|'L'|'S'|'q'|'u'\n");
  printf ("   'qali' RETURN 'w'|'p'|'n'|'q' \n");
  printf ("   'qbia' RETURN 'w'|'a'|'i'|'1'-'9'|'c'|' '&(two nr)\n");
  printf ("   'qbod' <name>(optional) RETURN 'w'|'b'|'a'|'i'|'r'|'s'|'g'|'q'|'u'\n");
  printf ("   'qcnt' RETURN 'w'|'n'|'p' \n");
  printf ("   'qcut' RETURN 'q'|'n'|'p' \n");
  printf ("   'qdel' RETURN 'w'|'p'|'l'|'s'|'b'|'L'|'S'|'q'\n");
  printf ("   'qdis' RETURN 'w'|'n'|'p'|'q'\n");
  printf ("   'qdiv' RETURN 'w'|'a'|'i'|'1'-'9'|' '&(two nr)\n");
  printf ("   'qenq' RETURN 'w'|'a'|'i'|'r'|'n'|'e'|'f'|'p'|'l'|'s'|'b'|'L'|'S'|'q'\n");
  printf ("   'qele' RETURN 's'|'v'|'n'|'q'\n");
  printf ("   'qflp' RETURN 'w'|'e'|'s'|'a'|'i'|'q' \n");
  printf ("   'qlin' <name>(optional) RETURN 'w'|'b'|'c'|'m'|'s'|'t'|'g'|'l'|'u' \n");
  printf ("   'qnod' RETURN 'w'|'p'|'m'|'u' \n");
  printf ("   'qpnt' <name>(optional)RETURN 'w'|'p'|'g'|'m'|'s'|'S'|'u' \n");
  printf ("   'qrem' <set> RETURN 'w'|'a'|'i'|'r'|'n'|'e'|'f'|'p'|'l'|'s'|'b'|'L'|'S'|'q'|'u'\n");
  printf ("   'qseq' RETURN 'nr' \n");
  printf ("   'qspl' RETURN 'w'|'s'|'q' \n");
  printf ("   'qsur' <name>(optional) RETURN 'w'|'a'|'b'|'i'|'r'|'1'-'9'|'g'|'q'|'u'|'s'|'S' \n");
  printf ("   'quit' \n");
  printf ("   'read' [<geo-file> ['add']]|[<ccx-file> 'inp' ['add']]|[<mesh-file.frd> <setname>]|[<edge-file> 'edg']|[<list-file> '-n'|'-e'[<column>]]|[<picture.xwd>]\n");
  printf ("   'rep'  \n");
  printf ("   'rnam' <set> <set> \n");
  printf ("   'rot'  ['u'|'d'|'r'|'l'|'c' <angle>]|['x'|'-x'|'y'|'-y'|'z'|'-z']\n");
  printf ("   'save' \n");
  printf ("   'scal' ['s'|'v'|'d'] [<value>]\n");
  printf ("   'send' <set> ['abq'|'adh'|'ans'|'ast'|'duns'|'fbd'|'frd'|'nas'|'tcg'|'stl'] [<RETURN>]|['comp']|['names']|['spc' <1-6,t> <value>]|['slide' 's'|'rx'|'ry'|'rz'|'tx'|'ty'|'tz']|['sur']|['pres' [<value>]|['lc'<nr> 'e'<nr>]]|['force' <f1> <f2> <f3> ]|['film' [[<temp>]|['lc'<nr> 'e'<nr>]] [[<coeff>]|['lc'<nr> 'e'<nr>]]]|['rad' [[<temp>]|['lc'<nr> 'e'<nr>]] [[<emis>|['lc'<nr> 'e'<nr>]]]|['dflux' [[<load>]|['lc'<nr> 'e'<nr>]]]|['cflux' <load>]|['mpc' <rotation> <v1> <v2> <v3> ]|['lc' <nr>]|['tmf']|['sta' <refspeed>]|['crp' <timefact> <refspeed> <writefreq>]\n");
  printf ("  OR 'send' <dep-set> <indep-set> 'nas'|'abq'|'ans' ['cycmpc' 'tx'|'ty'|'tz'|'rx'|'ry'|'rz'|'cx'|'cy'|'cz'<segments> 'c'|'u'<NR>]|['areampc' [<dofs(1-6,t)> 'c'|'u'<Nr>|['slide']]]|['gap' <vx> <vy> <vz> <tol> ]]\n");
  printf ("  OR 'send' <set> 'foam' [<base-type> <set>]|['cyclic' <set> <set> 'rx'|'ry'|'rz'|'cx'|'cy'|'cz'|<vx,vy,vz>]  \n");  
  printf ("  OR 'send' <set> 'isaac' [<base-type> <set>]  \n");  
  printf ("   'seqa' <set> ['afte'|'befo' <pnt>]|['end'] 'pnt' <pnt ..>] \n");
  printf ("   'seta' <set> ['n'|'e'|'p'|'l'|'c'|'s'|'b'|'S'|'L'|'se' <name> <name>..]|['n'|'e' <name> '-' <name> <steps>] \n");
  printf ("   'setc' <set> \n");
  printf ("   'seto' <set> \n");
  printf ("   'setr' <set> 'n'|'e'|'p'|'l'|'s'|'b'|'S'|'L'|'se' <name> <name>.. \n");
  printf ("   'split' <set> <set> \n");
  printf ("   'steps' <value> \n");
  printf ("   'surf' <name|!> <line|lcmb> <line|lcmb> <line|lcmb> <line|lcmb> \n");
  printf ("   'swep' <set> <new_set> ['scal' <fx> <fy> <fz> [<pnt>|<div>]]|['tra' <dx> <dy> <dz> <div>]|['rot' <p1> <p2> <alfa> <div>]|['rad' 'x'|'y'|'z'|'p'<pnt> <dr> <div>]|['mir' <P1> <P2> <div>] \n");
  printf ("   'text' <string> \n");
  printf ("   'tra' 'u'|'d'|'l'|'r' <relative-distance> \n");
  printf ("   'volu' <set> \n");
  printf ("   'zap'  <set> \n");
  printf ("   'zoom' [<scale>]|[<p1x> <p1y> <p2x> <p2y>] \n");
}

int compareInt(int *a, int *b)
{
  /* wird von qsort aufgerufen, vergleicht Integer-Felder */

  if ( a[0] < b[0] )
    return (-1) ;
  else if ( a[0] > b[0] )
    return (1) ;
  else
    {
    return (0) ;
    }
}

int compareFloat(double *a, double *b)
{
  /* wird von qsort aufgerufen, vergleicht Float-Felder */

  if ( a[0] < b[0] )
    return (-1) ;
  else if ( a[0] > b[0] )
    return (1) ;
  else
    {
    return (0) ;
    }
}


void getScaleValues( int anz_n, int anz_p, Points *point, Nodes *node, Scale *scale)
{
  int  i;

  /* -----------  MAX und MIN Werte feststellen -----------------  */

  scale->xmax=-10000000.; scale->xmin=10000000.;
  scale->ymax=-10000000.; scale->ymin=10000000.;
  scale->zmax=-10000000.; scale->zmin=10000000.;

  for (i=0; i<anz_n; i++ )
    {
    if (node[node[i].nr].nx > scale->xmax) scale->xmax=node[node[i].nr].nx;
    if (node[node[i].nr].nx < scale->xmin) scale->xmin=node[node[i].nr].nx;
    if (node[node[i].nr].ny > scale->ymax) scale->ymax=node[node[i].nr].ny;
    if (node[node[i].nr].ny < scale->ymin) scale->ymin=node[node[i].nr].ny;
    if (node[node[i].nr].nz > scale->zmax) scale->zmax=node[node[i].nr].nz;
    if (node[node[i].nr].nz < scale->zmin) scale->zmin=node[node[i].nr].nz;
    }
  for (i=0; i<anz_p; i++ )
    {
    if (point[i].px > scale->xmax) scale->xmax=point[i].px;
    if (point[i].px < scale->xmin) scale->xmin=point[i].px;
    if (point[i].py > scale->ymax) scale->ymax=point[i].py;
    if (point[i].py < scale->ymin) scale->ymin=point[i].py;
    if (point[i].pz > scale->zmax) scale->zmax=point[i].pz;
    if (point[i].pz < scale->zmin) scale->zmin=point[i].pz;
    }

  /* ------------  DATEN scalieren -------------------  */

  scale->x=(scale->xmax+scale->xmin)/2.;
  scale->y=(scale->ymax+scale->ymin)/2.;
  scale->z=(scale->zmax+scale->zmin)/2.;
  scale->xmax=scale->xmax-scale->x;
  scale->ymax=scale->ymax-scale->y;
  scale->zmax=scale->zmax-scale->z;
  scale->xmin=scale->xmin-scale->x;
  scale->ymin=scale->ymin-scale->y;
  scale->zmin=scale->zmin-scale->z;
  if (scale->xmax < (-scale->xmin)) scale->xmax=(-scale->xmin);
  if (scale->ymax < (-scale->ymin)) scale->ymax=(-scale->ymin);
  if (scale->zmax < (-scale->zmin)) scale->zmax=(-scale->zmin);
  scale->w=scale->xmax;
  if (scale->w < scale->ymax){ scale->w=scale->ymax;}
  if (scale->w < scale->zmax){ scale->w=scale->zmax;}

  scale->w/=0.4; /* nochmal scaliert */
  if (scale->w<=0.) scale->w=1.;
}



void defineColIndexes_light()
{
  int          range, win, dark;
  register int   i, n;
  float        r, g, b, base=1.4; /* low base gives more contrast */


  float mat_colormap[3];

  win =glutGetWindow();

  /* Index Startwerte fuer ambient, diffuse und specular Lichtanteile definieren */
  range=CMAP_CELLS_LIGHT;                  /* Anzahl der Grautoene in der Colormap */
  dark =CMAP_DARKSHIFT;             /* schwarzverschiebung der hellsten collour-cell */


  mat_colormap[0] = offset+1;
  mat_colormap[1] = offset+range/2;
  mat_colormap[2] = offset+range-1;

  /* Index Rampe definieren */
  n=0;
  for (i=0; i<=range; i++ )
  {
    /*    r = (base-1.)/base+pow(i/(float)((range+dark)-1),3)/base;
    g = (base-1.)/base+pow(i/(float)((range+dark)-1),3)/base;
    b = (base-1.)/base+pow(i/(float)((range+dark)-1),3)/base; */

    r = (base-1.)/base+i/(float)((range+dark)-1)/base;
    g = (base-1.)/base+i/(float)((range+dark)-1)/base;
    b = (base-1.)/base+i/(float)((range+dark)-1)/base;



    glutSetWindow( w0 );
      glutSetColor( i+offset, r, g, b );
    glutSetWindow( w1 );
      glutSetColor( i+offset, r, g, b );

    if ((npixels>0) && ((i+offset) >= pixels_return[0]) && ((i+offset)<=pixels_return[npixels-1]))
    {
      n++;
      xcolor[i+offset].pixel = i+offset;
      xcolor[i+offset].red   = r*65535.;
      xcolor[i+offset].green = g*65535.;
      xcolor[i+offset].blue  = b*65535.;
      /*
            printf ("colIndex[%d] %d %d %d %d\n", i+1, xcolor[i+offset].pixel,
	      xcolor[i+offset].red, xcolor[i+offset].green, xcolor[i+offset].blue ); 
      */
    }
  }
#ifndef WIN32
  storeColors( n, 0 );
#endif

  /* Reflexionseigenschaften des Materials aufbringen */
  glutSetWindow( w1 );
  glMaterialfv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, mat_colormap);

  glutSetWindow(win);
}

void defineColIndexes_load()
{
  register int   i, n;
  float          r, g, b;
  int win;

  win =glutGetWindow();
  /* define colormap values in both colormaps */

  n=0;
  for (i=0; i<steps; i++)
  {
    define_rgb( (float)i/(steps-1.), &r,&g,&b);
    glutSetWindow( w1);
        glutSetColor( i+offset, r, g, b );
    glutSetWindow( w0);
        glutSetColor( i+offset, r, g, b );

    if ( (npixels>0) && ((i+offset) >= pixels_return[0]) && ((i+offset)<=pixels_return[npixels-1]) )
      {
      n++;
      xcolor[i+offset].pixel = i+offset;
      xcolor[i+offset].red   = r*65535.;
      xcolor[i+offset].green = g*65535.;
      xcolor[i+offset].blue  = b*65535.;
 /*   printf ("colIndex[%d] %d %d %d %d\n", i+1, xcolor[i+offset].pixel, xcolor[i+offset].red,
             xcolor[i+offset].green, xcolor[i+offset].blue ); */
      }
  }
#ifndef WIN32
  storeColors( n, 0 );
#endif
  glutSetWindow(win);
}

void defineColIndexes_set()
{
  int          i,n, win;

  n=0;
  win =glutGetWindow();
  for (i=0; i<SET_COLS; i++)
  {
    glutSetWindow( w1);
        glutSetColor( i+offset+CMAP_CELLS_LIGHT, entity_r[i], entity_g[i], entity_b[i] );
    glutSetWindow( w0);
        glutSetColor( i+offset+CMAP_CELLS_LIGHT, entity_r[i], entity_g[i], entity_b[i] );
    if ( (npixels>0) && ((i+offset+CMAP_CELLS_LIGHT) >= pixels_return[CMAP_CELLS_LIGHT]) && ((i+offset+CMAP_CELLS_LIGHT)<=pixels_return[npixels-1]) )
      {
      n++;
      xcolor[i+offset+CMAP_CELLS_LIGHT].pixel = i+offset+CMAP_CELLS_LIGHT;
      xcolor[i+offset+CMAP_CELLS_LIGHT].red   = entity_r[i]*65535.;
      xcolor[i+offset+CMAP_CELLS_LIGHT].green = entity_g[i]*65535.;
      xcolor[i+offset+CMAP_CELLS_LIGHT].blue  = entity_b[i]*65535.;
      /*
      printf ("colIndex[%d] %d %d %d %d\n", i+1, xcolor[i+offset+CMAP_CELLS_LIGHT].pixel,
        xcolor[i+offset+CMAP_CELLS_LIGHT].red, xcolor[i+offset+CMAP_CELLS_LIGHT].green,
        xcolor[i+offset+CMAP_CELLS_LIGHT].blue ); 
      */
      }
  }
#ifndef WIN32
  storeColors( n, CMAP_CELLS_LIGHT);
#endif
  glutSetWindow(win);
}


void defineColTextur_load()
{
  int   i, n;
  float r, g, b;
  extern GLfloat   *contur_tex;
  GLint tex_id;

  /* define colormap values in both colormaps */
  if( (contur_tex= (GLfloat *)realloc( (GLfloat *)contur_tex, ((TEX_PIXELS+1)*3)*sizeof(GLfloat ) ))==NULL )
    printf("ERROR: realloc failed: defineColTextur_load \n\n" );

  if(steps>TEX_PIXELS) steps=TEX_PIXELS;

  n=0;
  for (i=0; i<steps; i++)
  {
    define_rgb( (float)i/(steps-1.), &r,&g,&b);
    contur_tex[n]  =r;
    contur_tex[n+1]=g;
    contur_tex[n+2]=b;
    n+=3;
  }
  for (; i<TEX_PIXELS; i++)
  {
    contur_tex[n]  =r;
    contur_tex[n+1]=g;
    contur_tex[n+2]=b;
    n+=3;
  }


  /*
  n=0;
  for (i=0; i<TEX_PIXELS; i++)
  {    printf("%d %d %lf %lf %lf\n",steps, i, contur_tex[n], contur_tex[n+1], contur_tex[n+2]); n+=3; }
  */
  glGenTextures(1, &tex_id);
  glBindTexture(GL_TEXTURE_1D, tex_id);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexImage1D(GL_TEXTURE_1D, 0, 3, TEX_PIXELS, 0, GL_RGB, GL_FLOAT, contur_tex);
}


void zoom(double xcur0, double ycur0, double xcur1, double ycur1)
{
  double  dx_cur, dy_cur, dso;

      dx_cur= xcur1-xcur0;
      dx_cur= sqrt( dx_cur*dx_cur );
      dy_cur= ycur1-ycur0;
      dy_cur= sqrt( dy_cur*dy_cur );
      dso=ds;
      if (dx_cur<dy_cur) ds*=dy_cur/2.;
      else ds*=dx_cur/2.;
      dtx=(dtx- (xcur1+xcur0)/2.)*dso/ds ;
      dty=(dty- (ycur1+ycur0)/2.)*dso/ds ;
      zoomFlag=0;
      glutPostRedisplay();
      updateDispLists();
}
void qzoom()
{
  static int i=0;
  static double xcur[2], ycur[2];

    xcur[i]=dx; ycur[i]=dy;
    if (i)
    {
      i=0;
      zoom(xcur[0], ycur[0], xcur[1], ycur[1]);
    }
    else
        i=1;
    printf ("P%d\n", i);
}

void center(double x, double y, double z)
{
      int i;

      centerPnt[0]=x;
      centerPnt[1]=y;
      centerPnt[2]=z;
        m_copy( &Rmem[0][0], &R[0][0] );  /* remember all rotations to now (memory) */
        for (i=0; i<4; i++) vmem[i]+=v[i]; /* remember all kompensations to now (memory) */
}
void qcenter(int x, int y)
{
      int i;
      double puf[3];

       for (i=0;i<3;i++) puf[i]=centerPnt[i];
        centerFlag=!centerFlag;
        printf ("pic new center\n");

        mode[0]='i';
        strcpy( pickfunc, "qcnt");
        glutSetWindow( w1);
        pick( (unsigned char)'n', x, y );
        if( (puf[0]==centerPnt[0])&&(puf[1]==centerPnt[1])&&(puf[2]==centerPnt[2]) )
        {
          pick( (unsigned char)'p', x, y );
          if( (puf[0]==centerPnt[0])&&(puf[1]==centerPnt[1])&&(puf[2]==centerPnt[2]) )
          {
            printf (" no node/point found, reseted to 0\n");
	    centerNode=0;
            centerPnt[0]=centerPnt[1]=centerPnt[2]=0;
            center( centerPnt[0], centerPnt[1], centerPnt[2]);
          }
        }
        pick( (unsigned char)'q', x, y );
        glutSetWindow( activWindow );
}

void rot_u(double a)
{
  int i,n;
  double b;

    b=a/90.; i=b;
    a=a*PI/180.;
    if(i<0) for(n=0; n<-i; n++)
    {  
      trackball( 1, trackbsize, curquat, 0.0, 0.0, 0.0, trackbsize );
      add_quats(curquat, lastquat, lastquat);
      build_rotmatrix( R, lastquat );
    }
    if(i>0) for(n=0; n<i; n++)
    {    
      trackball( 1, trackbsize, curquat, 0.0, 0.0, 0.0, -trackbsize );
      add_quats(curquat, lastquat, lastquat);
      build_rotmatrix( R, lastquat );
    }
    a=(b-i)*PI/2.;
    trackball( 1, trackbsize, curquat, 0.0, 0.0, 0.0, -sin(a)*trackbsize );
    add_quats(curquat, lastquat, lastquat);
    build_rotmatrix( R, lastquat );
    glutPostRedisplay();
}
void rot_r(double a)
{
  int i,n;
  double b;

    b=-a/90.; i=b;
    a=-a*PI/180.;
    if(i<0) for(n=0; n<-i; n++)
    {    
      trackball( 1, trackbsize, curquat, 0.0, 0.0, -trackbsize, 0.0 );
      add_quats(curquat, lastquat, lastquat);
      build_rotmatrix( R, lastquat );
    }
    if(i>0) for(n=0; n<i; n++)
    {    
      trackball( 1, trackbsize, curquat, 0.0, 0.0, trackbsize, 0.0 );
      add_quats(curquat, lastquat, lastquat);
      build_rotmatrix( R, lastquat );
    }
    a=(b-i)*PI/2.;
    trackball( 1, trackbsize, curquat, 0.0, 0.0, sin(a)*trackbsize, 0.0 );
    add_quats(curquat, lastquat, lastquat);
    build_rotmatrix( R, lastquat );
    glutPostRedisplay();
}
void rot_c(double a)
{
  int i,n;
  double b;

    b=a/90.; i=b;
    a=a*PI/180.;
    if(i<0) for(n=0; n<-i; n++)
    {    
      trackball( 1, trackbsize, curquat, trackbsize, 0.0, 0.0, -trackbsize );
      add_quats(curquat, lastquat, lastquat);
      build_rotmatrix( R, lastquat );
    }
    if(i>0) for(n=0; n<i; n++)
    {    
      trackball( 1, trackbsize, curquat, trackbsize, 0.0, 0.0, trackbsize );
      add_quats(curquat, lastquat, lastquat);
      build_rotmatrix( R, lastquat );
    }
    a=(b-i)*PI/2.;
    trackball( 1, trackbsize, curquat, trackbsize, 0.0, cos(a)*trackbsize, sin(a)*trackbsize );
    add_quats(curquat, lastquat, lastquat);
    build_rotmatrix( R, lastquat );
    glutPostRedisplay();
}

void rot_x(double a)
{

  /* Trackballfunktion inizialisieren, Blickrichtung +x */
    a*=90.*PI/180.;
    trackball( 1, trackbsize, lastquat, 0.0, 0.0, sin(a)*trackbsize, 0.0 );
    R[0][0]=cos(a);  R[1][0]=0.;  R[2][0]=sin(a);  R[3][0]=0.;
    R[0][1]=0.;  R[1][1]=1.;  R[2][1]=0.;  R[3][1]=0.;
    R[0][2]=-sin(a); R[1][2]=0.;  R[2][2]=cos(a);  R[3][2]=0.;
    R[0][3]=0.;  R[1][3]=0.;  R[2][3]=0.;  R[3][3]=1.;
    glutPostRedisplay();
}

void rot_y(double a)
{
    /* Trackballfunktion inizialisieren, Blickrichtung +y (rot_x)*/
    a*=-90.*PI/180.;
    trackball( 1, trackbsize, lastquat, 0.0, 0.0, 0.0, -sin(a)*trackbsize );
    R[0][0]=1.;  R[1][0]=0.;  R[2][0]=0.;  R[3][0]=0.;
    R[0][1]=0.;  R[1][1]=cos(a);  R[2][1]=-sin(a);  R[3][1]=0.;
    R[0][2]=0.;  R[1][2]=sin(a);  R[2][2]=cos(a);  R[3][2]=0.;
    R[0][3]=0.;  R[1][3]=0.;  R[2][3]=0.;  R[3][3]=1.;
    glutPostRedisplay();
}

void rot_z(double b)
{
  double a;
    /* Trackballfunktion inizialisieren, Blickrichtung +z (rot_z)*/
    a=0.;
    trackball( 1, trackbsize, lastquat, trackbsize, 0.0, cos(a)*trackbsize, sin(a)*trackbsize );
    R[0][0]=cos(a);  R[1][0]=-sin(a);  R[2][0]=0.;  R[3][0]=0.;
    R[0][1]=sin(a);  R[1][1]=cos(a);   R[2][1]=0.;  R[3][1]=0.;
    R[0][2]=0.;  R[1][2]=0.;  R[2][2]=1.;  R[3][2]=0.;
    R[0][3]=0.;  R[1][3]=0.;  R[2][3]=0.;  R[3][3]=1.;
    if(b==1) rot_r(180.);
    glutPostRedisplay();
}


void pre_rot( unsigned char *record)
{
  int  length;
  double angle;
  unsigned char type[MAX_LINE_LENGTH];

  length = sword( record, type );
  angle = atof( &record[length+1]);
  if (type[0]=='u') rot_u(angle);
  else if (type[0]=='r') rot_r(angle);
  else if (type[0]=='c') rot_c(angle);
  else if (type[0]=='d') rot_u(-angle);
  else if (type[0]=='l') rot_r(-angle);
  else if (type[0]=='x') rot_x(1.);
  else if (type[0]=='y') rot_y(1.);
  else if (type[0]=='z') rot_z(1.);
  else if (type[0]=='-')
  {
    if (type[1]=='x') rot_x(-1.);
    else if (type[1]=='y') rot_y(-1.);
    else if (type[1]=='z') rot_z(-1.);
    else errMsg(" rot type:%s not known\n", type);
  }
  else errMsg(" rot type:%s not known\n", type);
}

/* transformiert punkte-koordinaten und liefert die methode der transformation zurueck */
/*
   fehler: -1
   tra: 1
   rad: 2
   rot: 3
*/
int transform( unsigned char *record, int anz_n, Nodes *node )
{
  int  length, i;
  unsigned char v[MAX_LINE_LENGTH], dat[4][MAX_LINE_LENGTH];
  unsigned char type[MAX_LINE_LENGTH], pkt1[MAX_LINE_LENGTH], pkt2[MAX_LINE_LENGTH];
  int   pnr1, pnr2;
  double fi=0., dx=0., dy=0., dz=0., dr=0., x, y, z, r, dh, dq, l, h, q, h_offs, q_offs;
  double s[4], p1[3], p2[3], p1p2[3];
  double ph[3], p1ph[3];
  double el[3], eh[3], eq[3];   /* xyz koordinaten der lhq vektoren */
  double ex[3], ey[3], ez[3];   /* lhq koordinaten der xyz vektoren */

  length = sword( record, type );

  if(( compare(type,"tra",3) == 3 )||( compare(type,"TRA",3) == 3 ))
  {
    sscanf( record, "%*s %lf %lf %lf", &dx, &dy, &dz );
    for (i=0; i<anz_n; i++)
    {
      node[i].nx+= dx;
      node[i].ny+= dy;
      node[i].nz+= dz;
    }
    return(1);
  }
  else if(( compare(type,"sca",3) == 3 )||( compare(type,"SCA",3) == 3 ))
  {
    length=sscanf( record, "%*s %s %s %s %s", dat[0], dat[1], dat[2], dat[3] );
    for(i=0; i<length; i++) s[i]=atof(dat[i]);
    pnr1=getPntNr(dat[length-1]);
    if (pnr1==-1)
    {
      /* check if we have a valid number */
      if (s[length-1]==0.)
      {
        errMsg(" Argument:%s is not valid\n", dat[length-1] );
        return(-1);
      }
    }
    else length--;
    
    if (length==0) s[1]=s[2]=s[0]=1.;
    if (length==1) s[1]=s[2]=s[0];
    if (length==2) s[2]=1.;
    if (pnr1>-1)
    {
      ph[0]=(point[pnr1].px*scale->w+scale->x);
      ph[1]=(point[pnr1].py*scale->w+scale->y);
      ph[2]=(point[pnr1].pz*scale->w+scale->z);
    }
    else ph[0]=ph[1]=ph[2]=0.;                                                    

    for (i=0; i<anz_n; i++)
    {
      node[i].nx= ph[0] - s[0]*(ph[0]-node[i].nx);
      node[i].ny= ph[1] - s[1]*(ph[1]-node[i].ny);
      node[i].nz= ph[2] - s[2]*(ph[2]-node[i].nz);
    }
    gtol*=dx;
    return(1);
  }
  else if(( compare(type,"rad",3) == 3 )||( compare(type,"RAD",3) == 3 ))
  {
    i=sscanf( record, "%*s%s%lf", v, &dr );
    if(i<2) {printf ("ERROR: Some args are wrong, Nr of args:%d v:%1s dr:%lf\n", i, v, dr); return(-1);}
    if (v[0]=='p')
    {
      strcpy(pkt1, &v[1]);
      pnr1=getPntNr( pkt1 );
      if (pnr1==-1)
      {
        errMsg(" Point (%s) is undefined\n", pkt1 );
        return(-1);
      }
      ph[0]=(point[pnr1].px*scale->w+scale->x);
      ph[1]=(point[pnr1].py*scale->w+scale->y);
      ph[2]=(point[pnr1].pz*scale->w+scale->z);
    }

    for (i=0; i<anz_n; i++)
    {
      x=node[i].nx;
      y=node[i].ny;
      z=node[i].nz;
      if (v[0]=='x')
      {
        r=sqrt(y*y+z*z);
        if (r>gtol)
        {
          y=y*(r+dr)/r;
          z=z*(r+dr)/r;
        }
      }
      else if (v[0]=='y')
      {
        r=sqrt(x*x+z*z);
        if (r>gtol)
        {
          x=x*(r+dr)/r;
          z=z*(r+dr)/r;
        }
      }
      else if (v[0]=='z')
      {
        r=sqrt(y*y+x*x);
        if (r>gtol)
        {
          y=y*(r+dr)/r;
          x=x*(r+dr)/r;
        }
      }
      else if (v[0]=='p')
      {
        dx=x-ph[0];
        dy=y-ph[1];
        dz=z-ph[2];
        r=sqrt(dy*dy+dx*dx+dz*dz);
        if (r>gtol)
        {
          x=ph[0]+dx*(r+dr)/r;
          y=ph[1]+dy*(r+dr)/r;
          z=ph[2]+dz*(r+dr)/r;
        }
      }
      else
      { errMsg(" rotational Axis not known:%1s \n", v); return(-1); }
      node[i].nx= x;
      node[i].ny= y;
      node[i].nz= z;
    }
    return(2);
  }
  else if(( compare(type,"rot",3) == 3 )||( compare(type,"ROT",3) == 3 ))
  {
    sscanf( record, "%*s%s%s%lf", pkt1, pkt2, &fi );
    fi = fi*PI/180.;
    pnr1=getPntNr( pkt1 );
    pnr2=getPntNr( pkt2 );
      if (pnr1==-1)
      {
        errMsg(" Point (%s) is undefined\n", pkt1 );
        return(-1);
      }
      if (pnr2==-1)
      {
        errMsg(" Point (%s) is undefined\n", pkt2 );
        return(-1);
      }

    p1[0] = point[pnr1].px;
    p1[1] = point[pnr1].py;
    p1[2] = point[pnr1].pz;

    p2[0] = point[pnr2].px;
    p2[1] = point[pnr2].py;
    p2[2] = point[pnr2].pz;

    /* berechnung der Einheitsvektoren des Verdreh-Koordinatensystems */
    /* Exneu = p1p2/|p1p2| ist der Einheitsvektor in xneu richtung    */
    /* Eyneu = p1p2 X p1ph / |p1p2 X p1ph|     in yneu                */
    /* Ezneu = Exneu X Eyneu                   in zneu                */

    v_result( p1, p2, p1p2 );
    v_norm  ( p1p2, el );

    /* erzeuge einen Hilfspunkt der nicht auf der el-achse liegt  */
    ph[1] = p1p2[0];
    ph[2] = p1p2[1];
    ph[0] = p1p2[2];

    /* konstuiere damit den 2. einheitsvektor eh  */
    v_result( p1, ph, p1ph );
    v_prod( p1p2, p1ph, ph );
    v_norm (ph, eh);

    /* und der dritte: eq  */
    v_prod( p1p2, ph, ex );
    v_norm (ex, eq);

    /* berechnung der lhq-koordinaten der xyz einheitsvektoren durch zykl.vertausch.  */
    ex[0]=el[0];
    ex[1]=eh[0];
    ex[2]=eq[0];

    ey[0]=el[1];
    ey[1]=eh[1];
    ey[2]=eq[1];

    ez[0]=el[2];
    ez[1]=eh[2];
    ez[2]=eq[2];

    /* Berechnung der lhq-koordinaten der Drehachse (offset fuer die Drehung) */
    x=point[pnr1].px*scale->w+scale->x;
    y=point[pnr1].py*scale->w+scale->y;
    z=point[pnr1].pz*scale->w+scale->z;
    
    /* l=ex[0]*x+ey[0]*y+ez[0]*z; */
    h_offs=ex[1]*x+ey[1]*y+ez[1]*z;
    q_offs=ex[2]*x+ey[2]*y+ez[2]*z;

    /* Berechnung der lhq-koordinaten aller zu drehenden punkte */
    for (i=0; i<anz_n; i++)
    {
      x=node[i].nx;
      y=node[i].ny;
      z=node[i].nz;
      l=ex[0]*x+ey[0]*y+ez[0]*z;
      h=( ex[1]*x+ey[1]*y+ez[1]*z ) - h_offs ;
      q=( ex[2]*x+ey[2]*y+ez[2]*z ) - q_offs ;

      /* drehe um l  */
      dh=h*cos(fi)-q*sin(fi);
      dq=h*sin(fi)+q*cos(fi);
      dh+= h_offs;
      dq+= q_offs;

      node[i].nx=el[0]*l+eh[0]*dh+eq[0]*dq;
      node[i].ny=el[1]*l+eh[1]*dh+eq[1]*dq;
      node[i].nz=el[2]*l+eh[2]*dh+eq[2]*dq;
    }
    return(3);
  }
  else if(( compare(type,"mir",3) == 3 )||( compare(type,"MIR",3) == 3 ))
  {
    /* the "mirror" is placed at p2 and is perpendicular to p1p2 */
    sscanf( record, "%*s%s%s", pkt1, pkt2 );
    pnr1=getPntNr( pkt1 );
    pnr2=getPntNr( pkt2 );
      if (pnr1==-1)
      {
        errMsg(" Point (%s) is undefined\n", pkt1 );
        return(-1);
      }
      if (pnr2==-1)
      {
        errMsg(" Point (%s) is undefined\n", pkt2 );
        return(-1);
      }

    p1[0] = point[pnr1].px*scale->w+scale->x;
    p1[1] = point[pnr1].py*scale->w+scale->y;
    p1[2] = point[pnr1].pz*scale->w+scale->z;

    p2[0] = point[pnr2].px*scale->w+scale->x;
    p2[1] = point[pnr2].py*scale->w+scale->y;
    p2[2] = point[pnr2].pz*scale->w+scale->z;

    /* calculation of the first mirrored point (modification of p2) */
    v_result( p1, p2, p1p2 );
    l=2.;
    v_scal( &l, p1p2, p1p2 ); 
    v_add( p1,  p1p2, p2 );

    ph[0] = p2[0]+p1[0];
    ph[1] = p2[1]+p1[1];
    ph[2] = p2[2]+p1[2];

    fi=v_sprod(p1p2, p1p2);

    for (i=0; i<anz_n; i++)
    {
      el[0]=(ph[0]-2*node[i].nx) ;
      el[1]=(ph[1]-2*node[i].ny) ;
      el[2]=(ph[2]-2*node[i].nz) ;
      l=v_sprod(el, p1p2);
      h=l/fi;
      node[i].nx+= h*p1p2[0];
      node[i].ny+= h*p1p2[1];
      node[i].nz+= h*p1p2[2];
    }
    return(1);
  }
  else
  {
    printf(" ERROR: transformation not recognized: %s\n", type );
    return(-1);
  }
}


/* calculate the necessary division of the line with respect to the curvature */
int calcLineDiv(Lines *line, int nr, Points *point, double gtol_cos_a, double lmax, double lmin)
{
  int i;

  double e0[3], e1[3], v0[3], v1[3];
  double l, cos_a, min_cos_a=MAXVALUE;

  line[nr].div=MAX_LINE_DIV-(MAX_LINE_DIV%2);
 new_div:;
  /* generate the drawing points (called points now) on the line */
  rep(nr);

  /* calculate the angle between vectors from 1st point to second and to 3rd, over all points */
  for(i=0; i<line[nr].nip-6; i+=3)
  {
    v_result(&line[nr].ip[i],&line[nr].ip[i+3], v0); 
    v_result(&line[nr].ip[i],&line[nr].ip[i+6], v1); 
    v_norm(v0, e0);
    v_norm(v1, e1);
    cos_a= v_sprod(e0, e1);
    if(cos_a<min_cos_a) min_cos_a=cos_a;
  }
  if(!i) /* straight line */
  {
    min_cos_a=1;
    v_result(&line[nr].ip[i],&line[nr].ip[i+3], v0); 
    l=v_betrag(v0)/line[nr].div;
  }
  else
  {
    /* Calculate the length between points. It is sufficient to do it for the last sector */
    l=v_betrag(v0);
  }

  /* if the minimum cos_a in the line is close to 1 (parallel vectors) reduce the division by factor of 2 */
  if((min_cos_a>gtol_cos_a)&&(line[nr].div>MIN_LINE_DIV)&&(l<lmax))
  {
    if(l*2<lmax) { line[nr].div/=2; goto new_div; }
    else line[nr].div*=(double)l/lmax;
  }

  /* check the division if the elements would be too small */
  if(l<lmin)
  {
    line[nr].div*=(double)l/lmin;
  }

  if(line[nr].div<1) line[nr].div=MIN_LINE_DIV;
  if(line[nr].div>MAX_LINE_DIV-(MAX_LINE_DIV%2)) line[nr].div=MAX_LINE_DIV-(MAX_LINE_DIV%2);
  if((MIN_LINE_DIV%2==0)&&(line[nr].div%2!=0)) line[nr].div+=1;

  if(printFlag) printf("line:%s div:%d gtol_cos_a:%lf min_cos_a:%lf lmax:%lf l:%lf\n", line[nr].name, line[nr].div, gtol_cos_a, min_cos_a, lmax*scale->w, l*scale->w);

  return(line[nr].div);
}




void repNurl(int nr )
{
  int i,j;

  /* calculation of the controll-point-array for drawing purposes */
  if( nurbl[nr].name != (unsigned char *)NULL )
  {
    if( (nurbl[nr].ctlarray = (GLfloat *)realloc( (GLfloat *)nurbl[nr].ctlarray, (nurbl[nr].u_npnt*nurbl[nr].u_stride)*sizeof(GLfloat) )) == NULL )
    { printf(" ERROR: realloc failure in repNurbl(), nurbl:%s can not be shaped\n\n", nurbl[nr].name);
      return; }

    /* calculate the position of the controll-array */
    j=0; for (i=0; i<nurbl[nr].u_npnt; i++ )
    {
      nurbl[nr].ctlarray[j++]=nurbl[nr].weight[i]*(GLfloat)point[nurbl[nr].ctlpnt[i]].px ;
      nurbl[nr].ctlarray[j++]=nurbl[nr].weight[i]*(GLfloat)point[nurbl[nr].ctlpnt[i]].py ;
      nurbl[nr].ctlarray[j++]=nurbl[nr].weight[i]*(GLfloat)point[nurbl[nr].ctlpnt[i]].pz ;
      nurbl[nr].ctlarray[j++]=nurbl[nr].weight[i] ;
    }
  }
}


void calcNurbsResolution( int nr)
{
  int i;


  double p0[3], p0p1[3], p1[3], e_length,factor;
  double umin, umax,du,vmin,vmax,dv, lu, lv;
  Points tab_p[UV_STEPS];
  double dtab_u[UV_STEPS], dtab_v[UV_STEPS], dtab_05[UV_STEPS];

#if TEST
  printf("calcNurbsResolution-nurbs:%s \n", nurbs[nr].name);
#endif
  /* calculation of the u,v resolution based on real world scale */
  /* get the u and v range by looking into the knots */
  umin=nurbs[nr].uknt[0];
  umax=nurbs[nr].uknt[nurbs[nr].u_nknt-1];
  du=(umax-umin)/(UV_STEPS-1);
  vmin=nurbs[nr].vknt[0];
  vmax=nurbs[nr].vknt[nurbs[nr].v_nknt-1];
  dv=(vmax-vmin)/(UV_STEPS-1);
  if( (printFlag) && ((umin<0.)||(vmin<0.)) )
  {
    printf(" WARNING: in NURBS:%s umin or vmin negative! They are set to 0. in evalNurbs()\n", nurbs[nr].name);
    printf(" umin:%lf umax:%lf du:%lf\n", umin,umax,du);
    printf(" vmin:%lf vmax:%lf dv:%lf\n", vmin,vmax,dv);
  }
  for(i=0; i<UV_STEPS; i++) { dtab_u[i]=umin+du*i; dtab_v[i]=vmin+dv*i; }

  for(i=0; i<UV_STEPS; i++) { dtab_05[i]=(vmax+vmin)*.5; }
  evalNurbs( nurbs, nr, UV_STEPS, dtab_u, dtab_05, tab_p);
  lu=0.;
  for(i=1; i<UV_STEPS; i++)
  {
    p0[0]=tab_p[i-1].px;
    p0[1]=tab_p[i-1].py;
    p0[2]=tab_p[i-1].pz;
    p1[0]=tab_p[i].px;
    p1[1]=tab_p[i].py;
    p1[2]=tab_p[i].pz;
    v_result(p0,p1,p0p1);
    lu+=v_betrag(p0p1);
  }

  for(i=0; i<UV_STEPS; i++) { dtab_05[i]=(umax+umin)*.5; }
  evalNurbs( nurbs, nr, UV_STEPS, dtab_05, dtab_v, tab_p);
  lv=0.;
  for(i=1; i<UV_STEPS; i++)
  {
    p0[0]=tab_p[i-1].px;
    p0[1]=tab_p[i-1].py;
    p0[2]=tab_p[i-1].pz;
    p1[0]=tab_p[i].px;
    p1[1]=tab_p[i].py;
    p1[2]=tab_p[i].pz;
    v_result(p0,p1,p0p1);
    lv+=v_betrag(p0p1);
  }

  /* average resolution based on gtol which is related to the width of the model */
  e_length=gtol/scale->w*GTOL_NODE_DIST;
  nurbs[nr].ures=lu/(umax-umin)/e_length;
  nurbs[nr].vres=lv/(vmax-vmin)/e_length;

  factor=(GL_FEEDBACK_BUFF_SIZE/(13*vmax*umax))/(nurbs[nr].ures*nurbs[nr].vres);
  if(factor<1.)
  {
    nurbs[nr].ures*=factor;
    nurbs[nr].vres*=factor;
  }
  if(nurbs[nr].ures<(1+nurbs[nr].u_exp*2./(umax-umin))) nurbs[nr].ures=1+nurbs[nr].u_exp*2./(umax-umin);
  if(nurbs[nr].vres<(1+nurbs[nr].u_exp*2./(vmax-vmin))) nurbs[nr].vres=1+nurbs[nr].v_exp*2./(vmax-vmin);

#if TEST
  printf("nurbsresolution: maxdiv:%lf gtol:%lf scale:%lf eldist:%lf uv:%lf %lf luv:%lf %lf  el/uv: %d %d \n",factor, gtol, scale->w,e_length, umax, vmax, lu,lv, nurbs[nr].ures,nurbs[nr].vres); 
#endif
}



void repNurs(int nr )
{
  int i,j;


  /* calculation of an average position for the name-string */
  nurbs[nr].tx=nurbs[nr].ty=nurbs[nr].tz=0.;
  for (i=0; i<nurbs[nr].u_npnt; i++)
  {
    for (j=0; j<nurbs[nr].v_npnt; j++)
    {
      nurbs[nr].tx+=point[nurbs[nr].ctlpnt[i][j]].px ;
      nurbs[nr].ty+=point[nurbs[nr].ctlpnt[i][j]].py ;
      nurbs[nr].tz+=point[nurbs[nr].ctlpnt[i][j]].pz ;
    }
  }
  nurbs[nr].tx/=nurbs[nr].u_npnt*nurbs[nr].v_npnt;
  nurbs[nr].ty/=nurbs[nr].u_npnt*nurbs[nr].v_npnt;
  nurbs[nr].tz/=nurbs[nr].u_npnt*nurbs[nr].v_npnt;

  /* calculation of the controll-point-array for drawing purposes */
  if( nurbs[nr].name != (unsigned char *)NULL )
  {
    if( (nurbs[nr].ctlarray = (GLfloat *)realloc( (GLfloat *)nurbs[nr].ctlarray, (nurbs[nr].u_npnt*nurbs[nr].v_npnt*nurbs[nr].v_stride+5)*sizeof(GLfloat) )) == NULL )
    { printf(" ERROR: realloc failure in repNurbs(), nurbs:%s can not be shaped\n\n", nurbs[nr].name);
      return; }
     
    /* calculate the position of the control-array */
    for (i=0; i<nurbs[nr].u_npnt; i++)
    {
      for (j=0; j<nurbs[nr].v_npnt; j++)
      {
        nurbs[nr].ctlarray[i*(nurbs[nr].v_stride*nurbs[nr].v_npnt)+j*(nurbs[nr].v_stride)+0]=nurbs[nr].weight[i][j]*point[nurbs[nr].ctlpnt[i][j]].px;
        nurbs[nr].ctlarray[i*(nurbs[nr].v_stride*nurbs[nr].v_npnt)+j*(nurbs[nr].v_stride)+1]=nurbs[nr].weight[i][j]*point[nurbs[nr].ctlpnt[i][j]].py;
        nurbs[nr].ctlarray[i*(nurbs[nr].v_stride*nurbs[nr].v_npnt)+j*(nurbs[nr].v_stride)+2]=nurbs[nr].weight[i][j]*point[nurbs[nr].ctlpnt[i][j]].pz;
        nurbs[nr].ctlarray[i*(nurbs[nr].v_stride*nurbs[nr].v_npnt)+j*(nurbs[nr].v_stride)+3]=nurbs[nr].weight[i][j];
      }
    }
  }
  calcNurbsResolution(nr);
}



/* delete the trimming data which where created in repSurf before */
void untrimNurs(int nr )
{
  int patch, curve;

  for(patch=0; patch<nurbs[nr].patches; patch++)
  {
    for(curve=0; curve<nurbs[nr].nc[patch]; curve++)
    {
      free(nurbs[nr].uv[patch][curve]);
      free(nurbs[nr].xyz[patch][curve]);
    }
    free(nurbs[nr].np[patch]);
    free(nurbs[nr].uv[patch]);
    free(nurbs[nr].xyz[patch]);
  }
  if(!nurbs[nr].np)  free(nurbs[nr].np);
  if(!nurbs[nr].uv)  free(nurbs[nr].uv);
  if(!nurbs[nr].xyz) free(nurbs[nr].xyz);
  if(!nurbs[nr].nc)  free(nurbs[nr].nc);
  if(!nurbs[nr].vmax) free(nurbs[nr].vmax);
  if(!nurbs[nr].umax) free(nurbs[nr].umax);

  nurbs[nr].np=NULL;
  nurbs[nr].uv=NULL;
  nurbs[nr].xyz=NULL;

  nurbs[nr].nc=NULL;
  nurbs[nr].vmax=NULL;
  nurbs[nr].umax=NULL;
  
  nurbs[nr].patches=0;
}



int adjustFeedBack( int npgn, GLfloat *pgn, double **ptr)
{
  int i, n=0, m=0, nv, nbuf;
  double v1[3],v2[3],vn[3];
  double vbuf[2][3];

  GLfloat token;
  double *pgn_new;

  /* create a new array for the polygons with its normals (guessed to be twice as large) */
  if( (pgn_new= (double *)malloc( npgn*2*sizeof(double) )) == NULL )
  { printf(" ERROR: malloc failure in adjustFeedBack()\n\n"); exit(-1); }
  

  while((npgn-n))
  {
    token= pgn[n++];
    if(token==GL_POLYGON_TOKEN)
    {
      pgn_new[m++]=token;
      nv=pgn_new[m++]=pgn[n++];
      if(nv!=3) printf("GL_POLYGON_TOKEN with %d vertexes\n", nv);
      nbuf=n;
      for( i=0; i<nv; i++)
      {
        pgn[n]-=width_w1/2; pgn[n++]/=width_w1/2;  /* x */
        pgn[n]-=width_w1/2; pgn[n++]/=width_w1/2;  /* y */
        pgn[n]-=0.5;  pgn[n++]*=-2.;   /* z */
      }

      /* calculate the normal and add to the start of the polygon */
      vbuf[0][0]=pgn[n-nv*3];
      vbuf[0][1]=pgn[n-nv*3+1];
      vbuf[0][2]=pgn[n-nv*3+2];
      vbuf[1][0]=pgn[3+n-nv*3];
      vbuf[1][1]=pgn[3+n-nv*3+1];
      vbuf[1][2]=pgn[3+n-nv*3+2];
      v_result(vbuf[0],vbuf[1], v1); 
      vbuf[1][0]=pgn[6+n-nv*3];
      vbuf[1][1]=pgn[6+n-nv*3+1];
      vbuf[1][2]=pgn[6+n-nv*3+2];
      v_result(vbuf[0],vbuf[1], v2);
      v_prod(v1,v2,vn);
      v_norm(vn,&pgn_new[m]); m+=3;
      for( i=0; i<nv; i++)
      {
        pgn_new[m++]=pgn[nbuf++];  /* x */
        pgn_new[m++]=pgn[nbuf++];  /* y */
        pgn_new[m++]=pgn[nbuf++];  /* z */
      }
   
    }
    else if(token==GL_POINT_TOKEN) { printf("ERROR: unsupported token %lf\n",token ); exit(-1); }
    else if(token==GL_LINE_TOKEN) { printf("ERROR: unsupported token %lf\n",token ); exit(-1); }
    else if(token==GL_LINE_RESET_TOKEN) { printf("ERROR: unsupported token %lf\n",token ); exit(-1); }
    else if(token==GL_PASS_THROUGH_TOKEN) { printf("ERROR: unsupported token %lf\n",token ); exit(-1); } 
    else { printf("ERROR: unknown token %lf\n",token ); exit(-1); }
  }

  *ptr=pgn_new;
  return(m);  
} 



int fillBlendedSurf(int nr)
{
  int i,j,s;
  int setNrbuf, buf;

  int anz_p=0, anz_l=0, anz_s=0;
  Points *ptmp=NULL;
  Lines *ltmp=NULL;
  Gsur *stmp=NULL;

  fillSurfFlag=1;

  /* store surf in set */
  setNrbuf=pre_seta(specialset->tmp, "i", 0 );
  seta(setNrbuf,"s",nr);

  /* complete set */
  completeSet( specialset->tmp, "do") ;

  /* save the mesh data of the affected entities */
  if ((ptmp = (Points *)malloc((set[setNrbuf].anz_p+1)*sizeof(Points)) ) == NULL )
  { printf("\n ERROR: malloc failure\n\n"); return(-1); }
  anz_p=set[setNrbuf].anz_p;
  for(i=0; i<set[setNrbuf].anz_p; i++)
  {
    if ((ptmp[i].nod = (int *)malloc((int)(point[set[setNrbuf].pnt[i]].nn+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1);  }
    for(j=0; j<point[set[setNrbuf].pnt[i]].nn; j++)
    {
      ptmp[i].nod[j]=point[set[setNrbuf].pnt[i]].nod[j];
    }
    ptmp[i].nn=point[set[setNrbuf].pnt[i]].nn;
    free(point[set[setNrbuf].pnt[i]].nod);
    point[set[setNrbuf].pnt[i]].nod=NULL; 
    point[set[setNrbuf].pnt[i]].nn=-1;
  }
  if ((ltmp = (Lines  *)malloc((set[setNrbuf].anz_l+1)*sizeof(Lines )) ) == NULL )
  { printf("\n ERROR: malloc failure\n\n"); return(-1); }
  anz_l=set[setNrbuf].anz_l;
  for(i=0; i<set[setNrbuf].anz_l; i++)
  {
    if ((ltmp[i].nod = (int *)malloc((int)(line[set[setNrbuf].line[i]].nn+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1); }
    for(j=0; j<line[set[setNrbuf].line[i]].nn; j++)
    {
      ltmp[i].nod[j]=line[set[setNrbuf].line[i]].nod[j];
    } 
    if ((ltmp[i].elem = (int *)malloc((int)(line[set[setNrbuf].line[i]].ne+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1); }
    for(j=0; j<line[set[setNrbuf].line[i]].ne; j++)
    {
      ltmp[i].elem[j]=line[set[setNrbuf].line[i]].elem[j];
    } 
    ltmp[i].nn=line[set[setNrbuf].line[i]].nn;
    ltmp[i].ne=line[set[setNrbuf].line[i]].ne;
    ltmp[i].eattr=line[j].eattr;
    free(line[set[setNrbuf].line[i]].nod); free(line[set[setNrbuf].line[i]].elem);
    line[set[setNrbuf].line[i]].nod=NULL; line[set[setNrbuf].line[i]].elem=NULL; 
    line[set[setNrbuf].line[i]].nn=-1; line[set[setNrbuf].line[i]].ne=-1;
  }
  if ((stmp = (Gsur   *)malloc((set[setNrbuf].anz_s+1)*sizeof(Gsur  )) ) == NULL )
  { printf("\n ERROR: malloc failure\n\n"); return(-1); }
  anz_s=set[setNrbuf].anz_s;
  for(i=0; i<set[setNrbuf].anz_s; i++)
  {
    if ((stmp[i].nod = (int *)malloc((int)(surf[set[setNrbuf].surf[i]].nn+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1); }
    for(j=0; j<surf[set[setNrbuf].surf[i]].nn; j++)
    {
      stmp[i].nod[j]=surf[set[setNrbuf].surf[i]].nod[j];
    } 
    if ((stmp[i].elem = (int *)malloc((int)(surf[set[setNrbuf].surf[i]].ne+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n");  return(-1);}
    for(j=0; j<surf[set[setNrbuf].surf[i]].ne; j++)
    {
      stmp[i].elem[j]=surf[set[setNrbuf].surf[i]].elem[j];
    } 
    stmp[i].nn=surf[set[setNrbuf].surf[i]].nn;
    stmp[i].ne=surf[set[setNrbuf].surf[i]].ne;
    stmp[i].eattr=surf[j].eattr;
    surf[j].eattr=0;
    free(surf[set[setNrbuf].surf[i]].nod); free(surf[set[setNrbuf].surf[i]].elem);
    surf[set[setNrbuf].surf[i]].nod=NULL; surf[set[setNrbuf].surf[i]].elem=NULL; 
    surf[set[setNrbuf].surf[i]].nn=-1; surf[set[setNrbuf].surf[i]].ne=-1;
  }


  /* mesh points and lines with the standard routines */
  /* create the rendering poligones with an modified routine without mesh-improver */     
  buf= meshPoints(setNrbuf) ;
  buf= meshLines( setNrbuf);
  buf= meshSurfs( setNrbuf) ;

  /* delete the temporary entities which were created to substitute 3- and 5-sided surfs */
  /* warning, s is now redefined */
  s=getSetNr(specialset->zap); 
  if(s>-1) 
  {
    for(i=0; i<set[s].anz_b; i++)
    {
	if(printFlag) printf (" delete body:%s \n",  body[set[s].body[i]].name );
	setr( 0, "b",set[s].body[i] );
	body[set[s].body[i]].name = (unsigned char *)NULL ;
	body[set[s].body[i]].ns=0;
	free(body[set[s].body[i]].o);
	body[set[s].body[i]].o= NULL;
	free(body[set[s].body[i]].s);
	body[set[s].body[i]].s= NULL;
	body[set[s].body[i]].nn=-1;
	free(body[set[s].body[i]].nod);
	body[set[s].body[i]].nod= NULL;
	body[set[s].body[i]].ne=-1;
	free(body[set[s].body[i]].elem);
	body[set[s].body[i]].elem= NULL;      
	body[set[s].body[i]].etyp= 0;
    }
    for(i=0; i<set[s].anz_s; i++)
    {
	if(printFlag) printf (" delete surf:%s \n",  surf[set[s].surf[i]].name );
	setr( 0, "s",set[s].surf[i] );
	surf[set[s].surf[i]].name = (unsigned char *)NULL ;
	surf[set[s].surf[i]].nl= 0;
	free(surf[set[s].surf[i]].typ);
	surf[set[s].surf[i]].typ= NULL;
	free(surf[set[s].surf[i]].o);
	surf[set[s].surf[i]].o= NULL;
	free(surf[set[s].surf[i]].l);
	surf[set[s].surf[i]].l= NULL;
	surf[set[s].surf[i]].nn= -1;
	free(surf[set[s].surf[i]].nod);
	surf[set[s].surf[i]].nod= NULL;
	surf[set[s].surf[i]].ne= -1;
	free(surf[set[s].surf[i]].elem);
	surf[set[s].surf[i]].elem= NULL;
	surf[set[s].surf[i]].etyp= 0;
    }
    for(i=0; i<set[s].anz_l; i++)
    {
	if(printFlag) printf (" delete line:%s \n",  line[set[s].line[i]].name );
	setr( 0, "l",set[s].line[i] );
	line[set[s].line[i]].name = (unsigned char *)NULL ;
	line[set[s].line[i]].div = 0;
	if (line[set[s].line[i]].typ=='s')
	{
	  /* delete the set */
	  delSet(set[line[set[s].line[i]].trk].name);
	}
	line[set[s].line[i]].typ=' ';
	line[set[s].line[i]].etyp=0;
	line[set[s].line[i]].p1=-1;
	line[set[s].line[i]].p2=-1;
	line[set[s].line[i]].trk=-1;
	line[set[s].line[i]].nip= 0;
	free(line[set[s].line[i]].ip);
	line[set[s].line[i]].ip= NULL;
	line[set[s].line[i]].nn= -1;
	free(line[set[s].line[i]].nod);
	line[set[s].line[i]].nod = NULL;
	line[set[s].line[i]].ne= -1;
	free(line[set[s].line[i]].elem);
	line[set[s].line[i]].elem = NULL;
    }
    for(i=0; i<set[s].anz_c; i++)
    {
	if(printFlag) printf (" delete lcmb:%s \n",  lcmb[set[s].lcmb[i]].name );
	setr( 0, "c",set[s].lcmb[i] );
	lcmb[set[s].lcmb[i]].name = (unsigned char *)NULL;
	lcmb[set[s].lcmb[i]].nl=0;
	free(lcmb[set[s].lcmb[i]].o);
	lcmb[set[s].lcmb[i]].o= NULL;
	free(lcmb[set[s].lcmb[i]].l);
	lcmb[set[s].lcmb[i]].l= NULL;
	lcmb[set[s].lcmb[i]].p1=-1;
	lcmb[set[s].lcmb[i]].p2=-1;
    }
    for(i=0; i<set[s].anz_p; i++)
    {
	if(printFlag) printf (" delete pnt:%s \n",  point[set[s].pnt[i]].name );
	setr( 0, "p",set[s].pnt[i] );
	point[set[s].pnt[i]].name = (unsigned char *)NULL ; 
	free(point[set[s].pnt[i]].nod);
	point[set[s].pnt[i]].nod=NULL; 
	point[set[s].pnt[i]].nn=-1; 
    }
    /* delete the set itself */
    delSet(specialset->zap);
  }

  /* restore the mesh data of the affected entities */
  for(i=0; i<anz_p; i++)
  {
    point[set[setNrbuf].pnt[i]].nn=ptmp[i].nn;
    if ((point[set[setNrbuf].pnt[i]].nod = (int *)malloc((int)(point[set[setNrbuf].pnt[i]].nn+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1);  }
    for(j=0; j<ptmp[i].nn; j++)
    {
      point[set[setNrbuf].pnt[i]].nod[j]=ptmp[i].nod[j];
    }
    free(ptmp[i].nod);
    ptmp[i].nod=NULL; 
    ptmp[i].nn=-1;
  }
  for(i=0; i<anz_l; i++)
  {
    line[set[setNrbuf].line[i]].nn=ltmp[i].nn;
    line[set[setNrbuf].line[i]].ne=ltmp[i].ne;
    if ((line[set[setNrbuf].line[i]].nod = (int *)malloc((int)(line[set[setNrbuf].line[i]].nn+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1); }
    if ((line[set[setNrbuf].line[i]].elem = (int *)malloc((int)(line[set[setNrbuf].line[i]].ne+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1); }
    for(j=0; j<ltmp[i].nn; j++)
    {
      line[set[setNrbuf].line[i]].nod[j]=ltmp[i].nod[j];
    }
    for(j=0; j<ltmp[i].ne; j++)
    {
      line[set[setNrbuf].line[i]].elem[j]=ltmp[i].elem[j];
    }
    free(ltmp[i].nod);
    ltmp[i].nod=NULL; 
    ltmp[i].nn=-1;
    free(ltmp[i].elem);
    ltmp[i].elem=NULL; 
    ltmp[i].ne=-1;
  }
  for(i=0; i<anz_s; i++)
  {
    surf[i].eattr=stmp[i].eattr;
    surf[set[setNrbuf].surf[i]].nn=stmp[i].nn;
    surf[set[setNrbuf].surf[i]].ne=stmp[i].ne;
    if (( surf[set[setNrbuf].surf[i]].nod= (int *)malloc((int)(surf[set[setNrbuf].surf[i]].nn+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n"); return(-1); }
    if (( surf[set[setNrbuf].surf[i]].elem= (int *)malloc((int)(surf[set[setNrbuf].surf[i]].ne+1)*sizeof(int)) ) == NULL )
    { printf(" ERROR: malloc failure\n\n");  return(-1);}
    for(j=0; j<stmp[i].nn; j++)
    {
      surf[set[setNrbuf].surf[i]].nod[j]=stmp[i].nod[j];
    }
    for(j=0; j<stmp[i].ne; j++)
    {
      surf[set[setNrbuf].surf[i]].elem[j]=stmp[i].elem[j];
    }
    free(stmp[i].nod);
    stmp[i].nod=NULL; 
    stmp[i].nn=-1;
    free(stmp[i].elem);
    stmp[i].elem=NULL; 
    stmp[i].ne=-1;
  }
  
  fillSurfFlag=0;
  delSet(specialset->tmp);
  return(1);
}




/*  store the polygons in the master-surface for illuminated rendering */
/*  if the surface is nurbs-related: */
/*  - create trimming-points for dispaying trimmed Nurbs-Shapes */
/*  if the surf is BLENDed */
/*  - mesh the surface with tri3 without mesh improvements */
void repSurf(int nr )
{
  int i,j,l,cl,nip,flag,oprod;
  int n;    /* running number through all inner-points ip in the line-def */  
  int k=0;  /* running number through all corners in the surf-def */
  int p;    /* running number through all points of each closed curve (trimming-loops) of the surf */
  int cp;    /* running number through all points of each closed curve (trimming-loops) of the surf */
  static double *lcurve=NULL; /* tracks the length of all closed curves, the biggest is the outer loop. */
  static double *nu=NULL, *nv=NULL;  /* sum of the u and v coordinates for all curves, averaged */  
  static GLdouble *knt=NULL;           /* knot-buffer to invert nurbs-curves if necessary */
  double p0[3], p0p1[3], p0p2[3], p1[3], p2[3], p1p2[3], lp1p2, lmax=0.;
  double vn[3];
  int c_outer=0, patch;
  double *fbuf=NULL;
  int nclp;
  double *xyz=NULL;
  Nurbs nurb;
  int nurbsbuf;
  static GLint ipuf[2];

  int firstl, lastl;
  int *linbuf=NULL;
  unsigned char *oribuf=NULL;

  /* nurbs evaluation into the back-buffer */
  GLfloat *feedbackbuffer=NULL;
  GLint   size_fbb;

  double tol_ambig;


  /* if its a BLENDed surface */
  if(( surf[nr].name != (unsigned char *)NULL )&&(surf[nr].sh==-1)&&(surf[nr].nc>0))
  {
    printf("BLEND:%s\n",surf[nr].name);

    fillBlendedSurf(nr);
  }

  /* if its a NURBS related surface */
  if(( surf[nr].name != (unsigned char *)NULL )&&(surf[nr].sh>-1)&&(surf[nr].nc>0))
  {

    /* disable culling else not all surfs will be filled */
    glGetIntegerv( GL_CULL_FACE_MODE, ipuf );
    glDisable ( GL_CULL_FACE );

    /* check if the nurbs can be handled by the libGLU. */
    /* if not create an temporary approximation. The trias will be later corrected by the original nurbs */  
    if((nurbs[surf[nr].sh].u_exp>=gl_max_eval_order)||(nurbs[surf[nr].sh].v_exp>=gl_max_eval_order))
    {
      printf("WARNING: Nurbs:%s of order:%d %d will be redefined. Only %d is supported by the gl-lib.\n", nurbs[surf[nr].sh].name, nurbs[surf[nr].sh].u_exp+1, nurbs[surf[nr].sh].v_exp+1, gl_max_eval_order);
      nurbsbuf=1;

      /* save the original definition in a buffer */
      nurb.u_exp = nurbs[surf[nr].sh].u_exp;
      nurb.v_exp = nurbs[surf[nr].sh].v_exp;
      nurb.u_npnt= nurbs[surf[nr].sh].u_npnt;
      nurb.v_npnt= nurbs[surf[nr].sh].v_npnt;
      nurb.u_nknt= nurbs[surf[nr].sh].u_nknt;
      nurb.v_nknt= nurbs[surf[nr].sh].v_nknt;
      nurb.u_stride= nurbs[surf[nr].sh].u_stride;
      if ( (nurb.uknt = (GLfloat *)malloc( (nurbs[surf[nr].sh].u_nknt+1) * sizeof(GLfloat))) == NULL )
        printf("\n\n ERROR: realloc failed uknt\n\n");
      if ( (nurb.vknt = (GLfloat *)malloc( (nurbs[surf[nr].sh].v_nknt+1) * sizeof(GLfloat))) == NULL )
        printf("\n\n ERROR: realloc failed vknt\n\n");
      for(i=0; i<nurb.u_nknt; i++) { nurb.uknt[i]=nurbs[surf[nr].sh].uknt[i]; }
      for(i=0; i<nurb.v_nknt; i++) { nurb.vknt[i]=nurbs[surf[nr].sh].vknt[i]; }
      if( (nurb.ctlarray = (GLfloat *)malloc( (nurbs[surf[nr].sh].u_npnt*nurbs[surf[nr].sh].v_npnt*nurbs[surf[nr].sh].v_stride+5)*sizeof(GLfloat) )) == NULL )
      { printf(" ERROR: realloc failure in repairNurbs(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name); return; }
      for (i=0; i<nurbs[surf[nr].sh].u_npnt*nurbs[surf[nr].sh].v_npnt*nurbs[surf[nr].sh].v_stride+4; i++) nurb.ctlarray[i]=nurbs[surf[nr].sh].ctlarray[i];

      /* create the approximation */
      if(nurbs[surf[nr].sh].u_exp>=gl_max_eval_order) repairNurbs( nurbs, surf[nr].sh, nurbs[surf[nr].sh].u_exp-gl_max_eval_order+1, 0);
      if(nurbs[surf[nr].sh].v_exp>=gl_max_eval_order) repairNurbs( nurbs, surf[nr].sh, nurbs[surf[nr].sh].v_exp-gl_max_eval_order+1, 1);
      calcNurbsResolution(surf[nr].sh);
    }
    else nurbsbuf=0;


    if((nurbs[surf[nr].sh].u_exp<gl_max_eval_order)&&(nurbs[surf[nr].sh].v_exp<gl_max_eval_order))
    {
      patch=nurbs[surf[nr].sh].patches;
      surf[nr].patch=patch;
      nurbs[surf[nr].sh].patches++;
      printf("NURBS:%s patch%d\n",nurbs[surf[nr].sh].name, patch);

      if( (nurbs[surf[nr].sh].umax= (double *)realloc( (double *)nurbs[surf[nr].sh].umax, (nurbs[surf[nr].sh].patches)*sizeof(double) )) == NULL )
      { printf(" ERROR: realloc failure0 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nurbs[surf[nr].sh].vmax= (double *)realloc( (double *)nurbs[surf[nr].sh].vmax, (nurbs[surf[nr].sh].patches)*sizeof(double) )) == NULL )
      { printf(" ERROR: realloc failure1 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nurbs[surf[nr].sh].nc= (int *)realloc( (int *)nurbs[surf[nr].sh].nc, (nurbs[surf[nr].sh].patches)*sizeof(int) )) == NULL )
      { printf(" ERROR: realloc failure2 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }

      if( (nurbs[surf[nr].sh].np= (int **)realloc( (int **)nurbs[surf[nr].sh].np, (nurbs[surf[nr].sh].patches)*sizeof(int *) )) == NULL )
      { printf(" ERROR: realloc failure3 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nurbs[surf[nr].sh].np[patch]= (int *)malloc( (surf[nr].nc+1)*sizeof(int) )) == NULL )
      { printf(" ERROR: realloc failure4 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (lcurve= (double *)realloc( (double *)lcurve, (surf[nr].nc+1)*sizeof(double) )) == NULL )
      { printf(" ERROR: realloc failure5 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nu= (double *)realloc( (double *)nu, (surf[nr].nc+1)*sizeof(double) )) == NULL )
      { printf(" ERROR: realloc failure6 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nv= (double *)realloc( (double *)nv, (surf[nr].nc+1)*sizeof(double) )) == NULL )
      { printf(" ERROR: realloc failure7 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }

      if( (nurbs[surf[nr].sh].uv = (GLfloat ***)realloc( (GLfloat ***)nurbs[surf[nr].sh].uv, (nurbs[surf[nr].sh].patches)*sizeof(GLfloat **) )) == NULL )
      { printf(" ERROR: realloc failure8 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nurbs[surf[nr].sh].uv[patch] = (GLfloat **)malloc( (surf[nr].nc+1)*sizeof(GLfloat *) )) == NULL )
      { printf(" ERROR: realloc failure9 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nurbs[surf[nr].sh].xyz = (double ***)realloc( (double ***)nurbs[surf[nr].sh].xyz, (nurbs[surf[nr].sh].patches)*sizeof(double **) )) == NULL )
      { printf(" ERROR: realloc failure10 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      if( (nurbs[surf[nr].sh].xyz[patch] = (double **)malloc( (surf[nr].nc+1)*sizeof(double *) )) == NULL )
      { printf(" ERROR: realloc failure11 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
        return; }
      for (i=0; i<surf[nr].nc; i++)
      {
        lcurve[i]=nu[i]=nv[i]=0.;
        nurbs[surf[nr].sh].uv[patch][i]=NULL ;
        nurbs[surf[nr].sh].xyz[patch][i]=NULL ;
      }

      /* from here on a trimming attempt is made if necessary and repeated if failed */
      tol_ambig=TOL_AMBIG; 
     tryAgainToTrim:;
      k=0;
      for (i=0; i<surf[nr].nc; i++)
      {
        p=0;
        cp=0;
        nip=0;
        for(j=0; j<surf[nr].c[i]; j++)
	{
          /* store the locations of all line-points, they will be projected to the NURBS */
          if(surf[nr].typ[k]=='l')
	  {
            l=surf[nr].l[k];
            nip+=line[l].nip;

            if( (nurbs[surf[nr].sh].uv[patch][i] = (GLfloat *)realloc( (GLfloat *)nurbs[surf[nr].sh].uv[patch][i], (nip)*sizeof(GLfloat) ))==NULL )
            { printf(" ERROR: realloc failure12 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
              return; }
            if( (nurbs[surf[nr].sh].xyz[patch][i] = (double *)realloc( (double *)nurbs[surf[nr].sh].xyz[patch][i], (nip)*sizeof(double ) ))==NULL )
            { printf(" ERROR: realloc failure13 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
              return; }

            if(surf[nr].o[k]=='+')
            {             
              if(j==0)                     { n=0; flag=line[l].nip-3; }
              else if(j==surf[nr].c[i]-1)    { n=0; flag=line[l].nip; }
              else                         { n=0; flag=line[l].nip-3; }
              do
              {
                nurbs[surf[nr].sh].xyz[patch][i][p]=line[l].ip[n++];
                p++;
              }while(n<flag);
            }
            else
            {             
              if(j==0)                     { n=line[l].nip; flag=3; }
              else if(j==surf[nr].c[i]-1)    { n=line[l].nip; flag=0; }
              else                         { n=line[l].nip; flag=3; }
              while(n>flag)
              {
                nurbs[surf[nr].sh].xyz[patch][i][p+2]=line[l].ip[--n];
                nurbs[surf[nr].sh].xyz[patch][i][p+1]=line[l].ip[--n];
                nurbs[surf[nr].sh].xyz[patch][i][p]=line[l].ip[--n];
                p+=3;
              }
            }
	  }
          else
	  {
            /* first generate an array of internal points of all lines */
            nclp=0;
            for(cl=0; cl<lcmb[surf[nr].l[k]].nl; cl++)
	    {
              l=lcmb[surf[nr].l[k]].l[cl];

              if( (xyz = (double *)realloc( (double *)xyz, (nclp+line[l].nip)*sizeof(double ) ))==NULL )
              { printf(" ERROR: realloc failure15 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
                return; }

              if(lcmb[surf[nr].l[k]].o[cl]=='-') flag=-1;
              else flag=1;

              if(flag==1)
              {
                if(cl==0)                     { n=0; flag=line[l].nip-3; }
                else if(cl==lcmb[surf[nr].l[j]].nl-1)    { n=0; flag=line[l].nip; }
                else                         { n=0; flag=line[l].nip-3; }
                do
                {
                  xyz[nclp]=line[l].ip[n++];
                  nclp++;
                }while(n<flag);
              }
              else
              {
                if(cl==0)                     { n=line[l].nip; flag=3; }
                else if(cl==lcmb[surf[nr].l[j]].nl-1)    { n=line[l].nip; flag=0; }
                else                         { n=line[l].nip; flag=3; }
                while(n>flag)
                {
                  xyz[nclp]=line[l].ip[--n];
                  nclp++;
                  xyz[nclp]=line[l].ip[--n];
                  nclp++;
                  xyz[nclp]=line[l].ip[--n];
                  nclp++;
                }
              }
	    }

            /* then add this points to the line-loop */
            nip+=nclp;
            if( (nurbs[surf[nr].sh].uv[patch][i] = (GLfloat *)realloc( (GLfloat *)nurbs[surf[nr].sh].uv[patch][i], (nip)*sizeof(GLfloat) ))==NULL )
            { printf(" ERROR: realloc failure14 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
              return; }
            if( (nurbs[surf[nr].sh].xyz[patch][i] = (double *)realloc( (double *)nurbs[surf[nr].sh].xyz[patch][i], (nip)*sizeof(double ) ))==NULL )
            { printf(" ERROR: realloc failure15 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
              return; }

            if(surf[nr].o[k]=='+')
            {             
              if(j==0)                     { n=0; flag=nclp-3; }
              else if(j==surf[nr].c[i]-1)    { n=0; flag=nclp; }
              else                         { n=0; flag=nclp-3; }
              do
              {
                nurbs[surf[nr].sh].xyz[patch][i][p]=xyz[n++];
                p++;
              }while(n<flag);
            }
            else
            {             
              if(j==0)                     { n=nclp; flag=3; }
              else if(j==surf[nr].c[i]-1)    { n=nclp; flag=0; }
              else                         { n=nclp; flag=3; }
              while(n>flag)
              {
                nurbs[surf[nr].sh].xyz[patch][i][p+2]=xyz[--n];
                nurbs[surf[nr].sh].xyz[patch][i][p+1]=xyz[--n];
                nurbs[surf[nr].sh].xyz[patch][i][p]=xyz[--n];
                p+=3;
              }
            }
	  }

          k++;
	}
        nurbs[surf[nr].sh].np[patch][i]=p/3;
      }
      nurbs[surf[nr].sh].nc[patch]=surf[nr].nc;

      /* calc u,v coordinates for all trimming-points */
      trimNurbs(nurbs, surf[nr].sh, patch, tol_ambig);

      for (i=0; i<surf[nr].nc; i++)
      {
        /* determine the average point, needed to define the orientation of the curve */
        p1[0]=nurbs[surf[nr].sh].uv[patch][i][0];
        p1[1]=nurbs[surf[nr].sh].uv[patch][i][1];
        nu[i]+=p1[0];
        nv[i]+=p1[1];
        p1[2]=p2[2]=0.;
        cp=2; do
        {
          p2[0]=nurbs[surf[nr].sh].uv[patch][i][cp++];
          p2[1]=nurbs[surf[nr].sh].uv[patch][i][cp++];
          nu[i]+=p2[0];
          nv[i]+=p2[1];
          v_result( p1, p2, p1p2 );
          p1[0]=p2[0];
          p1[1]=p2[1];
          lp1p2=v_betrag( p1p2 );
          lcurve[i]+=lp1p2;
        }while(cp< nurbs[surf[nr].sh].np[patch][i]*2);
        nu[i]/=cp/2;
        nv[i]/=cp/2;

        if(lcurve[i]>lmax) { lmax=lcurve[i]; c_outer=i; }
      }
      if(printFlag) printf("outer curve:%d\n",c_outer);
      if(c_outer!=0) printf("WARNING: outer curve:%d, later qflp 'a' might be in error\n",c_outer);

      /* determine umax, vmax. Used in drawNurs_plot() */
      nurbs[surf[nr].sh].umax[patch]=nurbs[surf[nr].sh].vmax[patch]=-MAXVALUE;
      n=0; while(n<(nurbs[surf[nr].sh].np[patch][c_outer]*2))
      {
        if(nurbs[surf[nr].sh].umax[patch]<nurbs[surf[nr].sh].uv[patch][c_outer][n])
          nurbs[surf[nr].sh].umax[patch]=nurbs[surf[nr].sh].uv[patch][c_outer][n];
        n++;  
        if(nurbs[surf[nr].sh].vmax[patch]<nurbs[surf[nr].sh].uv[patch][c_outer][n])
          nurbs[surf[nr].sh].vmax[patch]=nurbs[surf[nr].sh].uv[patch][c_outer][n];  
        n++; 
      }
   
      if(printFlag) printf("patch:%d uvw_cp outer curve:%lf %lf %lf maxu:%lf maxv:%lf\n", patch, nu[c_outer], nv[c_outer], lmax, nurbs[surf[nr].sh].umax[patch], nurbs[surf[nr].sh].vmax[patch]);

      /* ORIENT-CHECK */
      /* check if the outer curve is correct oriented for trimming */
      /* the 1st has to be counter clockwhise and the others clockwhise */
      /* calculate the normal-vector of the outer-curve in the uv space of the nurbs */
      /* if its in -w direction then uv of the Nurbs must be changed */
      for(i=0; i<nurbs[surf[nr].sh].nc[patch]; i++)
      {
        p0[0]=nu[i];
        p0[1]=nv[i];
        p0[2]=0.;
        p1[2]=0.;
        p2[2]=0.;
        n=0; lmax=0.; do
        {
          /* add all normals based on uv[n] x uv[n+1] */
          p1[0]=nurbs[surf[nr].sh].uv[patch][i][n++];
          p1[1]=nurbs[surf[nr].sh].uv[patch][i][n++];
          p2[0]=nurbs[surf[nr].sh].uv[patch][i][n++];
          p2[1]=nurbs[surf[nr].sh].uv[patch][i][n++];
          v_result(p0, p1, p0p1);
          v_result(p0, p2, p0p2);
          v_prod(p0p1,p0p2,vn);
          lmax+=vn[2];
          /* printf("p1:%lf %lf p2:%lf %lf vn2:%lf \n", p1[0],p1[1], p2[0],p2[1],vn[2]); */
        }while(n<(nurbs[surf[nr].sh].np[patch][i]*2)-4);
  
        /* invert lmax for the inner curves for detection purposes*/
        if(i!=c_outer) lmax*=-1.;
        else 
        {
	  /* detect the orientation of the nurbs relative to the surf with the outer loop */
          if(lmax<0) surf[nr].sho='-'; else surf[nr].sho='+';
	}

        if(lmax<0.)
        {
          /* orientation of the curve must be changed (change u,v) */
          if( (knt= (GLdouble *)realloc( (GLdouble *)knt, ((nurbs[surf[nr].sh].np[patch][i]*2)+1)*sizeof(GLdouble) )) == NULL )
          { printf(" ERROR: realloc failure16 in repSurf(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name);
          return; }
          for (j=0; j<nurbs[surf[nr].sh].np[patch][i]*2; j++) knt[j]=nurbs[surf[nr].sh].uv[patch][i][j];
          n=(nurbs[surf[nr].sh].np[patch][i]*2)-1; j=0;
          do
          {
            nurbs[surf[nr].sh].uv[patch][i][j++]=knt[n-1];
            nurbs[surf[nr].sh].uv[patch][i][j++]=knt[n];
            n-=2;
          }while(n>0);
        }

        /* change the orientation also in the surf-definition */
        if(((lmax>0.)&&(surf[nr].sho=='-'))||((lmax<0.)&&(surf[nr].sho=='+')))
        {
          /* which lines are affected? */
          firstl=0; for(n=0; n<i; n++) firstl+=surf[nr].c[n]; lastl=firstl+surf[nr].c[n];

          if( (linbuf= (int *)malloc( (lastl-firstl+1)*sizeof(int) )) == NULL )
          { printf(" ERROR: realloc failure\n\n"); return; }
          if( (oribuf= (unsigned char *)malloc( (lastl-firstl+1)*sizeof(unsigned char) )) == NULL )
          { printf(" ERROR: realloc failure\n\n"); return; }

          j=0; for(n=firstl; n<lastl; n++)
          {
            linbuf[j]=surf[nr].l[n];
            if(surf[nr].o[n]=='+') oribuf[j++]='-'; else oribuf[j++]='+';
          }
          for(n=firstl; n<lastl; n++)
          {
            j--;
            surf[nr].l[n]=linbuf[j];
            surf[nr].o[n]=oribuf[j];
          }
          free(linbuf);
          free(oribuf);
        }
      }

      /* if the outer loop c_outer is not the first one (0) then rearrange the loops */
      if(c_outer!=0)
      {
        /* which lines are affected? */
        firstl=0; for(n=0; n<c_outer; n++) firstl+=surf[nr].c[n]; lastl=firstl+surf[nr].c[n];

        if( (linbuf= (int *)malloc( (lastl-firstl+1)*sizeof(int) )) == NULL )
        { printf(" ERROR: realloc failure\n\n"); return; }
        if( (oribuf= (unsigned char *)malloc( (lastl-firstl+1)*sizeof(unsigned char) )) == NULL )
        { printf(" ERROR: realloc failure\n\n"); return; }

        j=0; for(l=n=surf[nr].nl-1; n>=0; n--)
        {
          if((n<lastl)&&(n>=firstl))
	  {
            linbuf[j]=surf[nr].l[n];
            oribuf[j++]=surf[nr].o[n];
	  }
	  else
	  {
            surf[nr].l[l]=surf[nr].l[n];
            surf[nr].o[l--]=surf[nr].o[n];
	  }
        }
        j=0; for(n=l; n>=0; n--)
        {
          surf[nr].l[n]=linbuf[j];
          surf[nr].o[n]=oribuf[j++];
        }
        free(linbuf);
        free(oribuf);
      }
      /* end trim */

      /* now the trimmed region is defined. Render the nurbs-patch into the back-buffer and store */
      /* the poligons inside the surface */
      if(printFlag) printf("patch:%d of NURBS:%s is now rendered and stored in surf:%s\n", patch, nurbs[surf[nr].sh].name, surf[nr].name );

      /* malloc the feedbackbuffer, the address will be stored later and reallocated in surf[nr].pgn */
      size_fbb=GL_FEEDBACK_BUFF_SIZE;
      if( (feedbackbuffer= (GLfloat *)malloc(size_fbb*sizeof(GLfloat) )) == NULL )
      { printf(" ERROR: realloc failure in repSurf(), feedbackbuffer to big\n\n");
        return; }
      glLoadIdentity ();
      glOrtho( -1., 1., -1., 1., -1, 1. ); 
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glFeedbackBuffer (size_fbb, GL_3D, feedbackbuffer);
      glRenderMode (GL_FEEDBACK);

      /* draw the nurbs, copy from drawNurs_plot() */
      gluNurbsProperty(nurbs[surf[nr].sh].Nurb, GLU_DISPLAY_MODE, GLU_FILL);
      gluNurbsProperty(nurbs[surf[nr].sh].Nurb, GLU_CULLING, GL_TRUE);
      gluNurbsProperty(nurbs[surf[nr].sh].Nurb, GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE );
      gluNurbsProperty(nurbs[surf[nr].sh].Nurb, GLU_U_STEP,  nurbs[surf[nr].sh].ures );
      gluNurbsProperty(nurbs[surf[nr].sh].Nurb, GLU_V_STEP,  nurbs[surf[nr].sh].vres );
      gluBeginSurface(nurbs[surf[nr].sh].Nurb);
      gluNurbsSurface(nurbs[surf[nr].sh].Nurb,
      nurbs[surf[nr].sh].u_nknt, nurbs[surf[nr].sh].uknt,
      nurbs[surf[nr].sh].v_nknt, nurbs[surf[nr].sh].vknt,
      nurbs[surf[nr].sh].u_stride, nurbs[surf[nr].sh].v_stride,
      nurbs[surf[nr].sh].ctlarray,
      nurbs[surf[nr].sh].u_exp+1, nurbs[surf[nr].sh].v_exp+1,
      nurbs[surf[nr].sh].type);
      if(printFlag)
      {
        printf("nurbs-param:%d  %d %d  %d %d  %d %d  %d %d  %d  nod:%f %f %f %f arr:%f %f\n",size_fbb,
          nurbs[surf[nr].sh].ures,
          nurbs[surf[nr].sh].vres,
          nurbs[surf[nr].sh].u_nknt,
          nurbs[surf[nr].sh].v_nknt,
          nurbs[surf[nr].sh].u_stride, nurbs[surf[nr].sh].v_stride,
          nurbs[surf[nr].sh].u_exp+1, nurbs[surf[nr].sh].v_exp+1,
          nurbs[surf[nr].sh].type,
                 nurbs[nr].uknt[0],
                 nurbs[nr].uknt[nurbs[nr].u_nknt-1],
                 nurbs[nr].vknt[0],
                 nurbs[nr].vknt[nurbs[nr].v_nknt-1],
          nurbs[surf[nr].sh].ctlarray[0],
          nurbs[surf[nr].sh].ctlarray[nurbs[nr].u_npnt*nurbs[nr].v_npnt]
        );
      }
      
      for(i=0; i<nurbs[surf[nr].sh].nc[patch]; i++)
      {
        if(printFlag)
        {
	  printf("glu input in cgx format u,v,- %d %d %d\n", nurbs[surf[nr].sh].trimFlag, nurbs[surf[nr].sh].nc[patch], i);
	  n=0; for(j=0; j< nurbs[surf[nr].sh].np[patch][i]; j++)
          {
            printf(" pnt %d%d %lf %lf 0.\n",i,j, nurbs[surf[nr].sh].uv[patch][i][n], nurbs[surf[nr].sh].uv[patch][i][n+1]);
            n+=2;
          }
        }
        gluBeginTrim(nurbs[surf[nr].sh].Nurb);
        gluPwlCurve(nurbs[surf[nr].sh].Nurb, nurbs[surf[nr].sh].np[patch][i], nurbs[surf[nr].sh].uv[patch][i], (GLint)2, GLU_MAP1_TRIM_2);
        gluEndTrim(nurbs[surf[nr].sh].Nurb);
      }
      
      gluEndSurface(nurbs[surf[nr].sh].Nurb);
      surf[nr].npgn=glRenderMode (GL_RENDER);

      /* check if the surface could be trimmed and rendered */
      if(surf[nr].npgn<1)
      {
        if(tol_ambig==TOL_AMBIG) { tol_ambig/=10; goto tryAgainToTrim; }
        else if(tol_ambig==TOL_AMBIG/10) { tol_ambig=TOL_AMBIG*10; goto tryAgainToTrim; }
        else
        {
          /* try to make a mapped mesh */
          if(printFlag) printf(" GluNURBS: surf:%s could not be rendered, changed to mapped mesh\n", surf[nr].name);

          /* change the element attribute to mapped mesh */
          surf[nr].eattr=0;
          n=fillBlendedSurf(nr);
          if(n<1) surf[nr].npgn=0;

	  /* project the vertexes to the original nurbs only if no substitute surf was defined */
          if((!nurbsbuf)&&(n>0)) projSurfToNurbs( nurbs, surf[nr].sh, surf, nr, 0 );

          /* add surf to special set */
          pre_seta(specialset->bsur, "s", surf[nr].name );
        }
      }
      else
      {
        if(size_fbb<surf[nr].npgn) 
        {
          printf("ERROR in repSurf: feedbackbuffer:%d to small, increase at least to:%d \n", size_fbb, surf[nr].npgn);
          exit(-1);
        }

        /* store data from (GLfloat *)feedbackbuffer into  (double *)surf[nr].pgn */
        if (surf[nr].npgn) free(surf[nr].pgn);
  
        /* get the address of a new array including the normals */ 
        surf[nr].npgn=adjustFeedBack( surf[nr].npgn, feedbackbuffer, &surf[nr].pgn);
        free(feedbackbuffer);

        /* the triangles must be inverted if the product of the nurbs-ori and surf-ori is '-' */
        if(surf[nr].sho=='-') oprod=-1; else oprod=1;
        if(surf[nr].ori=='-') oprod*=-1; else oprod*=1;
        if(oprod==-1)
        {
          n=0;
          while((surf[nr].npgn-n))
          {
            /* switch interior of surf, code from pickfunktions (l:2560) */
            n++; /* jump over the polygon token (ie.GL_POLYGON_TOKEN) */
            j=surf[nr].pgn[n++];
            surf[nr].pgn[n]*=-1;
            surf[nr].pgn[n+1]*=-1;
            surf[nr].pgn[n+2]*=-1;
            n+=3;
            if ((fbuf = (double *)malloc((j*3)*sizeof(double)) ) == NULL )
            { printf("\n\nERROR: realloc failure in flip\n\n"); return; }
            for(k=0; k<j; k++)
            {
              fbuf[j*3-k*3-3]=surf[nr].pgn[n];
              fbuf[j*3-k*3-2]=surf[nr].pgn[n+1];
              fbuf[j*3-k*3-1]=surf[nr].pgn[n+2];
              n+=3;
            }
            n-=3*j;
            for(k=0; k<j; k++)
            {
              surf[nr].pgn[n]  =fbuf[k*3] ; 
              surf[nr].pgn[n+1]=fbuf[k*3+1];
              surf[nr].pgn[n+2]=fbuf[k*3+2];
              n+=3;
            }
            free(fbuf);
          }
        }
      }

      /* correct the position of the trias if an nurbs-approximation was used and change back to the original nurbs */
      if(nurbsbuf)
      {
        /* restore the original definition */
        nurbs[surf[nr].sh].u_exp = nurb.u_exp; 
        nurbs[surf[nr].sh].v_exp = nurb.v_exp;
        nurbs[surf[nr].sh].u_npnt= nurb.u_npnt;
        nurbs[surf[nr].sh].v_npnt= nurb.v_npnt;
        nurbs[surf[nr].sh].u_nknt= nurb.u_nknt;
        nurbs[surf[nr].sh].v_nknt= nurb.v_nknt;
        nurbs[surf[nr].sh].u_stride= nurb.u_stride;
        if ( (nurbs[surf[nr].sh].uknt = (GLfloat *)realloc(  (GLfloat *)nurbs[surf[nr].sh].uknt, (nurbs[surf[nr].sh].u_nknt+1) * sizeof(GLfloat))) == NULL )
          printf("\n\n ERROR: realloc failed uknt\n\n");
        if ( (nurbs[surf[nr].sh].vknt = (GLfloat *)realloc(  (GLfloat *)nurbs[surf[nr].sh].vknt, (nurbs[surf[nr].sh].v_nknt+1) * sizeof(GLfloat))) == NULL )
          printf("\n\n ERROR: realloc failed vknt\n\n");
        for(i=0; i<nurbs[surf[nr].sh].u_nknt; i++) { nurbs[surf[nr].sh].uknt[i]=nurb.uknt[i]; }
        for(i=0; i<nurbs[surf[nr].sh].v_nknt; i++) { nurbs[surf[nr].sh].vknt[i]=nurb.vknt[i]; }
        if( (nurbs[surf[nr].sh].ctlarray = (GLfloat *)realloc( (GLfloat *)nurbs[surf[nr].sh].ctlarray, (nurbs[surf[nr].sh].u_npnt*nurbs[surf[nr].sh].v_npnt*nurbs[surf[nr].sh].v_stride+5)*sizeof(GLfloat) )) == NULL )
        { printf(" ERROR: realloc failure in repairNurbs(), nurbs:%s can not be shaped\n\n", nurbs[surf[nr].sh].name); return; }
        for (i=0; i<nurbs[surf[nr].sh].u_npnt*nurbs[surf[nr].sh].v_npnt*4+4; i++) nurbs[surf[nr].sh].ctlarray[i]=nurb.ctlarray[i];
        free(nurb.ctlarray);
        free(nurb.uknt);
        free(nurb.vknt);

	/* project the vertexes to the original nurbs */
        projSurfToNurbs( nurbs, surf[nr].sh, surf, nr, 0 );
      }
    }
    else
    {
      printf("ERROR: Nurbs:%s of order:%d %d is not supported. Only %d is supported by the gl-lib.\n", nurbs[surf[nr].sh].name, nurbs[surf[nr].sh].u_exp+1, nurbs[surf[nr].sh].v_exp+1, gl_max_eval_order);
    }

    /* resore the original cull mode */
    if ( ipuf[0] == GL_BACK ) glCullFace ( GL_BACK );
    if ( ipuf[0] == GL_FRONT ) glCullFace ( GL_FRONT );
  }
}



/* create in-between-points in lines for dispaying curves */
void rep(int j )
{
  int k,n;
  double pn[3];

  /* calculation of the inner points of non-straight lines for drawing purposes */
  if( line[j].name != (unsigned char *)NULL )
  {
    if ((line[j].ip = (double *)realloc( (double *)line[j].ip, ((line[j].div+1)*3)*sizeof(double)) ) == NULL )
    { printf(" ERROR: realloc failure in rep(), Line:%s can not be shaped\n\n", line[j].name);
      return; }

    n=0;
    line[j].ip[n++]=point[line[j].p1].px;
    line[j].ip[n++]=point[line[j].p1].py;
    line[j].ip[n++]=point[line[j].p1].pz;
    if(line[j].typ=='a') for (k=0; k<line[j].div-1; k++)
    {
      arcNodes( j, k,line[j].div, pn );
      line[j].ip[n++]=pn[0];
      line[j].ip[n++]=pn[1];
      line[j].ip[n++]=pn[2];
    }
    else if (line[j].typ=='s') for (k=0; k<line[j].div-1; k++)
    {
      splineNodes( j, k,line[j].div, pn );
      line[j].ip[n++]=pn[0];
      line[j].ip[n++]=pn[1];
      line[j].ip[n++]=pn[2];
    }
    else if (line[j].typ=='n') for (k=0; k<line[j].div-1; k++)
    {
      nurlNodes( j, k,line[j].div, pn );
      line[j].ip[n++]=pn[0];
      line[j].ip[n++]=pn[1];
      line[j].ip[n++]=pn[2];
    }
    else for (k=0; k<line[j].div-1; k++)
    {
      /* must be! For the nurbs trimming all node-points are necessary */
      /* because long lines would not give enough inbetween points */
      straightNodes( j, k,line[j].div, pn );
      line[j].ip[n++]=pn[0];
      line[j].ip[n++]=pn[1];
      line[j].ip[n++]=pn[2];
    }
    line[j].ip[n++]=point[line[j].p2].px;
    line[j].ip[n++]=point[line[j].p2].py;
    line[j].ip[n++]=point[line[j].p2].pz;
    line[j].nip=n;
    /*   
  printf("line[%d].name:%s line[%d].typ:%c line[%d].div:%d line[%d].nip:%d\n"
  , j,line[j].name,j,line[j].typ,j,line[j].div,j, line[j].nip);
    */
  }
}


void adjustNodes()
{
  int i, n, n1,n2;

  for ( i=0; i<anz->e; i++ )
  {
    if(e_enqire[e_enqire[i].nr].type==4)
    {
    for (n=0; n<3; n++)  /*  additional nodes in center of areas */
    {
    node[e_enqire[e_enqire[i].nr].nod[20+n]].nx = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[0+n]].nx+
      node[e_enqire[e_enqire[i].nr].nod[1+n]].nx+
      node[e_enqire[e_enqire[i].nr].nod[5+n]].nx+
      node[e_enqire[e_enqire[i].nr].nod[4+n]].nx  ) +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[8+n]].nx+
      node[e_enqire[e_enqire[i].nr].nod[13+n]].nx+
      node[e_enqire[e_enqire[i].nr].nod[16+n]].nx+
      node[e_enqire[e_enqire[i].nr].nod[12+n]].nx ) ;
  
    node[e_enqire[e_enqire[i].nr].nod[20+n]].ny = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[0+n]].ny+
      node[e_enqire[e_enqire[i].nr].nod[1+n]].ny+
      node[e_enqire[e_enqire[i].nr].nod[5+n]].ny+
      node[e_enqire[e_enqire[i].nr].nod[4+n]].ny ) +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[8+n]].ny+
      node[e_enqire[e_enqire[i].nr].nod[13+n]].ny+
      node[e_enqire[e_enqire[i].nr].nod[16+n]].ny+
      node[e_enqire[e_enqire[i].nr].nod[12+n]].ny ) ;
  
    node[e_enqire[e_enqire[i].nr].nod[20+n]].nz = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[0+n]].nz+
      node[e_enqire[e_enqire[i].nr].nod[1+n]].nz+
      node[e_enqire[e_enqire[i].nr].nod[5+n]].nz+
      node[e_enqire[e_enqire[i].nr].nod[4+n]].nz ) +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[8+n]].nz +
      node[e_enqire[e_enqire[i].nr].nod[13+n]].nz+
      node[e_enqire[e_enqire[i].nr].nod[16+n]].nz+
      node[e_enqire[e_enqire[i].nr].nod[12+n]].nz ) ;
    }
  
    /* create  new node in center of area4 */
    node[e_enqire[e_enqire[i].nr].nod[23  ]].nx = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[3]].nx +
      node[e_enqire[e_enqire[i].nr].nod[0]].nx +
      node[e_enqire[e_enqire[i].nr].nod[4]].nx +
      node[e_enqire[e_enqire[i].nr].nod[7]].nx ) +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[11]].nx +
      node[e_enqire[e_enqire[i].nr].nod[12]].nx +
      node[e_enqire[e_enqire[i].nr].nod[19]].nx +
      node[e_enqire[e_enqire[i].nr].nod[15]].nx )  ;
  
    node[e_enqire[e_enqire[i].nr].nod[23  ]].ny = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[3]].ny +
      node[e_enqire[e_enqire[i].nr].nod[0]].ny +
      node[e_enqire[e_enqire[i].nr].nod[4]].ny +
      node[e_enqire[e_enqire[i].nr].nod[7]].ny ) +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[11]].ny+
      node[e_enqire[e_enqire[i].nr].nod[12]].ny+
      node[e_enqire[e_enqire[i].nr].nod[19]].ny+
      node[e_enqire[e_enqire[i].nr].nod[15]].ny ) ;
  
    node[e_enqire[e_enqire[i].nr].nod[23  ]].nz = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[3]].nz +
      node[e_enqire[e_enqire[i].nr].nod[0]].nz +
      node[e_enqire[e_enqire[i].nr].nod[4]].nz +
      node[e_enqire[e_enqire[i].nr].nod[7]].nz )  +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[11]].nz+
      node[e_enqire[e_enqire[i].nr].nod[12]].nz+
      node[e_enqire[e_enqire[i].nr].nod[19]].nz+
      node[e_enqire[e_enqire[i].nr].nod[15]].nz ) ;
    for (n=0; n<2; n++)  /* create last 2 new nodes in center of areas */
    {
      n1=n*4;
      n2=n*8;
    node[e_enqire[e_enqire[i].nr].nod[24+n]].nx = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[0+n1]].nx +
      node[e_enqire[e_enqire[i].nr].nod[1+n1]].nx +
      node[e_enqire[e_enqire[i].nr].nod[2+n1]].nx +
      node[e_enqire[e_enqire[i].nr].nod[3+n1]].nx )  +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[8+n2]].nx +
      node[e_enqire[e_enqire[i].nr].nod[9+n2]].nx  +
      node[e_enqire[e_enqire[i].nr].nod[10+n2]].nx +
      node[e_enqire[e_enqire[i].nr].nod[11+n2]].nx ) ;
  
    node[e_enqire[e_enqire[i].nr].nod[24+n]].ny = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[0+n1]].ny +
      node[e_enqire[e_enqire[i].nr].nod[1+n1]].ny +
      node[e_enqire[e_enqire[i].nr].nod[2+n1]].ny +
      node[e_enqire[e_enqire[i].nr].nod[3+n1]].ny )  +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[8+n2]].ny +
      node[e_enqire[e_enqire[i].nr].nod[9+n2]].ny  +
      node[e_enqire[e_enqire[i].nr].nod[10+n2]].ny +
      node[e_enqire[e_enqire[i].nr].nod[11+n2]].ny   ) ;
  
    node[e_enqire[e_enqire[i].nr].nod[24+n]].nz = -1./4.* (
      node[e_enqire[e_enqire[i].nr].nod[0+n1]].nz +
      node[e_enqire[e_enqire[i].nr].nod[1+n1]].nz +
      node[e_enqire[e_enqire[i].nr].nod[2+n1]].nz +
      node[e_enqire[e_enqire[i].nr].nod[3+n1]].nz )  +
      1./2.*(
      node[e_enqire[e_enqire[i].nr].nod[8+n2]].nz +
      node[e_enqire[e_enqire[i].nr].nod[9+n2]].nz  +
      node[e_enqire[e_enqire[i].nr].nod[10+n2]].nz +
      node[e_enqire[e_enqire[i].nr].nod[11+n2]].nz   ) ;
    }
    }
  }
}

