1 // Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <string.h>
7 #include <sstream>
8 #include "Field.h"
9 #include "GmshConfig.h"
10 #include "GmshMessage.h"
11 #include "GModel.h"
12 #include "GModelIO_GEO.h"
13 #include "GModelIO_OCC.h"
14 #include "Numeric.h"
15 #include "StringUtils.h"
16 #include "Geo.h"
17 #include "scriptStringInterface.h"
18 #include "OpenFile.h"
19 #include "Context.h"
20 #include "OS.h"
21 #include "Parser.h"
22 
23 #if defined(HAVE_ONELAB)
24 #include "onelab.h"
25 #endif
26 
scriptAddCommand(const std::string & text,const std::string & fileNameOrEmpty,const std::string & lang)27 static void scriptAddCommand(const std::string &text,
28                              const std::string &fileNameOrEmpty,
29                              const std::string &lang)
30 {
31   if(lang != "geo") {
32     if(!text.empty()) printf("%s: %s\n", lang.c_str(), text.c_str());
33     return;
34   }
35 
36   const std::string &fileName = fileNameOrEmpty;
37   if(fileName.empty()) {
38     std::string base = (getenv("PWD") ? "" : CTX::instance()->homeDir);
39     GModel::current()->setFileName(base + CTX::instance()->defaultFileName);
40     GModel::current()->setName("");
41   }
42 
43   Msg::Debug("Adding `%s' to file `%s'", text.c_str(), fileName.c_str());
44   std::vector<std::string> split = SplitFileName(fileName);
45   std::string noExt = split[0] + split[1], ext = split[2];
46   // make sure we don't add stuff in a non-geo file
47   static bool proceed = false;
48   if(!CTX::instance()->expertMode && !proceed) {
49     if(ext.size() && ext != ".geo" && ext != ".GEO") {
50       std::ostringstream sstream;
51       sstream << "A scripting command is going to be appended to a non-`.geo' "
52                  "file. Are\nyou sure you want to proceed?\n\n"
53                  "You probably want to create a new `.geo' file containing the "
54                  "command\n`Merge \""
55               << split[1] + split[2]
56               << "\";' and use that file instead.\n\n"
57                  "(To disable this warning in the future, select `Enable "
58                  "expert mode'\nin the option dialog.)";
59       int ret = Msg::GetAnswer(sstream.str().c_str(), 2, "Cancel",
60                                "Proceed as is", "Create new `.geo' file");
61       if(ret == 2) {
62         std::string newFileName = split[0] + split[1] + ".geo";
63         if(CTX::instance()->confirmOverwrite) {
64           if(!StatFile(newFileName)) {
65             std::ostringstream sstream;
66             sstream << "File '" << newFileName
67                     << "' already exists.\n\nDo you want to replace it?";
68             if(!Msg::GetAnswer(sstream.str().c_str(), 0, "Cancel", "Replace"))
69               return;
70           }
71         }
72         FILE *fp = Fopen(newFileName.c_str(), "w");
73         if(!fp) {
74           Msg::Error("Unable to open file '%s'", newFileName.c_str());
75           return;
76         }
77         fprintf(fp, "Merge \"%s\";\n//+\n%s\n", (split[1] + split[2]).c_str(),
78                 text.c_str());
79         fclose(fp);
80         OpenProject(newFileName);
81         return;
82       }
83       else if(ret == 1)
84         proceed = true;
85       else if(ret == 0)
86         return;
87     }
88   }
89 
90 #if defined(HAVE_PARSER)
91   std::string tmpFileName =
92     CTX::instance()->homeDir + CTX::instance()->tmpFileName;
93   FILE *gmsh_yyin_old = gmsh_yyin;
94   FILE *tmp_file;
95   if(!(tmp_file = Fopen(tmpFileName.c_str(), "w"))) {
96     Msg::Error("Unable to open temporary file '%s'", tmpFileName.c_str());
97     return;
98   }
99   fprintf(tmp_file, "%s\n", text.c_str());
100   fclose(tmp_file);
101   gmsh_yyin = Fopen(tmpFileName.c_str(), "r");
102   while(!feof(gmsh_yyin)) { gmsh_yyparse(); }
103   fclose(gmsh_yyin);
104   gmsh_yyin = gmsh_yyin_old;
105 
106   GModel::current()->getGEOInternals()->synchronize(GModel::current());
107   if(GModel::current()->getOCCInternals())
108     GModel::current()->getOCCInternals()->synchronize(GModel::current());
109   GModel::current()->setName(split[1]);
110   CTX::instance()->mesh.changed = ENT_ALL;
111 
112   FILE *fp = Fopen(fileName.c_str(), "a");
113   if(!fp) {
114     Msg::Error("Unable to open file '%s'", fileName.c_str());
115     return;
116   }
117   fprintf(fp, "//+\n%s\n", text.c_str());
118   fclose(fp);
119 #else
120   Msg::Error("GEO file creation not available without Gmsh parser");
121 #endif
122 
123   // mark Gmsh data as changed in onelab
124   if(text.find("Physical") != std::string::npos) {
125     // re-import the physical groups in onelab, and only ask to re-save the mesh
126     Msg::ImportPhysicalGroupsInOnelab();
127     Msg::SetOnelabChanged(1);
128   }
129   else if(text.find("MeshSize") != std::string::npos) {
130     // only ask to remesh and re-save
131     Msg::SetOnelabChanged(2);
132   }
133   else {
134     // ask to reload the geometry, remesh and re-save
135     Msg::SetOnelabChanged(3);
136   }
137 }
138 
scriptRemoveLastCommand(const std::string & fileName)139 void scriptRemoveLastCommand(const std::string &fileName)
140 {
141   if(StatFile(fileName)) return;
142   // FIXME: make this work with compressed files
143   std::ifstream t;
144   t.open(fileName.c_str(), std::ifstream::in);
145   std::stringstream buffer;
146   buffer << t.rdbuf();
147   std::string s(buffer.str());
148   int found = (int)s.rfind("//+");
149   if(found != (int)std::string::npos) { s.erase(found); }
150   else {
151     Msg::Warning("Could not find last command in script `%s'",
152                  fileName.c_str());
153     return;
154   }
155   FILE *fp = Fopen(fileName.c_str(), "w");
156   if(fp) {
157     fprintf(fp, "%s", s.c_str());
158     fclose(fp);
159   }
160   else {
161     Msg::Error("Could not open file `%s'", fileName.c_str());
162   }
163   OpenProject(fileName);
164 }
165 
list2String(List_T * list,const std::string & lang)166 static std::string list2String(List_T *list, const std::string &lang)
167 {
168   std::ostringstream sstream;
169   if(lang == "py" || lang == "jl")
170     sstream << "[";
171   else if(lang == "geo" || lang == "cpp")
172     sstream << "{";
173   for(int i = 0; i < List_Nbr(list); i++) {
174     int num;
175     List_Read(list, i, &num);
176     if(i) sstream << ", ";
177     sstream << num;
178   }
179   if(lang == "py" || lang == "jl")
180     sstream << "]";
181   else if(lang == "geo" || lang == "cpp")
182     sstream << "}";
183   return sstream.str();
184 }
185 
vector2String(const std::vector<int> & v,const std::string & lang)186 static std::string vector2String(const std::vector<int> &v,
187                                  const std::string &lang)
188 {
189   std::ostringstream sstream;
190   if(lang == "py" || lang == "jl")
191     sstream << "[";
192   else if(lang == "geo" || lang == "cpp")
193     sstream << "{";
194   for(std::size_t i = 0; i < v.size(); i++) {
195     if(i) sstream << ", ";
196     sstream << v[i];
197   }
198   if(lang == "py" || lang == "jl")
199     sstream << "]";
200   else if(lang == "geo" || lang == "cpp")
201     sstream << "}";
202   return sstream.str();
203 }
204 
dimTags2String(const std::vector<std::pair<int,int>> & l,const std::string & lang)205 static std::string dimTags2String(const std::vector<std::pair<int, int> > &l,
206                                   const std::string &lang)
207 {
208   std::ostringstream sstream;
209   if(lang == "py" || lang == "jl")
210     sstream << "[";
211   else if(lang == "cpp")
212     sstream << "{";
213 
214   for(std::size_t i = 0; i < l.size(); i++) {
215     if(lang == "geo") {
216       switch(l[i].first) {
217       case 0: sstream << "Point{" << l[i].second << "}; "; break;
218       case 1: sstream << "Curve{" << l[i].second << "}; "; break;
219       case 2: sstream << "Surface{" << l[i].second << "}; "; break;
220       case 3: sstream << "Volume{" << l[i].second << "}; "; break;
221       }
222     }
223     else if(lang == "py" || lang == "jl") {
224       if(i) sstream << ", ";
225       sstream << "(" << l[i].first << ", " << l[i].second << ")";
226     }
227     else if(lang == "cpp") {
228       if(i) sstream << ", ";
229       sstream << "{" << l[i].first << ", " << l[i].second << "}";
230     }
231     else {
232       Msg::Error("Unhandled language ('%s') in script generator", lang.c_str());
233     }
234   }
235 
236   if(lang == "py" || lang == "jl")
237     sstream << "]";
238   else if(lang == "cpp")
239     sstream << "}";
240   return sstream.str();
241 }
242 
243 static std::string currentFactory = "geo";
244 
checkOCC(std::ostringstream & sstream,const std::string & lang)245 static void checkOCC(std::ostringstream &sstream, const std::string &lang)
246 {
247   currentFactory = "occ";
248 #if defined(HAVE_PARSER)
249   if(lang == "geo" && gmsh_yyfactory != "OpenCASCADE") {
250     sstream << "SetFactory(\"OpenCASCADE\");\n";
251     return;
252   }
253 #endif
254 }
255 
scriptSetFactory(const std::string & factory,const std::string & fileName)256 void scriptSetFactory(const std::string &factory, const std::string &fileName)
257 {
258   if(factory == "OpenCASCADE")
259     currentFactory = "occ";
260   else
261     currentFactory = "geo";
262   for(auto &lang : CTX::instance()->scriptLang) {
263     std::ostringstream sstream;
264     if(lang == "geo") {
265       sstream << "SetFactory(\"" << factory << "\");";
266       scriptAddCommand(sstream.str(), fileName, lang);
267     }
268   }
269 }
270 
api(const std::string & name,const std::string & args,const std::string & lang)271 static std::string api(const std::string &name, const std::string &args,
272                        const std::string &lang)
273 {
274   if(lang == "py" || lang == "jl")
275     return ReplaceSubString("/", ".", name) + "(" + args + ")";
276   else if(lang == "cpp")
277     return ReplaceSubString("/", "::", name) + "(" + args + ");";
278 
279   Msg::Error("Unhandled language ('%s') in script generator", lang.c_str());
280   return "";
281 }
282 
scriptSetMeshSize(const std::string & fileName,const std::vector<int> & l,const std::string & lc)283 void scriptSetMeshSize(const std::string &fileName, const std::vector<int> &l,
284                        const std::string &lc)
285 {
286   for(auto &lang : CTX::instance()->scriptLang) {
287     std::ostringstream sstream;
288     if(lang == "geo") {
289       sstream << "MeshSize " << vector2String(l, lang) << " = " << lc << ";";
290     }
291     else {
292       std::vector<std::pair<int, int> > dimTags;
293       for(auto t : l) dimTags.push_back(std::make_pair(0, t));
294       sstream << api("gmsh/model/mesh/setSize",
295                      dimTags2String(dimTags, lang) + ", " + lc, lang);
296     }
297     scriptAddCommand(sstream.str(), fileName, lang);
298   }
299 }
300 
scriptRecombineSurface(const std::string & fileName,const std::vector<int> & l)301 void scriptRecombineSurface(const std::string &fileName,
302                             const std::vector<int> &l)
303 {
304   for(auto &lang : CTX::instance()->scriptLang) {
305     std::ostringstream sstream;
306     if(lang == "geo")
307       sstream << "Recombine Surface " << vector2String(l, lang) << ";";
308     else if(currentFactory == "geo")
309       sstream << api("gmsh/model/geo/mesh/setRecombine", vector2String(l, lang),
310                      lang);
311     else
312       sstream << api("gmsh/model/occ/synchronize", "", lang) << "\n"
313               << api("gmsh/model/mesh/setRecombine", vector2String(l, lang),
314                      lang);
315     scriptAddCommand(sstream.str(), fileName, lang);
316   }
317 }
318 
scriptSetTransfiniteLine(std::vector<int> & l,const std::string & fileName,const std::string & type,const std::string & typearg,const std::string & pts)319 void scriptSetTransfiniteLine(std::vector<int> &l, const std::string &fileName,
320                               const std::string &type,
321                               const std::string &typearg,
322                               const std::string &pts)
323 {
324   for(auto &lang : CTX::instance()->scriptLang) {
325     std::ostringstream sstream;
326     if(lang == "geo") {
327       sstream << "Transfinite Curve {";
328       for(std::size_t i = 0; i < l.size(); i++) {
329         if(i) sstream << ", ";
330         sstream << l[i];
331       }
332       sstream << "} = " << pts;
333       if(typearg.size()) sstream << " Using " << type << " " << typearg;
334       sstream << ";";
335     }
336     else {
337       // TODO
338     }
339     scriptAddCommand(sstream.str(), fileName, lang);
340   }
341 }
342 
scriptSetTransfiniteSurface(std::vector<int> & l,const std::string & fileName,const std::string & dir)343 void scriptSetTransfiniteSurface(std::vector<int> &l,
344                                  const std::string &fileName,
345                                  const std::string &dir)
346 {
347   for(auto &lang : CTX::instance()->scriptLang) {
348     std::ostringstream sstream;
349     if(lang == "geo") {
350       sstream << "Transfinite Surface {" << l[0] << "}";
351       if(l.size() > 1) {
352         sstream << " = {";
353         for(std::size_t i = 1; i < l.size(); i++) {
354           if(i > 1) sstream << ", ";
355           sstream << l[i];
356         }
357         sstream << "}";
358       }
359       if(dir != "Left") sstream << " " << dir;
360       sstream << ";";
361     }
362     else {
363       // TODO
364     }
365     scriptAddCommand(sstream.str(), fileName, lang);
366   }
367 }
368 
scriptSetTransfiniteVolume(std::vector<int> & l,const std::string & fileName)369 void scriptSetTransfiniteVolume(std::vector<int> &l,
370                                 const std::string &fileName)
371 {
372   for(auto &lang : CTX::instance()->scriptLang) {
373     std::ostringstream sstream;
374     if(lang == "geo") {
375       sstream << "Transfinite Volume{" << l[0] << "} = {";
376       for(std::size_t i = 1; i < l.size(); i++) {
377         if(i > 1) sstream << ", ";
378         sstream << l[i];
379       }
380       sstream << "};";
381     }
382     else {
383       // TODO
384     }
385     scriptAddCommand(sstream.str(), fileName, lang);
386   }
387 }
388 
scriptEmbed(const std::string & fileName,const std::string & what,std::vector<int> & l,int dim,int tag)389 void scriptEmbed(const std::string &fileName, const std::string &what,
390                  std::vector<int> &l, int dim, int tag)
391 {
392   for(auto &lang : CTX::instance()->scriptLang) {
393     std::ostringstream sstream;
394     if(lang == "geo") {
395       sstream << what << "" << vector2String(l, lang) << " In ";
396       if(dim == 2)
397         sstream << "Surface{";
398       else
399         sstream << "Volume{";
400       sstream << tag << "};";
401     }
402     else {
403       // TODO
404     }
405     scriptAddCommand(sstream.str(), fileName, lang);
406   }
407 }
408 
scriptAddParameter(const std::string & par,const std::string & value,const std::string & label,const std::string & path,const std::string & fileName)409 void scriptAddParameter(const std::string &par, const std::string &value,
410                         const std::string &label, const std::string &path,
411                         const std::string &fileName)
412 {
413   for(auto &lang : CTX::instance()->scriptLang) {
414     std::ostringstream sstream;
415     if(lang == "geo") {
416       sstream << par << " = DefineNumber[ " << value;
417       sstream << ", Name \"";
418       if(path.size() && label.size())
419         sstream << path << "/" << label;
420       else if(path.size())
421         sstream << path << "/" << par;
422       else if(label.size())
423         sstream << label;
424       else
425         sstream << par;
426       sstream << "\" ];";
427     }
428     else {
429       // TODO
430     }
431     scriptAddCommand(sstream.str(), fileName, lang);
432   }
433 }
434 
scriptAddPoint(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & lc)435 void scriptAddPoint(const std::string &fileName, const std::string &x,
436                     const std::string &y, const std::string &z,
437                     const std::string &lc)
438 {
439   for(auto &lang : CTX::instance()->scriptLang) {
440     std::ostringstream sstream;
441     if(lang == "geo") {
442       sstream << "Point(" << GModel::current()->getMaxElementaryNumber(0) + 1
443               << ") = {" << x << ", " << y << ", " << z;
444       if(lc.size()) sstream << ", " << lc;
445       sstream << "};";
446     }
447     else {
448       std::string addPointStr = "gmsh/model/" + currentFactory + "/addPoint";
449       std::ostringstream args;
450       args << x << ", " << y << ", " << z;
451       if(lc.size()) args << ", " << lc;
452       sstream << api(addPointStr, args.str(), lang);
453     }
454     scriptAddCommand(sstream.str(), fileName, lang);
455   }
456 }
457 
scriptAddFieldOption(int field_id,const std::string & option_name,const std::string & option_value,int option_type,const std::string & fileName)458 void scriptAddFieldOption(int field_id, const std::string &option_name,
459                           const std::string &option_value, int option_type,
460                           const std::string &fileName)
461 {
462   for(auto &lang : CTX::instance()->scriptLang) {
463     std::ostringstream sstream;
464     if(lang == "geo") {
465       sstream << "Field[" << field_id << "]." << option_name << " = "
466               << option_value << ";";
467     }
468     else {
469       std::ostringstream args;
470       switch(option_type) {
471       case FIELD_OPTION_DOUBLE:
472       case FIELD_OPTION_INT:
473       case FIELD_OPTION_BOOL:
474         args << field_id << ", \"" << option_name << "\", " << option_value;
475         sstream << api("gmsh/model/mesh/field/setNumber", args.str(), lang);
476         break;
477       case FIELD_OPTION_STRING:
478       case FIELD_OPTION_PATH:
479         args << field_id << ", \"" << option_name << "\", " << option_value;
480         sstream << api("gmsh/model/mesh/field/setString", args.str(), lang);
481         break;
482       case FIELD_OPTION_LIST:
483       case FIELD_OPTION_LIST_DOUBLE:
484         std::string list_val = option_value;
485         if(lang == "py" || lang == "jl") {
486           ReplaceSubStringInPlace("{", "[", list_val);
487           ReplaceSubStringInPlace("}", "]", list_val);
488         }
489         args << field_id << ", \"" << option_name << "\", " << list_val;
490         sstream << api("gmsh/model/mesh/field/setNumbers", args.str(), lang);
491         break;
492       }
493     }
494     scriptAddCommand(sstream.str(), fileName, lang);
495   }
496 }
497 
scriptAddField(int field_id,const std::string & type_name,const std::string & fileName)498 void scriptAddField(int field_id, const std::string &type_name,
499                     const std::string &fileName)
500 {
501   for(auto &lang : CTX::instance()->scriptLang) {
502     std::ostringstream sstream;
503     if(lang == "geo") {
504       sstream << "Field[" << field_id << "] = " << type_name << ";";
505     }
506     else {
507       std::ostringstream args;
508       args << "\"" << type_name << "\"" << ", " << field_id;
509       sstream << api("gmsh/model/mesh/field/add", args.str(), lang);
510     }
511     scriptAddCommand(sstream.str(), fileName, lang);
512   }
513 }
514 
scriptDeleteField(int field_id,const std::string & fileName)515 void scriptDeleteField(int field_id, const std::string &fileName)
516 {
517   for(auto &lang : CTX::instance()->scriptLang) {
518     std::ostringstream sstream;
519     if(lang == "geo") { sstream << "Delete Field [" << field_id << "];"; }
520     else {
521       sstream << api("gmsh/model/mesh/field/remove",
522                      std::to_string(field_id), lang);
523     }
524     scriptAddCommand(sstream.str(), fileName, lang);
525   }
526 }
527 
scriptSetBackgroundField(int field_id,const std::string & fileName)528 void scriptSetBackgroundField(int field_id, const std::string &fileName)
529 {
530   for(auto &lang : CTX::instance()->scriptLang) {
531     std::ostringstream sstream;
532     if(lang == "geo") { sstream << "Background Field = " << field_id << ";"; }
533     else {
534       sstream << api("gmsh/model/mesh/field/setAsBackgroundMesh",
535                      std::to_string(field_id), lang);
536     }
537     scriptAddCommand(sstream.str(), fileName, lang);
538   }
539 }
540 
scriptAddCurve(const std::string & type,std::vector<int> & p,const std::string & fileName)541 void scriptAddCurve(const std::string &type, std::vector<int> &p,
542                     const std::string &fileName)
543 {
544   for(auto &lang : CTX::instance()->scriptLang) {
545     std::ostringstream sstream;
546     if(lang == "geo") {
547       sstream << type << "(" << GModel::current()->getMaxElementaryNumber(1) + 1
548               << ") = {";
549       for(std::size_t i = 0; i < p.size(); i++) {
550         if(i) sstream << ", ";
551         sstream << p[i];
552       }
553       sstream << "};";
554     }
555     else {
556       // TODO
557     }
558     scriptAddCommand(sstream.str(), fileName, lang);
559   }
560 }
561 
scriptAddCircleArc(int p1,int p2,int p3,const std::string & fileName)562 void scriptAddCircleArc(int p1, int p2, int p3, const std::string &fileName)
563 {
564   for(auto &lang : CTX::instance()->scriptLang) {
565     std::ostringstream sstream;
566     if(lang == "geo") {
567       sstream << "Circle(" << GModel::current()->getMaxElementaryNumber(1) + 1
568               << ") = {" << p1 << ", " << p2 << ", " << p3 << "};";
569     }
570     else {
571       // TODO
572     }
573     scriptAddCommand(sstream.str(), fileName, lang);
574   }
575 }
576 
scriptAddEllipseArc(int p1,int p2,int p3,int p4,const std::string & fileName)577 void scriptAddEllipseArc(int p1, int p2, int p3, int p4,
578                          const std::string &fileName)
579 {
580   for(auto &lang : CTX::instance()->scriptLang) {
581     std::ostringstream sstream;
582     if(lang == "geo") {
583       sstream << "Ellipse(" << GModel::current()->getMaxElementaryNumber(1) + 1
584               << ") = {" << p1 << ", " << p2 << ", " << p3 << ", " << p4
585               << "};";
586     }
587     else {
588       // TODO
589     }
590     scriptAddCommand(sstream.str(), fileName, lang);
591   }
592 }
593 
scriptAddCurveLoop(List_T * list,const std::string & fileName,int * numloop)594 void scriptAddCurveLoop(List_T *list, const std::string &fileName, int *numloop)
595 {
596   if(RecognizeLineLoop(list, numloop)) return;
597   *numloop = GModel::current()->getGEOInternals()->getMaxTag(-1) + 1;
598   if(GModel::current()->getOCCInternals())
599     *numloop = std::max(
600       *numloop, GModel::current()->getOCCInternals()->getMaxTag(-1) + 1);
601 
602   for(auto &lang : CTX::instance()->scriptLang) {
603     std::ostringstream sstream;
604     if(lang == "geo") {
605       sstream << "Curve Loop(" << *numloop << ") = " << list2String(list, lang)
606               << ";";
607     }
608     else {
609       // TODO
610     }
611     scriptAddCommand(sstream.str(), fileName, lang);
612   }
613 }
614 
scriptAddSurface(const std::string & type,List_T * list,const std::string & fileName)615 void scriptAddSurface(const std::string &type, List_T *list,
616                       const std::string &fileName)
617 {
618   for(auto &lang : CTX::instance()->scriptLang) {
619     std::ostringstream sstream;
620     if(lang == "geo") {
621       sstream << type << "(" << GModel::current()->getMaxElementaryNumber(2) + 1
622               << ") = " << list2String(list, lang) << ";";
623     }
624     else {
625       // TODO
626     }
627     scriptAddCommand(sstream.str(), fileName, lang);
628   }
629 }
630 
scriptAddSurfaceLoop(List_T * list,const std::string & fileName,int * numloop)631 void scriptAddSurfaceLoop(List_T *list, const std::string &fileName,
632                           int *numloop)
633 {
634   if(RecognizeSurfaceLoop(list, numloop)) return;
635   *numloop = GModel::current()->getGEOInternals()->getMaxTag(-2) + 1;
636   if(GModel::current()->getOCCInternals())
637     *numloop = std::max(
638       *numloop, GModel::current()->getOCCInternals()->getMaxTag(-2) + 1);
639 
640   for(auto &lang : CTX::instance()->scriptLang) {
641     std::ostringstream sstream;
642     if(lang == "geo") {
643       sstream << "Surface Loop(" << *numloop
644               << ") = " << list2String(list, lang) << ";";
645     }
646     else {
647       // TODO
648     }
649     scriptAddCommand(sstream.str(), fileName, lang);
650   }
651 }
652 
scriptAddVolume(List_T * list,const std::string & fileName)653 void scriptAddVolume(List_T *list, const std::string &fileName)
654 {
655   for(auto &lang : CTX::instance()->scriptLang) {
656     std::ostringstream sstream;
657     if(lang == "geo") {
658       sstream << "Volume(" << GModel::current()->getMaxElementaryNumber(3) + 1
659               << ") = " << list2String(list, lang) << ";";
660     }
661     else {
662       // TODO
663     }
664     scriptAddCommand(sstream.str(), fileName, lang);
665   }
666 }
667 
scriptAddRemovePhysicalGroup(const std::string & fileName,const std::string & what,const std::vector<int> & l,const std::string & name,int forceTag,bool append,const std::string & mode)668 void scriptAddRemovePhysicalGroup(const std::string &fileName,
669                                   const std::string &what,
670                                   const std::vector<int> &l,
671                                   const std::string &name, int forceTag,
672                                   bool append, const std::string &mode)
673 {
674   for(auto &lang : CTX::instance()->scriptLang) {
675     std::ostringstream sstream;
676     if(lang == "geo") {
677       sstream << "Physical " << what << "(";
678       if(name.size()) {
679         sstream << "\"" << name << "\"";
680         if(forceTag) sstream << ", " << forceTag;
681       }
682       else {
683         sstream
684           << (forceTag ?
685                 forceTag :
686                 GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1);
687       }
688       sstream << ") ";
689       if(mode == "Remove")
690         sstream << "-";
691       else if(append)
692         sstream << "+";
693       sstream << "= " << vector2String(l, lang) << ";";
694     }
695     else {
696       // TODO
697     }
698     scriptAddCommand(sstream.str(), fileName, lang);
699   }
700 }
701 
scriptSetCompound(const std::string & fileName,const std::string & type,const std::vector<int> & l)702 void scriptSetCompound(const std::string &fileName, const std::string &type,
703                        const std::vector<int> &l)
704 {
705   for(auto &lang : CTX::instance()->scriptLang) {
706     std::ostringstream sstream;
707     if(lang == "geo") {
708       sstream << "Compound " << type << " " << vector2String(l, lang) << ";";
709     }
710     else {
711       // TODO
712     }
713     scriptAddCommand(sstream.str(), fileName, lang);
714   }
715 }
716 
scriptAddCircle(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & r,const std::string & alpha1,const std::string & alpha2)717 void scriptAddCircle(const std::string &fileName, const std::string &x,
718                      const std::string &y, const std::string &z,
719                      const std::string &r, const std::string &alpha1,
720                      const std::string &alpha2)
721 {
722   for(auto &lang : CTX::instance()->scriptLang) {
723     std::ostringstream sstream;
724     checkOCC(sstream, lang);
725     if(lang == "geo") {
726       sstream << "Circle(" << GModel::current()->getMaxElementaryNumber(1) + 1
727               << ") = {" << x << ", " << y << ", " << z << ", " << r;
728       if(alpha1.size()) sstream << ", " << alpha1;
729       if(alpha1.size() && alpha2.size()) sstream << ", " << alpha2;
730       sstream << "};";
731     }
732     else {
733       // TODO
734     }
735     scriptAddCommand(sstream.str(), fileName, lang);
736   }
737 }
738 
scriptAddEllipse(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & rx,const std::string & ry,const std::string & alpha1,const std::string & alpha2)739 void scriptAddEllipse(const std::string &fileName, const std::string &x,
740                       const std::string &y, const std::string &z,
741                       const std::string &rx, const std::string &ry,
742                       const std::string &alpha1, const std::string &alpha2)
743 {
744   for(auto &lang : CTX::instance()->scriptLang) {
745     std::ostringstream sstream;
746     checkOCC(sstream, lang);
747     if(lang == "geo") {
748       sstream << "Ellipse(" << GModel::current()->getMaxElementaryNumber(1) + 1
749               << ") = {" << x << ", " << y << ", " << z << ", " << rx << ", "
750               << ry;
751       if(alpha1.size()) sstream << ", " << alpha1;
752       if(alpha1.size() && alpha2.size()) sstream << ", " << alpha2;
753       sstream << "};";
754     }
755     else {
756       // TODO
757     }
758     scriptAddCommand(sstream.str(), fileName, lang);
759   }
760 }
761 
scriptAddDisk(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & rx,const std::string & ry)762 void scriptAddDisk(const std::string &fileName, const std::string &x,
763                    const std::string &y, const std::string &z,
764                    const std::string &rx, const std::string &ry)
765 {
766   for(auto &lang : CTX::instance()->scriptLang) {
767     std::ostringstream sstream;
768     checkOCC(sstream, lang);
769     if(lang == "geo") {
770       sstream << "Disk(" << GModel::current()->getMaxElementaryNumber(2) + 1
771               << ") = {" << x << ", " << y << ", " << z << ", " << rx << ", "
772               << ry << "};";
773     }
774     else {
775       // TODO
776     }
777     scriptAddCommand(sstream.str(), fileName, lang);
778   }
779 }
780 
scriptAddRectangle(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & dx,const std::string & dy,const std::string & roundedRadius)781 void scriptAddRectangle(const std::string &fileName, const std::string &x,
782                         const std::string &y, const std::string &z,
783                         const std::string &dx, const std::string &dy,
784                         const std::string &roundedRadius)
785 {
786   for(auto &lang : CTX::instance()->scriptLang) {
787     std::ostringstream sstream;
788     checkOCC(sstream, lang);
789     if(lang == "geo") {
790       sstream << "Rectangle("
791               << GModel::current()->getMaxElementaryNumber(2) + 1 << ") = {"
792               << x << ", " << y << ", " << z << ", " << dx << ", " << dy;
793       if(roundedRadius.size()) sstream << ", " << roundedRadius;
794       sstream << "};";
795     }
796     else {
797       // TODO
798     }
799     scriptAddCommand(sstream.str(), fileName, lang);
800   }
801 }
802 
scriptAddSphere(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & r,const std::string & alpha1,const std::string & alpha2,const std::string & alpha3)803 void scriptAddSphere(const std::string &fileName, const std::string &x,
804                      const std::string &y, const std::string &z,
805                      const std::string &r, const std::string &alpha1,
806                      const std::string &alpha2, const std::string &alpha3)
807 {
808   for(auto &lang : CTX::instance()->scriptLang) {
809     std::ostringstream sstream;
810     checkOCC(sstream, lang);
811     if(lang == "geo") {
812       sstream << "Sphere(" << GModel::current()->getMaxElementaryNumber(3) + 1
813               << ") = {" << x << ", " << y << ", " << z << ", " << r;
814       if(alpha1.size()) sstream << ", " << alpha1;
815       if(alpha1.size() && alpha2.size()) sstream << ", " << alpha2;
816       if(alpha1.size() && alpha2.size() && alpha3.size())
817         sstream << ", " << alpha3;
818       sstream << "};";
819     }
820     else {
821       // TODO
822     }
823     scriptAddCommand(sstream.str(), fileName, lang);
824   }
825 }
826 
scriptAddCylinder(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & dx,const std::string & dy,const std::string & dz,const std::string & r,const std::string & alpha)827 void scriptAddCylinder(const std::string &fileName, const std::string &x,
828                        const std::string &y, const std::string &z,
829                        const std::string &dx, const std::string &dy,
830                        const std::string &dz, const std::string &r,
831                        const std::string &alpha)
832 {
833   for(auto &lang : CTX::instance()->scriptLang) {
834     std::ostringstream sstream;
835     checkOCC(sstream, lang);
836     if(lang == "geo") {
837       sstream << "Cylinder(" << GModel::current()->getMaxElementaryNumber(3) + 1
838               << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", "
839               << dy << ", " << dz << ", " << r;
840       if(alpha.size()) sstream << ", " << alpha;
841       sstream << "};";
842     }
843     else {
844       // TODO
845     }
846     scriptAddCommand(sstream.str(), fileName, lang);
847   }
848 }
849 
scriptAddBox(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & dx,const std::string & dy,const std::string & dz)850 void scriptAddBox(const std::string &fileName, const std::string &x,
851                   const std::string &y, const std::string &z,
852                   const std::string &dx, const std::string &dy,
853                   const std::string &dz)
854 {
855   for(auto &lang : CTX::instance()->scriptLang) {
856     std::ostringstream sstream;
857     checkOCC(sstream, lang);
858     if(lang == "geo") {
859       sstream << "Box(" << GModel::current()->getMaxElementaryNumber(3) + 1
860               << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", "
861               << dy << ", " << dz << "};";
862     }
863     else {
864       // TODO
865     }
866     scriptAddCommand(sstream.str(), fileName, lang);
867   }
868 }
869 
scriptAddTorus(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & r1,const std::string & r2,const std::string & alpha)870 void scriptAddTorus(const std::string &fileName, const std::string &x,
871                     const std::string &y, const std::string &z,
872                     const std::string &r1, const std::string &r2,
873                     const std::string &alpha)
874 {
875   for(auto &lang : CTX::instance()->scriptLang) {
876     std::ostringstream sstream;
877     checkOCC(sstream, lang);
878     if(lang == "geo") {
879       sstream << "Torus(" << GModel::current()->getMaxElementaryNumber(3) + 1
880               << ") = {" << x << ", " << y << ", " << z << ", " << r1 << ", "
881               << r2;
882       if(alpha.size()) sstream << ", " << alpha;
883       sstream << "};";
884     }
885     else {
886       // TODO
887     }
888     scriptAddCommand(sstream.str(), fileName, lang);
889   }
890 }
891 
scriptAddCone(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & dx,const std::string & dy,const std::string & dz,const std::string & r1,const std::string & r2,const std::string & alpha)892 void scriptAddCone(const std::string &fileName, const std::string &x,
893                    const std::string &y, const std::string &z,
894                    const std::string &dx, const std::string &dy,
895                    const std::string &dz, const std::string &r1,
896                    const std::string &r2, const std::string &alpha)
897 {
898   for(auto &lang : CTX::instance()->scriptLang) {
899     std::ostringstream sstream;
900     checkOCC(sstream, lang);
901     if(lang == "geo") {
902       sstream << "Cone(" << GModel::current()->getMaxElementaryNumber(3) + 1
903               << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", "
904               << dy << ", " << dz << ", " << r1 << ", " << r2;
905       if(alpha.size()) sstream << ", " << alpha;
906       sstream << "};";
907     }
908     else {
909       // TODO
910     }
911     scriptAddCommand(sstream.str(), fileName, lang);
912   }
913 }
914 
scriptAddWedge(const std::string & fileName,const std::string & x,const std::string & y,const std::string & z,const std::string & dx,const std::string & dy,const std::string & dz,const std::string & ltx)915 void scriptAddWedge(const std::string &fileName, const std::string &x,
916                     const std::string &y, const std::string &z,
917                     const std::string &dx, const std::string &dy,
918                     const std::string &dz, const std::string &ltx)
919 {
920   for(auto &lang : CTX::instance()->scriptLang) {
921     std::ostringstream sstream;
922     checkOCC(sstream, lang);
923     if(lang == "geo") {
924       sstream << "Wedge(" << GModel::current()->getMaxElementaryNumber(3) + 1
925               << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", "
926               << dy << ", " << dz << ", " << ltx << "};";
927     }
928     else {
929       // TODO
930     }
931     scriptAddCommand(sstream.str(), fileName, lang);
932   }
933 }
934 
scriptTranslate(const std::string & fileName,const std::vector<std::pair<int,int>> & l,const std::string & tx,const std::string & ty,const std::string & tz,bool duplicata)935 void scriptTranslate(const std::string &fileName,
936                      const std::vector<std::pair<int, int> > &l,
937                      const std::string &tx, const std::string &ty,
938                      const std::string &tz, bool duplicata)
939 {
940   for(auto &lang : CTX::instance()->scriptLang) {
941     std::ostringstream sstream;
942     if(lang == "geo") {
943       sstream << "Translate {" << tx << ", " << ty << ", " << tz << "} {\n  ";
944       if(duplicata) sstream << "Duplicata { ";
945       sstream << dimTags2String(l, lang);
946       if(duplicata) sstream << "}";
947       sstream << "\n}";
948     }
949     else {
950       // TODO
951     }
952     scriptAddCommand(sstream.str(), fileName, lang);
953   }
954 }
955 
scriptRotate(const std::string & fileName,const std::vector<std::pair<int,int>> & l,const std::string & ax,const std::string & ay,const std::string & az,const std::string & px,const std::string & py,const std::string & pz,const std::string & angle,bool duplicata)956 void scriptRotate(const std::string &fileName,
957                   const std::vector<std::pair<int, int> > &l,
958                   const std::string &ax, const std::string &ay,
959                   const std::string &az, const std::string &px,
960                   const std::string &py, const std::string &pz,
961                   const std::string &angle, bool duplicata)
962 {
963   for(auto &lang : CTX::instance()->scriptLang) {
964     std::ostringstream sstream;
965     if(lang == "geo") {
966       sstream << "Rotate {{" << ax << ", " << ay << ", " << az << "}, {" << px
967               << ", " << py << ", " << pz << "}, " << angle << "} {\n  ";
968       if(duplicata) sstream << "Duplicata { ";
969       sstream << dimTags2String(l, lang);
970       if(duplicata) sstream << "}";
971       sstream << "\n}";
972     }
973     else {
974       // TODO
975     }
976     scriptAddCommand(sstream.str(), fileName, lang);
977   }
978 }
979 
scriptDilate(const std::string & fileName,const std::vector<std::pair<int,int>> & l,const std::string & cx,const std::string & cy,const std::string & cz,const std::string & sx,const std::string & sy,const std::string & sz,bool duplicata)980 void scriptDilate(const std::string &fileName,
981                   const std::vector<std::pair<int, int> > &l,
982                   const std::string &cx, const std::string &cy,
983                   const std::string &cz, const std::string &sx,
984                   const std::string &sy, const std::string &sz, bool duplicata)
985 {
986   for(auto &lang : CTX::instance()->scriptLang) {
987     std::ostringstream sstream;
988     if(lang == "geo") {
989       sstream << "Dilate {{" << cx << ", " << cy << ", " << cz << "}, {" << sx
990               << ", " << sy << ", " << sz << "}} {\n  ";
991       if(duplicata) sstream << "Duplicata { ";
992       sstream << dimTags2String(l, lang);
993       if(duplicata) sstream << "}";
994       sstream << "\n}";
995     }
996     else {
997       // TODO
998     }
999     scriptAddCommand(sstream.str(), fileName, lang);
1000   }
1001 }
1002 
scriptMirror(const std::string & fileName,const std::vector<std::pair<int,int>> & l,const std::string & sa,const std::string & sb,const std::string & sc,const std::string & sd,bool duplicata)1003 void scriptMirror(const std::string &fileName,
1004                   const std::vector<std::pair<int, int> > &l,
1005                   const std::string &sa, const std::string &sb,
1006                   const std::string &sc, const std::string &sd, bool duplicata)
1007 {
1008   for(auto &lang : CTX::instance()->scriptLang) {
1009     std::ostringstream sstream;
1010     if(lang == "geo") {
1011       sstream << "Symmetry {" << sa << ", " << sb << ", " << sc << ", " << sd
1012               << "} {\n  ";
1013       if(duplicata) sstream << "Duplicata { ";
1014       sstream << dimTags2String(l, lang);
1015       if(duplicata) sstream << "}";
1016       sstream << "\n}";
1017     }
1018     else {
1019       // TODO
1020     }
1021     scriptAddCommand(sstream.str(), fileName, lang);
1022   }
1023 }
1024 
scriptExtrude(const std::string & fileName,const std::vector<std::pair<int,int>> & l,const std::string & tx,const std::string & ty,const std::string & tz,bool extrudeMesh,const std::string & layers,bool recombineMesh)1025 void scriptExtrude(const std::string &fileName,
1026                    const std::vector<std::pair<int, int> > &l,
1027                    const std::string &tx, const std::string &ty,
1028                    const std::string &tz, bool extrudeMesh,
1029                    const std::string &layers, bool recombineMesh)
1030 {
1031   for(auto &lang : CTX::instance()->scriptLang) {
1032     std::ostringstream sstream;
1033     if(lang == "geo") {
1034       sstream << "Extrude {" << tx << ", " << ty << ", " << tz << "} {\n  "
1035               << dimTags2String(l, lang);
1036       if(extrudeMesh) {
1037         sstream << "Layers {" << layers << "}; ";
1038         if(recombineMesh) sstream << "Recombine;";
1039       }
1040       sstream << "\n}";
1041     }
1042     else {
1043       // TODO
1044     }
1045     scriptAddCommand(sstream.str(), fileName, lang);
1046   }
1047 }
1048 
scriptProtude(const std::string & fileName,const std::vector<std::pair<int,int>> & l,const std::string & ax,const std::string & ay,const std::string & az,const std::string & px,const std::string & py,const std::string & pz,const std::string & angle,bool extrudeMesh,const std::string & layers,bool recombineMesh)1049 void scriptProtude(const std::string &fileName,
1050                    const std::vector<std::pair<int, int> > &l,
1051                    const std::string &ax, const std::string &ay,
1052                    const std::string &az, const std::string &px,
1053                    const std::string &py, const std::string &pz,
1054                    const std::string &angle, bool extrudeMesh,
1055                    const std::string &layers, bool recombineMesh)
1056 {
1057   for(auto &lang : CTX::instance()->scriptLang) {
1058     std::ostringstream sstream;
1059     if(lang == "geo") {
1060       sstream << "Extrude {{" << ax << ", " << ay << ", " << az << "}, {" << px
1061               << ", " << py << ", " << pz << "}, " << angle << "} {\n  "
1062               << dimTags2String(l, lang);
1063       if(extrudeMesh) {
1064         sstream << "Layers{" << layers << "}; ";
1065         if(recombineMesh) sstream << "Recombine;";
1066       }
1067       sstream << "\n}";
1068     }
1069     else {
1070       // TODO
1071     }
1072     scriptAddCommand(sstream.str(), fileName, lang);
1073   }
1074 }
1075 
scriptAddPipe(const std::string & fileName,const std::vector<std::pair<int,int>> & l,const std::vector<int> & l2)1076 void scriptAddPipe(const std::string &fileName,
1077                    const std::vector<std::pair<int, int> > &l,
1078                    const std::vector<int> &l2)
1079 {
1080   for(auto &lang : CTX::instance()->scriptLang) {
1081     std::ostringstream sstream;
1082     checkOCC(sstream, lang);
1083     if(lang == "geo") {
1084       int wire = GModel::current()->getGEOInternals()->getMaxTag(-1) + 1;
1085       if(GModel::current()->getOCCInternals())
1086         wire = std::max(
1087           wire, GModel::current()->getOCCInternals()->getMaxTag(-1) + 1);
1088       sstream << "Wire(" << wire << ") = " << vector2String(l2, lang) << ";\n";
1089       sstream << "Extrude { " << dimTags2String(l, lang) << "} Using Wire {"
1090               << wire << "}\n";
1091     }
1092     else {
1093       // TODO
1094     }
1095     scriptAddCommand(sstream.str(), fileName, lang);
1096   }
1097 }
1098 
scriptSplitCurve(int edge_id,List_T * vertices,const std::string & fileName)1099 void scriptSplitCurve(int edge_id, List_T *vertices,
1100                       const std::string &fileName)
1101 {
1102   for(auto &lang : CTX::instance()->scriptLang) {
1103     std::ostringstream sstream;
1104     if(lang == "geo") {
1105       sstream << "Split Curve {" << edge_id << "} Point "
1106               << list2String(vertices, lang) << ";";
1107     }
1108     else {
1109       // TODO
1110     }
1111     scriptAddCommand(sstream.str(), fileName, lang);
1112   }
1113 }
1114 
scriptBoolean(const std::string & fileName,const std::string & op,const std::vector<std::pair<int,int>> & object,const std::vector<std::pair<int,int>> & tool,int deleteObject,int deleteTool)1115 void scriptBoolean(const std::string &fileName, const std::string &op,
1116                    const std::vector<std::pair<int, int> > &object,
1117                    const std::vector<std::pair<int, int> > &tool,
1118                    int deleteObject, int deleteTool)
1119 {
1120   for(auto &lang : CTX::instance()->scriptLang) {
1121     std::ostringstream sstream;
1122     checkOCC(sstream, lang);
1123     if(lang == "geo") {
1124       sstream << op << "{ " << dimTags2String(object, lang);
1125       if(deleteObject) sstream << "Delete; ";
1126       sstream << "}{ " << dimTags2String(tool, lang);
1127       if(deleteTool) sstream << "Delete; ";
1128       sstream << "}";
1129     }
1130     else {
1131       // TODO
1132     }
1133     scriptAddCommand(sstream.str(), fileName, lang);
1134   }
1135 }
1136 
scriptFillet(const std::string & fileName,const std::vector<int> & regions,const std::vector<int> & edges,const std::string & radius)1137 void scriptFillet(const std::string &fileName, const std::vector<int> &regions,
1138                   const std::vector<int> &edges, const std::string &radius)
1139 {
1140   for(auto &lang : CTX::instance()->scriptLang) {
1141     std::ostringstream sstream;
1142     checkOCC(sstream, lang);
1143     if(lang == "geo") {
1144       sstream << "Fillet " << vector2String(regions, lang)
1145               << vector2String(edges, lang) << "{" << radius << "}";
1146     }
1147     else {
1148       // TODO
1149     }
1150     scriptAddCommand(sstream.str(), fileName, lang);
1151   }
1152 }
1153 
scriptCoherence(const std::string & fileName)1154 void scriptCoherence(const std::string &fileName)
1155 {
1156   for(auto &lang : CTX::instance()->scriptLang) {
1157     if(lang == "geo") { scriptAddCommand("Coherence;", fileName, lang); }
1158     else {
1159       // TODO
1160     }
1161   }
1162 }
1163 
scriptDeleteEntities(const std::string & fileName,const std::vector<std::pair<int,int>> & l,bool recursive)1164 void scriptDeleteEntities(const std::string &fileName,
1165                           const std::vector<std::pair<int, int> > &l,
1166                           bool recursive)
1167 {
1168   for(auto &lang : CTX::instance()->scriptLang) {
1169     std::ostringstream sstream;
1170     if(lang == "geo") {
1171       if(recursive) sstream << "Recursive ";
1172       sstream << "Delete {\n  " << dimTags2String(l, lang) << "\n}";
1173     }
1174     else {
1175       // TODO
1176     }
1177     scriptAddCommand(sstream.str(), fileName, lang);
1178   }
1179 }
1180 
scriptSetVisibilityAll(int mode,const std::string & fileName)1181 void scriptSetVisibilityAll(int mode, const std::string &fileName)
1182 {
1183   for(auto &lang : CTX::instance()->scriptLang) {
1184     if(lang == "geo") {
1185       if(mode)
1186         scriptAddCommand("Show \"*\";", fileName, lang);
1187       else
1188         scriptAddCommand("Hide \"*\";", fileName, lang);
1189     }
1190     else {
1191       // TODO
1192     }
1193   }
1194 }
1195 
scriptSetVisibility(int mode,const std::vector<std::pair<int,int>> & l,const std::string & fileName)1196 void scriptSetVisibility(int mode, const std::vector<std::pair<int, int> > &l,
1197                          const std::string &fileName)
1198 {
1199   for(auto &lang : CTX::instance()->scriptLang) {
1200     std::ostringstream sstream;
1201     if(lang == "geo") {
1202       if(mode)
1203         sstream << "Show {\n  " << dimTags2String(l, lang) << "\n}";
1204       else
1205         sstream << "Hide {\n  " << dimTags2String(l, lang) << "\n}";
1206     }
1207     else {
1208       // TODO
1209     }
1210     scriptAddCommand(sstream.str(), fileName, lang);
1211   }
1212 }
1213