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 <cmath>
7 #include "GmshConfig.h"
8 #include "OctreePost.h"
9 #include "CutParametric.h"
10 #include "Context.h"
11 #include "mathEvaluator.h"
12
13 #if defined(HAVE_OPENGL)
14 #include "drawContext.h"
15 #endif
16
17 StringXNumber CutParametricOptions_Number[] = {
18 {GMSH_FULLRC, "MinU", GMSH_CutParametricPlugin::callbackMinU, 0.},
19 {GMSH_FULLRC, "MaxU", GMSH_CutParametricPlugin::callbackMaxU, 2 * 3.1416},
20 {GMSH_FULLRC, "NumPointsU", GMSH_CutParametricPlugin::callbackNU, 180.},
21 {GMSH_FULLRC, "MinV", GMSH_CutParametricPlugin::callbackMinV, 0.},
22 {GMSH_FULLRC, "MaxV", GMSH_CutParametricPlugin::callbackMaxV, 2 * 3.1416},
23 {GMSH_FULLRC, "NumPointsV", GMSH_CutParametricPlugin::callbackNV, 180.},
24 {GMSH_FULLRC, "ConnectPoints", GMSH_CutParametricPlugin::callbackConnect, 0.},
25 {GMSH_FULLRC, "View", nullptr, -1.}};
26
27 StringXString CutParametricOptions_String[] = {
28 {GMSH_FULLRC, "X", GMSH_CutParametricPlugin::callbackX,
29 "2 * Cos(u) * Sin(v)"},
30 {GMSH_FULLRC, "Y", GMSH_CutParametricPlugin::callbackY,
31 "4 * Sin(u) * Sin(v)"},
32 {GMSH_FULLRC, "Z", GMSH_CutParametricPlugin::callbackZ,
33 "0.1 + 0.5 * Cos(v)"}};
34
35 extern "C" {
GMSH_RegisterCutParametricPlugin()36 GMSH_Plugin *GMSH_RegisterCutParametricPlugin()
37 {
38 return new GMSH_CutParametricPlugin();
39 }
40 }
41
getU(int i)42 static double getU(int i)
43 {
44 double minU = CutParametricOptions_Number[0].def;
45 double maxU = CutParametricOptions_Number[1].def;
46 int nbU = (int)CutParametricOptions_Number[2].def;
47
48 if(nbU == 1)
49 return minU;
50 else
51 return minU + (double)(i) / (double)(nbU - 1) * (maxU - minU);
52 }
53
getV(int i)54 static double getV(int i)
55 {
56 double minV = CutParametricOptions_Number[3].def;
57 double maxV = CutParametricOptions_Number[4].def;
58 int nbV = (int)CutParametricOptions_Number[5].def;
59
60 if(nbV == 1)
61 return minV;
62 else
63 return minV + (double)(i) / (double)(nbV - 1) * (maxV - minV);
64 }
65
66 int GMSH_CutParametricPlugin::recompute = 1;
67 std::vector<double> GMSH_CutParametricPlugin::x;
68 std::vector<double> GMSH_CutParametricPlugin::y;
69 std::vector<double> GMSH_CutParametricPlugin::z;
70
fillXYZ()71 int GMSH_CutParametricPlugin::fillXYZ()
72 {
73 std::vector<std::string> expressions(3), variables(2);
74 for(int i = 0; i < 3; i++)
75 expressions[i] = CutParametricOptions_String[i].def;
76 variables[0] = "u";
77 variables[1] = "v";
78 mathEvaluator f(expressions, variables);
79 if(expressions.empty()) return 0;
80
81 int nbU = (int)CutParametricOptions_Number[2].def;
82 int nbV = (int)CutParametricOptions_Number[5].def;
83 x.resize(nbU * nbV);
84 y.resize(nbU * nbV);
85 z.resize(nbU * nbV);
86 std::vector<double> val(2), res(3);
87 for(int i = 0; i < nbU; ++i) {
88 val[0] = getU(i);
89 for(int j = 0; j < nbV; ++j) {
90 val[1] = getV(j);
91 if(f.eval(val, res)) {
92 x[i * nbV + j] = res[0];
93 y[i * nbV + j] = res[1];
94 z[i * nbV + j] = res[2];
95 }
96 }
97 }
98 return 1;
99 }
100
draw(void * context)101 void GMSH_CutParametricPlugin::draw(void *context)
102 {
103 #if defined(HAVE_OPENGL)
104 if(recompute) {
105 fillXYZ();
106 recompute = 0;
107 }
108 glColor4ubv((GLubyte *)&CTX::instance()->color.fg);
109 int nbU = CutParametricOptions_Number[2].def;
110 int nbV = CutParametricOptions_Number[5].def;
111 if(CutParametricOptions_Number[6].def && x.size() > 1) {
112 if(nbU == 1 || nbV == 1) {
113 glBegin(GL_LINES);
114 for(std::size_t i = 1; i < x.size(); ++i) {
115 glVertex3d(x[i - 1], y[i - 1], z[i - 1]);
116 glVertex3d(x[i], y[i], z[i]);
117 }
118 glEnd();
119 }
120 else {
121 glBegin(GL_TRIANGLES);
122 for(int i = 0; i < nbU - 1; ++i) {
123 for(int j = 0; j < nbV - 1; ++j) {
124 int v = i * nbV + j;
125 glVertex3d(x[v], y[v], z[v]);
126 glVertex3d(x[v + 1], y[v + 1], z[v + 1]);
127 glVertex3d(x[v + 1 + nbV], y[v + 1 + nbV], z[v + 1 + nbV]);
128
129 glVertex3d(x[v], y[v], z[v]);
130 glVertex3d(x[v + nbV], y[v + nbV], z[v + nbV]);
131 glVertex3d(x[v + 1 + nbV], y[v + 1 + nbV], z[v + 1 + nbV]);
132 }
133 }
134 glEnd();
135 }
136 }
137 else {
138 drawContext *ctx = (drawContext *)context;
139 for(std::size_t i = 0; i < x.size(); ++i)
140 ctx->drawSphere(CTX::instance()->pointSize, x[i], y[i], z[i], 1);
141 }
142 #endif
143 }
144
callback(int num,int action,double value,double * opt,double step,double min,double max)145 double GMSH_CutParametricPlugin::callback(int num, int action, double value,
146 double *opt, double step, double min,
147 double max)
148 {
149 switch(action) { // configure the input field
150 case 1: return step;
151 case 2: return min;
152 case 3: return max;
153 default: break;
154 }
155 *opt = value;
156 recompute = 1;
157 GMSH_Plugin::setDrawFunction(draw);
158 return 0.;
159 }
160
callbackStr(int num,int action,const std::string & value,std::string & opt)161 std::string GMSH_CutParametricPlugin::callbackStr(int num, int action,
162 const std::string &value,
163 std::string &opt)
164 {
165 opt = value;
166 recompute = 1;
167 GMSH_Plugin::setDrawFunction(draw);
168 return opt;
169 }
170
callbackMinU(int num,int action,double value)171 double GMSH_CutParametricPlugin::callbackMinU(int num, int action, double value)
172 {
173 return callback(num, action, value, &CutParametricOptions_Number[0].def, 0.01,
174 0., 10.);
175 }
176
callbackMaxU(int num,int action,double value)177 double GMSH_CutParametricPlugin::callbackMaxU(int num, int action, double value)
178 {
179 return callback(num, action, value, &CutParametricOptions_Number[1].def, 0.01,
180 0., 10.);
181 }
182
callbackNU(int num,int action,double value)183 double GMSH_CutParametricPlugin::callbackNU(int num, int action, double value)
184 {
185 return callback(num, action, value, &CutParametricOptions_Number[2].def, 1, 1,
186 1000);
187 }
188
callbackMinV(int num,int action,double value)189 double GMSH_CutParametricPlugin::callbackMinV(int num, int action, double value)
190 {
191 return callback(num, action, value, &CutParametricOptions_Number[3].def, 0.01,
192 0., 10.);
193 }
194
callbackMaxV(int num,int action,double value)195 double GMSH_CutParametricPlugin::callbackMaxV(int num, int action, double value)
196 {
197 return callback(num, action, value, &CutParametricOptions_Number[4].def, 0.01,
198 0., 10.);
199 }
200
callbackNV(int num,int action,double value)201 double GMSH_CutParametricPlugin::callbackNV(int num, int action, double value)
202 {
203 return callback(num, action, value, &CutParametricOptions_Number[5].def, 1, 1,
204 1000);
205 }
206
callbackConnect(int num,int action,double value)207 double GMSH_CutParametricPlugin::callbackConnect(int num, int action,
208 double value)
209 {
210 return callback(num, action, value, &CutParametricOptions_Number[6].def, 1, 0,
211 1);
212 }
213
callbackX(int num,int action,const std::string & value)214 std::string GMSH_CutParametricPlugin::callbackX(int num, int action,
215 const std::string &value)
216 {
217 return callbackStr(num, action, value, CutParametricOptions_String[0].def);
218 }
219
callbackY(int num,int action,const std::string & value)220 std::string GMSH_CutParametricPlugin::callbackY(int num, int action,
221 const std::string &value)
222 {
223 return callbackStr(num, action, value, CutParametricOptions_String[1].def);
224 }
225
callbackZ(int num,int action,const std::string & value)226 std::string GMSH_CutParametricPlugin::callbackZ(int num, int action,
227 const std::string &value)
228 {
229 return callbackStr(num, action, value, CutParametricOptions_String[2].def);
230 }
231
getHelp() const232 std::string GMSH_CutParametricPlugin::getHelp() const
233 {
234 return "Plugin(CutParametric) cuts the view `View' with "
235 "the parametric function (`X'(u,v), `Y'(u,v), `Z'(u,v)), "
236 "using `NumPointsU' values of the parameter u in "
237 "[`MinU', `MaxU'] and `NumPointsV' values of the parameter v in "
238 "[`MinV', `MaxV'].\n\n"
239 "If `ConnectPoints' is set, the plugin creates surface or line "
240 "elements; otherwise, the plugin generates points.\n\n"
241 "If `View' < 0, the plugin is run on the current view.\n\n"
242 "Plugin(CutParametric) creates one new list-based view.";
243 }
244
getNbOptions() const245 int GMSH_CutParametricPlugin::getNbOptions() const
246 {
247 return sizeof(CutParametricOptions_Number) / sizeof(StringXNumber);
248 }
249
getOption(int iopt)250 StringXNumber *GMSH_CutParametricPlugin::getOption(int iopt)
251 {
252 return &CutParametricOptions_Number[iopt];
253 }
254
getNbOptionsStr() const255 int GMSH_CutParametricPlugin::getNbOptionsStr() const
256 {
257 return sizeof(CutParametricOptions_String) / sizeof(StringXString);
258 }
259
getOptionStr(int iopt)260 StringXString *GMSH_CutParametricPlugin::getOptionStr(int iopt)
261 {
262 return &CutParametricOptions_String[iopt];
263 }
264
addInView(int connect,int i,int nbcomp,int nbtime,double x0,double y0,double z0,double * res0,double x,double y,double z,double * res,std::vector<double> & P,int * nP,std::vector<double> & L,int * nL)265 static void addInView(int connect, int i, int nbcomp, int nbtime, double x0,
266 double y0, double z0, double *res0, double x, double y,
267 double z, double *res, std::vector<double> &P, int *nP,
268 std::vector<double> &L, int *nL)
269 {
270 if(connect) {
271 if(i) {
272 L.push_back(x0);
273 L.push_back(x);
274 L.push_back(y0);
275 L.push_back(y);
276 L.push_back(z0);
277 L.push_back(z);
278 for(int k = 0; k < nbtime; ++k) {
279 for(int l = 0; l < nbcomp; ++l) L.push_back(res0[nbcomp * k + l]);
280 for(int l = 0; l < nbcomp; ++l) L.push_back(res[nbcomp * k + l]);
281 }
282 (*nL)++;
283 }
284 }
285 else {
286 P.push_back(x);
287 P.push_back(y);
288 P.push_back(z);
289 for(int k = 0; k < nbtime; ++k)
290 for(int l = 0; l < nbcomp; ++l) P.push_back(res[nbcomp * k + l]);
291 (*nP)++;
292 }
293 }
294
addInView(int nbcomp,int nbtime,double x0,double y0,double z0,double * res0,double x1,double y1,double z1,double * res1,double x2,double y2,double z2,double * res2,double x3,double y3,double z3,double * res3,std::vector<double> & Q,int * nQ)295 static void addInView(int nbcomp, int nbtime, double x0, double y0, double z0,
296 double *res0, double x1, double y1, double z1,
297 double *res1, double x2, double y2, double z2,
298 double *res2, double x3, double y3, double z3,
299 double *res3, std::vector<double> &Q, int *nQ)
300 {
301 Q.push_back(x0);
302 Q.push_back(x1);
303 Q.push_back(x2);
304 Q.push_back(x3);
305 Q.push_back(y0);
306 Q.push_back(y1);
307 Q.push_back(y2);
308 Q.push_back(y3);
309 Q.push_back(z0);
310 Q.push_back(z1);
311 Q.push_back(z2);
312 Q.push_back(z3);
313 for(int k = 0; k < nbtime; ++k) {
314 for(int l = 0; l < nbcomp; ++l) Q.push_back(res0[nbcomp * k + l]);
315 for(int l = 0; l < nbcomp; ++l) Q.push_back(res1[nbcomp * k + l]);
316 for(int l = 0; l < nbcomp; ++l) Q.push_back(res2[nbcomp * k + l]);
317 for(int l = 0; l < nbcomp; ++l) Q.push_back(res3[nbcomp * k + l]);
318 }
319 (*nQ)++;
320 }
321
execute(PView * v)322 PView *GMSH_CutParametricPlugin::execute(PView *v)
323 {
324 int iView = (int)CutParametricOptions_Number[7].def;
325
326 PView *v1 = getView(iView, v);
327 if(!v1) return v;
328
329 if(!fillXYZ()) return v;
330
331 PViewData *data1 = getPossiblyAdaptiveData(v1);
332
333 int numSteps = data1->getNumTimeSteps();
334 int nbU = (int)CutParametricOptions_Number[2].def;
335 int nbV = (int)CutParametricOptions_Number[5].def;
336 int connect = (int)CutParametricOptions_Number[6].def;
337 if(nbU < 2 && nbV < 2) connect = 0;
338
339 OctreePost o(v1);
340
341 PView *v2 = new PView();
342 PViewDataList *data2 = getDataList(v2);
343
344 double *res0 = new double[9 * numSteps];
345 double *res1 = new double[9 * numSteps];
346 double *res2 = new double[9 * numSteps];
347 double *res3 = new double[9 * numSteps];
348 double x0 = 0., y0 = 0., z0 = 0., x1 = 0., y1 = 0., z1 = 0.;
349 double x2 = 0., y2 = 0., z2 = 0., x3 = 0., y3 = 0., z3 = 0.;
350
351 for(int k = 0; k < 9 * numSteps; ++k) res0[k] = res1[k] = 0.;
352
353 if(nbU == 1 || nbV == 1 || !connect) {
354 for(std::size_t i = 0; i < x.size(); ++i) {
355 if(i && connect) {
356 x0 = x1;
357 y0 = y1;
358 z0 = z1;
359 for(int k = 0; k < 9 * numSteps; ++k) res0[k] = res1[k];
360 }
361
362 x1 = x[i];
363 y1 = y[i];
364 z1 = z[i];
365
366 if(data1->getNumScalars()) {
367 o.searchScalar(x1, y1, z1, res1);
368 addInView(connect, i, 1, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
369 data2->SP, &data2->NbSP, data2->SL, &data2->NbSL);
370 }
371 if(data1->getNumVectors()) {
372 o.searchVector(x1, y1, z1, res1);
373 addInView(connect, i, 3, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
374 data2->VP, &data2->NbVP, data2->VL, &data2->NbVL);
375 }
376 if(data1->getNumTensors()) {
377 o.searchTensor(x1, y1, z1, res1);
378 addInView(connect, i, 9, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
379 data2->TP, &data2->NbTP, data2->TL, &data2->NbTL);
380 }
381 }
382 }
383 else {
384 for(int i = 0; i < nbU - 1; ++i) {
385 for(int j = 0; j < nbV - 1; ++j) {
386 int v = i * nbV + j;
387 x0 = x[v];
388 y0 = y[v];
389 z0 = z[v];
390 x1 = x[v + 1];
391 y1 = y[v + 1];
392 z1 = z[v + 1];
393 x2 = x[v + nbV + 1];
394 y2 = y[v + nbV + 1];
395 z2 = z[v + nbV + 1];
396 x3 = x[v + nbV];
397 y3 = y[v + nbV];
398 z3 = z[v + nbV];
399
400 if(data1->getNumScalars()) {
401 o.searchScalar(x0, y0, z0, res0);
402 o.searchScalar(x1, y1, z1, res1);
403 o.searchScalar(x2, y2, z2, res2);
404 o.searchScalar(x3, y3, z3, res3);
405 addInView(1, numSteps, x0, y0, z0, res0, x1, y1, z1, res1, x2, y2, z2,
406 res2, x3, y3, z3, res3, data2->SQ, &data2->NbSQ);
407 }
408 if(data1->getNumVectors()) {
409 o.searchVector(x0, y0, z0, res0);
410 o.searchVector(x1, y1, z1, res1);
411 o.searchVector(x2, y2, z2, res2);
412 o.searchVector(x3, y3, z3, res3);
413 addInView(3, numSteps, x0, y0, z0, res0, x1, y1, z1, res1, x2, y2, z2,
414 res2, x3, y3, z3, res3, data2->VQ, &data2->NbVQ);
415 }
416 if(data1->getNumTensors()) {
417 o.searchTensor(x0, y0, z0, res0);
418 o.searchTensor(x1, y1, z1, res1);
419 o.searchTensor(x2, y2, z2, res2);
420 o.searchTensor(x3, y3, z3, res3);
421 addInView(9, numSteps, x0, y0, z0, res0, x1, y1, z1, res1, x2, y2, z2,
422 res2, x3, y3, z3, res3, data2->TQ, &data2->NbTQ);
423 }
424 }
425 }
426 }
427
428 delete[] res0;
429 delete[] res1;
430 delete[] res2;
431 delete[] res3;
432
433 data2->setName(data1->getName() + "_CutParametric");
434 data2->setFileName(data1->getName() + "_CutParametric.pos");
435 data2->finalize();
436
437 return v2;
438 }
439