gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
Iso.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 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 "Numeric.h"
7 
8 static void affect(double *xi, double *yi, double *zi, int i, double *xp,
9  double *yp, double *zp, int j)
10 {
11  xi[i] = xp[j];
12  yi[i] = yp[j];
13  zi[i] = zp[j];
14 }
15 
16 double InterpolateIso(double *X, double *Y, double *Z, double *Val, double V,
17  int I1, int I2, double *XI, double *YI, double *ZI)
18 {
19  if(Val[I1] == Val[I2]) {
20  *XI = X[I1];
21  *YI = Y[I1];
22  *ZI = Z[I1];
23  return 0;
24  }
25  else {
26  double coef = (V - Val[I1]) / (Val[I2] - Val[I1]);
27  *XI = coef * (X[I2] - X[I1]) + X[I1];
28  *YI = coef * (Y[I2] - Y[I1]) + Y[I1];
29  *ZI = coef * (Z[I2] - Z[I1]) + Z[I1];
30  return coef;
31  }
32 }
33 
34 // Compute an iso-point in a line
35 
36 int IsoLine(double *X, double *Y, double *Z, double *Val, double V, double *Xp,
37  double *Yp, double *Zp)
38 {
39  if(Val[0] == Val[1]) return 0;
40 
41  if((Val[0] >= V && Val[1] <= V) || (Val[1] >= V && Val[0] <= V)) {
42  InterpolateIso(X, Y, Z, Val, V, 0, 1, Xp, Yp, Zp);
43  return 1;
44  }
45  return 0;
46 }
47 
48 // Compute an iso-line inside a triangle
49 
50 int IsoTriangle(double *X, double *Y, double *Z, double *Val, double V,
51  double *Xp, double *Yp, double *Zp)
52 {
53  if(Val[0] == Val[1] && Val[0] == Val[2]) return 0;
54 
55  int nb = 0;
56  if((Val[0] >= V && Val[1] <= V) || (Val[1] >= V && Val[0] <= V)) {
57  InterpolateIso(X, Y, Z, Val, V, 0, 1, &Xp[nb], &Yp[nb], &Zp[nb]);
58  nb++;
59  }
60  if((Val[0] >= V && Val[2] <= V) || (Val[2] >= V && Val[0] <= V)) {
61  InterpolateIso(X, Y, Z, Val, V, 0, 2, &Xp[nb], &Yp[nb], &Zp[nb]);
62  nb++;
63  }
64  if((Val[1] >= V && Val[2] <= V) || (Val[2] >= V && Val[1] <= V)) {
65  InterpolateIso(X, Y, Z, Val, V, 1, 2, &Xp[nb], &Yp[nb], &Zp[nb]);
66  nb++;
67  }
68 
69  if(nb == 2) return 2;
70  return 0;
71 }
72 
73 // Compute an iso-polygon inside a tetrahedron
74 
75 int IsoSimplex(double *X, double *Y, double *Z, double *Val, double V,
76  double *Xp, double *Yp, double *Zp, double n[3])
77 {
78  if(Val[0] == Val[1] && Val[0] == Val[2] && Val[0] == Val[3]) return 0;
79 
80  int nb = 0;
81  if((Val[0] >= V && Val[1] <= V) || (Val[1] >= V && Val[0] <= V)) {
82  InterpolateIso(X, Y, Z, Val, V, 0, 1, &Xp[nb], &Yp[nb], &Zp[nb]);
83  nb++;
84  }
85  if((Val[0] >= V && Val[2] <= V) || (Val[2] >= V && Val[0] <= V)) {
86  InterpolateIso(X, Y, Z, Val, V, 0, 2, &Xp[nb], &Yp[nb], &Zp[nb]);
87  nb++;
88  }
89  if((Val[0] >= V && Val[3] <= V) || (Val[3] >= V && Val[0] <= V)) {
90  InterpolateIso(X, Y, Z, Val, V, 0, 3, &Xp[nb], &Yp[nb], &Zp[nb]);
91  nb++;
92  }
93  if((Val[1] >= V && Val[2] <= V) || (Val[2] >= V && Val[1] <= V)) {
94  InterpolateIso(X, Y, Z, Val, V, 1, 2, &Xp[nb], &Yp[nb], &Zp[nb]);
95  nb++;
96  }
97  if((Val[1] >= V && Val[3] <= V) || (Val[3] >= V && Val[1] <= V)) {
98  InterpolateIso(X, Y, Z, Val, V, 1, 3, &Xp[nb], &Yp[nb], &Zp[nb]);
99  nb++;
100  }
101  if((Val[2] >= V && Val[3] <= V) || (Val[3] >= V && Val[2] <= V)) {
102  InterpolateIso(X, Y, Z, Val, V, 2, 3, &Xp[nb], &Yp[nb], &Zp[nb]);
103  nb++;
104  }
105 
106  // Remove identical nodes (this can happen if an edge belongs to the
107  // zero levelset). We should be doing this even for nb < 4, but it
108  // would slow us down even more (and we don't really care if some
109  // nodes in a postprocessing element are identical)
110  if(nb > 4) {
111  double xi[6], yi[6], zi[6];
112  affect(xi, yi, zi, 0, Xp, Yp, Zp, 0);
113  int ni = 1;
114  for(int j = 1; j < nb; j++) {
115  for(int i = 0; i < ni; i++) {
116  if(fabs(Xp[j] - xi[i]) < 1.e-12 && fabs(Yp[j] - yi[i]) < 1.e-12 &&
117  fabs(Zp[j] - zi[i]) < 1.e-12) {
118  break;
119  }
120  if(i == ni - 1) {
121  affect(xi, yi, zi, i + 1, Xp, Yp, Zp, j);
122  ni++;
123  }
124  }
125  }
126  for(int i = 0; i < ni; i++) affect(Xp, Yp, Zp, i, xi, yi, zi, i);
127  nb = ni;
128  }
129 
130  if(nb < 3 || nb > 4) return 0;
131 
132  // 3 possible quads at this point: (0,2,5,3), (0,1,5,4) or
133  // (1,2,4,3), so simply invert the 2 last vertices for having the
134  // quad ordered
135  if(nb == 4) {
136  double x = Xp[3], y = Yp[3], z = Zp[3];
137  Xp[3] = Xp[2];
138  Yp[3] = Yp[2];
139  Zp[3] = Zp[2];
140  Xp[2] = x;
141  Yp[2] = y;
142  Zp[2] = z;
143  }
144 
145  // to get a nice isosurface, we should have n . grad v > 0, where n
146  // is the normal to the polygon and v is the unknown field we want
147  // to draw
148  double v1[3] = {Xp[2] - Xp[0], Yp[2] - Yp[0], Zp[2] - Zp[0]};
149  double v2[3] = {Xp[1] - Xp[0], Yp[1] - Yp[0], Zp[1] - Zp[0]};
150  prodve(v1, v2, n);
151  norme(n);
152 
153  double g[3];
154  gradSimplex(X, Y, Z, Val, g);
155 
156  if(prosca(g, n) > 0.0) {
157  double Xpi[6], Ypi[6], Zpi[6];
158  for(int i = 0; i < nb; i++) {
159  Xpi[i] = Xp[i];
160  Ypi[i] = Yp[i];
161  Zpi[i] = Zp[i];
162  }
163  for(int i = 0; i < nb; i++) {
164  Xp[i] = Xpi[nb - i - 1];
165  Yp[i] = Ypi[nb - i - 1];
166  Zp[i] = Zpi[nb - i - 1];
167  }
168  }
169  else {
170  n[0] = -n[0];
171  n[1] = -n[1];
172  n[2] = -n[2];
173  }
174 
175  return nb;
176 }
177 
178 // Compute the line between the two iso-points V1 and V2 in a line
179 
180 int CutLine(double *X, double *Y, double *Z, double *Val, double V1, double V2,
181  double *Xp2, double *Yp2, double *Zp2, double *Vp2)
182 {
183  int io[2];
184  if(Val[0] < Val[1]) {
185  io[0] = 0;
186  io[1] = 1;
187  }
188  else {
189  io[0] = 1;
190  io[1] = 0;
191  }
192 
193  if(Val[io[0]] > V2 || Val[io[1]] < V1) return 0;
194 
195  if(V1 <= Val[io[0]] && Val[io[1]] <= V2) {
196  for(int i = 0; i < 2; i++) {
197  Vp2[i] = Val[i];
198  Xp2[i] = X[i];
199  Yp2[i] = Y[i];
200  Zp2[i] = Z[i];
201  }
202  return 2;
203  }
204 
205  if(V1 <= Val[io[0]]) {
206  Vp2[0] = Val[io[0]];
207  Xp2[0] = X[io[0]];
208  Yp2[0] = Y[io[0]];
209  Zp2[0] = Z[io[0]];
210  }
211  else {
212  Vp2[0] = V1;
213  InterpolateIso(X, Y, Z, Val, V1, io[0], io[1], &Xp2[0], &Yp2[0], &Zp2[0]);
214  }
215 
216  if(V2 >= Val[io[1]]) {
217  Vp2[1] = Val[io[1]];
218  Xp2[1] = X[io[1]];
219  Yp2[1] = Y[io[1]];
220  Zp2[1] = Z[io[1]];
221  }
222  else {
223  Vp2[1] = V2;
224  InterpolateIso(X, Y, Z, Val, V2, io[0], io[1], &Xp2[1], &Yp2[1], &Zp2[1]);
225  }
226 
227  return 2;
228 }
229 
230 // Compute the polygon between the two iso-lines V1 and V2 in a
231 // triangle
232 
233 int CutTriangle(double *X, double *Y, double *Z, double *Val, double V1,
234  double V2, double *Xp2, double *Yp2, double *Zp2, double *Vp2)
235 {
236  // fill io so that it contains an indexing of the nodes such that
237  // Val[io[i]] > Val[io[j]] if i > j
238  int io[3] = {0, 1, 2};
239  for(int i = 0; i < 2; i++) {
240  for(int j = i + 1; j < 3; j++) {
241  if(Val[io[i]] > Val[io[j]]) {
242  int iot = io[i];
243  io[i] = io[j];
244  io[j] = iot;
245  }
246  }
247  }
248 
249  if(Val[io[0]] > V2 || Val[io[2]] < V1) return 0;
250 
251  if(V1 <= Val[io[0]] && Val[io[2]] <= V2) {
252  for(int i = 0; i < 3; i++) {
253  Vp2[i] = Val[i];
254  Xp2[i] = X[i];
255  Yp2[i] = Y[i];
256  Zp2[i] = Z[i];
257  }
258  return 3;
259  }
260 
261  int Np = 0, Fl = 0;
262  double Xp[10], Yp[10], Zp[10], Vp[10];
263 
264  if(V1 <= Val[io[0]]) {
265  Vp[Np] = Val[io[0]];
266  Xp[Np] = X[io[0]];
267  Yp[Np] = Y[io[0]];
268  Zp[Np] = Z[io[0]];
269  Np++;
270  Fl = 1;
271  }
272  else if(Val[io[0]] < V1 && V1 <= Val[io[1]]) {
273  Vp[Np] = V1;
274  InterpolateIso(X, Y, Z, Val, V1, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]);
275  Np++;
276  Vp[Np] = V1;
277  InterpolateIso(X, Y, Z, Val, V1, io[0], io[1], &Xp[Np], &Yp[Np], &Zp[Np]);
278  Np++;
279  Fl = 1;
280  }
281  else {
282  Vp[Np] = V1;
283  InterpolateIso(X, Y, Z, Val, V1, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]);
284  Np++;
285  Vp[Np] = V1;
286  InterpolateIso(X, Y, Z, Val, V1, io[1], io[2], &Xp[Np], &Yp[Np], &Zp[Np]);
287  Np++;
288  Fl = 0;
289  }
290 
291  if(V2 == Val[io[0]]) { return 0; }
292  else if((Val[io[0]] < V2) && (V2 < Val[io[1]])) {
293  Vp[Np] = V2;
294  InterpolateIso(X, Y, Z, Val, V2, io[0], io[1], &Xp[Np], &Yp[Np], &Zp[Np]);
295  Np++;
296  Vp[Np] = V2;
297  InterpolateIso(X, Y, Z, Val, V2, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]);
298  Np++;
299  }
300  else if(V2 < Val[io[2]]) {
301  if(Fl) {
302  Vp[Np] = Val[io[1]];
303  Xp[Np] = X[io[1]];
304  Yp[Np] = Y[io[1]];
305  Zp[Np] = Z[io[1]];
306  Np++;
307  }
308  Vp[Np] = V2;
309  InterpolateIso(X, Y, Z, Val, V2, io[1], io[2], &Xp[Np], &Yp[Np], &Zp[Np]);
310  Np++;
311  Vp[Np] = V2;
312  InterpolateIso(X, Y, Z, Val, V2, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]);
313  Np++;
314  }
315  else {
316  if(Fl) {
317  Vp[Np] = Val[io[1]];
318  Xp[Np] = X[io[1]];
319  Yp[Np] = Y[io[1]];
320  Zp[Np] = Z[io[1]];
321  Np++;
322  }
323  Vp[Np] = Val[io[2]];
324  Xp[Np] = X[io[2]];
325  Yp[Np] = Y[io[2]];
326  Zp[Np] = Z[io[2]];
327  Np++;
328  }
329 
330  Vp2[0] = Vp[0];
331  Xp2[0] = Xp[0];
332  Yp2[0] = Yp[0];
333  Zp2[0] = Zp[0];
334 
335  int Np2 = 1;
336 
337  for(int i = 1; i < Np; i++) {
338  if((Xp[i] != Xp2[Np2 - 1]) || (Yp[i] != Yp2[Np2 - 1]) ||
339  (Zp[i] != Zp2[Np2 - 1])) {
340  Vp2[Np2] = Vp[i];
341  Xp2[Np2] = Xp[i];
342  Yp2[Np2] = Yp[i];
343  Zp2[Np2] = Zp[i];
344  Np2++;
345  }
346  }
347 
348  if(Xp2[0] == Xp2[Np2 - 1] && Yp2[0] == Yp2[Np2 - 1] &&
349  Zp2[0] == Zp2[Np2 - 1]) {
350  Np2--;
351  }
352 
353  // check and fix orientation
354  double in1[3] = {X[1] - X[0], Y[1] - Y[0], Z[1] - Z[0]};
355  double in2[3] = {X[2] - X[0], Y[2] - Y[0], Z[2] - Z[0]};
356  double inn[3];
357  prodve(in1, in2, inn);
358  double out1[3] = {Xp2[1] - Xp2[0], Yp2[1] - Yp2[0], Zp2[1] - Zp2[0]};
359  double out2[3] = {Xp2[2] - Xp2[0], Yp2[2] - Yp2[0], Zp2[2] - Zp2[0]};
360  double outn[3];
361  prodve(out1, out2, outn);
362 
363  if(prosca(inn, outn) < 0.0) {
364  for(int i = 0; i < Np2; i++) {
365  Vp[i] = Vp2[Np2 - i - 1];
366  Xp[i] = Xp2[Np2 - i - 1];
367  Yp[i] = Yp2[Np2 - i - 1];
368  Zp[i] = Zp2[Np2 - i - 1];
369  }
370  for(int i = 0; i < Np2; i++) {
371  Vp2[i] = Vp[i];
372  Xp2[i] = Xp[i];
373  Yp2[i] = Yp[i];
374  Zp2[i] = Zp[i];
375  }
376  }
377 
378  return Np2;
379 }
affect
static void affect(double *xi, double *yi, double *zi, int i, double *xp, double *yp, double *zp, int j)
Definition: Iso.cpp:8
CutLine
int CutLine(double *X, double *Y, double *Z, double *Val, double V1, double V2, double *Xp2, double *Yp2, double *Zp2, double *Vp2)
Definition: Iso.cpp:180
Numeric.h
prosca
double prosca(double const a[3], double const b[3])
Definition: Numeric.h:112
IsoLine
int IsoLine(double *X, double *Y, double *Z, double *Val, double V, double *Xp, double *Yp, double *Zp)
Definition: Iso.cpp:36
InterpolateIso
double InterpolateIso(double *X, double *Y, double *Z, double *Val, double V, int I1, int I2, double *XI, double *YI, double *ZI)
Definition: Iso.cpp:16
prodve
void prodve(double a[3], double b[3], double c[3])
Definition: Numeric.h:105
CutTriangle
int CutTriangle(double *X, double *Y, double *Z, double *Val, double V1, double V2, double *Xp2, double *Yp2, double *Zp2, double *Vp2)
Definition: Iso.cpp:233
z
const double z
Definition: GaussQuadratureQuad.cpp:56
gradSimplex
void gradSimplex(double *x, double *y, double *z, double *v, double *grad)
Definition: Numeric.cpp:475
IsoSimplex
int IsoSimplex(double *X, double *Y, double *Z, double *Val, double V, double *Xp, double *Yp, double *Zp, double n[3])
Definition: Iso.cpp:75
norme
double norme(double a[3])
Definition: Numeric.h:123
IsoTriangle
int IsoTriangle(double *X, double *Y, double *Z, double *Val, double V, double *Xp, double *Yp, double *Zp)
Definition: Iso.cpp:50