netgen/libsrc/csg/csgparser.cpp
2021-04-12 15:51:40 +02:00

1404 lines
30 KiB
C++

#include <mystdlib.h>
#include <myadt.hpp>
#include <linalg.hpp>
#include <csg.hpp>
namespace netgen
{
static kwstruct defkw[] =
{
{ TOK_RECO, "algebraic3d" },
{ TOK_SOLID, "solid" },
{ TOK_TLO, "tlo" },
{ TOK_CURVE2D, "curve2d" },
{ TOK_CURVE3D, "curve3d" },
{ TOK_BOUNDINGBOX, "boundingbox" },
{ TOK_OR, "or" },
{ TOK_AND, "and" },
{ TOK_NOT, "not" },
{ TOK_SINGULAR, "singular" },
{ TOK_EDGE, "edge" },
{ TOK_FACE, "face" },
{ TOK_POINT, "point" },
{ TOK_IDENTIFY, "identify" },
{ TOK_CLOSESURFACES, "closesurfaces" },
{ TOK_CLOSEEDGES, "closeedges" },
{ TOK_PERIODIC, "periodic" },
{ TOK_BOUNDARYCONDITION, "boundarycondition" },
{ TOK_BOUNDARYCONDITIONNAME, "boundaryconditionname" },
{ TOK_DEFINE, "define" },
{ TOK_CONSTANT, "constant" },
{ TOKEN_TYPE(0), 0 }
};
static primstruct defprim[] =
{
{ TOK_PLANE, "plane" },
{ TOK_SPHERE, "sphere" },
{ TOK_CYLINDER, "cylinder" },
{ TOK_CONE, "cone" },
{ TOK_ELLIPTICCONE, "ellipticcone" },
{ TOK_ELLIPTICCYLINDER, "ellipticcylinder" },
{ TOK_ELLIPSOID, "ellipsoid" },
{ TOK_ORTHOBRICK, "orthobrick" },
{ TOK_POLYHEDRON, "polyhedron" },
{ TOK_TORUS, "torus" },
{ TOK_TUBE, "tube" },
{ TOK_GENCYL, "gencyl" },
{ TOK_EXTRUSION, "extrusion" },
{ TOK_REVOLUTION, "revolution" },
{ TOK_TRANSLATE, "translate" },
{ TOK_MULTITRANSLATE, "multitranslate" },
{ TOK_ROTATE, "rotate" },
{ TOK_MULTIROTATE, "multirotate" },
{ PRIMITIVE_TYPE(0), 0 }
};
static CSGeometry * geom;
CSGScanner :: CSGScanner (istream & ascanin)
{
scanin = &ascanin;
token = TOK_END;
num_value = 0;
linenum = 1;
}
void CSGScanner :: ReadNext ()
{
char ch;
// scan whitespaces
do
{
scanin->get(ch);
//if (ch == '\n')
// linenum++;
// end of file reached
if (scanin->eof())
{
token = TOK_END;
return;
}
if (ch == '\n')
linenum++;
// skip comment line
if (ch == '#')
{
while (ch != '\n')
{
scanin->get(ch);
if (scanin->eof())
{
token = TOK_END;
return;
}
}
linenum++;
}
}
while (isspace(ch));
switch (ch)
{
case '(': case ')':
case '[': case ']':
case '-':
case '=': case ',': case ';':
{
token = TOKEN_TYPE (ch);
break;
}
default:
{
if (isdigit (ch) || ch == '.')
{
scanin->putback (ch);
(*scanin) >> num_value;
token = TOK_NUM;
return;
}
if (isalpha (ch))
{
string_value = string (1, ch);
scanin->get(ch);
while (isalnum(ch) || ch == '_')
{
string_value += ch;
scanin->get(ch);
}
scanin->putback (ch);
}
int nr = 0;
while (defkw[nr].kw)
{
if (string_value == defkw[nr].name)
{
token = defkw[nr].kw;
return;
}
nr++;
}
nr = 0;
while (defprim[nr].kw)
{
if (string_value == defprim[nr].name)
{
token = TOK_PRIMITIVE;
prim_token = defprim[nr].kw;
return;
}
nr++;
}
token = TOK_STRING;
}
}
}
void CSGScanner :: Error (const string & err)
{
stringstream errstr;
errstr << "Parsing error in line " << linenum << ": " << endl << err << endl;
throw string(errstr.str());
}
/*
Solid = Term { OR Term }
Term = Primary { AND Primary }
Primary = PRIM | IDENT | ( Solid ) | NOT Primary
*/
void ParseChar (CSGScanner & scan, char ch)
{
if (scan.GetToken() != TOKEN_TYPE(ch))
scan.Error (string ("token '") + string(1, ch) + string("' expected"));
scan.ReadNext();
}
double ParseNumber(CSGScanner & scan)
{
if (scan.GetToken() == '-')
{
scan.ReadNext();
return -ParseNumber (scan);
}
if (scan.GetToken() != TOK_NUM) scan.Error ("number expected");
double val = scan.GetNumValue();
scan.ReadNext();
return val;
}
Vec<3> ParseVector (CSGScanner & scan)
{
Vec<3> v;
v(0) = ParseNumber (scan);
ParseChar (scan, ',');
v(1) = ParseNumber (scan);
ParseChar (scan, ',');
v(2) = ParseNumber (scan);
return v;
}
CSGScanner & operator>> (CSGScanner & scan, char ch)
{
if (scan.GetToken() != TOKEN_TYPE(ch))
scan.Error (string ("token '") + string(1, ch) + string("' expected"));
scan.ReadNext();
return scan;
}
CSGScanner & operator>> (CSGScanner & scan, double & d)
{
d = ParseNumber (scan);
return scan;
}
CSGScanner & operator>> (CSGScanner & scan, int & i)
{
i = int (ParseNumber (scan));
return scan;
}
CSGScanner & operator>> (CSGScanner & scan, Point<3> & p)
{
scan >> p(0) >> ',' >> p(1) >> ',' >> p(2);
return scan;
}
CSGScanner & operator>> (CSGScanner & scan, Vec<3> & v)
{
scan >> v(0) >> ',' >> v(1) >> ',' >> v(2);
return scan;
}
Solid * ParseSolid (CSGScanner & scan);
Solid * ParseTerm (CSGScanner & scan);
Solid * ParsePrimary (CSGScanner & scan);
Solid * ParsePrimary (CSGScanner & scan)
{
if (scan.GetToken() == TOK_PRIMITIVE)
{
switch (scan.GetPrimitiveToken())
{
case TOK_PLANE:
{
Point<3> p;
Vec<3> v;
scan.ReadNext();
scan >> '(' >> p >> ';' >> v >> ')';
OneSurfacePrimitive * surf = new Plane ( p, v );
geom->AddSurfaces (surf);
return new Solid (surf);
}
case TOK_CYLINDER:
{
Point<3> pa, pb;
double r;
scan.ReadNext();
scan >> '(' >> pa >> ';' >> pb >> ';' >> r >> ')';
OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r );
geom->AddSurfaces (surf);
return new Solid (surf);
}
case TOK_ELLIPTICCYLINDER:
{
Point<3> pa;
Vec<3> vl, vs;
scan.ReadNext();
scan >> '(' >> pa >> ';' >> vl >> ';' >> vs >> ')';
OneSurfacePrimitive * surf = new EllipticCylinder ( pa, vl, vs);
geom->AddSurfaces (surf);
return new Solid (surf);
}
case TOK_ELLIPSOID:
{
Point<3> pa;
Vec<3> v1, v2, v3;
scan.ReadNext();
scan >> '(' >> pa >> ';' >> v1 >> ';' >> v2 >> ';' >> v3 >> ')';
OneSurfacePrimitive * surf = new Ellipsoid ( pa, v1, v2, v3);
geom->AddSurfaces (surf);
return new Solid (surf);
}
case TOK_CONE:
{
Point<3> pa, pb;
double ra, rb;
scan.ReadNext();
scan >> '(' >> pa >> ';' >> ra >> ';' >> pb >> ';' >> rb >> ')';
OneSurfacePrimitive * surf = new Cone ( pa, pb, ra, rb );
geom->AddSurfaces (surf);
return new Solid (surf);
}
case TOK_ELLIPTICCONE:
{
Point<3> a;
Vec<3> vl, vs;
double h, vlr;
scan.ReadNext();
scan >> '(' >> a >> ';' >> vl >> ';' >> vs >> ';' >> h >>';' >> vlr >> ')';
OneSurfacePrimitive * surf = new EllipticCone ( a, vl, vs, h, vlr );
geom->AddSurfaces (surf);
return new Solid (surf);
}
case TOK_SPHERE:
{
Point<3> p;
double r;
scan.ReadNext();
scan >> '(' >> p >> ';' >> r >> ')';
OneSurfacePrimitive * surf = new Sphere ( p, r );
geom->AddSurfaces (surf);
return new Solid (surf);
}
case TOK_ORTHOBRICK:
{
Point<3> pa, pb;
scan.ReadNext();
scan >> '(' >> pa >> ';' >> pb >> ')';
Primitive * nprim = new OrthoBrick (pa, pb);
geom->AddSurfaces (nprim);
return new Solid (nprim);
}
case TOK_POLYHEDRON:
{
// Added by Dalibor Lukas, October 15, 2003
Point<3> p;
//int pi1, pi2, pi3, pi4;
scan.ReadNext();
ParseChar (scan, '(');
Polyhedra * polyhedron = new Polyhedra;
// scanning the points
while (1)
{
p = Point<3> (ParseVector (scan));
ParseChar (scan, ';');
polyhedron->AddPoint(p);
if (scan.GetToken() == ';')
{
scan.ReadNext();
break;
}
}
// scanning the faces
int inputface = 0;
while (1)
{
NgArray<int> pnums,cleaned_pnums;
for(int i=0; i<3; i++)
{
pnums.Append((int) (ParseNumber (scan)));
if(i<2)
ParseChar (scan, ',');
}
if (scan.GetToken() == TOK_COMMA)
{
ParseChar (scan, ',');
pnums.Append((int) (ParseNumber (scan)));
}
for(int i=0; i<pnums.Size(); i++)
if(!cleaned_pnums.Contains(pnums[i]))
cleaned_pnums.Append(pnums[i]);
if(cleaned_pnums.Size() == 3)
{
polyhedron->AddFace(cleaned_pnums[0]-1,
cleaned_pnums[1]-1,
cleaned_pnums[2]-1,
inputface);
}
else if(cleaned_pnums.Size() == 4)
{
polyhedron->AddFace(cleaned_pnums[0]-1,
cleaned_pnums[1]-1,
cleaned_pnums[2]-1,
inputface);
polyhedron->AddFace(cleaned_pnums[0]-1,
cleaned_pnums[2]-1,
cleaned_pnums[3]-1,
inputface);
}
else
{
ostringstream msg;
msg << "Something wrong with polyhedron face:";
for(int i=0; i<pnums.Size(); i++)
msg << " " << pnums[i];
throw NgException(msg.str());
}
if (scan.GetToken() == ')')
{
scan.ReadNext();
break;
}
scan.ReadNext();
inputface++;
}
geom->AddSurfaces (polyhedron);
return new Solid (polyhedron);
}
case TOK_REVOLUTION:
{
Point<3> p0,p1;
scan.ReadNext();
scan >> '(' >> p0 >> ';' >> p1 >> ';';
string spline = scan.GetStringValue();
scan.ReadNext();
scan >> ')';
if(!geom->GetSplineCurve2d(spline))
{
scan.Error ( string("2D Spline curve not found: ") + spline );
break;
}
Primitive * nprim = new Revolution(p0,p1,
*(geom->GetSplineCurve2d(spline)));
geom->AddSurfaces (nprim);
return new Solid(nprim);
}
case TOK_EXTRUSION:
{
scan.ReadNext();
scan >> '(';
string epath = scan.GetStringValue();
scan.ReadNext();
scan >> ';';
string profile = scan.GetStringValue();
scan.ReadNext();
Vec<3> z_dir;
scan >> ';' >> z_dir(0) >> ',' >> z_dir(1) >> ',' >> z_dir(2) >> ')';
if(!geom->GetSplineCurve2d(profile))
{
scan.Error ( string("2D Spline curve not found: ") + profile );
break;
}
if(!geom->GetSplineCurve3d(epath))
{
scan.Error ( string("2D Spline curve not found: ") + epath );
break;
}
Primitive * nprim = new Extrusion(geom->GetSplineCurve3d(epath),
geom->GetSplineCurve2d(profile),
z_dir);
geom->AddSurfaces (nprim);
return new Solid(nprim);
}
/// Torus
/// Lorenzo Codecasa (codecasa@elet.polimi.it)
/// April 27th, 2005
///
/// begin...
case TOK_TORUS:
{
Point<3> pc;
Vec<3> vn;
double R, r;
scan.ReadNext();
scan >> '(' >> pc >> ';' >> vn >> ';' >> R >> ';' >> r >> ')';
OneSurfacePrimitive * surf = new Torus ( pc, vn, R, r );
geom->AddSurfaces (surf);
return new Solid (surf);
}
/// ..end
case TOK_TRANSLATE:
{
Vec<3> v;
scan.ReadNext();
ParseChar (scan, '(');
v = ParseVector (scan);
ParseChar (scan, ';');
Solid * sol1 = ParseSolid (scan);
ParseChar (scan, ')');
Solid * nsol = sol1 -> Copy(*geom);
Transformation<3> trans(v);
nsol -> Transform (trans);
return nsol;
}
case TOK_ROTATE:
{
Point<3> c;
Vec<3> v;
scan.ReadNext();
scan >> '(' >> c >> ';' >> v >> ';';
Solid * sol1 = ParseSolid (scan);
ParseChar (scan, ')');
Solid * nsol = sol1 -> Copy(*geom);
Transformation<3> trans(c,v(0),v(1),v(2));
nsol -> Transform (trans);
return nsol;
}
case TOK_MULTITRANSLATE:
{
Vec<3> v;
int n;
scan.ReadNext();
scan >> '(' >> v >> ';' >> n >> ';';
Solid * sol1 = ParseSolid (scan);
scan >> ')';
Solid * hsol = sol1;
for (int i = 1; i <= n; i++)
{
Solid * nsol = sol1 -> Copy(*geom);
Transformation<3> trans(double(i) * v);
nsol -> Transform (trans);
hsol = new Solid (Solid::UNION, hsol, nsol);
}
return hsol;
}
case TOK_MULTIROTATE:
{
Point<3> c;
Vec<3> v;
int n;
scan.ReadNext();
scan >> '(' >> c >> ';' >> v >> ';' >> n >> ';';
Solid * sol1 = ParseSolid (scan);
scan >> ')';
Transformation<3> trans(c, v(0), v(1), v(2));
Transformation<3> multi(Vec<3>(0,0,0));
Transformation<3> ht;
Solid * hsol = sol1;
for (int i = 1; i <= n; i++)
{
Solid * nsol = sol1 -> Copy(*geom);
nsol -> Transform (multi);
hsol = new Solid (Solid::UNION, hsol, nsol);
ht=multi;
multi.Combine (trans, ht);
}
return hsol;
}
default:
{
scan.Error (string ("unknown primary ") + scan.GetStringValue());
}
}
}
else if (scan.GetToken() == TOK_STRING &&
geom->GetSolid(scan.GetStringValue()))
{
Solid * sol = const_cast<Solid*> (geom->GetSolid(scan.GetStringValue()));
scan.ReadNext();
return sol;
}
else if (scan.GetToken() == TOK_NOT)
{
scan.ReadNext();
Solid * sol1 = ParsePrimary (scan);
return new Solid (Solid::SUB, sol1);
}
else if (scan.GetToken() == '(')
{
scan.ReadNext();
Solid * sol1 = ParseSolid (scan);
scan.ReadNext();
return sol1;
}
scan.Error (string ("not a primary, name = ")+
scan.GetStringValue());
return 0;
}
Solid * ParseTerm (CSGScanner & scan)
{
Solid * sol = ParsePrimary(scan);
while (scan.GetToken() == TOK_AND)
{
scan.ReadNext();
Solid * sol2 = ParsePrimary(scan);
sol = new Solid (Solid::SECTION, sol, sol2);
}
return sol;
}
Solid * ParseSolid (CSGScanner & scan)
{
Solid * sol = ParseTerm(scan);
while (scan.GetToken() == TOK_OR)
{
scan.ReadNext();
Solid * sol2 = ParseTerm(scan);
sol = new Solid (Solid::UNION, sol, sol2);
}
return sol;
}
template <int D>
void LoadSpline (SplineGeometry<D> & spline, CSGScanner & scan)
{
double hd;
Point<D> x;
int nump, numseg;
//scan.ReadNext();
scan >> nump >> ';';
hd = 1;
spline.geompoints.SetSize(nump);
for(int i = 0; i<nump; i++)
{
if(D==2)
scan >> x(0) >> ',' >> x(1) >> ';';
else if(D==3)
scan >> x(0) >> ',' >> x(1) >> ',' >> x(2) >> ';';
spline.geompoints[i] = GeomPoint<D>(x,hd);
}
scan >> numseg;// >> ';';
spline.splines.SetSize(numseg);
int pnums,pnum1,pnum2,pnum3;
for(int i = 0; i<numseg; i++)
{
scan >> ';' >> pnums >> ',';
if (pnums == 2)
{
scan >> pnum1 >> ',' >> pnum2;// >> ';';
spline.splines[i] = new LineSeg<D>(spline.geompoints[pnum1-1],
spline.geompoints[pnum2-1]);
}
else if (pnums == 3)
{
scan >> pnum1 >> ',' >> pnum2 >> ','
>> pnum3;// >> ';';
spline.splines[i] = new SplineSeg3<D>(spline.geompoints[pnum1-1],
spline.geompoints[pnum2-1],
spline.geompoints[pnum3-1]);
}
else if (pnums == 4)
{
scan >> pnum1 >> ',' >> pnum2 >> ','
>> pnum3;// >> ';';
spline.splines[i] = new CircleSeg<D>(spline.geompoints[pnum1-1],
spline.geompoints[pnum2-1],
spline.geompoints[pnum3-1]);
}
}
}
void ParseFlags (CSGScanner & scan, Flags & flags)
{
while (scan.GetToken() == '-')
{
scan.ReadNext();
string name = scan.GetStringValue();
scan.ReadNext();
if (scan.GetToken() == '=')
{
scan.ReadNext();
if (scan.GetToken() == TOK_STRING)
{
flags.SetFlag (name.c_str(), scan.GetStringValue().c_str());
scan.ReadNext();
}
else if (scan.GetToken() == '[')
{
scan.ReadNext();
if(scan.GetToken() == '-' || scan.GetToken() == TOK_NUM)
{
Array<double> vals;
vals.Append (ParseNumber(scan));
while (scan.GetToken() == ',')
{
scan.ReadNext();
vals.Append (ParseNumber(scan));
}
ParseChar (scan, ']');
flags.SetFlag (name, vals);
}
else
{ // string list
Array<string> vals;
vals.Append(scan.GetStringValue());
scan.ReadNext();
while (scan.GetToken() == ',')
{
scan.ReadNext();
vals.Append(scan.GetStringValue());
scan.ReadNext();
}
ParseChar (scan, ']');
flags.SetFlag (name, vals);
}
}
else if (scan.GetToken() == TOK_NUM)
{
flags.SetFlag (name.c_str(), scan.GetNumValue());
scan.ReadNext();
}
}
else
{
flags.SetFlag (name.c_str());
}
}
}
/*
Main parsing function for CSG geometry
*/
CSGeometry * ParseCSG (istream & istr, CSGeometry * instance=nullptr)
{
CSGScanner scan(istr);
if (instance)
{
new (instance) CSGeometry;
geom = instance;
}
else
geom = new CSGeometry;
scan.ReadNext();
if (scan.GetToken() != TOK_RECO) // keyword 'algebraic3d'
return 0;
scan.ReadNext();
try
{
while (1)
{
if (scan.GetToken() == TOK_END) break;
if (scan.GetToken() == TOK_SOLID)
{
scan.ReadNext();
if (scan.GetToken() != TOK_STRING)
scan.Error ("name identifier expected");
string solidname = scan.GetStringValue();
scan.ReadNext();
ParseChar (scan, '=');
Solid * solid = ParseSolid (scan);
Flags flags;
ParseFlags (scan, flags);
geom->SetSolid (solidname.c_str(), new Solid (Solid::ROOT, solid));
geom->SetFlags (solidname.c_str(), flags);
ParseChar (scan, ';');
PrintMessage (4, "define solid ", solidname);
}
else if (scan.GetToken() == TOK_TLO)
{ // a TopLevelObject definition
scan.ReadNext();
string name = scan.GetStringValue();
scan.ReadNext();
if (scan.GetToken() != TOK_STRING)
{ // a solid TLO
Flags flags;
ParseFlags (scan, flags);
ParseChar (scan, ';');
if (!geom->GetSolid (name))
scan.Error ("Top-Level-Object "+name+" not defined");
int tlonr =
geom->SetTopLevelObject ((Solid*)geom->GetSolid(name));
TopLevelObject * tlo = geom->GetTopLevelObject (tlonr);
if (flags.NumListFlagDefined ("col"))
{
const Array<double> & col =
flags.GetNumListFlag ("col");
tlo->SetRGB (col[0], col[1], col[2]);
}
if (flags.GetDefineFlag ("transparent"))
tlo->SetTransparent (1);
tlo->SetMaterial (flags.GetStringFlag ("material", ""));
tlo->SetLayer (int(flags.GetNumFlag ("layer", 1)));
if (flags.NumFlagDefined ("maxh"))
tlo->SetMaxH (flags.GetNumFlag("maxh", 1e10));
}
else
{ // a surface TLO
string surfname = scan.GetStringValue();
scan.ReadNext();
Flags flags;
ParseFlags (scan, flags);
ParseChar (scan, ';');
NgArray<int> si;
geom->GetSolid(surfname)->GetSurfaceIndices(si);
int tlonr =
geom->SetTopLevelObject ((Solid*)geom->GetSolid(name),
(Surface*)geom->GetSurface(si.Get(1)));
TopLevelObject * tlo = geom->GetTopLevelObject (tlonr);
if (flags.NumListFlagDefined ("col"))
{
const auto& col = flags.GetNumListFlag ("col");
tlo->SetRGB (col[0], col[1], col[2]);
}
if (flags.GetDefineFlag ("transparent"))
tlo->SetTransparent (1);
if (flags.NumFlagDefined ("maxh"))
tlo->SetMaxH (flags.GetNumFlag("maxh", 1e10));
tlo->SetLayer (int(flags.GetNumFlag ("layer", 1)));
tlo->SetBCProp (int(flags.GetNumFlag ("bc", -1)));
if ( flags.StringFlagDefined("bcname") )
tlo->SetBCName ( flags.GetStringFlag ("bcname", "default") );
}
}
else if (scan.GetToken() == TOK_IDENTIFY)
{
scan.ReadNext();
switch (scan.GetToken())
{
case TOK_CLOSESURFACES:
{
scan.ReadNext();
string name1 = scan.GetStringValue();
scan.ReadNext();
string name2 = scan.GetStringValue();
scan.ReadNext();
Flags flags;
ParseFlags (scan, flags);
ParseChar (scan, ';');
NgArray<int> si1, si2;
geom->GetSolid(name1)->GetSurfaceIndices(si1);
geom->GetSolid(name2)->GetSurfaceIndices(si2);
const TopLevelObject * domain = 0;
if (flags.StringFlagDefined ("tlo"))
{
domain =
geom->GetTopLevelObject (geom->GetSolid(flags.GetStringFlag ("tlo","")));
if (!domain)
scan.Error ("identification needs undefined tlo");
}
geom->AddIdentification
(new CloseSurfaceIdentification
(geom->GetNIdentifications()+1, *geom,
geom->GetSurface (si1[0]), geom->GetSurface (si2[0]),
domain,
flags));
break;
}
case TOK_PERIODIC:
{
scan.ReadNext();
string name1 = scan.GetStringValue();
scan.ReadNext();
string name2 = scan.GetStringValue();
scan.ReadNext();
ParseChar (scan, ';');
NgArray<int> si1, si2;
geom->GetSolid(name1)->GetSurfaceIndices(si1);
geom->GetSolid(name2)->GetSurfaceIndices(si2);
geom->AddIdentification
(new PeriodicIdentification
(geom->GetNIdentifications()+1,
*geom,
geom->GetSurface (si1.Get(1)),
geom->GetSurface (si2.Get(1))));
break;
}
default:
scan.Error ("keyword 'closesurfaces' or 'periodic' expected");
}
}
else if (scan.GetToken() == TOK_SINGULAR)
{
scan.ReadNext();
switch (scan.GetToken())
{
case TOK_FACE:
{
scan.ReadNext();
string name1 = scan.GetStringValue(); // tlo
scan.ReadNext();
string name2 = scan.GetStringValue();
scan.ReadNext();
Flags flags;
ParseFlags (scan, flags);
int factor = int(flags.GetNumFlag("factor",1));
// cout << "Singular Face with factor " << factor << endl;
PrintMessageCR (3, "Singular Face with factor ", factor);
ParseChar (scan, ';');
const Solid * sol = geom->GetSolid(name2);
if(!sol)
scan.Error ("unknown solid in singular face definition");
else
for (int i = 0; i < geom->GetNTopLevelObjects(); i++)
if (name1 == geom->GetTopLevelObject (i)->GetSolid()->Name())
geom->singfaces.Append (new SingularFace (i+1, sol,factor));
break;
}
case TOK_EDGE:
{
scan.ReadNext();
string name1 = scan.GetStringValue();
scan.ReadNext();
string name2 = scan.GetStringValue();
scan.ReadNext();
Flags flags;
ParseFlags (scan, flags);
int factor = int(flags.GetNumFlag("factor",1));
double maxhinit = flags.GetNumFlag("maxh",-1);
ParseChar (scan, ';');
const Solid * s1 = geom->GetSolid(name1);
const Solid * s2 = geom->GetSolid(name2);
PrintMessageCR (3, "Singular Edge with factor ", factor);
int domnr = -1;
if (flags.StringFlagDefined ("tlo"))
{
const Solid * sol =
geom->GetSolid(flags.GetStringFlag ("tlo",""));
for (int i = 0; i < geom->GetNTopLevelObjects(); i++)
if (geom->GetTopLevelObject(i)->GetSolid() == sol)
domnr = i;
// cout << "domnr = " << domnr;
}
if(!s1 || !s2)
scan.Error ("unknown solid ins singular edge definition");
else
geom->singedges.Append (new SingularEdge (1, domnr,
*geom, s1, s2, factor,
maxhinit));
break;
}
case TOK_POINT:
{
scan.ReadNext();
string name1 = scan.GetStringValue();
scan.ReadNext();
string name2 = scan.GetStringValue();
scan.ReadNext();
string name3 = scan.GetStringValue();
scan.ReadNext();
Flags flags;
ParseFlags (scan, flags);
int factor = int(flags.GetNumFlag("factor",1));
ParseChar (scan, ';');
const Solid * s1 = geom->GetSolid(name1);
const Solid * s2 = geom->GetSolid(name2);
const Solid * s3 = geom->GetSolid(name3);
// cout << "Singular Point with factor " << factor << endl;
PrintMessageCR (3, "Singular Point with factor ", factor);
geom->singpoints.Append (new SingularPoint (1, s1, s2, s3, factor));
break;
}
default:
scan.Error ("keyword 'face' or 'edge' or 'point' expected");
}
}
else if (scan.GetToken() == TOK_POINT)
{
Point<3> p;
scan.ReadNext();
ParseChar (scan, '(');
p = Point<3> (ParseVector (scan));
ParseChar (scan, ')');
Flags flags;
ParseFlags (scan, flags);
int factor = int(flags.GetNumFlag("factor",0));
ParseChar (scan, ';');
geom->AddUserPoint (p, factor);
}
else if (scan.GetToken() == TOK_BOUNDINGBOX)
{
Point<3> p1, p2;
scan.ReadNext();
ParseChar (scan, '(');
p1 = Point<3> (ParseVector (scan));
ParseChar (scan, ';');
p2 = Point<3> (ParseVector (scan));
ParseChar (scan, ')');
ParseChar (scan, ';');
geom->SetBoundingBox (Box<3> (p1, p2));
}
else if (scan.GetToken() == TOK_CURVE2D)
{
scan.ReadNext();
if (scan.GetToken() != TOK_STRING)
scan.Error ("name identifier expected");
string curvename = scan.GetStringValue();
scan.ReadNext();
ParseChar (scan, '=');
ParseChar (scan, '(');
auto newspline = make_shared<SplineGeometry<2>>();
// newspline->CSGLoad(scan);
LoadSpline (*newspline, scan);
ParseChar (scan, ')');
ParseChar (scan, ';');
geom->SetSplineCurve(curvename.c_str(),newspline);
PrintMessage (4, "define 2d curve ", curvename);
}
else if (scan.GetToken() == TOK_CURVE3D)
{
scan.ReadNext();
if (scan.GetToken() != TOK_STRING)
scan.Error ("name identifier expected");
string curvename = scan.GetStringValue();
scan.ReadNext();
ParseChar (scan, '=');
ParseChar (scan, '(');
auto newspline = make_shared<SplineGeometry<3>>();
// newspline->CSGLoad(scan);
LoadSpline (*newspline, scan);
ParseChar (scan, ')');
ParseChar (scan, ';');
geom->SetSplineCurve(curvename.c_str(),newspline);
PrintMessage (4, "define 3d curve ", curvename);
}
else if (scan.GetToken() == TOK_BOUNDARYCONDITION)
{
scan.ReadNext();
string name1 = scan.GetStringValue();
scan.ReadNext();
string name2 = scan.GetStringValue();
scan.ReadNext();
int num = int (ParseNumber (scan));
ParseChar (scan, ';');
CSGeometry::BCModification bcm;
bcm.bcname = NULL;
NgArray<int> si;
geom->GetSolid(name1)->GetSurfaceIndices(si);
if(si.Size() == 0)
{
string errstring = "solid \""; errstring += name1; errstring += "\" has no surfaces";
scan.Error (errstring);
}
bcm.tlonr = -1;
int i;
for (i = 0; i < geom->GetNTopLevelObjects(); i++)
if (string (geom->GetTopLevelObject(i)->GetSolid()->Name())
== name2)
{
bcm.tlonr = i;
break;
}
if(bcm.tlonr == -1)
{
string errstring = "tlo \""; errstring += name2; errstring += "\" not found";
scan.Error(errstring);
}
bcm.bcnr = num;
for (i = 0; i < si.Size(); i++)
{
bcm.si = si[i];
geom->bcmodifications.Append (bcm);
}
}
else if (scan.GetToken() == TOK_BOUNDARYCONDITIONNAME)
{
scan.ReadNext();
string name1 = scan.GetStringValue();
scan.ReadNext();
string name2 = scan.GetStringValue();
scan.ReadNext();
string bcname = scan.GetStringValue();
scan.ReadNext();
ParseChar(scan, ';');
CSGeometry::BCModification bcm;
bcm.bcname = NULL;
NgArray<int> si;
geom->GetSolid(name1)->GetSurfaceIndices(si);
if(si.Size() == 0)
{
string errstring = "solid \""; errstring += name1; errstring += "\" has no surfaces";
scan.Error (errstring);
}
bcm.tlonr = -1;
int i;
for (i = 0; i < geom->GetNTopLevelObjects(); i++)
if (string (geom->GetTopLevelObject(i)->GetSolid()->Name())
== name2)
{
bcm.tlonr = i;
break;
}
if(bcm.tlonr == -1)
{
string errstring = "tlo \""; errstring += name2; errstring += "\" not found";
scan.Error(errstring);
}
bcm.bcnr = -1;
for (i = 0; i < si.Size(); i++)
{
bcm.si = si[i];
geom->bcmodifications.Append (bcm);
geom->bcmodifications.Last().bcname = new string(bcname);
}
}
else if (scan.GetToken() == TOK_DEFINE)
{
scan.ReadNext();
string name;
double val;
switch (scan.GetToken())
{
case TOK_CONSTANT:
scan.ReadNext();
name = scan.GetStringValue();
scan.ReadNext();
ParseChar(scan, '=');
val = ParseNumber(scan);
if(name == "identprec")
geom->SetIdEps(val);
break;
default:
scan.Error ("keyword 'constant' expected");
}
}
else
{
cout << "read unidentified token " << scan.GetToken()
<< " (as char: \"" << char(scan.GetToken()) << "\")"
<< " string = " << scan.GetStringValue() << endl;
scan.ReadNext();
}
}
}
catch (string errstr)
{
cout << "caught error " << errstr << endl;
throw NgException (errstr);
}
(*testout) << geom->GetNTopLevelObjects() << " TLOs:" << endl;
for (int i = 0; i < geom->GetNTopLevelObjects(); i++)
{
const TopLevelObject * tlo = geom->GetTopLevelObject(i);
if (tlo->GetSolid())
(*testout) << i << ": " << *tlo->GetSolid() << endl;
}
(*testout) << geom->GetNSurf() << " Surfaces" << endl;
for (int i = 0; i < geom->GetNSurf(); i++)
(*testout) << i << ": " << *geom->GetSurface(i) << endl;
return geom;
/*
do
{
scan.ReadNext();
if (scan.GetToken() == TOK_STRING)
cout << "found string " << scan.GetStringValue() << endl;
else
cout << "token = " << int(scan.GetToken()) << endl;
}
while (scan.GetToken() != TOK_END);
*/
}
};