1 #include <mystdlib.h>
2 #include <myadt.hpp>
3 
4 #include <linalg.hpp>
5 #include <csg.hpp>
6 
7 
8 namespace netgen
9 {
10   static kwstruct defkw[] =
11     {
12       { TOK_RECO,    "algebraic3d" },
13       { TOK_SOLID,   "solid" },
14       { TOK_TLO,     "tlo" },
15       { TOK_CURVE2D, "curve2d" },
16       { TOK_CURVE3D, "curve3d" },
17       { TOK_BOUNDINGBOX, "boundingbox" },
18       { TOK_OR,      "or" },
19       { TOK_AND,     "and" },
20       { TOK_NOT,     "not" },
21       { TOK_SINGULAR, "singular" },
22       { TOK_EDGE,     "edge" },
23       { TOK_FACE,     "face" },
24       { TOK_POINT,    "point" },
25       { TOK_IDENTIFY, "identify" },
26       { TOK_CLOSESURFACES, "closesurfaces" },
27       { TOK_CLOSEEDGES, "closeedges" },
28       { TOK_PERIODIC,  "periodic" },
29       { TOK_BOUNDARYCONDITION, "boundarycondition" },
30       { TOK_BOUNDARYCONDITIONNAME, "boundaryconditionname" },
31       { TOK_DEFINE, "define" },
32       { TOK_CONSTANT, "constant" },
33       { TOKEN_TYPE(0), 0 }
34     };
35 
36   static primstruct defprim[] =
37     {
38       { TOK_PLANE,     "plane" },
39       { TOK_SPHERE,    "sphere" },
40       { TOK_CYLINDER,  "cylinder" },
41       { TOK_CONE,      "cone" },
42       { TOK_ELLIPTICCYLINDER, "ellipticcylinder" },
43       { TOK_ELLIPSOID, "ellipsoid" },
44       { TOK_ORTHOBRICK, "orthobrick" },
45       { TOK_POLYHEDRON, "polyhedron" },
46       { TOK_TORUS,      "torus" },
47 
48       { TOK_TUBE,      "tube" },
49       { TOK_GENCYL,    "gencyl" },
50       { TOK_EXTRUSION,  "extrusion" },
51       { TOK_REVOLUTION, "revolution" },
52 
53       { TOK_TRANSLATE, "translate" },
54       { TOK_MULTITRANSLATE, "multitranslate" },
55       { TOK_ROTATE,   "rotate" },
56       { TOK_MULTIROTATE, "multirotate" },
57       { PRIMITIVE_TYPE(0), 0 }
58     };
59 
60   static CSGeometry * geom;
61 
62 
CSGScanner(istream & ascanin)63   CSGScanner :: CSGScanner (istream & ascanin)
64   {
65     scanin = &ascanin;
66     token = TOK_END;
67     num_value = 0;
68     linenum = 1;
69   }
70 
71 
ReadNext()72   void CSGScanner :: ReadNext ()
73   {
74     char ch;
75 
76 
77     // scan whitespaces
78     do
79       {
80 	scanin->get(ch);
81 
82 	//if (ch == '\n')
83 	//  linenum++;
84 
85 	// end of file reached
86 	if (scanin->eof())
87 	  {
88 	    token = TOK_END;
89 	    return;
90 	  }
91 	if (ch == '\n')
92 	  linenum++;
93 
94 
95 	// skip comment line
96 	if (ch == '#')
97 	  {
98 	    while (ch != '\n')
99 	      {
100 		scanin->get(ch);
101 		if (scanin->eof())
102 		  {
103 		    token = TOK_END;
104 		    return;
105 		  }
106 	      }
107 	    linenum++;
108 	  }
109       }
110     while (isspace(ch));
111 
112     switch (ch)
113       {
114       case '(': case ')':
115       case '[': case ']':
116       case '-':
117       case '=': case ',': case ';':
118 	{
119 	  token = TOKEN_TYPE (ch);
120 	  break;
121 	}
122 
123       default:
124 	{
125 	  if (isdigit (ch) || ch == '.')
126 	    {
127 	      scanin->putback (ch);
128 	      (*scanin) >> num_value;
129 	      token = TOK_NUM;
130 	      return;
131 	    }
132 
133 	  if (isalpha (ch))
134 	    {
135 	      string_value = string (1, ch);
136 	      scanin->get(ch);
137 	      while (isalnum(ch) || ch == '_')
138 		{
139 		  string_value += ch;
140 		  scanin->get(ch);
141 		}
142 	      scanin->putback (ch);
143 	    }
144 
145 	  int nr = 0;
146 	  while (defkw[nr].kw)
147 	    {
148 	      if (string_value == defkw[nr].name)
149 		{
150 		  token = defkw[nr].kw;
151 		  return;
152 		}
153 	      nr++;
154 	    }
155 
156 	  nr = 0;
157 	  while (defprim[nr].kw)
158 	    {
159 	      if (string_value == defprim[nr].name)
160 		{
161 		  token = TOK_PRIMITIVE;
162 		  prim_token = defprim[nr].kw;
163 		  return;
164 		}
165 	      nr++;
166 	    }
167 
168 	  token = TOK_STRING;
169 	}
170       }
171   }
172 
Error(const string & err)173   void CSGScanner :: Error (const string & err)
174   {
175     stringstream errstr;
176     errstr << "Parsing error in line " << linenum << ": " << endl << err << endl;
177     throw string(errstr.str());
178   }
179 
180 
181   /*
182     Solid = Term { OR Term }
183     Term  = Primary { AND Primary }
184     Primary = PRIM | IDENT | ( Solid ) | NOT Primary
185   */
186 
ParseChar(CSGScanner & scan,char ch)187   void ParseChar (CSGScanner & scan, char ch)
188   {
189     if (scan.GetToken() != TOKEN_TYPE(ch))
190       scan.Error (string ("token '") + string(1, ch) + string("' expected"));
191     scan.ReadNext();
192   }
193 
ParseNumber(CSGScanner & scan)194   double ParseNumber(CSGScanner & scan)
195   {
196     if (scan.GetToken() == '-')
197       {
198 	scan.ReadNext();
199 	return -ParseNumber (scan);
200       }
201     if (scan.GetToken() != TOK_NUM) scan.Error ("number expected");
202     double val = scan.GetNumValue();
203     scan.ReadNext();
204     return val;
205   }
206 
ParseVector(CSGScanner & scan)207   Vec<3> ParseVector (CSGScanner & scan)
208   {
209     Vec<3> v;
210     v(0) = ParseNumber (scan);
211     ParseChar (scan, ',');
212     v(1) = ParseNumber (scan);
213     ParseChar (scan, ',');
214     v(2) = ParseNumber (scan);
215     return v;
216   }
217 
218 
operator >>(CSGScanner & scan,char ch)219   CSGScanner & operator>> (CSGScanner & scan, char ch)
220   {
221     if (scan.GetToken() != TOKEN_TYPE(ch))
222       scan.Error (string ("token '") + string(1, ch) + string("' expected"));
223     scan.ReadNext();
224     return scan;
225   }
226 
operator >>(CSGScanner & scan,double & d)227   CSGScanner & operator>> (CSGScanner & scan, double & d)
228   {
229     d = ParseNumber (scan);
230     return scan;
231   }
232 
operator >>(CSGScanner & scan,int & i)233   CSGScanner & operator>> (CSGScanner & scan, int & i)
234   {
235     i = int (ParseNumber (scan));
236     return scan;
237   }
238 
operator >>(CSGScanner & scan,Point<3> & p)239   CSGScanner & operator>> (CSGScanner & scan, Point<3> & p)
240   {
241     scan >> p(0) >> ',' >> p(1) >> ',' >> p(2);
242     return scan;
243   }
244 
operator >>(CSGScanner & scan,Vec<3> & v)245   CSGScanner & operator>> (CSGScanner & scan, Vec<3> & v)
246   {
247     scan >> v(0) >> ',' >> v(1) >> ',' >> v(2);
248     return scan;
249   }
250 
251 
252   Solid * ParseSolid (CSGScanner & scan);
253   Solid * ParseTerm (CSGScanner & scan);
254   Solid * ParsePrimary (CSGScanner & scan);
255 
256 
ParsePrimary(CSGScanner & scan)257   Solid * ParsePrimary (CSGScanner & scan)
258   {
259     if (scan.GetToken() == TOK_PRIMITIVE)
260       {
261 	switch (scan.GetPrimitiveToken())
262 	  {
263 	  case TOK_PLANE:
264 	    {
265 	      Point<3> p;
266 	      Vec<3> v;
267 
268 	      scan.ReadNext();
269 	      scan >> '(' >> p >> ';' >> v >> ')';
270 
271 	      OneSurfacePrimitive * surf = new Plane ( p, v );
272 	      geom->AddSurfaces (surf);
273 	      return new Solid (surf);
274 	    }
275 
276 	  case TOK_CYLINDER:
277 	    {
278 	      Point<3> pa, pb;
279 	      double r;
280 
281 	      scan.ReadNext();
282 	      scan >> '(' >> pa >> ';' >> pb >> ';' >> r >> ')';
283 
284 	      OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r );
285 	      geom->AddSurfaces (surf);
286 	      return new Solid (surf);
287 	    }
288 
289 	  case TOK_ELLIPTICCYLINDER:
290 	    {
291 	      Point<3> pa;
292 	      Vec<3> vl, vs;
293 
294 	      scan.ReadNext();
295 	      scan >> '(' >> pa >> ';' >> vl >> ';' >> vs >> ')';
296 
297 	      OneSurfacePrimitive * surf = new EllipticCylinder ( pa, vl, vs);
298 	      geom->AddSurfaces (surf);
299 	      return new Solid (surf);
300 	    }
301 
302 
303 	  case TOK_ELLIPSOID:
304 	    {
305 	      Point<3> pa;
306 	      Vec<3> v1, v2, v3;
307 
308 	      scan.ReadNext();
309 	      scan >> '(' >> pa >> ';' >> v1 >> ';' >> v2 >> ';' >> v3 >> ')';
310 
311 	      OneSurfacePrimitive * surf = new Ellipsoid ( pa, v1, v2, v3);
312 	      geom->AddSurfaces (surf);
313 	      return new Solid (surf);
314 	    }
315 
316 
317 	  case TOK_CONE:
318 	    {
319 	      Point<3> pa, pb;
320 	      double ra, rb;
321 
322 	      scan.ReadNext();
323 	      scan >> '(' >> pa >> ';' >> ra >> ';' >> pb >> ';' >> rb >> ')';
324 
325 	      OneSurfacePrimitive * surf = new Cone ( pa, pb, ra, rb );
326 	      geom->AddSurfaces (surf);
327 	      return new Solid (surf);
328 	    }
329 
330 
331 
332 	  case TOK_SPHERE:
333 	    {
334 	      Point<3> p;
335 	      double r;
336 
337 	      scan.ReadNext();
338 	      scan >> '(' >> p >> ';' >> r >> ')';
339 
340 	      OneSurfacePrimitive * surf = new Sphere ( p, r );
341 	      geom->AddSurfaces (surf);
342 	      return new Solid (surf);
343 	    }
344 
345 	  case TOK_ORTHOBRICK:
346 	    {
347 	      Point<3> pa, pb;
348 
349 	      scan.ReadNext();
350 	      scan >> '(' >> pa >> ';' >> pb >> ')';
351 
352 
353 	      Primitive * nprim = new OrthoBrick (pa, pb);
354 	      geom->AddSurfaces (nprim);
355 	      return new Solid (nprim);
356 	    }
357 
358 	  case TOK_POLYHEDRON:
359 	    {
360 	      // Added by Dalibor Lukas, October 15, 2003
361 
362 	      Point<3> p;
363 	      //int pi1, pi2, pi3, pi4;
364 
365 	      scan.ReadNext();
366 	      ParseChar (scan, '(');
367 
368 	      Polyhedra * polyhedron = new Polyhedra;
369 
370 	      // scanning the points
371 	      while (1)
372 		{
373 		  p = Point<3> (ParseVector (scan));
374 		  ParseChar (scan, ';');
375 
376 		  polyhedron->AddPoint(p);
377 
378 		  if (scan.GetToken() == ';')
379 		    {
380 		      scan.ReadNext();
381 		      break;
382 		    }
383 		}
384 
385 	      // scanning the faces
386 	      int inputface = 0;
387 	      while (1)
388 		{
389 		  Array<int> pnums,cleaned_pnums;
390 		  for(int i=0; i<3; i++)
391 		    {
392 		      pnums.Append((int) (ParseNumber (scan)));
393 		      if(i<2)
394 			ParseChar (scan, ',');
395 		    }
396 
397 		  if (scan.GetToken() == TOK_COMMA)
398 		    {
399 		      ParseChar (scan, ',');
400 		      pnums.Append((int) (ParseNumber (scan)));
401 		    }
402 
403 		  for(int i=0; i<pnums.Size(); i++)
404 		    if(!cleaned_pnums.Contains(pnums[i]))
405 		      cleaned_pnums.Append(pnums[i]);
406 
407 		  if(cleaned_pnums.Size() == 3)
408 		    {
409 		      polyhedron->AddFace(cleaned_pnums[0]-1,
410 					  cleaned_pnums[1]-1,
411 					  cleaned_pnums[2]-1,
412 					  inputface);
413 		    }
414 		  else if(cleaned_pnums.Size() == 4)
415 		    {
416 		      polyhedron->AddFace(cleaned_pnums[0]-1,
417 					  cleaned_pnums[1]-1,
418 					  cleaned_pnums[2]-1,
419 					  inputface);
420 		      polyhedron->AddFace(cleaned_pnums[0]-1,
421 					  cleaned_pnums[2]-1,
422 					  cleaned_pnums[3]-1,
423 					  inputface);
424 		    }
425 		  else
426 		    {
427 		      ostringstream msg;
428 		      msg << "Something wrong with polyhedron face:";
429 		      for(int i=0; i<pnums.Size(); i++)
430 			msg << " " << pnums[i];
431 		      throw NgException(msg.str());
432 		    }
433 
434 
435 
436 		  if (scan.GetToken() == ')')
437 		    {
438 		      scan.ReadNext();
439 		      break;
440 		    }
441 		  scan.ReadNext();
442 		  inputface++;
443 		}
444 
445 	      geom->AddSurfaces (polyhedron);
446 	      return new Solid (polyhedron);
447 	    }
448 
449 
450 	  case TOK_REVOLUTION:
451 	    {
452 	      Point<3> p0,p1;
453 
454 	      scan.ReadNext();
455 	      scan >> '(' >> p0 >> ';' >> p1 >> ';';
456 
457 	      string spline = scan.GetStringValue();
458 
459 	      scan.ReadNext();
460 	      scan >> ')';
461 
462 	      if(!geom->GetSplineCurve2d(spline))
463 		{
464 		  scan.Error ( string("2D Spline curve not found: ") + spline );
465 		  break;
466 		}
467 
468 	      Primitive * nprim = new Revolution(p0,p1,
469 						 *(geom->GetSplineCurve2d(spline)));
470 
471 	      geom->AddSurfaces (nprim);
472 	      return new Solid(nprim);
473 	    }
474 
475 
476 	  case TOK_EXTRUSION:
477 	    {
478 	      scan.ReadNext();
479 	      scan >> '(';
480 	      string epath = scan.GetStringValue();
481 	      scan.ReadNext();
482 	      scan >> ';';
483 	      string profile = scan.GetStringValue();
484 
485 
486 	      scan.ReadNext();
487 	      Vec<3> z_dir;
488 	      scan >> ';' >> z_dir(0) >> ',' >> z_dir(1) >> ',' >> z_dir(2) >> ')';
489 
490 	      if(!geom->GetSplineCurve2d(profile))
491 		{
492 		  scan.Error ( string("2D Spline curve not found: ") + profile );
493 		  break;
494 		}
495 	      if(!geom->GetSplineCurve3d(epath))
496 		{
497 		  scan.Error ( string("2D Spline curve not found: ") + epath );
498 		  break;
499 		}
500 
501 	      Primitive * nprim = new Extrusion(*(geom->GetSplineCurve3d(epath)),
502 						*(geom->GetSplineCurve2d(profile)),
503 						z_dir);
504 	      geom->AddSurfaces (nprim);
505 	      return new Solid(nprim);
506 	    }
507 
508 
509 	  /// Torus
510     	  /// Lorenzo Codecasa (codecasa@elet.polimi.it)
511     	  /// April 27th, 2005
512 	  ///
513 	  /// begin...
514 	  case TOK_TORUS:
515 	    {
516 	      Point<3> pc;
517 	      Vec<3> vn;
518 	      double R, r;
519 
520 	      scan.ReadNext();
521 	      scan >> '(' >> pc >> ';' >> vn >> ';' >> R >> ';' >> r >> ')';
522 
523 	      OneSurfacePrimitive * surf = new Torus ( pc, vn, R, r );
524 	      geom->AddSurfaces (surf);
525 	      return new Solid (surf);
526 	    }
527 	  /// ..end
528 
529 
530 
531 
532 	  case TOK_TRANSLATE:
533 	    {
534 	      Vec<3> v;
535 	      scan.ReadNext();
536 
537 	      ParseChar (scan, '(');
538 	      v = ParseVector (scan);
539 	      ParseChar (scan, ';');
540 
541 	      Solid * sol1 = ParseSolid (scan);
542 
543 	      ParseChar (scan, ')');
544 
545 	      Solid * nsol = sol1 -> Copy(*geom);
546 	      Transformation<3> trans(v);
547 	      nsol -> Transform (trans);
548 	      return nsol;
549 	    }
550 
551 
552 	  case TOK_ROTATE:
553 	    {
554 	      Point<3> c;
555 	      Vec<3> v;
556 	      scan.ReadNext();
557 
558 	      scan >> '(' >> c >> ';' >> v >> ';';
559 
560 	      Solid * sol1 = ParseSolid (scan);
561 
562 	      ParseChar (scan, ')');
563 
564 	      Solid * nsol = sol1 -> Copy(*geom);
565 	      Transformation<3> trans(c,v(0),v(1),v(2));
566 	      nsol -> Transform (trans);
567 	      return nsol;
568 	    }
569 
570 
571 	  case TOK_MULTITRANSLATE:
572 	    {
573 	      Vec<3> v;
574 	      int n;
575 
576 	      scan.ReadNext();
577 
578 	      scan >> '(' >> v >> ';' >> n >> ';';
579 
580 	      Solid * sol1 = ParseSolid (scan);
581 
582 	      scan >> ')';
583 
584 	      Solid * hsol = sol1;
585 	      for (int i = 1; i <= n; i++)
586 		{
587 		  Solid * nsol = sol1 -> Copy(*geom);
588 		  Transformation<3> trans(double(i) * v);
589 
590 		  nsol -> Transform (trans);
591 		  hsol = new Solid (Solid::UNION, hsol, nsol);
592 		}
593 	      return hsol;
594 	    }
595 
596 
597 	  case TOK_MULTIROTATE:
598 	    {
599 	      Point<3> c;
600 	      Vec<3> v;
601 	      int n;
602 
603 	      scan.ReadNext();
604 
605 	      scan >> '(' >> c >> ';' >> v >> ';' >> n >> ';';
606 	      Solid * sol1 = ParseSolid (scan);
607 	      scan >> ')';
608 
609 	      Transformation<3> trans(c, v(0), v(1), v(2));
610 	      Transformation<3> multi(Vec<3>(0,0,0));
611 	      Transformation<3> ht;
612 
613 	      Solid * hsol = sol1;
614 	      for (int i = 1; i <= n; i++)
615 		{
616 		  Solid * nsol = sol1 -> Copy(*geom);
617 
618 		  nsol -> Transform (multi);
619 		  hsol = new Solid (Solid::UNION, hsol, nsol);
620 
621 		  ht=multi;
622 		  multi.Combine (trans, ht);
623 		}
624 	      return hsol;
625 	    }
626 
627 
628 	  default:
629 	    {
630 	      scan.Error (string ("unknown primary ") + scan.GetStringValue());
631 	    }
632 
633 	  }
634       }
635 
636     else if (scan.GetToken() == TOK_STRING &&
637 	     geom->GetSolid(scan.GetStringValue()))
638 
639       {
640 	Solid * sol = const_cast<Solid*> (geom->GetSolid(scan.GetStringValue()));
641 	scan.ReadNext();
642 	return sol;
643       }
644 
645     else if (scan.GetToken() == TOK_NOT)
646 
647       {
648 	scan.ReadNext();
649 	Solid * sol1 = ParsePrimary (scan);
650 	return new Solid (Solid::SUB, sol1);
651       }
652 
653     else if (scan.GetToken() == '(')
654 
655       {
656 	scan.ReadNext();
657 	Solid * sol1 = ParseSolid (scan);
658 	scan.ReadNext();
659 	return sol1;
660       }
661 
662     scan.Error (string ("not a primary, name = ")+
663 		scan.GetStringValue());
664     return 0;
665   }
666 
667 
668 
ParseTerm(CSGScanner & scan)669   Solid * ParseTerm (CSGScanner & scan)
670   {
671     Solid * sol = ParsePrimary(scan);
672     while (scan.GetToken() == TOK_AND)
673       {
674 	scan.ReadNext();
675 	Solid * sol2 = ParsePrimary(scan);
676 	sol = new Solid (Solid::SECTION, sol, sol2);
677       }
678     return sol;
679   }
680 
681 
ParseSolid(CSGScanner & scan)682   Solid * ParseSolid (CSGScanner & scan)
683   {
684     Solid * sol = ParseTerm(scan);
685     while (scan.GetToken() == TOK_OR)
686       {
687 	scan.ReadNext();
688 	Solid * sol2 = ParseTerm(scan);
689 	sol = new Solid (Solid::UNION, sol, sol2);
690       }
691     return sol;
692   }
693 
694 
695   template <int D>
LoadSpline(SplineGeometry<D> & spline,CSGScanner & scan)696   void LoadSpline (SplineGeometry<D> & spline, CSGScanner & scan)
697   {
698     double hd;
699     Point<D> x;
700     int nump, numseg;
701 
702     //scan.ReadNext();
703     scan >> nump >> ';';
704 
705     hd = 1;
706     spline.geompoints.SetSize(nump);
707     for(int i = 0; i<nump; i++)
708       {
709 	if(D==2)
710 	  scan >> x(0) >> ',' >> x(1) >> ';';
711 	else if(D==3)
712 	  scan >> x(0) >> ',' >> x(1) >> ',' >> x(2) >> ';';
713 
714 	spline.geompoints[i] = GeomPoint<D>(x,hd);
715       }
716 
717     scan >> numseg;// >> ';';
718 
719     spline.splines.SetSize(numseg);
720 
721   int pnums,pnum1,pnum2,pnum3;
722 
723 
724   for(int i = 0; i<numseg; i++)
725     {
726       scan >> ';' >> pnums >> ',';
727       if (pnums == 2)
728 	{
729 	  scan >> pnum1 >> ',' >> pnum2;// >> ';';
730 	  spline.splines[i] = new LineSeg<D>(spline.geompoints[pnum1-1],
731 					     spline.geompoints[pnum2-1]);
732 	}
733       else if (pnums == 3)
734 	{
735 	  scan >> pnum1 >> ',' >> pnum2 >> ','
736 	       >> pnum3;// >> ';';
737 	  spline.splines[i] = new SplineSeg3<D>(spline.geompoints[pnum1-1],
738 						spline.geompoints[pnum2-1],
739 						spline.geompoints[pnum3-1]);
740 	}
741       else if (pnums == 4)
742 	{
743 	  scan >> pnum1 >> ',' >> pnum2 >> ','
744 	       >> pnum3;// >> ';';
745 	  spline.splines[i] = new CircleSeg<D>(spline.geompoints[pnum1-1],
746 					       spline.geompoints[pnum2-1],
747 					       spline.geompoints[pnum3-1]);
748 	}
749     }
750   }
751 
752 
753 
754 
ParseFlags(CSGScanner & scan,Flags & flags)755   void ParseFlags (CSGScanner & scan, Flags & flags)
756   {
757     while (scan.GetToken() == '-')
758       {
759 	scan.ReadNext();
760 	string name = scan.GetStringValue();
761 	scan.ReadNext();
762 	if (scan.GetToken() == '=')
763 	  {
764 	    scan.ReadNext();
765 	    if (scan.GetToken() == TOK_STRING)
766 	      {
767 		flags.SetFlag (name.c_str(), scan.GetStringValue().c_str());
768 		scan.ReadNext();
769 	      }
770 	    else if (scan.GetToken() == '[')
771 	      {
772 		scan.ReadNext();
773 
774 		if(scan.GetToken() == '-' || scan.GetToken() == TOK_NUM)
775 		  {
776 		    Array<double> vals;
777 		    vals.Append (ParseNumber(scan));
778 		    while (scan.GetToken() == ',')
779 		      {
780 			scan.ReadNext();
781 			vals.Append (ParseNumber(scan));
782 		      }
783 		    ParseChar (scan, ']');
784 		    flags.SetFlag (name.c_str(), vals);
785 		  }
786 		else
787 		  { // string list
788 		    Array<char*> vals;
789 		    string val = scan.GetStringValue();
790 		    vals.Append(new char[val.size()+1]);
791 		    strcpy(vals.Last(),val.c_str());
792 		    scan.ReadNext();
793 
794 		    while (scan.GetToken() == ',')
795 		      {
796 			scan.ReadNext();
797 			val = scan.GetStringValue();
798 			vals.Append(new char[val.size()+1]);
799 			strcpy(vals.Last(),val.c_str());
800 			scan.ReadNext();
801 		      }
802 		    ParseChar (scan, ']');
803 		    flags.SetFlag (name.c_str(), vals);
804 		    for(int i=0; i<vals.Size(); i++)
805 		      delete [] vals[i];
806 		  }
807 	      }
808 	    else if (scan.GetToken() == TOK_NUM)
809 	      {
810 		flags.SetFlag (name.c_str(), scan.GetNumValue());
811 		scan.ReadNext();
812 	      }
813 	  }
814 	else
815 	  {
816 	    flags.SetFlag (name.c_str());
817 	  }
818       }
819   }
820 
821 
822   /*
823     Main parsing function for CSG geometry
824   */
ParseCSG(istream & istr)825   CSGeometry * ParseCSG (istream & istr)
826   {
827     CSGScanner scan(istr);
828 
829     geom = new CSGeometry;
830 
831     scan.ReadNext();
832     if (scan.GetToken() != TOK_RECO)  // keyword 'algebraic3d'
833       return 0;
834 
835     scan.ReadNext();
836 
837     try
838       {
839 	while (1)
840 	  {
841 	    if (scan.GetToken() == TOK_END) break;
842 
843 	    if (scan.GetToken() == TOK_SOLID)
844 	      {
845 		scan.ReadNext();
846 		if (scan.GetToken() != TOK_STRING)
847 		  scan.Error ("name identifier expected");
848 		string solidname = scan.GetStringValue();
849 
850 		scan.ReadNext();
851 
852 		ParseChar (scan, '=');
853 		Solid * solid = ParseSolid (scan);
854 
855 		Flags flags;
856 		ParseFlags (scan, flags);
857 
858 		geom->SetSolid (solidname.c_str(), new Solid (Solid::ROOT, solid));
859 		geom->SetFlags (solidname.c_str(), flags);
860 
861 		ParseChar (scan, ';');
862 
863 		PrintMessage (4, "define solid ", solidname);
864 	      }
865 
866 	    else if (scan.GetToken() == TOK_TLO)
867 
868 	      { // a TopLevelObject definition
869 
870 		scan.ReadNext();
871 
872 		string name = scan.GetStringValue();
873 		scan.ReadNext();
874 
875 		if (scan.GetToken() != TOK_STRING)
876 
877 		  { // a solid TLO
878 
879 		    Flags flags;
880 		    ParseFlags (scan, flags);
881 
882 		    ParseChar (scan, ';');
883 		    if (!geom->GetSolid (name))
884 		      scan.Error ("Top-Level-Object "+name+" not defined");
885 
886 		    int tlonr =
887 		      geom->SetTopLevelObject ((Solid*)geom->GetSolid(name));
888 		    TopLevelObject * tlo = geom->GetTopLevelObject (tlonr);
889 
890 		    if (flags.NumListFlagDefined ("col"))
891 		      {
892 			const Array<double> & col =
893 			  flags.GetNumListFlag ("col");
894 			tlo->SetRGB (col[0], col[1], col[2]);
895 		      }
896 
897 		    if (flags.GetDefineFlag ("transparent"))
898 		      tlo->SetTransparent (1);
899 
900 		    tlo->SetMaterial (flags.GetStringFlag ("material", ""));
901 		    tlo->SetLayer (int(flags.GetNumFlag ("layer", 1)));
902 		    if (flags.NumFlagDefined ("maxh"))
903 		      tlo->SetMaxH (flags.GetNumFlag("maxh", 1e10));
904 		  }
905 
906 		else
907 
908 		  { // a surface TLO
909 
910 		    string surfname = scan.GetStringValue();
911 		    scan.ReadNext();
912 
913 		    Flags flags;
914 		    ParseFlags (scan, flags);
915 
916 		    ParseChar (scan, ';');
917 
918 		    Array<int> si;
919 		    geom->GetSolid(surfname)->GetSurfaceIndices(si);
920 		    int tlonr =
921 		      geom->SetTopLevelObject ((Solid*)geom->GetSolid(name),
922 					       (Surface*)geom->GetSurface(si.Get(1)));
923 		    TopLevelObject * tlo = geom->GetTopLevelObject (tlonr);
924 		    if (flags.NumListFlagDefined ("col"))
925 		      {
926 			const Array<double> & col = flags.GetNumListFlag ("col");
927 			tlo->SetRGB (col.Get(1), col.Get(2), col.Get(3));
928 		      }
929 		    if (flags.GetDefineFlag ("transparent"))
930 		      tlo->SetTransparent (1);
931 
932 		    if (flags.NumFlagDefined ("maxh"))
933 		      tlo->SetMaxH (flags.GetNumFlag("maxh", 1e10));
934 		    tlo->SetLayer (int(flags.GetNumFlag ("layer", 1)));
935 		    tlo->SetBCProp (int(flags.GetNumFlag ("bc", -1)));
936 		    if ( flags.StringFlagDefined("bcname") )
937 		      tlo->SetBCName ( flags.GetStringFlag ("bcname", "default") );
938 		  }
939 	      }
940 
941 	    else if (scan.GetToken() == TOK_IDENTIFY)
942 
943 	      {
944 
945 		scan.ReadNext();
946 		switch (scan.GetToken())
947 		  {
948 		  case TOK_CLOSESURFACES:
949 		    {
950 		      scan.ReadNext();
951 
952 		      string name1 = scan.GetStringValue();
953 		      scan.ReadNext();
954 
955 		      string name2 = scan.GetStringValue();
956 		      scan.ReadNext();
957 
958 		      Flags flags;
959 		      ParseFlags (scan, flags);
960 
961 		      ParseChar (scan, ';');
962 
963 
964 		      Array<int> si1, si2;
965 		      geom->GetSolid(name1)->GetSurfaceIndices(si1);
966 		      geom->GetSolid(name2)->GetSurfaceIndices(si2);
967 
968 		      const TopLevelObject * domain = 0;
969 		      if (flags.StringFlagDefined ("tlo"))
970 			{
971 			  domain =
972 			    geom->GetTopLevelObject (geom->GetSolid(flags.GetStringFlag ("tlo","")));
973 			  if (!domain)
974 			    scan.Error ("identification needs undefined tlo");
975 			}
976 
977 		      geom->AddIdentification
978 			(new CloseSurfaceIdentification
979 			 (geom->GetNIdentifications()+1, *geom,
980 			  geom->GetSurface (si1[0]), geom->GetSurface (si2[0]),
981 			  domain,
982 			  flags));
983 
984 		      break;
985 		    }
986 
987 		  case TOK_PERIODIC:
988 		    {
989 		      scan.ReadNext();
990 
991 		      string name1 = scan.GetStringValue();
992 		      scan.ReadNext();
993 
994 		      string name2 = scan.GetStringValue();
995 		      scan.ReadNext();
996 
997 		      ParseChar (scan, ';');
998 
999 
1000 		      Array<int> si1, si2;
1001 		      geom->GetSolid(name1)->GetSurfaceIndices(si1);
1002 		      geom->GetSolid(name2)->GetSurfaceIndices(si2);
1003 
1004 		      geom->AddIdentification
1005 			(new PeriodicIdentification
1006 			 (geom->GetNIdentifications()+1,
1007 			  *geom,
1008 			  geom->GetSurface (si1.Get(1)),
1009 			  geom->GetSurface (si2.Get(1))));
1010 		      break;
1011 		    }
1012 
1013 		  default:
1014 		    scan.Error ("keyword 'closesurfaces' or 'periodic' expected");
1015 		  }
1016 
1017 	      }
1018 
1019 	    else if (scan.GetToken() == TOK_SINGULAR)
1020 
1021 	      {
1022 
1023 		scan.ReadNext();
1024 		switch (scan.GetToken())
1025 		  {
1026 		  case TOK_FACE:
1027 		    {
1028 		      scan.ReadNext();
1029 
1030 		      string name1 = scan.GetStringValue();  // tlo
1031 		      scan.ReadNext();
1032 
1033 		      string name2 = scan.GetStringValue();
1034 		      scan.ReadNext();
1035 
1036 		      Flags flags;
1037 		      ParseFlags (scan, flags);
1038 		      int factor = int(flags.GetNumFlag("factor",1));
1039 		      // cout << "Singular Face with factor " << factor << endl;
1040 		      PrintMessageCR (3, "Singular Face  with factor ", factor);
1041 
1042 		      ParseChar (scan, ';');
1043 
1044 		      const Solid * sol = geom->GetSolid(name2);
1045 
1046 		      if(!sol)
1047 			scan.Error ("unknown solid in singular face definition");
1048 		      else
1049 			for (int i = 0; i < geom->GetNTopLevelObjects(); i++)
1050 			  if (name1 == geom->GetTopLevelObject (i)->GetSolid()->Name())
1051 			    geom->singfaces.Append (new SingularFace (i+1, sol,factor));
1052 
1053 		      break;
1054 		    }
1055 
1056 		  case TOK_EDGE:
1057 		    {
1058 		      scan.ReadNext();
1059 
1060 		      string name1 = scan.GetStringValue();
1061 		      scan.ReadNext();
1062 
1063 		      string name2 = scan.GetStringValue();
1064 		      scan.ReadNext();
1065 
1066 		      Flags flags;
1067 		      ParseFlags (scan, flags);
1068 		      int factor = int(flags.GetNumFlag("factor",1));
1069 		      double maxhinit = flags.GetNumFlag("maxh",-1);
1070 		      ParseChar (scan, ';');
1071 
1072 		      const Solid * s1 = geom->GetSolid(name1);
1073 		      const Solid * s2 = geom->GetSolid(name2);
1074 		      PrintMessageCR (3, "Singular Edge  with factor ", factor);
1075 
1076 		      int domnr = -1;
1077 		      if (flags.StringFlagDefined ("tlo"))
1078 			{
1079 			  const Solid * sol =
1080 			    geom->GetSolid(flags.GetStringFlag ("tlo",""));
1081 
1082 			  for (int i = 0; i < geom->GetNTopLevelObjects(); i++)
1083 			    if (geom->GetTopLevelObject(i)->GetSolid() == sol)
1084 			      domnr = i;
1085 
1086 			  // cout << "domnr = " << domnr;
1087 			}
1088 
1089 		      if(!s1 || !s2)
1090 			scan.Error ("unknown solid ins singular edge definition");
1091 		      else
1092 			geom->singedges.Append (new SingularEdge (1, domnr,
1093 								  *geom, s1, s2, factor,
1094 								  maxhinit));
1095 		      break;
1096 		    }
1097 
1098 		  case TOK_POINT:
1099 		    {
1100 		      scan.ReadNext();
1101 
1102 		      string name1 = scan.GetStringValue();
1103 		      scan.ReadNext();
1104 		      string name2 = scan.GetStringValue();
1105 		      scan.ReadNext();
1106 		      string name3 = scan.GetStringValue();
1107 		      scan.ReadNext();
1108 
1109 		      Flags flags;
1110 		      ParseFlags (scan, flags);
1111 		      int factor = int(flags.GetNumFlag("factor",1));
1112 		      ParseChar (scan, ';');
1113 
1114 		      const Solid * s1 = geom->GetSolid(name1);
1115 		      const Solid * s2 = geom->GetSolid(name2);
1116 		      const Solid * s3 = geom->GetSolid(name3);
1117 		      // cout << "Singular Point with factor " << factor << endl;
1118 		      PrintMessageCR (3, "Singular Point  with factor ", factor);
1119 		      geom->singpoints.Append (new SingularPoint (1, s1, s2, s3, factor));
1120 		      break;
1121 		    }
1122 		  default:
1123 		    scan.Error ("keyword 'face' or 'edge' or 'point' expected");
1124 		  }
1125 	      }
1126 
1127 
1128 	    else if (scan.GetToken() == TOK_POINT)
1129 	      {
1130 		Point<3> p;
1131 
1132 		scan.ReadNext();
1133 		ParseChar (scan, '(');
1134 		p = Point<3> (ParseVector (scan));
1135 		ParseChar (scan, ')');
1136 
1137 
1138 		Flags flags;
1139 		ParseFlags (scan, flags);
1140 		int factor = int(flags.GetNumFlag("factor",0));
1141 
1142 		ParseChar (scan, ';');
1143 
1144 		geom->AddUserPoint (p, factor);
1145 	      }
1146 
1147 	    else if (scan.GetToken() == TOK_BOUNDINGBOX)
1148 	      {
1149 		Point<3> p1, p2;
1150 
1151 		scan.ReadNext();
1152 		ParseChar (scan, '(');
1153 		p1 = Point<3> (ParseVector (scan));
1154 		ParseChar (scan, ';');
1155 		p2 = Point<3> (ParseVector (scan));
1156 		ParseChar (scan, ')');
1157 		ParseChar (scan, ';');
1158 
1159 		geom->SetBoundingBox (Box<3> (p1, p2));
1160 	      }
1161 
1162 	    else if (scan.GetToken() == TOK_CURVE2D)
1163 	      {
1164 		scan.ReadNext();
1165 
1166 
1167 		if (scan.GetToken() != TOK_STRING)
1168 		  scan.Error ("name identifier expected");
1169 		string curvename = scan.GetStringValue();
1170 
1171 		scan.ReadNext();
1172 
1173 		ParseChar (scan, '=');
1174 		ParseChar (scan, '(');
1175 
1176 		SplineGeometry<2> * newspline = new SplineGeometry<2>;
1177 		// newspline->CSGLoad(scan);
1178 		LoadSpline (*newspline, scan);
1179 
1180 		ParseChar (scan, ')');
1181 		ParseChar (scan, ';');
1182 
1183 		geom->SetSplineCurve(curvename.c_str(),newspline);
1184 
1185 		PrintMessage (4, "define 2d curve ", curvename);
1186 	      }
1187 
1188 	    else if (scan.GetToken() == TOK_CURVE3D)
1189 	      {
1190 		scan.ReadNext();
1191 
1192 
1193 		if (scan.GetToken() != TOK_STRING)
1194 		  scan.Error ("name identifier expected");
1195 		string curvename = scan.GetStringValue();
1196 
1197 		scan.ReadNext();
1198 
1199 		ParseChar (scan, '=');
1200 		ParseChar (scan, '(');
1201 
1202 		SplineGeometry<3> * newspline = new SplineGeometry<3>;
1203 		// newspline->CSGLoad(scan);
1204 		LoadSpline (*newspline, scan);
1205 
1206 		ParseChar (scan, ')');
1207 		ParseChar (scan, ';');
1208 
1209 		geom->SetSplineCurve(curvename.c_str(),newspline);
1210 
1211 		PrintMessage (4, "define 3d curve ", curvename);
1212 	      }
1213 
1214 	    else if (scan.GetToken() == TOK_BOUNDARYCONDITION)
1215 	      {
1216 		scan.ReadNext();
1217 
1218 		string name1 = scan.GetStringValue();
1219 		scan.ReadNext();
1220 
1221 		string name2 = scan.GetStringValue();
1222 		scan.ReadNext();
1223 
1224 		int num = int (ParseNumber (scan));
1225 		ParseChar (scan, ';');
1226 
1227 
1228 		CSGeometry::BCModification bcm;
1229 		bcm.bcname = NULL;
1230 		Array<int> si;
1231 
1232 		geom->GetSolid(name1)->GetSurfaceIndices(si);
1233 		if(si.Size() == 0)
1234 		  {
1235 		    string errstring = "solid \""; errstring += name1; errstring += "\" has no surfaces";
1236 		    scan.Error (errstring);
1237 		  }
1238 
1239 		bcm.tlonr = -1;
1240 		int i;
1241 		for (i = 0; i < geom->GetNTopLevelObjects(); i++)
1242 		  if (string (geom->GetTopLevelObject(i)->GetSolid()->Name())
1243 		      == name2)
1244 		    {
1245 		      bcm.tlonr = i;
1246 		      break;
1247 		    }
1248 		if(bcm.tlonr == -1)
1249 		  {
1250 		    string errstring = "tlo \""; errstring += name2; errstring += "\" not found";
1251 		    scan.Error(errstring);
1252 		  }
1253 
1254 
1255 		bcm.bcnr = num;
1256 		for (i = 0; i < si.Size(); i++)
1257 		  {
1258 		    bcm.si = si[i];
1259 		    geom->bcmodifications.Append (bcm);
1260 		  }
1261 	      }
1262 
1263 	    else if (scan.GetToken() == TOK_BOUNDARYCONDITIONNAME)
1264 	      {
1265 		scan.ReadNext();
1266 
1267 		string name1 = scan.GetStringValue();
1268 		scan.ReadNext();
1269 
1270 		string name2 = scan.GetStringValue();
1271 		scan.ReadNext();
1272 
1273 		string bcname = scan.GetStringValue();
1274 		scan.ReadNext();
1275 		ParseChar(scan, ';');
1276 
1277 
1278 		CSGeometry::BCModification bcm;
1279 		bcm.bcname = NULL;
1280 
1281 
1282 		Array<int> si;
1283 
1284 		geom->GetSolid(name1)->GetSurfaceIndices(si);
1285 		if(si.Size() == 0)
1286 		  {
1287 		    string errstring = "solid \""; errstring += name1; errstring += "\" has no surfaces";
1288 		    scan.Error (errstring);
1289 		  }
1290 
1291 		bcm.tlonr = -1;
1292 		int i;
1293 		for (i = 0; i < geom->GetNTopLevelObjects(); i++)
1294 		  if (string (geom->GetTopLevelObject(i)->GetSolid()->Name())
1295 		      == name2)
1296 		    {
1297 		      bcm.tlonr = i;
1298 		      break;
1299 		    }
1300 		if(bcm.tlonr == -1)
1301 		  {
1302 		    string errstring = "tlo \""; errstring += name2; errstring += "\" not found";
1303 		    scan.Error(errstring);
1304 		  }
1305 
1306 
1307 		bcm.bcnr = -1;
1308 		for (i = 0; i < si.Size(); i++)
1309 		  {
1310 		    bcm.si = si[i];
1311 		    geom->bcmodifications.Append (bcm);
1312 		    geom->bcmodifications.Last().bcname = new string(bcname);
1313 		  }
1314 	      }
1315 
1316 	    else if (scan.GetToken() == TOK_DEFINE)
1317 	      {
1318 		scan.ReadNext();
1319 		string name;
1320 		double val;
1321 
1322 		switch (scan.GetToken())
1323 		  {
1324 		  case TOK_CONSTANT:
1325 		    scan.ReadNext();
1326 
1327 		    name = scan.GetStringValue();
1328 		    scan.ReadNext();
1329 
1330 		    ParseChar(scan, '=');
1331 		    val = ParseNumber(scan);
1332 
1333 		    if(name == "identprec")
1334 		      geom->SetIdEps(val);
1335 
1336 
1337 
1338 		    break;
1339 		  default:
1340 		    scan.Error ("keyword 'constant' expected");
1341 		  }
1342 	      }
1343 
1344 
1345 	    else
1346 	      {
1347 		cout << "read unidentified token " << scan.GetToken()
1348 		     << " (as char: \"" << char(scan.GetToken()) << "\")"
1349 		     << " string = " << scan.GetStringValue() << endl;
1350 		scan.ReadNext();
1351 	      }
1352 	  }
1353       }
1354     catch (string errstr)
1355       {
1356 	cout << "caught error " << errstr << endl;
1357 	throw NgException (errstr);
1358       }
1359 
1360 
1361 
1362     (*testout) << geom->GetNTopLevelObjects() << " TLOs:" << endl;
1363     for (int i = 0; i < geom->GetNTopLevelObjects(); i++)
1364       {
1365 	const TopLevelObject * tlo = geom->GetTopLevelObject(i);
1366 	if (tlo->GetSolid())
1367 	  (*testout) << i << ": " << *tlo->GetSolid() << endl;
1368       }
1369 
1370     (*testout) << geom->GetNSurf() << " Surfaces" << endl;
1371     for (int i = 0; i < geom->GetNSurf(); i++)
1372       (*testout) << i << ": " << *geom->GetSurface(i) << endl;
1373 
1374     return geom;
1375     /*
1376       do
1377       {
1378       scan.ReadNext();
1379       if (scan.GetToken() == TOK_STRING)
1380       cout << "found string " << scan.GetStringValue() << endl;
1381       else
1382       cout << "token = " << int(scan.GetToken()) << endl;
1383       }
1384       while (scan.GetToken() != TOK_END);
1385     */
1386   }
1387 
1388 
1389 };
1390 
1391