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 <x)
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> ®ions,
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