// $Source: /usr/local/SimSoft/Sfx3D/src/gts/gtstgb.cpp,v $
// $Revision: 1.2 $
// $Author: baum $
// $Date: 2001/11/29 15:18:10 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name: Release-14 $
// State assigned to revision
// $State: Exp $
//
//
// $Log: gtstgb.cpp,v $
// Revision 1.2  2001/11/29 15:18:10  baum
// -Realzeitsteuerung eingebaut
// -Handsteuerung eingebaut
//

/*** Windows headers ***/
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
//#include <winnt.h>
#endif /*WIN32*/

#include <ctype.h>

#include "gtsglob.h"
#include "gtstgb.h"
#include "gtsbst.h"
#include "gtsb00.h"
#include "gtsb01.h"
#include "gtsb02.h"
#include "gtsb03.h"
#include "gtsb04.h"
#include "gtsb05.h"
#include "gtsb06.h"
#include "gtsb07.h"
#include "gtsb10.h"
#include "gtsb08.h"
#include "gtsb09.h"
#include "gtsb12.h"
#include "gtsb14.h"
#include "gtsb15.h"
#include "gtsb16.h"
#include "gtsb17.h"
#include "gtsb18.h"
#include "gtsb19.h"
#include "gtsb20.h"
#include "gtsb23.h"
#include "gtsb24.h"
#include "gtsb25.h"
#include "gtsb26.h"
#include "gtsb28.h"
#include "gtsb29.h"
#include "gtsb30.h"
#include "gtsb31.h"
#include "gtsb32.h"
#include "gtsb33.h"
#include "gtsb34.h"
#include "gtsb35.h"
#include "gtsb36.h"
#include "gtsb37.h"
#include "gtsb38.h"
#include "gtsb39.h"

#include "XGraph/AllViews.h" // to use UnitPrimitives in "UnitPrim.h"
#include "VrmlPars.h"

//==================================================================
//		Declaration
//		for abstract baseclass BstInfo
//==================================================================

BstInfo::BstInfo  ()
  : ObjAusgabeArt (0), ObjInfoArt (0), ObjGroesse (0.0),
    ObjText ()
 { }

BstInfo::BstInfo  (const BstInfo& copy)
  : ObjAusgabeArt (copy.ObjAusgabeArt), ObjInfoArt  (copy.ObjInfoArt),
    ObjGroesse    (copy.ObjGroesse),    ObjText (copy.ObjText)
 { }

BstInfo::~BstInfo ()
 { }

void BstInfo::operator = (const BstInfo& copy) {
  ObjAusgabeArt = copy.ObjAusgabeArt;
  ObjInfoArt    = copy.ObjInfoArt;
  ObjGroesse    = copy.ObjGroesse;
  ObjText       = copy.ObjText;
}

//==================================================================
//		Declaration
//		for class BstTextInfo
//==================================================================

/*static*/ Attribute* BstTextInfo::ClassTextAttribute = ColorAttribute::create ("black");

BstTextInfo::BstTextInfo ()
  : BstInfo (), ObjGeometry ()
 { }

BstTextInfo::BstTextInfo (const BstTextInfo& copy)
  : BstInfo (copy), ObjGeometry ()
 { 
  ObjGeometry.setPos (copy.ObjGeometry.Pos());
 }

BstTextInfo::~BstTextInfo ( )
 { }

void BstTextInfo::operator = (const BstTextInfo& copy) {
  if (this == &copy) return;
  else BstInfo::operator = (copy);
}

void BstTextInfo::read (InputFile& fin,
                           int ausgabe /*= 0*/, int info /*= 7*/) {
  SFXToken tok;
  ObjAusgabeArt = ausgabe;
  ObjInfoArt    = info;
  tok.nextToken (fin);       ObjGroesse = atof (tok ());
  tok.nextToken (fin);       double x = atof (tok ());
  tok.nextToken (fin);       double y = atof (tok ());
  ObjGeometry.setPos (Vec3D (x, y, 0.02)); // kleiner Z-Offset!!!
  tok.nextToken (fin);
  ObjText = Ustring(tok());
  if (ObjText[ObjText.len()-1] == ';')
      ObjText.delPart (ObjText.len()-1, 1);
} // ENDE read

void BstTextInfo::write (ostream& ostrm) const
{
   Write (ostrm, "%14d ",    ObjAusgabeArt);
   Write (ostrm, "%4d ",     ObjInfoArt);
   Write (ostrm, "%9.3f ",   ObjGroesse);
   Write (ostrm, "%9.3f ",   ObjGeometry.Pos().X());
   Write (ostrm, "%9.3f ",   ObjGeometry.Pos().Y());
   Write (ostrm, "   %s;\n", ObjText.str());
}  // ENDE write

void BstTextInfo::setText (Ustring newText) {
    ObjText = newText;
}

void BstTextInfo::show (GeoObject& parent) {
  if (ObjGeometry.Mum() != &parent)
    ObjGeometry.setParent (parent);

  ObjGeometry.setSelectionToMum ();

  if (ObjGeometry.PattArray().Count())
    while (ObjGeometry.PattArray().Last())
      ObjGeometry.remove (*(ObjGeometry.PattArray().Last()));

  Pattern *tmp = Pattern::find ( (Ustring ("BstText_") + ObjText).str() );
  if (tmp)
    ObjGeometry.insert (*tmp);
  else {
    Pattern       *patt = Pattern::create ();
    Primitive     *prim = Text::create ((char*) ObjText.str(), ObjGroesse);
    GeoPattern    *gpText = GeoPattern::create (*prim, *ClassTextAttribute);
    patt->insert  (*gpText);
    patt->setName ( (Ustring ("BstText_") + ObjText).str() );
    ObjGeometry.insert (*patt);
  }
} // ENDE show

//==================================================================
//		Declaration
//		for class typBibliothek
//==================================================================

void typBibliothek::leseBasisNamen ()
{
  SFXToken tok;
  LCursor<BstBasis> zhilfe;
  unsigned satz;
  for (zhilfe = BstBasisListe; zhilfe; zhilfe++)
  {
    satz = zhilfe()->getTyp() * getTypMulti() + getTypOffset();
    if (!tok.findSentence (satz, *fbb))
       Msg.Error ("typBibliothek::leseBasisNamen()",
                "Satznr.= %d in TGB-Datei nicht vorhanden", satz);

    tok.nextToken (*fbb);
    tok.nextToken (*fbb);
    zhilfe()->setName (tok());
    tok.EndOfLine (*fbb);
    zhilfe()->read (*fbb, satz, getVarMulti());
  }
}  // ENDE leseBasisNamen

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::LeseInhaltverzeichnis ()
{
  SFXToken tok;
  tok.Reset (*fbb);
  if (!tok.findSentence (2, *fbb))
       Msg.Error ("typBibliothek::LeseInhaltverzeichnis()",
                "Satznr.= 2 in TGB-Datei nicht vorhanden");
  tok.nextToken (*fbb);
  int AnzEintraege = atoi (tok());
  tok.EndOfLine (*fbb);

  if (!tok.findSentence (3, *fbb))
       Msg.Error ("typBibliothek::LeseInhaltverzeichnis()",
                "Satznr.= 3 in TGB-Datei nicht vorhanden");

   int bTyp, vTyp, i;
   for (i = 1; i <= AnzEintraege; i++)
   {
     tok.nextToken (*fbb);  bTyp = atoi (tok());
     tok.nextToken (*fbb);  vTyp = atoi (tok());
     erzeugeInhaltsverzeichnis (bTyp, vTyp);
     if (i % 8 == 0)
	 {
       tok.EndOfLine (*fbb);
       tok.nextToken (*fbb);
	 }
   }
   tok.EndOfLine (*fbb);
   leseBasisNamen();
}  // ENDE LeseInhaltverzeichnis

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::erzeugeInhaltsverzeichnis (unsigned bTyp, unsigned vTyp)
{
  LCursor<BstBasis> zBasis = BsttypInListe (bTyp);

  if (zBasis == NULL)
  {
    BstBasis *zhilfe = new BstBasis (bTyp);
    EndeGliedern (*zhilfe);
    VarianteInBstBasisListe (*zhilfe, bTyp, vTyp);
  }
  else
  VarianteInBstBasisListe (*zBasis(), bTyp, vTyp);
}  //  ENDE erzeugeInhaltsverzeichnis

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LCursor<BstBasis> typBibliothek::BsttypInListe (unsigned int Btyp)
{
   LCursor<BstBasis> zhilfe;

   for (zhilfe = BstBasisListe;
       (zhilfe && (zhilfe()->getTyp() != Btyp)); zhilfe++) ;
   return zhilfe;
}  // ENDE LeseInhaltverzeichnis

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::VarianteInBstBasisListe
            (BstBasis &zhilfe, unsigned Btyp, unsigned Vtyp)
{
   BstVariante *z1hilfe = new BstVariante (Btyp, Vtyp);
   zhilfe.append (*z1hilfe);
}  // VarianteInBstBasisListe

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::AusgabeInhaltsverzeichnis ()
{
   Write("TGB:  --->  %s\n", DatName.str());

   LCursor<BstBasis> zhilfe;
   for (zhilfe = BstBasisListe; zhilfe ; zhilfe++)
   {
     zhilfe()->AusgabeInhaltsverzeichnis ();
   }
}  // ENDE typInhaltsverzeichnis

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typBibliothek::typBibliothek (Ustring name)
  : BstBasisListe   (),
    DatName         (name),
    ObjTexturesPath (),
    ObjVrmlPath     (),
    ObjTypOffset    (20),
    ObjTypMulti     (1000),
    ObjVarMulti     (20),
    ObjSegOffset    (2),
    ObjNumPosOffset (4),
    ObjSymPosOffset (5),
    ObjInfo1Offset  (7),
    ObjInfo2Offset  (10),
    ObjInfo3Offset  (12),
    ObjTextOffset   (16)
{
  //fbb = new InputFile (DatName.str());
  //fbb = new InputFile ("D:\Sfx3D_VC6\tgb\tgb_tgb.3bb");
   Oeffnen();
  leseOffset ();
  LeseInhaltverzeichnis ();
   //fbb->close();
  //rudi: 04-01-07: Versuch1!!!
  //delete fbb;
   Schliessen();
//  AusgabeInhaltsverzeichnis ();
};  // ENDE typBibliothek

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::leseOffset (void)
{
  SFXToken tok;
  if (!tok.findSentence (5, *fbb))
       Msg.Error ("typBibliothek::leseOffset()",
                  "Satznr.= 5 in TGB-Datei nicht vorhanden");

  tok.nextToken (*fbb);   ObjTypOffset    = atoi (tok());
  tok.nextToken (*fbb);   ObjTypMulti     = atoi (tok());
  tok.nextToken (*fbb);   ObjVarMulti     = atoi (tok());
  tok.nextToken (*fbb);   ObjSegOffset    = atoi (tok());
  tok.nextToken (*fbb);   ObjNumPosOffset = atoi (tok());
  tok.nextToken (*fbb);   ObjSymPosOffset = atoi (tok());
  tok.nextToken (*fbb);   ObjInfo1Offset  = atoi (tok());
  tok.nextToken (*fbb);   ObjInfo2Offset  = atoi (tok());
  tok.nextToken (*fbb);   ObjInfo3Offset  = atoi (tok());
  tok.nextToken (*fbb);   ObjTextOffset   = atoi (tok());
}  // leseOffset

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::Oeffnen ()
{
  fbb = new InputFile (DatName.str());
} // ENDE Oeffnen

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::Schliessen () {
   fbb->close();
   if (fbb)
      delete fbb;
   fbb = NULL;
}  // ENDE Schliessen

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool typBibliothek::LeseBaustein (unsigned btyp, unsigned vtyp)
{
  BstVariante *zBstein = SucheBaustein (btyp, vtyp);

  if (!zBstein) {
       Msg.Error ("typBibliothek::LeseBaustein()",
                  "Basistyp=%d, Varianttyp=%d in Bibliothek nicht gefunden",
                   btyp, vtyp);
    return false;
  }
  else
    if (! (*zBstein) ) { // wurde schon gelesen?!
      zBstein->read (*fbb);
  }
  return true;
}  // ENDE LeseBaustein

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BstVariante* typBibliothek::SucheBaustein (unsigned btyp, unsigned vtyp)
{
   LCursor<BstBasis> zhilfe;
   for (zhilfe = BstBasisListe; zhilfe; zhilfe++)
       if ((zhilfe()->getTyp() == btyp)) break;

   if (zhilfe != NULL)
     return zhilfe()->findBstVariante (vtyp);
   return NULL;
}  // ENDE SucheBaustein

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BstVariante *typBibliothek::SucheBausteinUeberIndex
                           (unsigned bindex, unsigned vindex)
{
   LCursor<BstBasis> zhilfe;
   unsigned i = 0;
   for (zhilfe = BstBasisListe; zhilfe; zhilfe++)
      if (i < bindex) i++;
      else break;

   if (zhilfe != NULL) return zhilfe()->findBstUeberIndex (vindex);

   Msg.Warning ("typBibliothek::SucheBausteinUeberIndex",
                "Bausteintyp mit Index=%d nicht gefunden", bindex);
   return NULL;
}  // ENDE SucheBaustein

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned typBibliothek::getTypOffset () const
{
  return ObjTypOffset;
} // ENDE getTypOffset

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned typBibliothek::getTypMulti () const
{
  return ObjTypMulti;
} // ENDE getTypMulti

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned typBibliothek::getVarMulti () const
{
  return ObjVarMulti;
} // ENDE getVarMulti

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned typBibliothek::getSegOffset () const
{
  return ObjSegOffset;
} // ENDE getSegOffset

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned typBibliothek::getNumPosOffset () const
{
  return ObjNumPosOffset;
} // ENDE getNumPosOffset

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned typBibliothek::getInfo1Offset () const
{
  return ObjInfo1Offset;
} // ENDE getInfo1Offset

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned typBibliothek::getTextOffset () const
{
  return ObjTextOffset;
} // ENDE getTextOffset

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::setTexturesPath (Ustring texturepath)
{
  ObjTexturesPath = texturepath;
} // ENDE setTexturesPath

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void typBibliothek::setVrmlPath (Ustring vrmlpath)
{
  ObjVrmlPath = vrmlpath;
} // ENDE setVrmlPath

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ustring typBibliothek::getTexturesPath () const
{
  return ObjTexturesPath;
} // ENDE getTexturesPath

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ustring typBibliothek::getVrmlPath () const
{
  return ObjVrmlPath;
} // ENDE getVrmlPath

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ustring typBibliothek::BausteinNamen () {
  Ustring buf;
  for (LCursor<BstBasis> zhilfe = BstBasisListe; zhilfe ; zhilfe++) {
    buf += "{";
    buf += zhilfe()->getName();
    buf += "}\t";
  }
  return buf;
} // ENDE BausteinNamen

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ustring typBibliothek::VariantNamenUeberBausteintyp (unsigned btyp)
{
   LCursor<BstBasis> zhilfe;
   for (zhilfe = BstBasisListe; zhilfe ; zhilfe++)
       if ((zhilfe()->getTyp() == btyp)) break;

   if (zhilfe != NULL)
     return zhilfe()->getVariantNamen ();

   Msg.Warning ("typBibliothek::VariantNamenUeberBausteintyp",
                "Bausteintyp=%d nicht gefunden", btyp);
   return Ustring();
} // ENDE VariantNamenUeberBausteintyp

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ustring typBibliothek::VariantNamenUeberIndex (unsigned index)
{
   LCursor<BstBasis> zhilfe;
   unsigned zaehler = 0;
   for (zhilfe = BstBasisListe; zhilfe; zhilfe++) {
     if (zaehler == index) break;
     zaehler++;
   }
   if (zhilfe != NULL)
     return zhilfe()->getVariantNamen ();

   Msg.Warning ("typBibliothek::VariantNamenUeberIndex",
                "Bausteintyp mit Index==%d nicht gefunden", index);
   return Ustring();
} // ENDE VariantNamenUeberIndex

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typBibliothek::~typBibliothek ()
{
  while (!BstBasisListe.isEmpty())
         delete BstBasisListe.removeFirst();
};  // ENDE ~typBibliothek

//==================================================================
//		Declaration
//		for class BstBasis
//==================================================================

BstBasis::BstBasis (unsigned typ)
  : ObjName (), ObjTyp (typ), ObjVariantListe ()
 { }

BstBasis::~BstBasis () {
  while (!ObjVariantListe.isEmpty())
    delete ObjVariantListe.removeFirst();
}

void BstBasis::read (InputFile& fin, unsigned beginSatz, unsigned variantSatz)
{
  SFXToken tok;
  unsigned satznr;
  for (LCursor<BstVariante> zhilfe (ObjVariantListe); zhilfe; zhilfe++)
  {
    satznr = beginSatz + zhilfe()->getVariante() * variantSatz;
    if (!tok.findSentence (satznr, fin))
       Msg.Error ("BstBasis::read()",
                  "Satznr.= %d in TGB-Datei nicht vorhanden", satznr);

    tok.nextToken (fin);
    tok.nextToken (fin);
    tok.nextToken (fin);
    tok.nextToken (fin);
    tok.nextToken (fin);
    zhilfe()->setName (tok());
    tok.EndOfLine (fin);
  }
}  // ENDE read

void BstBasis::append (const BstVariante& newVariante) {
  ObjVariantListe.append (newVariante);
}

BstVariante* BstBasis::findBstVariante   (const unsigned variante) const {
  for (LCursor<BstVariante> zhilfe (ObjVariantListe); zhilfe; zhilfe++)
    if ((zhilfe()->getVariante() == variante))
      return zhilfe();

  Msg.Warning ("BstBasis::findBstVariante",
                 "Variante %d nicht gefunden", variante);
  return NULL;
}

BstVariante* BstBasis::findBstUeberIndex (const unsigned index) const {
  unsigned i = 0;

  for (LCursor<BstVariante> zhilfe = ObjVariantListe; zhilfe; zhilfe++, i++)
    if (i == index) return zhilfe();

    Msg.Warning ("BstBasis::findBstUeberIndex",
                 "Bausteinvariante mit Index=%d nicht gefunden", index);
  return NULL;
}

void BstBasis::AusgabeInhaltsverzeichnis ()
{
  Write ("\nBasisTyp=%d  ", ObjTyp);
  Write ("==>%s<\n", ObjName.str());

  for (LCursor<BstVariante> zhilfe = ObjVariantListe; zhilfe ; zhilfe++) {
    Write ("     VariantTyp=%d  ", zhilfe()->getVariante());
    Write ("==>%s<\n", zhilfe()->getName().str());
  }
} // ENDE AusgabeInhaltsverzeichnis

void BstBasis::setName (const char *name) {
  ObjName = Ustring (name);
}

void BstBasis::setName (const Ustring& name) {
  ObjName = name;
}

unsigned       BstBasis::getTyp  () const {
  return ObjTyp;
}

const Ustring& BstBasis::getName () const {
  return ObjName;
}

Ustring BstBasis::getVariantNamen () const {
  Ustring buf;
  for (LCursor<BstVariante> zhilfe = ObjVariantListe; zhilfe; zhilfe++) {
    buf += "{";
    buf += zhilfe()->getName();
    buf += "}\t";
  }
  return buf;
}

//==================================================================
//		Declaration
//		for class BstVariante
//==================================================================
/*static*/ unsigned   BstVariante::ClassRefCounter = 0;
/*static*/ Attribute* BstVariante::ClassPermAttribute;
/*static*/ Attribute* BstVariante::ClassArrowAttribute;

/*static*/ Pattern* BstVariante::ClassArrowTipPattern = NULL;
/*static*/ Pattern* BstVariante::ClassArrowStickPattern = NULL;

/*static*/ void BstVariante::setup () {
  BstVariante::ClassPermAttribute = MaterialAttribute::create ("machinegreen");
  BstVariante::ClassArrowAttribute = MaterialAttribute::create ("ruby");
}

/*static*/ void BstVariante::cleanup () {
  BstVariante::ClassPermAttribute->dispose ();
  BstVariante::ClassPermAttribute = NULL;
  BstVariante::ClassArrowAttribute->dispose ();
  BstVariante::ClassArrowAttribute = NULL;
}

BstVariante::BstVariante (const unsigned typ, const unsigned variante)
 : ObjName (),          ObjTyp (typ),       ObjVariante   (variante),
   ObjFlusswinkel (),   ObjBstNrInfo (),    ObjGeometries (2),
   ObjBSPBasis (NULL),  ObjBTPBasis (NULL),
   ObjPalPositions (2) {
  if (!(ClassRefCounter++)) {
    setup ();
  }
}

BstVariante::~BstVariante () {
  while (ObjGeometries.Last ()) {
    ObjGeometries.Last ()->deleteContents ();
    delete ObjGeometries.removeLast ();
  }
  while (ObjPalPositions.Last ()) delete ObjPalPositions.removeLast();
  if (ObjBSPBasis) delete ObjBSPBasis;
  if (ObjBTPBasis) delete ObjBTPBasis;
  if (!(--ClassRefCounter)) {
    cleanup ();
  }
}

bool BstVariante::operator ! () const {
  return ObjGeometries.isEmpty ();
}

BstVariante::operator void*  () const {
  return (!ObjGeometries.isEmpty () ? (void*) 1 : NULL);
}

void BstVariante::read (InputFile& fin) {
  SFXToken tok;
  unsigned begin  = ObjTyp      * TgbBibliothek->getTypMulti() +
                    ObjVariante * TgbBibliothek->getVarMulti() +
                    TgbBibliothek->getTypOffset();
  unsigned satznr = begin;

  if (!tok.findSentence (satznr, fin))
       Msg.Error ("BstVariante::read()",
                  "Satznr.= %d in TGB-Datei nicht vorhanden", satznr);

  tok.nextToken (fin);
  tok.nextToken (fin);
  tok.nextToken (fin);
  tok.nextToken (fin);
  ObjFlusswinkel = Angle (atof(tok()));

  GeoObject* obj = new GeoObject ();
//  obj->setName (tok());
  ObjGeometries.append (*obj);
  tok.EndOfLine (fin);

  satznr = begin + TgbBibliothek->getSegOffset();
  if (!tok.findSentence (satznr, fin))
       Msg.Error ("BstVariante::read()",
                  "Satznr.= %d in TGB-Datei nicht vorhanden", satznr);
  readKontur (fin);
  switch (ObjTyp) {
    case tWeiche:
    case tKettenfoerderer:
    case tQuerfoerderer:
    case tLinearStaufoerderer:       showArrow (); break;
    case tRechtsKurveStaufoerderer:
    case tLinksKurveStaufoerderer:
    default: break;
  }

  satznr = begin + TgbBibliothek->getNumPosOffset();
  if (!tok.findSentence (satznr, fin))
       Msg.Error ("BstVariante::read()",
                  "Satznr.= %d in TGB-Datei nicht vorhanden", satznr);
  readBstNr (fin);

  satznr = begin + TgbBibliothek->getInfo1Offset();
  if (!tok.findSentence (satznr, fin))
       Msg.Error ("BstVariante::read()",
                  "Satznr.= %d in TGB-Datei nicht vorhanden", satznr);
  readPositions (fin);

  initBTPParameter (this);
  initBSPParameter ();
} // ENDE read

void BstVariante::setName (const char *name) {
  ObjName = Ustring (name);
}

void BstVariante::setName (const Ustring& name) {
  ObjName = name;
}

unsigned     BstVariante::getTyp       () const {
  return ObjTyp;
}

unsigned     BstVariante::getVariante  () const {
  return ObjVariante;
}

const Ustring& BstVariante::getName      () const {
  return ObjName;
}

const BstTextInfo& BstVariante::BstNrInfo () const {
  return ObjBstNrInfo;
}

GeoObject *BstVariante::MyGeometry () const {
  return ObjGeometries.First ();
}

const DynArray<GeoObject> BstVariante::AllGeometries () const {
  return ObjGeometries;
}

typBSPBasis* BstVariante::BSP  () const {
  return ObjBSPBasis;
}

typBTPBasis* BstVariante::BTP  () const {
  return ObjBTPBasis;
}

const DynArray<Vec3D>& BstVariante::PalPositions   () const {
  return ObjPalPositions;
}

void BstVariante::readKontur (InputFile& fin)
{
  int number, satznr, primId;
  double x, y, z;
  Ustring objName;
  VrmlParser* p;

  GeoObject* obj = ObjGeometries.First ();
  Pattern* pat = Pattern::create ();
  obj->insert (*pat);

  SFXToken tok;
  InputFile* file = &fin;

  Vec3D begin, end, v1, v2, v3;
  Angle bAngle, eAngle;

  GeoPattern    *gp;
  Primitive     *prim;

  Attribute *attr = ClassPermAttribute;

  tok.nextToken (*file);
  number = atoi (tok ());
  tok.EndOfLine (*file);

  for (int i = 0; i < number; i++) {
    tok.nextToken (*file);
    satznr = atoi (tok ());
    tok.nextToken (*file);
    primId = atoi (tok ());

    switch (primId) {
      case 1:                     // Line
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        z = 0.0;
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        z = 0.0;
        end = Vec3D (x, y, z);
          
        if (begin == end) {
          Meld.Ausgabe (2, satznr, i+1);
          break;
        }
        gp = GeoPattern::create (*(Line::create (begin, end)), *attr);
        pat->insert (*gp);
        break;

      case 2:                      // LineArc
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        z = 0.0;
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); z = atof (tok()); // now z is the radius!!

        tok.nextToken (*file); bAngle = Angle (atof (tok()));
        tok.nextToken (*file); eAngle = Angle (atof (tok()));

        if (!z) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Arc with null-radius");
          break;
        }
        prim = LineArc::create ( z, z, bAngle, eAngle, begin);
        gp = GeoPattern::create (*prim, *attr);
        pat->insert(*gp);
        break;

      case 3:
      case 10:                     // Rectangle 2 vectors
        tok.nextToken (*file);  x = atof (tok());
        tok.nextToken (*file);  y = atof (tok());
        tok.nextToken (*file);  z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file);  x = atof (tok());
        tok.nextToken (*file);  y = atof (tok());
        tok.nextToken (*file);  z = atof (tok());
        end = Vec3D (x, y, z);

        if (begin == end) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Rect with null-size");
          break;
        }
        gp = GeoPattern::create (*PlaneQuad::create (begin, end), *attr);
        pat->insert (*gp);
        break;

      case 11:                     // Rectangle 4 vectors
        tok.nextToken (*file);  x = atof (tok());
        tok.nextToken (*file);  y = atof (tok());
        tok.nextToken (*file);  z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file);  x = atof (tok());
        tok.nextToken (*file);  y = atof (tok());
        tok.nextToken (*file);  z = atof (tok());
        v1 = Vec3D (x, y, z);

        tok.nextToken (*file);  x = atof (tok());
        tok.nextToken (*file);  y = atof (tok());
        tok.nextToken (*file);  z = atof (tok());
        end = Vec3D (x, y, z);

        tok.nextToken (*file);  x = atof (tok());
        tok.nextToken (*file);  y = atof (tok());
        tok.nextToken (*file);  z = atof (tok());
        v2 = Vec3D (x, y, z);

        prim = PlaneQuad::create (begin, v1, end, v2);
        gp = GeoPattern::create (*prim, *attr);
        pat->insert (*gp);
        break;

      case 13:                     // Triangle
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        end = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        v1 = Vec3D (x, y, z);

        prim = Triangle::create (begin, end, v1);
        gp = GeoPattern::create (*prim, *attr);
        pat->insert (*gp);
        break;

      case 15:                     // PlaneArcSegment
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); z = atof (tok()); // now z is the radius!!
        tok.nextToken (*file); y = atof (tok()); // now y is the distance!!

        tok.nextToken (*file); bAngle = Angle (atof (tok()));
        tok.nextToken (*file); eAngle = Angle (atof (tok()));

        if (!z) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Disc with null-radius");
          break;
        }
        prim = PlaneArc::create ( z, z, y, bAngle, eAngle, begin);
        gp = GeoPattern::create (*prim, *attr);
        pat->insert(*gp);
        break;

      case 17:                     // Text
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); objName = tok (); // text
        tok.nextToken (*file); x = atof (tok()); // size
        tok.nextToken (*file); y = atof (tok()); // thickness

        gp = GeoPattern::create (*Text::create (objName.str (), x, y, begin), *attr);
        pat->insert (*gp);
        break;

      case 20:                     // Cube
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        end = Vec3D (x, y, z);

        if (begin == end) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Cube with null-size ");
          break;
        }
        gp = GeoPattern::create (*Cube::create (begin, end), *attr);
        pat->insert (*gp);
        break;

      case 21:                     // Cube with UpDirection
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        end = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        v1 = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        v2 = Vec3D (x, y, z);

        v3 = v2.cross (EX);
        if (!v3) v3 = EY;
        v3 = EX * rotHMatrx3D (v3, v2.angle (EX) - Angle (90.0));

        gp = GeoPattern::create (*Cube::create (begin, end), *attr, Location(v1, v3, v2));
        pat->insert (*gp);
        break;

      case 25:                     // Cylinder
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        end = Vec3D (x, y, z); // for the up-vec

        tok.nextToken (*file); y = atof (tok()); // now y is the radius!!
        tok.nextToken (*file); z = atof (tok()); // now z is the height!!

        if (!z || !y) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Cylinder with null-size");
          break;
        }
        v1 = end.cross (EX);
        if (!v1) v1 = EY;
        v2 = EX * rotHMatrx3D (v1, end.angle (EX) - Angle (90.0));
        gp = GeoPattern::create (*Cylinder::create (y, z), *attr,
                                 Location (begin, v2, end));
        pat->insert(*gp);
        break;

      case 26:                     // Tube
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        end = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok()); // now x is the radius!!
        tok.nextToken (*file); y = atof (tok()); // now y is the height!!
        tok.nextToken (*file); z = atof (tok()); // now z is the distance!!

        tok.nextToken (*file); bAngle = Angle (atof (tok()));
        tok.nextToken (*file); eAngle = Angle (atof (tok()));

        if (!x || !y) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Tube with null-size");
          break;
        }
        v1 = end.cross (EX);
        if (!v1) v1 = EY;
        v2 = EX * rotHMatrx3D (v1, end.angle (EX) - Angle (90.0));
        gp = GeoPattern::create (*Tube::create (x, x, y, z, bAngle, eAngle), *attr,
                                 Location (begin, v2, end));
        pat->insert(*gp);
        break;

      case 27:                     // Cone
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        end = Vec3D (x, y, z);

        tok.nextToken (*file); x = atof (tok()); // now x is the radius!!
        tok.nextToken (*file); y = atof (tok()); // now y is the height!!
        tok.nextToken (*file); z = atof (tok()); // now z is the dist!!

        if (!x || !y) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Cone with null-size");
          break;
        }
        v1 = end.cross (EX);
        if (!v1) v1 = EY;
        v2 = EX * rotHMatrx3D (v1, end.angle (EX) - Angle (90.0));
        gp = GeoPattern::create (*Cone::create (x, y, z), *attr,
                                 Location (begin, v2, end));
        pat->insert (*gp);
        break;

      case 28:                     // Sphere
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        tok.nextToken (*file); z = atof (tok());
        begin = Vec3D (x, y, z);

        tok.nextToken (*file); z = atof (tok()); // now z is the radius!!
        if (!z) {
          Msg.Warning ("BstVariante::readKontur (...)",
                       "Primitive Sphere with null-radius");
          break;
        }
        gp = GeoPattern::create (*Sphere::create (z), *attr,
                                 Location (begin, EX, EZ));
        pat->insert(*gp);
        break;

      case 30:                     // SubPattern
        obj = new GeoObject ();
        ObjGeometries.append (*obj);
        pat = Pattern::create ();
        obj->insert (*pat);
        attr = ClassPermAttribute;
        break;

      case 4:  // RGB-color-values
      case 40:
        tok.nextToken (*file);
        if (tok.isDouble ()) {
          x = atof (tok());
          tok.nextToken (*file); y = atof (tok());
          tok.nextToken (*file); z = atof (tok());
          attr = ColorAttribute::create (RGBAColor (x, y, z));
        }
        else
          attr = ColorAttribute::create (tok ());
        break;

      case 41: // material (only by name!!)
        tok.nextToken (*file);
        attr = MaterialAttribute::create (tok ());
        break;

      case 42: // texture (by file name!!)
        tok.nextToken (*file);
        objName = TgbBibliothek->getTexturesPath ();
        objName += tok ();
        tok.nextToken (*file); x = atof (tok());
        tok.nextToken (*file); y = atof (tok());
        attr = TexAttribute::create (objName.str (), Vec2D (x, y), RGBAColor (0.8, 0.8, 0.8));
        break;

      case 50: // VRML-File
        tok.nextToken (*file);
        objName = TgbBibliothek->getVrmlPath ();
        objName += tok ();
        p = new VrmlParser (objName);
        p->parse (*obj);
        delete p;
        break;

      default : break;
    } // ENDE switch
    tok.EndOfLine (fin);
  }
}  // ENDE readKontur

void BstVariante::readPositions (InputFile& fin) {
  double x, y, z;
  SFXToken tok;
  tok.nextToken (fin);
  unsigned anzEintraege = atoi(tok());
  tok.EndOfLine (fin);

  if (anzEintraege) {
    unsigned pack = (anzEintraege / 4); // max 4 Positions pro Zeile
    tok.nextToken (fin); // ueberlesen der Satznummer!!!
    for (unsigned j = 0; j <= pack; j++) {
      unsigned i = 0;
      unsigned stop = (anzEintraege < 4) ? anzEintraege : 4;
      for (; i < stop; i++) {
        tok.nextToken (fin);       x = atof(tok());
        tok.nextToken (fin);       y = atof(tok());
        tok.nextToken (fin);       z = atof(tok());
        ObjPalPositions.append (*(new Vec3D (x, y, z)));
      }
      anzEintraege -= 4;
      tok.EndOfLine (fin);
    }
  }
} // ENDE readPositions

void BstVariante::readBstNr (InputFile& fin) {
  SFXToken tok;
  ObjBstNrInfo.read (fin);
  tok.EndOfLine (fin);
} // ENDE readBstNr

void BstVariante::initBTPParameter (const BstVariante *zTGB)
{
  switch (ObjTyp)
  {
    case tLayout               : ObjBTPBasis = new typBTPLayout              (); break;
    case tQuelle               : ObjBTPBasis = new typBTPQuelle              (); break;
    case tSenke                : ObjBTPBasis = new typBTPSenke               (); break;
    case tLinearStaufoerderer  : ObjBTPBasis = new typBTPStaufoerderer       (zTGB); break;
    case tWeiche               : ObjBTPBasis = new typBTPWeiche              (); break;
    case tVWagen               : ObjBTPBasis = new typBTPVWagen              (); break;
    case tGasse                : ObjBTPBasis = new typBTPGasse               (); break;
    case tMaschine             : ObjBTPBasis = new typBTPMaschine            (); break;
    case tDrehpuffer           : ObjBTPBasis = new typBTPDrehpuffer          (zTGB); break;
    case tMehrfachLader        : ObjBTPBasis = new typBTPMehrfachLader       (); break;
    case tLaufkran             : ObjBTPBasis = new typBTPLaufkran            (); break;
    case tAbstrakteRegaleinheit: ObjBTPBasis = new typBTPRegaleinheit        (); break;
    case tRechtsKurveStaufoerderer
                      : ObjBTPBasis = new typBTPRechtsKurveStaufoerderer (zTGB); break;
    case tLinksKurveStaufoerderer
                      : ObjBTPBasis = new typBTPLinksKurveStaufoerderer  (zTGB); break;
    case tSammler              : ObjBTPBasis = new typBTPSammler             (); break;
    case tVereinzeler          : ObjBTPBasis = new typBTPVereinzeler         (); break;
    case tRegaleinheit         : ObjBTPBasis = new typBTPRegaleinheit        (); break;
    case tRegalverwalter       : ObjBTPBasis = new typBTPRegalverwalter      (); break;
    case tNcPoolverwalter      : ObjBTPBasis = new typBTPNcPoolverwalter     (); break;
    case tKettenfoerderer      : ObjBTPBasis = new typBTPKettenfoerderer     (zTGB); break;
    case tQuerfoerderer        : ObjBTPBasis = new typBTPQuerfoerderer       (); break;
    case tKommissionierer      : ObjBTPBasis = new typBTPKommissionierer     (zTGB); break;
    case tKomVerwalter         : ObjBTPBasis = new typBTPKomVerwalter        (); break;
    case tFtsLadepool          : ObjBTPBasis = new typBTPFtsLadepool         (); break;
    case tFtsLadeplatz         : ObjBTPBasis = new typBTPFtsLadeplatz        (); break;
    case tFtsVerwalter         : ObjBTPBasis = new typBTPFtsVerwalter        (); break;
    case tFtsWagen             : ObjBTPBasis = new typBTPFtsWagen            (); break;
    case tFtsEinbahnstrecke    : ObjBTPBasis = new typBTPFtsEinbahnstrecke   (); break;
    case tFtsZweibahnstrecke   : ObjBTPBasis = new typBTPFtsZweibahnstrecke  (); break;
    case tFtsKurve             : ObjBTPBasis = new typBTPFtsKurve            (); break;
    case tFtsAbzweigung        : ObjBTPBasis = new typBTPFtsAbzweigung       (); break;
    case tFtsKreuzung          : ObjBTPBasis = new typBTPFtsKreuzung         (); break;
    case tFtsEinbahnMitInhalt  : ObjBTPBasis = new typBTPFtsEinbahnMitInhalt (); break;
    case tFtsZweibahnMitInhalt : ObjBTPBasis = new typBTPFtsZweibahnMitInhalt(); break;
    case tFtsEndstrecke        : ObjBTPBasis = new typBTPFtsEndstrecke       (); break;
    default : break;
  } // ENDE switch
} // ENDE initBTPParameter

void BstVariante::initBSPParameter ()
{
  switch (ObjTyp)
  {
    case tLayout               : ObjBSPBasis = new typBSPVariante0 (); break;
    case tQuelle               : ObjBSPBasis = new typBSPVariante2 (); break;
    case tSenke                : ObjBSPBasis = new typBSPVariante2 (); break;
    case tLinearStaufoerderer  : ObjBSPBasis = new typBSPVariante1 (); break;
    case tWeiche               : ObjBSPBasis = new typBSPVariante1 (); break;
    case tVWagen               : ObjBSPBasis = new typBSPVariante1 (); break;
    case tGasse                : ObjBSPBasis = new typBSPVariante1 (); break;
    case tMaschine             : ObjBSPBasis = new typBSPVariante2 (); break;
    case tDrehpuffer           : ObjBSPBasis = new typBSPVariante1 (); break;
    case tMehrfachLader        : ObjBSPBasis = new typBSPVariante1 (); break;
    case tLaufkran             : ObjBSPBasis = new typBSPVariante1 (); break;
    case tAbstrakteRegaleinheit: ObjBSPBasis = new typBSPVariante1 (); break;
    case tRechtsKurveStaufoerderer : ObjBSPBasis = new typBSPVariante1 (); break;
    case tLinksKurveStaufoerderer  : ObjBSPBasis = new typBSPVariante1 (); break;
    case tSammler              : ObjBSPBasis = new typBSPVariante2 (); break;
    case tVereinzeler          : ObjBSPBasis = new typBSPVariante2 (); break;
    case tRegaleinheit         : ObjBSPBasis = new typBSPVariante1 (); break;
    case tRegalverwalter       : ObjBSPBasis = new typBSPVariante2 (); break;
    case tNcPoolverwalter      : ObjBSPBasis = new typBSPVariante2 (); break;
    case tKettenfoerderer      : ObjBSPBasis = new typBSPVariante1 (); break;
    case tQuerfoerderer        : ObjBSPBasis = new typBSPVariante1 (); break;
    case tKommissionierer      : ObjBSPBasis = new typBSPVariante2 (); break;
    case tKomVerwalter         : ObjBSPBasis = new typBSPVariante2 (); break;
    case tFtsLadepool          : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsLadeplatz         : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsVerwalter         : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsWagen             : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsEinbahnstrecke    : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsZweibahnstrecke   : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsKurve             : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsAbzweigung        : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsKreuzung          : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsEinbahnMitInhalt  : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsZweibahnMitInhalt : ObjBSPBasis = new typBSPVariante1 (); break;
    case tFtsEndstrecke        : ObjBSPBasis = new typBSPVariante1 (); break;

    default : break;
  } // ENDE switch
} // ENDE initBSPParameter

void BstVariante::showArrow () {
  if (!ClassArrowTipPattern) {
    ClassArrowStickPattern = Pattern::create (*GeoPattern::create (*Cylinder::create (0.05, 1.2),
                                                                  *ClassArrowAttribute,
                                                                  Location (Vec3D (-0.7, 0.0, 0.2), -EZ, EX)));
    ClassArrowTipPattern = Pattern::create (*GeoPattern::create (*Cone::create (0.2, 0.325, 0.0),
                                                                *ClassArrowAttribute,
                                                                Location (Vec3D (0.5, 0.0, 0.2), -EZ, EX)));
  }
  ObjGeometries.First ()->insert (*ClassArrowTipPattern);
  ObjGeometries.First ()->insert (*ClassArrowStickPattern);
} // ENDE showArrow


