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 "GmshConfig.h"
7 #include "OctreePost.h"
8 #include "CutGrid.h"
9 #include "Context.h"
10
11 #if defined(HAVE_OPENGL)
12 #include "drawContext.h"
13 #endif
14
15 StringXNumber CutGridOptions_Number[] = {
16 {GMSH_FULLRC, "X0", GMSH_CutGridPlugin::callbackX0, 0.},
17 {GMSH_FULLRC, "Y0", GMSH_CutGridPlugin::callbackY0, 0.},
18 {GMSH_FULLRC, "Z0", GMSH_CutGridPlugin::callbackZ0, 0.},
19 {GMSH_FULLRC, "X1", GMSH_CutGridPlugin::callbackX1, 1.},
20 {GMSH_FULLRC, "Y1", GMSH_CutGridPlugin::callbackY1, 0.},
21 {GMSH_FULLRC, "Z1", GMSH_CutGridPlugin::callbackZ1, 0.},
22 {GMSH_FULLRC, "X2", GMSH_CutGridPlugin::callbackX2, 0.},
23 {GMSH_FULLRC, "Y2", GMSH_CutGridPlugin::callbackY2, 1.},
24 {GMSH_FULLRC, "Z2", GMSH_CutGridPlugin::callbackZ2, 0.},
25 {GMSH_FULLRC, "NumPointsU", GMSH_CutGridPlugin::callbackU, 20},
26 {GMSH_FULLRC, "NumPointsV", GMSH_CutGridPlugin::callbackV, 20},
27 {GMSH_FULLRC, "ConnectPoints", GMSH_CutGridPlugin::callbackConnect, 1},
28 {GMSH_FULLRC, "View", nullptr, -1.}};
29
30 extern "C" {
GMSH_RegisterCutGridPlugin()31 GMSH_Plugin *GMSH_RegisterCutGridPlugin() { return new GMSH_CutGridPlugin(); }
32 }
33
draw(void * context)34 void GMSH_CutGridPlugin::draw(void *context)
35 {
36 #if defined(HAVE_OPENGL)
37 glColor4ubv((GLubyte *)&CTX::instance()->color.fg);
38 double p[3];
39 drawContext *ctx = (drawContext *)context;
40
41 getPoint(0, 0, p);
42 ctx->drawString("(X0, Y0, Z0)", p[0], p[1], p[2]);
43 if(getNbU() > 1) {
44 getPoint(getNbU() - 1, 0, p);
45 ctx->drawString("(X1, Y1, Z1)", p[0], p[1], p[2]);
46 }
47 if(getNbV() > 1) {
48 getPoint(0, getNbV() - 1, p);
49 ctx->drawString("(X2, Y2, Z2)", p[0], p[1], p[2]);
50 }
51
52 if(CutGridOptions_Number[11].def) {
53 glBegin(GL_LINES);
54 for(int i = 0; i < getNbU(); ++i) {
55 getPoint(i, 0, p);
56 glVertex3d(p[0], p[1], p[2]);
57 getPoint(i, getNbV() - 1, p);
58 glVertex3d(p[0], p[1], p[2]);
59 }
60 for(int i = 0; i < getNbV(); ++i) {
61 getPoint(0, i, p);
62 glVertex3d(p[0], p[1], p[2]);
63 getPoint(getNbU() - 1, i, p);
64 glVertex3d(p[0], p[1], p[2]);
65 }
66 glEnd();
67 }
68 else {
69 for(int i = 0; i < getNbU(); ++i) {
70 for(int j = 0; j < getNbV(); ++j) {
71 getPoint(i, j, p);
72 ctx->drawSphere(CTX::instance()->pointSize, p[0], p[1], p[2], 1);
73 }
74 }
75 }
76 #endif
77 }
78
callback(int num,int action,double value,double * opt,double step,double min,double max)79 double GMSH_CutGridPlugin::callback(int num, int action, double value,
80 double *opt, double step, double min,
81 double max)
82 {
83 switch(action) { // configure the input field
84 case 1: return step;
85 case 2: return min;
86 case 3: return max;
87 default: break;
88 }
89 *opt = value;
90 GMSH_Plugin::setDrawFunction(draw);
91 return 0.;
92 }
93
callbackX0(int num,int action,double value)94 double GMSH_CutGridPlugin::callbackX0(int num, int action, double value)
95 {
96 return callback(num, action, value, &CutGridOptions_Number[0].def,
97 CTX::instance()->lc / 100., CTX::instance()->min[0],
98 CTX::instance()->max[0]);
99 }
100
callbackY0(int num,int action,double value)101 double GMSH_CutGridPlugin::callbackY0(int num, int action, double value)
102 {
103 return callback(num, action, value, &CutGridOptions_Number[1].def,
104 CTX::instance()->lc / 100., CTX::instance()->min[1],
105 CTX::instance()->max[1]);
106 }
107
callbackZ0(int num,int action,double value)108 double GMSH_CutGridPlugin::callbackZ0(int num, int action, double value)
109 {
110 return callback(num, action, value, &CutGridOptions_Number[2].def,
111 CTX::instance()->lc / 100., CTX::instance()->min[2],
112 CTX::instance()->max[2]);
113 }
114
callbackX1(int num,int action,double value)115 double GMSH_CutGridPlugin::callbackX1(int num, int action, double value)
116 {
117 return callback(num, action, value, &CutGridOptions_Number[3].def,
118 CTX::instance()->lc / 100., CTX::instance()->min[0],
119 CTX::instance()->max[0]);
120 }
121
callbackY1(int num,int action,double value)122 double GMSH_CutGridPlugin::callbackY1(int num, int action, double value)
123 {
124 return callback(num, action, value, &CutGridOptions_Number[4].def,
125 CTX::instance()->lc / 100., CTX::instance()->min[1],
126 CTX::instance()->max[1]);
127 }
128
callbackZ1(int num,int action,double value)129 double GMSH_CutGridPlugin::callbackZ1(int num, int action, double value)
130 {
131 return callback(num, action, value, &CutGridOptions_Number[5].def,
132 CTX::instance()->lc / 100., CTX::instance()->min[2],
133 CTX::instance()->max[2]);
134 }
135
callbackX2(int num,int action,double value)136 double GMSH_CutGridPlugin::callbackX2(int num, int action, double value)
137 {
138 return callback(num, action, value, &CutGridOptions_Number[6].def,
139 CTX::instance()->lc / 100., CTX::instance()->min[0],
140 CTX::instance()->max[0]);
141 }
142
callbackY2(int num,int action,double value)143 double GMSH_CutGridPlugin::callbackY2(int num, int action, double value)
144 {
145 return callback(num, action, value, &CutGridOptions_Number[7].def,
146 CTX::instance()->lc / 100., CTX::instance()->min[1],
147 CTX::instance()->max[1]);
148 }
149
callbackZ2(int num,int action,double value)150 double GMSH_CutGridPlugin::callbackZ2(int num, int action, double value)
151 {
152 return callback(num, action, value, &CutGridOptions_Number[8].def,
153 CTX::instance()->lc / 100., CTX::instance()->min[2],
154 CTX::instance()->max[2]);
155 }
156
callbackU(int num,int action,double value)157 double GMSH_CutGridPlugin::callbackU(int num, int action, double value)
158 {
159 return callback(num, action, value, &CutGridOptions_Number[9].def, 1, 1, 200);
160 }
161
callbackV(int num,int action,double value)162 double GMSH_CutGridPlugin::callbackV(int num, int action, double value)
163 {
164 return callback(num, action, value, &CutGridOptions_Number[10].def, 1, 1,
165 200);
166 }
167
callbackConnect(int num,int action,double value)168 double GMSH_CutGridPlugin::callbackConnect(int num, int action, double value)
169 {
170 return callback(num, action, value, &CutGridOptions_Number[11].def, 1, 0, 1);
171 }
172
getHelp() const173 std::string GMSH_CutGridPlugin::getHelp() const
174 {
175 return "Plugin(CutGrid) cuts the view `View' with a "
176 "rectangular grid defined by the 3 points "
177 "(`X0',`Y0',`Z0') (origin), (`X1',`Y1',`Z1') (axis of U) "
178 "and (`X2',`Y2',`Z2') (axis of V).\n\n"
179 "The number of points along U and V is set with the "
180 "options `NumPointsU' and `NumPointsV'.\n\n"
181 "If `ConnectPoints' is zero, the plugin creates points; "
182 "otherwise, the plugin generates quadrangles, lines or "
183 "points depending on the values of `NumPointsU' and "
184 "`NumPointsV'.\n\n"
185 "If `View' < 0, the plugin is run on the current view.\n\n"
186 "Plugin(CutGrid) creates one new list-based view.";
187 }
188
getNbOptions() const189 int GMSH_CutGridPlugin::getNbOptions() const
190 {
191 return sizeof(CutGridOptions_Number) / sizeof(StringXNumber);
192 }
193
getOption(int iopt)194 StringXNumber *GMSH_CutGridPlugin::getOption(int iopt)
195 {
196 return &CutGridOptions_Number[iopt];
197 }
198
getNbU()199 int GMSH_CutGridPlugin::getNbU() { return (int)CutGridOptions_Number[9].def; }
200
getNbV()201 int GMSH_CutGridPlugin::getNbV() { return (int)CutGridOptions_Number[10].def; }
202
getPoint(int iU,int iV,double * X)203 void GMSH_CutGridPlugin::getPoint(int iU, int iV, double *X)
204 {
205 double u = getNbU() > 1 ? (double)iU / (double)(getNbU() - 1.) : 0.;
206 double v = getNbV() > 1 ? (double)iV / (double)(getNbV() - 1.) : 0.;
207 X[0] = CutGridOptions_Number[0].def +
208 u * (CutGridOptions_Number[3].def - CutGridOptions_Number[0].def) +
209 v * (CutGridOptions_Number[6].def - CutGridOptions_Number[0].def);
210 X[1] = CutGridOptions_Number[1].def +
211 u * (CutGridOptions_Number[4].def - CutGridOptions_Number[1].def) +
212 v * (CutGridOptions_Number[7].def - CutGridOptions_Number[1].def);
213 X[2] = CutGridOptions_Number[2].def +
214 u * (CutGridOptions_Number[5].def - CutGridOptions_Number[2].def) +
215 v * (CutGridOptions_Number[8].def - CutGridOptions_Number[2].def);
216 }
217
addInView(int numsteps,int connect,int nbcomp,double *** pnts,double *** vals,std::vector<double> & P,int * nP,std::vector<double> & L,int * nL,std::vector<double> & Q,int * nQ)218 void GMSH_CutGridPlugin::addInView(int numsteps, int connect, int nbcomp,
219 double ***pnts, double ***vals,
220 std::vector<double> &P, int *nP,
221 std::vector<double> &L, int *nL,
222 std::vector<double> &Q, int *nQ)
223 {
224 if(!connect || (getNbU() == 1 && getNbV() == 1)) { // generate points
225
226 for(int i = 0; i < getNbU(); ++i) {
227 for(int j = 0; j < getNbV(); ++j) {
228 P.push_back(pnts[i][j][0]);
229 P.push_back(pnts[i][j][1]);
230 P.push_back(pnts[i][j][2]);
231 (*nP)++;
232 for(int k = 0; k < numsteps; ++k) {
233 for(int l = 0; l < nbcomp; ++l)
234 P.push_back(vals[i][j][nbcomp * k + l]);
235 }
236 }
237 }
238 }
239 else { // generate lines or quads
240
241 if(getNbU() == 1) {
242 for(int i = 0; i < getNbV() - 1; ++i) {
243 L.push_back(pnts[0][i][0]);
244 L.push_back(pnts[0][i + 1][0]);
245 L.push_back(pnts[0][i][1]);
246 L.push_back(pnts[0][i + 1][1]);
247 L.push_back(pnts[0][i][2]);
248 L.push_back(pnts[0][i + 1][2]);
249 (*nL)++;
250 for(int k = 0; k < numsteps; ++k) {
251 for(int l = 0; l < nbcomp; ++l)
252 L.push_back(vals[0][i][nbcomp * k + l]);
253 for(int l = 0; l < nbcomp; ++l)
254 L.push_back(vals[0][i + 1][nbcomp * k + l]);
255 }
256 }
257 }
258 else if(getNbV() == 1) {
259 for(int i = 0; i < getNbU() - 1; ++i) {
260 L.push_back(pnts[i][0][0]);
261 L.push_back(pnts[i + 1][0][0]);
262 L.push_back(pnts[i][0][1]);
263 L.push_back(pnts[i + 1][0][1]);
264 L.push_back(pnts[i][0][2]);
265 L.push_back(pnts[i + 1][0][2]);
266 (*nL)++;
267 for(int k = 0; k < numsteps; ++k) {
268 for(int l = 0; l < nbcomp; ++l)
269 L.push_back(vals[i][0][nbcomp * k + l]);
270 for(int l = 0; l < nbcomp; ++l)
271 L.push_back(vals[i + 1][0][nbcomp * k + l]);
272 }
273 }
274 }
275 else {
276 for(int i = 0; i < getNbU() - 1; ++i) {
277 for(int j = 0; j < getNbV() - 1; ++j) {
278 Q.push_back(pnts[i][j][0]);
279 Q.push_back(pnts[i + 1][j][0]);
280 Q.push_back(pnts[i + 1][j + 1][0]);
281 Q.push_back(pnts[i][j + 1][0]);
282 Q.push_back(pnts[i][j][1]);
283 Q.push_back(pnts[i + 1][j][1]);
284 Q.push_back(pnts[i + 1][j + 1][1]);
285 Q.push_back(pnts[i][j + 1][1]);
286 Q.push_back(pnts[i][j][2]);
287 Q.push_back(pnts[i + 1][j][2]);
288 Q.push_back(pnts[i + 1][j + 1][2]);
289 Q.push_back(pnts[i][j + 1][2]);
290 (*nQ)++;
291 for(int k = 0; k < numsteps; ++k) {
292 for(int l = 0; l < nbcomp; ++l)
293 Q.push_back(vals[i][j][nbcomp * k + l]);
294 for(int l = 0; l < nbcomp; ++l)
295 Q.push_back(vals[i + 1][j][nbcomp * k + l]);
296 for(int l = 0; l < nbcomp; ++l)
297 Q.push_back(vals[i + 1][j + 1][nbcomp * k + l]);
298 for(int l = 0; l < nbcomp; ++l)
299 Q.push_back(vals[i][j + 1][nbcomp * k + l]);
300 }
301 }
302 }
303 }
304 }
305 }
306
GenerateView(PView * v1,int connect)307 PView *GMSH_CutGridPlugin::GenerateView(PView *v1, int connect)
308 {
309 if(getNbU() <= 0 || getNbV() <= 0) return v1;
310
311 PViewData *data1 = getPossiblyAdaptiveData(v1);
312
313 PView *v2 = new PView();
314 PViewDataList *data2 = getDataList(v2);
315
316 OctreePost o(v1);
317
318 int nbs = data1->getNumScalars();
319 int nbv = data1->getNumVectors();
320 int nbt = data1->getNumTensors();
321 int maxcomp = nbt ? 9 : (nbv ? 3 : 1);
322 int numsteps = data1->getNumTimeSteps();
323
324 double ***pnts = new double **[getNbU()];
325 double ***vals = new double **[getNbU()];
326 for(int i = 0; i < getNbU(); i++) {
327 pnts[i] = new double *[getNbV()];
328 vals[i] = new double *[getNbV()];
329 for(int j = 0; j < getNbV(); j++) {
330 pnts[i][j] = new double[3];
331 vals[i][j] = new double[maxcomp * numsteps];
332 getPoint(i, j, pnts[i][j]);
333 }
334 }
335
336 if(nbs) {
337 for(int i = 0; i < getNbU(); i++)
338 for(int j = 0; j < getNbV(); j++)
339 o.searchScalar(pnts[i][j][0], pnts[i][j][1], pnts[i][j][2], vals[i][j]);
340 addInView(numsteps, connect, 1, pnts, vals, data2->SP, &data2->NbSP,
341 data2->SL, &data2->NbSL, data2->SQ, &data2->NbSQ);
342 }
343
344 if(nbv) {
345 for(int i = 0; i < getNbU(); i++)
346 for(int j = 0; j < getNbV(); j++)
347 o.searchVector(pnts[i][j][0], pnts[i][j][1], pnts[i][j][2], vals[i][j]);
348 addInView(numsteps, connect, 3, pnts, vals, data2->VP, &data2->NbVP,
349 data2->VL, &data2->NbVL, data2->VQ, &data2->NbVQ);
350 }
351
352 if(nbt) {
353 for(int i = 0; i < getNbU(); i++)
354 for(int j = 0; j < getNbV(); j++)
355 o.searchTensor(pnts[i][j][0], pnts[i][j][1], pnts[i][j][2], vals[i][j]);
356 addInView(numsteps, connect, 9, pnts, vals, data2->TP, &data2->NbTP,
357 data2->TL, &data2->NbTL, data2->TQ, &data2->NbTQ);
358 }
359
360 for(int i = 0; i < getNbU(); i++) {
361 for(int j = 0; j < getNbV(); j++) {
362 delete[] pnts[i][j];
363 delete[] vals[i][j];
364 }
365 delete[] pnts[i];
366 delete[] vals[i];
367 }
368 delete[] pnts;
369 delete[] vals;
370
371 data2->setName(data1->getName() + "_CutGrid");
372 data2->setFileName(data1->getName() + "_CutGrid.pos");
373 data2->finalize();
374
375 return v2;
376 }
377
execute(PView * v)378 PView *GMSH_CutGridPlugin::execute(PView *v)
379 {
380 int connectPoints = (int)CutGridOptions_Number[11].def;
381 int iView = (int)CutGridOptions_Number[12].def;
382
383 PView *v1 = getView(iView, v);
384 if(!v1) return v;
385
386 return GenerateView(v1, connectPoints);
387 }
388