1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Luc BILLARD, Damien
3 CALISTE, Olivier D'Astier, laboratoire L_Sim, (2001-2005)
4
5 Adresse mèl :
6 BILLARD, non joignable par mèl ;
7 CALISTE, damien P caliste AT cea P fr.
8 D'ASTIER, dastier AT iie P cnam P fr.
9
10 Ce logiciel est un programme informatique servant à visualiser des
11 structures atomiques dans un rendu pseudo-3D.
12
13 Ce logiciel est régi par la licence CeCILL soumise au droit français et
14 respectant les principes de diffusion des logiciels libres. Vous pouvez
15 utiliser, modifier et/ou redistribuer ce programme sous les conditions
16 de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
17 sur le site "http://www.cecill.info".
18
19 Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
20 pris connaissance de la licence CeCILL, et que vous en avez accepté les
21 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
22 */
23
24 /* LICENCE SUM UP
25 Copyright CEA, contributors : Luc BILLARD and Damien
26 CALISTE and Olivier D'Astier, laboratoire L_Sim, (2001-2005)
27
28 E-mail addresses :
29 BILLARD, not reachable any more ;
30 CALISTE, damien P caliste AT cea P fr.
31 D'ASTIER, dastier AT iie P cnam P fr.
32
33 This software is a computer program whose purpose is to visualize atomic
34 configurations in 3D.
35
36 This software is governed by the CeCILL license under French law and
37 abiding by the rules of distribution of free software. You can use,
38 modify and/ or redistribute the software under the terms of the CeCILL
39 license as circulated by CEA, CNRS and INRIA at the following URL
40 "http://www.cecill.info".
41
42 The fact that you are presently reading this means that you have had
43 knowledge of the CeCILL license and that you accept its terms. You can
44 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
45 */
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50
51 #include <math.h>
52
53 #include <visu_tools.h>
54 #include "surfaces.h"
55 #include "pot2surf.h"
56
57 /**
58 * SECTION:pot2surf
59 * @short_description: Creates surfaces from scalar fields.
60 *
61 * <para>Originally written by Luc Billard for his program
62 * VISUALISE. It has been since transformed to a single function and
63 * integrated in V_Sim. .pot file are text files which specification
64 * are the following :
65 * <itemizedlist>
66 * <listitem><para>1st line: full pathname of the potential file to
67 * read</para></listitem>
68 * <listitem><para>2nd line: full pathname of the surface file to
69 * build</para></listitem>
70 * <listitem><para>3rd line: an integer giving the nbr n of
71 * isosurfaces to build </para></listitem>
72 * <listitem><para>Each of the n following lines must match the
73 * pattern [value name] where value is a real number for the isovalue
74 * and name is the name given for the corresponding isosurface to
75 * build. Each surface should be named surface_*.</para></listitem>
76 * </itemizedlist>
77 * The function will fail if it finds no isosurface corresponding to
78 * some of the given isovalues. The <link
79 * linkend="v-sim-panelSurfacesTools">panelSurfacesTools</link>
80 * contains a frontend to build valid .instruc files. This panel is
81 * originally integrated in V_Sim. You can access it through the
82 * Convert tab in the Isosurfaces panel.</para>
83 */
84
85 #define ISOSURFACES_FLAG_POTENTIAL "# potentialValue"
86
87
88 static int nx, ny, nz;
89 static double dxx, dyx, dyy, dzx, dzy, dzz;
90 static double exx, eyx, eyy, ezx, ezy, ezz;
91 static int nxm1, nym1, nzm1;
92 static int nz3, nyz3, nxyz3;
93 static double dxx1, dyx1, dyy1, dzx1, dzy1, dzz1;
94 static double ***f = NULL;
95 static double isovalue;
96 static FILE *in = NULL;
97
98 static int *itab = NULL;
99 static double *xs = NULL, *ys = NULL, *zs = NULL, *xns = NULL, *yns = NULL, *zns = NULL;
100 static gboolean create_fromSF_uniform(VisuSurface **surf, const VisuScalarField *field,
101 double isoValue, const gchar *name);
102 static gboolean create_fromSF_nonuniform(VisuSurface **surf, const VisuScalarField *field,
103 double isoValue, const gchar *name);
104 static gboolean Create_surf(int nelez3, int neleyz3, int nelexyz3,
105 guint sizem1[3], int *iTab, GArray *points,
106 double isoValue, const VisuScalarField *field, double scalarBox[6],
107 const gchar *name, VisuSurface **surf);
108
109 /* Tables from :
110 http://www.swin.edu.au/astronomy/pbourke/modelling/polygonise/index.html
111 (valid link on February 25, 2002)
112
113 YOU WILL FIND MANY VERY INTERESTING PAGES at Paul Bourke's site:
114 http://astronomy.swin.edu.au/pbourke/
115
116 Other routines by Luc Billard, on March 1, 2002
117 */
118
119 static int edgeTable[256]={
120 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
121 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
122 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
123 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
124 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
125 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
126 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
127 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
128 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
129 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
130 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
131 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
132 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
133 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
134 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
135 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
136 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
137 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
138 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
139 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
140 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
141 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
142 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
143 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
144 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
145 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
146 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
147 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
148 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
149 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
150 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
151 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 };
152
153 static int triTable[256][16] =
154 {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
155 {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
156 {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
157 {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
158 {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
159 {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
160 {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
161 {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
162 {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
163 {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
164 {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
165 {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
166 {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
167 {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
168 {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
169 {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
170 {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
171 {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
172 {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
173 {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
174 {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
175 {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
176 {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
177 {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
178 {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
179 {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
180 {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
181 {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
182 {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
183 {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
184 {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
185 {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
186 {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
187 {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
188 {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
189 {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
190 {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
191 {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
192 {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
193 {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
194 {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
195 {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
196 {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
197 {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
198 {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
199 {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
200 {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
201 {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
202 {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
203 {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
204 {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
205 {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
206 {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
207 {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
208 {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
209 {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
210 {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
211 {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
212 {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
213 {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
214 {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
215 {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
216 {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
217 {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
218 {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
219 {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
220 {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
221 {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
222 {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
223 {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
224 {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
225 {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
226 {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
227 {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
228 {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
229 {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
230 {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
231 {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
232 {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
233 {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
234 {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
235 {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
236 {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
237 {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
238 {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
239 {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
240 {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
241 {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
242 {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
243 {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
244 {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
245 {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
246 {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
247 {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
248 {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
249 {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
250 {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
251 {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
252 {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
253 {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
254 {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
255 {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
256 {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
257 {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
258 {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
259 {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
260 {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
261 {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
262 {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
263 {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
264 {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
265 {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
266 {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
267 {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
268 {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
269 {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
270 {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
271 {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
272 {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
273 {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
274 {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
275 {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
276 {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
277 {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
278 {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
279 {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
280 {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
281 {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
282 {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
283 {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
284 {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
285 {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
286 {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
287 {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
288 {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
289 {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
290 {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
291 {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
292 {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
293 {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
294 {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
295 {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
296 {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
297 {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
298 {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
299 {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
300 {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
301 {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
302 {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
303 {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
304 {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
305 {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
306 {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
307 {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
308 {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
309 {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
310 {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
311 {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
312 {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
313 {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
314 {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
315 {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
316 {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
317 {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
318 {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
319 {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
320 {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
321 {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
322 {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
323 {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
324 {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
325 {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
326 {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
327 {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
328 {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
329 {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
330 {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
331 {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
332 {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
333 {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
334 {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
335 {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
336 {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
337 {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
338 {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
339 {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
340 {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
341 {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
342 {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
343 {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
344 {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
345 {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
346 {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
347 {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
348 {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
349 {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
350 {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
351 {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
352 {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
353 {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
354 {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
355 {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
356 {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
357 {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
358 {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
359 {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
360 {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
361 {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
362 {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
363 {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
364 {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
365 {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
366 {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
367 {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
368 {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
369 {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
370 {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
371 {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
372 {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
373 {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
374 {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
375 {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
376 {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
377 {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
378 {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
379 {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
380 {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
381 {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
382 {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
383 {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
384 {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
385 {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
386 {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
387 {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
388 {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
389 {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
390 {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
391 {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
392 {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
393 {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
394 {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
395 {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
396 {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
397 {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
398 {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
399 {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
400 {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
401 {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
402 {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
403 {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
404 {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
405 {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
406 {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
407 {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
408 {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
409 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};
410
411 /******************************************************************************/
412
gx(int i,int j,int k)413 static double gx(int i, int j, int k) {
414 if(i > 0 && i < nxm1) {
415 return (f[i+1][j][k]-f[i-1][j][k]) / 2.0;
416 }
417 else if(i == 0) {
418 return (f[i+1][j][k]-f[i][j][k]);
419 }
420 else {
421 return (f[i][j][k]-f[i-1][j][k]);
422 }
423 }
424
425 /******************************************************************************/
426
gy(int i,int j,int k)427 static double gy(int i, int j, int k) {
428 if(j > 0 && j < nym1) {
429 return (f[i][j+1][k]-f[i][j-1][k]) / 2.0;
430 }
431 else if(j == 0) {
432 return (f[i][j+1][k]-f[i][j][k]);
433 }
434 else {
435 return (f[i][j][k]-f[i][j-1][k]);
436 }
437 }
438
439 /******************************************************************************/
440
gz(int i,int j,int k)441 static double gz(int i, int j, int k) {
442 if(k > 0 && k < nzm1) {
443 return (f[i][j][k+1]-f[i][j][k-1]) / 2.0;
444 }
445 else if(k == 0) {
446 return (f[i][j][k+1]-f[i][j][k]);
447 }
448 else {
449 return (f[i][j][k]-f[i][j][k-1]);
450 }
451 }
452
453 /******************************************************************************/
454
calc(guint * n1,guint * n2)455 static GString* calc(guint *n1, guint *n2) {
456
457 /* I label local cell vertices as in ref. above
458 and assigns x y z names like this :
459
460 y
461 |
462
463 4----------5
464 /. /|
465 7----------6 |
466 | . | |
467 | . | |
468 | 0........|.1 --x
469 |/ |/
470 3----------2
471
472 /
473 z
474
475 */
476 register int i, j, k;
477 guint n;
478 double fac;
479 double xu, yu, zu, xui, xuij, yuj;
480 int cubeindex;
481 int e;
482 int vertlist[12];
483 int m1, m2, m3;
484 double ux, uy, uz, vx, vy, vz, wx, wy, wz, s;
485 double xnu, ynu, znu;
486 GString *out;
487
488 /* edges are labelled from each corner:
489 x+ then z+ then y+
490 for k varying fastest
491 then j varying fastest
492 then i varying fastest
493 */
494 n = 0;
495 for(i=0; i<nx; i++) {
496 xui = i*dxx1;
497 for(j=0; j<ny; j++) {
498 xuij = xui+j*dyx1;
499 yuj = j*dyy1;
500 for(k=0; k<nz; k++) {
501 xu = xuij+k*dzx1;
502 yu = yuj+k*dzy1;
503 zu = k*dzz1;
504 xnu = gx(i, j, k);
505 ynu = gy(i, j, k);
506 znu = gz(i, j, k);
507 if(i<nxm1) {
508 if((isovalue-f[i][j][k] < 0.0 && isovalue-f[i+1][j][k] >= 0) ||
509 (isovalue-f[i][j][k] >= 0.0 && isovalue-f[i+1][j][k] < 0)) {
510 fac = (isovalue-f[i][j][k])/(f[i+1][j][k]-f[i][j][k]);
511 itab[n] = *n2;
512 xs[*n2] = xu + fac*dxx1;
513 ys[*n2] = yu;
514 zs[*n2] = zu;
515 ux = xnu + fac*(gx(i+1, j, k) - xnu);
516 uy = ynu + fac*(gy(i+1, j, k) - ynu);
517 uz = znu + fac*(gz(i+1, j, k) - znu);
518 ux = ux*exx+uy*eyx+uz*ezx;
519 uy = uy*eyy+uz*ezy;
520 uz = uz*ezz;
521 s = sqrt(ux*ux+uy*uy+uz*uz);
522 if(s <= 0.0) {
523 g_warning("normal direction assumed");
524 xns[*n2] = 1.0;
525 yns[*n2] = 0.0;
526 zns[*n2] = 0.0;
527 }
528 else {
529 xns[*n2] = ux/s;
530 yns[*n2] = uy/s;
531 zns[*n2] = uz/s;
532 }
533 *n2 += 1;
534 }
535 else {
536 itab[n] = -1;
537 }
538 }
539 else {
540 itab[n] = -1;
541 }
542 n++;
543 if(k<nzm1) {
544 if((isovalue-f[i][j][k] < 0.0 && isovalue-f[i][j][k+1] >= 0) ||
545 (isovalue-f[i][j][k] >= 0.0 && isovalue-f[i][j][k+1] < 0)) {
546 fac = (isovalue-f[i][j][k])/(f[i][j][k+1]-f[i][j][k]);
547 itab[n] = *n2;
548 xs[*n2] = xu + fac*dzx1;
549 ys[*n2] = yu + fac*dzy1;
550 zs[*n2] = zu + fac*dzz1;
551 ux = xnu + fac*(gx(i, j, k+1) - xnu);
552 uy = ynu + fac*(gy(i, j, k+1) - ynu);
553 uz = znu + fac*(gz(i, j, k+1) - znu);
554 ux = ux*exx+uy*eyx+uz*ezx;
555 uy = uy*eyy+uz*ezy;
556 uz = uz*ezz;
557 s = sqrt(ux*ux+uy*uy+uz*uz);
558 if(s <= 0.0) {
559 g_warning("normal direction assumed");
560 xns[*n2] = 1.0;
561 yns[*n2] = 0.0;
562 zns[*n2] = 0.0;
563 }
564 else {
565 xns[*n2] = ux/s;
566 yns[*n2] = uy/s;
567 zns[*n2] = uz/s;
568 }
569 *n2 += 1;
570 }
571 else {
572 itab[n] = -1;
573 }
574 }
575 else {
576 itab[n] = -1;
577 }
578 n++;
579 if(j<nym1) {
580 if((isovalue-f[i][j][k] < 0.0 && isovalue-f[i][j+1][k] >= 0) ||
581 (isovalue-f[i][j][k] >= 0.0 && isovalue-f[i][j+1][k] < 0)) {
582 fac = (isovalue-f[i][j][k])/(f[i][j+1][k]-f[i][j][k]);
583 itab[n] = *n2;
584 xs[*n2] = xu + fac*dyx1;
585 ys[*n2] = yu + fac*dyy1;
586 zs[*n2] = zu;
587 ux = xnu + fac*(gx(i, j+1, k) - xnu);
588 uy = ynu + fac*(gy(i, j+1, k) - ynu);
589 uz = znu + fac*(gz(i, j+1, k) - znu);
590 ux = ux*exx+uy*eyx+uz*ezx;
591 uy = uy*eyy+uz*ezy;
592 uz = uz*ezz;
593 s = sqrt(ux*ux+uy*uy+uz*uz);
594 if(s <= 0.0) {
595 g_warning("normal direction assumed");
596 xns[*n2] = 1.0;
597 yns[*n2] = 0.0;
598 zns[*n2] = 0.0;
599 }
600 else {
601 xns[*n2] = ux/s;
602 yns[*n2] = uy/s;
603 zns[*n2] = uz/s;
604 }
605 *n2 += 1;
606 }
607 else {
608 itab[n] = -1;
609 }
610 }
611 else {
612 itab[n] = -1;
613 }
614 n++;
615 }
616 }
617 }
618
619 if(*n2 == 0) {
620 g_warning("no isosurfaces found.");
621 return (GString*)0;
622 }
623
624 out = g_string_new("");
625 for(i=0; i<nxm1; i++) {
626 for(j=0; j<nym1; j++) {
627 for(k=0; k<nzm1; k++) {
628 cubeindex = 0;
629 if (f[i ][j ][k ] < isovalue) cubeindex |= 1;
630 if (f[i+1][j ][k ] < isovalue) cubeindex |= 2;
631 if (f[i+1][j ][k+1] < isovalue) cubeindex |= 4;
632 if (f[i ][j ][k+1] < isovalue) cubeindex |= 8;
633 if (f[i ][j+1][k ] < isovalue) cubeindex |= 16;
634 if (f[i+1][j+1][k ] < isovalue) cubeindex |= 32;
635 if (f[i+1][j+1][k+1] < isovalue) cubeindex |= 64;
636 if (f[i ][j+1][k+1] < isovalue) cubeindex |= 128;
637
638 e = edgeTable[cubeindex];
639
640 if (e == 0) continue;
641
642 n = i*nyz3+j*nz3+k*3;
643
644 if (e & 1 ) vertlist[0 ] = itab[n];
645 if (e & 2 ) vertlist[1 ] = itab[n + nyz3 + 1];
646 if (e & 4 ) vertlist[2 ] = itab[n + 3];
647 if (e & 8 ) vertlist[3 ] = itab[n + 1];
648 if (e & 16 ) vertlist[4 ] = itab[n + nz3];
649 if (e & 32 ) vertlist[5 ] = itab[n + nyz3 + 1 + nz3];
650 if (e & 64 ) vertlist[6 ] = itab[n + 3 + nz3];
651 if (e & 128 ) vertlist[7 ] = itab[n + 1 + nz3];
652 if (e & 256 ) vertlist[8 ] = itab[n + 2];
653 if (e & 512 ) vertlist[9 ] = itab[n + nyz3 + 2];
654 if (e & 1024) vertlist[10] = itab[n + nyz3 + 3 + 2];
655 if (e & 2048) vertlist[11] = itab[n + 3 + 2];
656
657 for (n = 0; triTable[cubeindex][n]!= -1; n += 3) {
658 m1 = vertlist[triTable[cubeindex][n ]];
659 if(m1 == -1)
660 {
661 g_warning("m1 %d %d %d", i, j, k);
662 g_string_free(out, TRUE);
663 return (GString*)0;
664 }
665 m2 = vertlist[triTable[cubeindex][n+1]];
666 if(m2 == -1)
667 {
668 g_warning("m2 %d %d %d", i, j, k);
669 g_string_free(out, TRUE);
670 return (GString*)0;
671 }
672 m3 = vertlist[triTable[cubeindex][n+2]];
673 if(m3 == -1)
674 {
675 g_warning("m3 %d %d %d", i, j, k);
676 g_string_free(out, TRUE);
677 return (GString*)0;
678 }
679 ux = xs[m2] - xs[m1];
680 uy = ys[m2] - ys[m1];
681 uz = zs[m2] - zs[m1];
682 vx = xs[m3] - xs[m1];
683 vy = ys[m3] - ys[m1];
684 vz = zs[m3] - zs[m1];
685 wx = uy*vz-uz*vy;
686 wy = uz*vx-ux*vz;
687 wz = ux*vy-uy*vx;
688 s = sqrt(wx*wx+wy*wy+wz*wz);
689 if(s <= 0.0) continue;
690 g_string_append_printf(out, "3 %d %d %d\n", m1+1, m2+1, m3+1);
691 *n1 += 1;
692 }
693 }
694 }
695 }
696
697 if(*n1 == 0) {
698 g_warning("no isosurfaces found.");
699 return (GString*)0;
700 }
701
702
703 for(n=0; n<*n2; n++)
704 g_string_append_printf(out, "%g %g %g %g %g %g\n",
705 xs[n], ys[n], zs[n], xns[n], yns[n], zns[n]);
706
707 return out;
708 }
709
710 /**
711 * visu_surface_createFromPotentialFile:
712 * @surf_file_to_write: target surf file
713 * @pot_file_to_read: source pot file
714 * @nsurfs_to_build: number of surfaces to build
715 * @surf_value: an array with iso-values
716 * @surf_name: an array with iso-surface names.
717 *
718 * Read the given pot file and produce an associated surf
719 * file. WARNING, it may be removed later.
720 *
721 * Deprecated: 3.7
722 *
723 * Returns: 0 in case of success, n!=0 otherwise.
724 */
725 #ifndef V_SIM_DISABLE_DEPRECATED
visu_surface_createFromPotentialFile(const gchar * surf_file_to_write,const gchar * pot_file_to_read,int nsurfs_to_build,const float * surf_value,const gchar ** surf_name)726 int visu_surface_createFromPotentialFile(const gchar *surf_file_to_write, const gchar *pot_file_to_read, int nsurfs_to_build,
727 const float *surf_value, const gchar **surf_name)
728 {
729 register int i, j, k;
730 char rep[TOOL_MAX_LINE_LENGTH], info[TOOL_MAX_LINE_LENGTH];
731 double v;
732 GString *out, *local;
733 guint n1, n2;
734 int n1_tot, n2_tot;
735 gchar *comment;
736 GError *error;
737
738 n1_tot = 0;
739 n2_tot = 0;
740
741 in = fopen(pot_file_to_read,"r");
742 if (!in) {
743 (void)fprintf(stderr, "\aERROR: cannot read potential file %s\n", pot_file_to_read);
744 return 1;
745 }
746 DBG_fprintf(stderr, "pot2surf : Reading potential file %s\n", pot_file_to_read);
747
748 out = g_string_new("");
749 DBG_fprintf(stderr, "pot2surf : Writing surface file %s ...\n", surf_file_to_write);
750
751 /* 1st line (comment) */
752 g_return_val_if_fail(fgets(rep, TOOL_MAX_LINE_LENGTH, in), 1);
753 rep[strlen(rep)-1] = 0; /* skipping \n */
754 DBG_fprintf(stderr, "Pot2surf : read comment line '%s'\n", rep);
755 comment = g_strdup(rep);
756
757 g_return_val_if_fail(fgets(rep, TOOL_MAX_LINE_LENGTH, in), 1);
758 g_return_val_if_fail(sscanf(rep, "%d %d %d", &nx, &ny, &nz) != 3, 1);
759
760 f = g_malloc(nx*sizeof(double **));
761 for(i=0; i<nx; i++) {
762 f[i] = g_malloc(ny*sizeof(double *));
763 for(j=0; j<ny; j++) {
764 f[i][j] = g_malloc(nz*sizeof(double));
765 }
766 }
767
768 nxm1 = nx - 1;
769 nym1 = ny - 1;
770 nzm1 = nz - 1;
771
772 nz3 = 3*nz;
773 nyz3 = ny*nz3;
774 nxyz3 = nx*nyz3;
775
776 itab = g_malloc(nxyz3*sizeof(int));
777
778 xs = g_malloc(nxyz3*sizeof(double));
779 ys = g_malloc(nxyz3*sizeof(double));
780 zs = g_malloc(nxyz3*sizeof(double));
781 xns = g_malloc(nxyz3*sizeof(double));
782 yns = g_malloc(nxyz3*sizeof(double));
783 zns = g_malloc(nxyz3*sizeof(double));
784
785 g_return_val_if_fail(fgets(rep, TOOL_MAX_LINE_LENGTH, in), 1);
786 g_return_val_if_fail(sscanf(rep, "%lf %lf %lf", &dxx, &dyx, &dyy) != 3, 1);
787 g_return_val_if_fail(fgets(rep, TOOL_MAX_LINE_LENGTH, in), 1);
788 g_return_val_if_fail(sscanf(rep, "%lf %lf %lf", &dzx, &dzy, &dzz) != 3, 1);;
789
790 v = dxx*dyy*dzz;
791 exx = dyy*dzz/v;
792 eyx = -dyx*dzz/v;
793 ezx = (dyx*dzy-dyy*dzx)/v;
794 eyy = dxx*dzz/v;
795 ezy = -dxx*dzy/v;
796 ezz = dxx*dyy/v;
797
798 dxx1 = dxx/nx;
799 dyx1 = dyx/ny;
800 dyy1 = dyy/ny;
801 dzx1 = dzx/nz;
802 dzy1 = dzy/nz;
803 dzz1 = dzz/nz;
804
805 g_return_val_if_fail(fgets(rep, TOOL_MAX_LINE_LENGTH, in), 1);
806 if(sscanf(rep, "%s", info) != 1) {
807 (void)fprintf(stderr, "\aERROR: missing chain xyz OR zyx\n");
808 return 1;
809 }
810 if(!strcmp(info, "xyz")) {
811 for ( k = 0; k < nz; k++ )
812 for ( j = 0; j < ny; j++ )
813 for ( i = 0; i < nx; i++ )
814 g_return_val_if_fail(fscanf(in, "%lf", &f[i][j][k]) != 1, 1);
815 }
816 else if(!strcmp(info, "zyx")) {
817 for ( i = 0; i < nx; i++ )
818 for ( j = 0; j < ny; j++ )
819 for ( k = 0; k < nz; k++ )
820 g_return_val_if_fail(fscanf(in, "%lf", &f[i][j][k]) != 1, 1);
821 }
822 else {
823 (void)fprintf(stderr,
824 "\aERROR: 5th line should contain chain xyz OR zyx\n");
825 return 1;
826 }
827
828 for(k=0; k<nsurfs_to_build; k++) {
829
830 isovalue = surf_value[k];
831
832 DBG_fprintf(stderr, "Building isosurface for isovalue = %f (%s)\n",
833 isovalue, surf_name[k]);
834 g_string_append_printf(out, "%s %f\n", ISOSURFACES_FLAG_POTENTIAL, isovalue);
835 if (surf_name[k])
836 g_string_append(out, surf_name[k]);
837 g_string_append(out, "\n");
838
839 n1 = 0;
840 n2 = 0;
841 local = calc(&n1, &n2);
842 if(!local)
843 return 1;
844 DBG_fprintf(stderr, " Found %d facets and %d points\n", n1, n2);
845 g_string_append_printf(out, "%12d%12d", n1, n2);
846 g_string_append(out, local->str);
847 g_string_free(local, TRUE);
848
849 n1_tot += n1;
850 n2_tot += n2;
851 }
852
853 local = g_string_new(comment);
854 g_free(comment);
855 g_string_append_printf(local, "%f %f %f\n", dxx, dyx, dyy);
856 g_string_append_printf(local, "%f %f %f\n", dzx, dzy, dzz);
857 g_string_append_printf(local, "%12d%12d%12d", nsurfs_to_build, n1_tot, n2_tot);
858 g_string_prepend(out, local->str);
859 g_string_free(local, TRUE);
860
861 DBG_fprintf(stderr,
862 "Found a total of %d facets and %d points\n", n1_tot, n2_tot);
863 DBG_fprintf(stderr, "Done.\n");
864
865 for(i=0; i<nx; i++)
866 {
867 for(j=0; j<ny; j++)
868 g_free(f[i][j]);
869 g_free(f[i]);
870 }
871 g_free(f);
872
873 g_free(itab);
874
875 g_free(xs);
876 g_free(ys);
877 g_free(zs);
878 g_free(xns);
879 g_free(yns);
880 g_free(zns);
881
882 error = (GError*)0;
883 if (!g_file_set_contents(surf_file_to_write, out->str, -1, &error))
884 {
885 g_warning("%s", error->message);
886 g_error_free(error);
887 return 1;
888 }
889 g_string_free(out, TRUE);
890
891 return 0;
892 }
893 #endif
894
895 /******************************************************************************/
896 /******************************************************************************/
897
898
899 /* DEVELOPMENT AREA
900 Methods are copied to be callable without all static stuff everywhere. */
901
getDeltaMesh(int i,double * mesh,int size,gboolean periodic)902 static double getDeltaMesh(int i, double *mesh, int size, gboolean periodic)
903 {
904 if (i >= size - 1)
905 {
906 if (periodic)
907 return 1. + mesh[(i + 1)%size] - mesh[i%size];
908 else
909 return (mesh[size] - mesh[size - 1]);
910 }
911 return (mesh[i + 1] - mesh[i]);
912 }
913
914 /**
915 * visu_surface_new_fromScalarField:
916 * @field: the scalar field to create the surface from ;
917 * @isoValue: the value of the isosurface ;
918 * @name: (allow-none): the name of the surface to use (can be NULL).
919 *
920 * Create on the fly a surface from the scalar field @field. If
921 * @name is given, the surface is created with it, if not, "Isosurface
922 * @id + 1" is used. @surf can already contains several surfaces, in
923 * that case, the new surface is added. If @surf is NULL, then a new
924 * #VisuSurface object is created and returned.
925 *
926 * Returns: (transfer full): the newly created surface, if any.
927 */
visu_surface_new_fromScalarField(const VisuScalarField * field,double isoValue,const gchar * name)928 VisuSurface* visu_surface_new_fromScalarField(const VisuScalarField *field,
929 double isoValue,
930 const gchar *name)
931 {
932 VisuSurface *surf;
933
934 surf = (VisuSurface*)0;
935 switch (visu_scalar_field_getMeshtype(field))
936 {
937 case VISU_SCALAR_FIELD_MESH_UNIFORM:
938 create_fromSF_uniform (&surf, field, isoValue, name);
939 break;
940 case VISU_SCALAR_FIELD_MESH_NON_UNIFORM:
941 create_fromSF_nonuniform(&surf, field, isoValue, name);
942 break;
943 default:
944 g_warning("Wrong value for 'meshtype'.");
945 return FALSE;
946 }
947 if (surf)
948 g_object_set_data(G_OBJECT(surf), "origin", (gpointer)field);
949 return surf;
950 }
951
952 /**
953 * visu_surface_new_defaultFromScalarField:
954 * @field: a #VisuScalarField object.
955 * @neg: (transfer full) (out): a #VisuSurface location.
956 * @pos: (transfer full) (out): a #VisuSurface location.
957 *
958 * Creates one or two surface from @field. If @field is mostly
959 * positive, one surface is generated at the mean value. If @field has
960 * equivalent negative and positive values, two surfaces are
961 * generated, one for th mean negative value and one for the mean
962 * positive value.
963 *
964 * Since: 3.8
965 **/
visu_surface_new_defaultFromScalarField(const VisuScalarField * field,VisuSurface ** neg,VisuSurface ** pos)966 void visu_surface_new_defaultFromScalarField(const VisuScalarField *field,
967 VisuSurface **neg,
968 VisuSurface **pos)
969 {
970 double mimax[2];
971 VisuSurface *surf;
972 VisuSurfaceResource *res;
973 gchar *label;
974 static guint id = 0;
975 int blue[4] = {0, 24, 185, 196}, red[4] = {185, 24, 0, 196};
976 gboolean new;
977
978 if (neg)
979 *neg = (VisuSurface*)0;
980 if (pos)
981 *pos = (VisuSurface*)0;
982 id += 1;
983 visu_scalar_field_getMinMax(field, mimax);
984 /* For densities, this create only one surface. For
985 wavefunctions, it create two and set their style
986 accordingly. */
987 if (mimax[0] <= mimax[1] && mimax[0] * mimax[1] < 0.f &&
988 MIN(ABS(mimax[0]), ABS(mimax[1])) / MAX(ABS(mimax[0]), ABS(mimax[1])) > 0.2)
989 {
990 label = g_strdup_printf(_("Negative (%d)"), id);
991 res = visu_surface_resource_new_fromName(label, &new);
992 if (new)
993 g_object_set(res, "color", tool_color_addIntRGBA(blue),
994 "rendered", TRUE, NULL);
995 g_object_unref(res);
996 surf = visu_surface_new_fromScalarField(field, mimax[0] / 2., label);
997 g_free(label);
998 if (surf && neg)
999 *neg = surf;
1000 else if (surf)
1001 g_object_unref(surf);
1002
1003 label = g_strdup_printf(_("Positive (%d)"), id);
1004 res = visu_surface_resource_new_fromName(label, &new);
1005 if (new)
1006 g_object_set(res, "color", tool_color_addIntRGBA(red),
1007 "rendered", TRUE, NULL);
1008 g_object_unref(res);
1009 surf = visu_surface_new_fromScalarField(field, mimax[1] / 2., label);
1010 g_free(label);
1011 if (surf && pos)
1012 *pos = surf;
1013 else if (surf)
1014 g_object_unref(surf);
1015 }
1016 else if (mimax[0] <= mimax[1])
1017 {
1018 surf = visu_surface_new_fromScalarField(field, (mimax[0] + mimax[1]) / 2.,
1019 (const gchar*)0);
1020 if (surf && pos)
1021 *pos = surf;
1022 else if (surf)
1023 g_object_unref(surf);
1024 }
1025 else
1026 {
1027 surf = visu_surface_new_fromScalarField(field, 0., (gchar*)0);
1028 if (surf && pos)
1029 *pos = surf;
1030 else if (surf)
1031 g_object_unref(surf);
1032 }
1033 }
1034
_setNormal(double nrm[3],double s,double vux,double vuy,double vuz)1035 static void _setNormal(double nrm[3], double s, double vux, double vuy, double vuz)
1036 {
1037 if (s <= 0.0)
1038 {
1039 g_warning("normal direction assumed");
1040 nrm[0] = 1.;
1041 nrm[1] = 0.;
1042 nrm[2] = 0.;
1043 }
1044 else
1045 {
1046 nrm[0] = vux/s;
1047 nrm[1] = vuy/s;
1048 nrm[2] = vuz/s;
1049 }
1050 }
1051
1052 /**
1053 * create_fromSF_uniform:
1054 * @surf: a location on a #VisuSurface pointer ;
1055 * @field: the scalar field to create the surface from ;
1056 * @isoValue: the value of the isosurface ;
1057 * @id: an integer identifying the surface ;
1058 * @name: the name of the surface to use (can be NULL).
1059 *
1060 * Create on the fly a surface from the scalar field @field. If @name is given, the surface
1061 * is created with it, if not, "Isosurface @id + 1" is used. @surf can already
1062 * contains several surfaces, in that case, the new surface is added. If @surf is
1063 * NULL, then a new #VisuSurface object is created and returned.
1064 *
1065 * Returns: TRUE if the surface is created.
1066 */
1067
create_fromSF_uniform(VisuSurface ** surf,const VisuScalarField * field,double isoValue,const gchar * name)1068 static gboolean create_fromSF_uniform(VisuSurface **surf, const VisuScalarField *field,
1069 double isoValue, const gchar *name)
1070 {
1071
1072 /* I label local cell vertices as in ref. above
1073 and assigns x y z names like this :
1074
1075 y
1076 |
1077
1078 4----------5
1079 /. /|
1080 7----------6 |
1081 | . | |
1082 | . | |
1083 | 0........|.1 --x
1084 |/ |/
1085 3----------2
1086
1087 /
1088 z
1089
1090 */
1091
1092 /* Local variables */
1093
1094 register guint i, j, k;
1095 int n;
1096 int nelez3, neleyz3, nelexyz3;
1097 guint sizem1[3]; /*nx-1, ny-1 ,nz-1 : number of mesh intervals in the x,y and z direction*/
1098 guint scalarGrid[3]; /*nx, ny ,nz : number of mesh nodes in the x,y and z direction*/
1099 int *iTab;
1100 double fac;
1101 double xu, yu, zu, xui, xuij, yuj;
1102 double vux, vuy, vuz, s;
1103 double vxnu, vynu, vznu, v;
1104 double orthoBox[6]; /* inverse length of the box*/
1105 double dBox[6]; /*step of the mesh*/
1106 GArray *points;
1107 VisuSurfacePoint at;
1108 double val1, val2;
1109 VisuBox *box;
1110 double scalarBox[VISU_BOX_N_VECTORS]; /*define the box edges and topology*/
1111 gboolean per[3], status;
1112 float scalarShift[3];
1113
1114 /* Routine code*/
1115
1116 /* Ensure that the pointer is not zero */
1117 g_return_val_if_fail(surf, FALSE);
1118
1119 /* edges are labelled from each corner:
1120 x+ then z+ then y+
1121 for k varying fastest
1122 then j varying fastest
1123 then i varying fastest
1124 */
1125
1126 /* Get data from the field. */
1127 box = visu_boxed_getBox(VISU_BOXED(field));
1128 for (i = 0; i < VISU_BOX_N_VECTORS; i++)
1129 scalarBox[i] = visu_box_getGeometry(box, i);
1130 visu_box_getPeriodicity(box, per);
1131 visu_scalar_field_getGridSize(field, scalarGrid);
1132 visu_pointset_getTranslation(VISU_POINTSET(field), scalarShift);
1133
1134 DBG_fprintf(stderr, "Pot2surf : compute isosurface at value %g from"
1135 " field %p.\n", isoValue, (gpointer)field);
1136 DBG_fprintf(stderr, " | periodic %d, %d, %d.\n", per[0], per[1], per[2]);
1137 DBG_fprintf(stderr, " | value %g.\n", isoValue);
1138 DBG_fprintf(stderr, " | size %d %d %d.\n", scalarGrid[0],
1139 scalarGrid[1], scalarGrid[2]);
1140 DBG_fprintf(stderr, " | box %g %g %g\n", scalarBox[0],
1141 scalarBox[1], scalarBox[2]);
1142 DBG_fprintf(stderr, " | %g %g %g.\n", scalarBox[3],
1143 scalarBox[4], scalarBox[5]);
1144 DBG_fprintf(stderr, " | shift %g %g %g\n", scalarShift[0],
1145 scalarShift[1], scalarShift[2]);
1146
1147 /* Compute some local values. */
1148 if (per[0])
1149 scalarGrid[0] += 1;
1150 if (per[1])
1151 scalarGrid[1] += 1;
1152 if (per[2])
1153 scalarGrid[2] += 1;
1154 for (i = 0; i < 3; i++)
1155 sizem1[i] = scalarGrid[i] - 1;
1156 v = scalarBox[0] * scalarBox[2] * scalarBox[5]; /* volume of the box = Lx*Ly*Lz */
1157 orthoBox[0] = scalarBox[2] * scalarBox[5] / v; /* 1/Lx */
1158 orthoBox[1] = -scalarBox[1] * scalarBox[5] / v;
1159 orthoBox[2] = scalarBox[0] * scalarBox[5] / v; /* 1/Ly */
1160 orthoBox[3] = (scalarBox[1] * scalarBox[4] - scalarBox[2] * scalarBox[3]) / v;
1161 orthoBox[4] = -scalarBox[0] * scalarBox[4] / v;
1162 orthoBox[5] = scalarBox[0] * scalarBox[2] / v; /* 1/Lz */
1163 dBox[0] = scalarBox[0] / sizem1[0];
1164 dBox[1] = scalarBox[1] / sizem1[1];
1165 dBox[2] = scalarBox[2] / sizem1[1];
1166 dBox[3] = scalarBox[3] / sizem1[2];
1167 dBox[4] = scalarBox[4] / sizem1[2];
1168 dBox[5] = scalarBox[5] / sizem1[2];
1169 nelez3 = 3 * scalarGrid[2];
1170 neleyz3 = scalarGrid[1] * nelez3;
1171 nelexyz3 = scalarGrid[0] * neleyz3; /* 3*nx*ny*nz */
1172
1173 /* Allocate buffers. */
1174 points = g_array_sized_new(FALSE, FALSE, sizeof(VisuSurfacePoint), nelexyz3 / 10);
1175 /* Indexes. */
1176 iTab = g_malloc(nelexyz3 * sizeof(int));
1177
1178 n = 0;
1179 for(i=0; i<scalarGrid[0]; i++) {
1180 xui = i*dBox[0];
1181 for(j=0; j<scalarGrid[1]; j++) {
1182 xuij = xui+j*dBox[1];
1183 yuj = j*dBox[2];
1184 for(k=0; k<scalarGrid[2]; k++) {
1185 xu = xuij+k*dBox[3] - scalarShift[0];
1186 yu = yuj+k*dBox[4] - scalarShift[1];
1187 zu = k*dBox[5] - scalarShift[2]; /* xu,yu,zu coordinate in the mesh corresponding to index i,j,k */
1188 vxnu = visu_scalar_field_getGradAt(field, i, j, k, TOOL_XYZ_X);
1189 vynu = visu_scalar_field_getGradAt(field, i, j, k, TOOL_XYZ_Y);
1190 vznu = visu_scalar_field_getGradAt(field, i, j, k, TOOL_XYZ_Z);
1191 val1 = visu_scalar_field_getAt(field, i, j, k); /* v(i,j,k) */
1192 if(i<sizem1[0]) {
1193 val2 = visu_scalar_field_getAt(field, i + 1, j, k); /* v(i+1,j,k)*/
1194 if((isoValue - val1 < 0.0 && isoValue - val2 >= 0.0) ||
1195 (isoValue - val1 >= 0.0 && isoValue - val2 < 0.0)) {
1196 fac = (isoValue - val1) / (val2 - val1);
1197 iTab[n] = points->len;
1198 at.at[0] = xu + fac*dBox[0]; /* surface intersection
1199 coordinates*/
1200 at.at[1] = yu;
1201 at.at[2] = zu;
1202 vux = vxnu + fac*(visu_scalar_field_getGradAt(field, i+1, j, k, TOOL_XYZ_X) - vxnu);
1203 vuy = vynu + fac*(visu_scalar_field_getGradAt(field, i+1, j, k, TOOL_XYZ_Y) - vynu);
1204 vuz = vznu + fac*(visu_scalar_field_getGradAt(field, i+1, j, k, TOOL_XYZ_Z) - vznu);
1205 vux = vux*orthoBox[0]+vuy*orthoBox[1]+vuz*orthoBox[3];
1206 vuy = vuy*orthoBox[2]+vuz*orthoBox[4];
1207 vuz = vuz*orthoBox[5];
1208 s = sqrt(vux*vux+vuy*vuy+vuz*vuz);
1209 _setNormal(at.normal, s, vux, vuy, vuz);
1210 g_array_append_val(points, at);
1211 }
1212 else {
1213 iTab[n] = -1;
1214 }
1215 }
1216 else {
1217 iTab[n] = -1;
1218 }
1219 n++;
1220 if(k<sizem1[2]) {
1221 val2 = visu_scalar_field_getAt(field, i, j, k + 1);
1222 if((isoValue - val1 < 0.0 && isoValue - val2 >= 0.0) ||
1223 (isoValue - val1 >= 0.0 && isoValue - val2 < 0.0)) {
1224 fac = (isoValue - val1) / (val2 - val1);
1225 iTab[n] = points->len;
1226 at.at[0] = xu + fac*dBox[3];
1227 at.at[1] = yu + fac*dBox[4];
1228 at.at[2] = zu + fac*dBox[5];
1229 vux = vxnu + fac*(visu_scalar_field_getGradAt(field, i, j, k+1, TOOL_XYZ_X) - vxnu);
1230 vuy = vynu + fac*(visu_scalar_field_getGradAt(field, i, j, k+1, TOOL_XYZ_Y) - vynu);
1231 vuz = vznu + fac*(visu_scalar_field_getGradAt(field, i, j, k+1, TOOL_XYZ_Z) - vznu);
1232 vux = vux*orthoBox[0]+vuy*orthoBox[1]+vuz*orthoBox[3];
1233 vuy = vuy*orthoBox[2]+vuz*orthoBox[4];
1234 vuz = vuz*orthoBox[5];
1235 s = sqrt(vux*vux+vuy*vuy+vuz*vuz);
1236 _setNormal(at.normal, s, vux, vuy, vuz);
1237 g_array_append_val(points, at);
1238 }
1239 else {
1240 iTab[n] = -1;
1241 }
1242 }
1243 else {
1244 iTab[n] = -1;
1245 }
1246 n++;
1247 if(j<sizem1[1]) {
1248 val2 = visu_scalar_field_getAt(field, i, j + 1, k);
1249 if((isoValue - val1 < 0.0 && isoValue - val2 >= 0.0) ||
1250 (isoValue - val1 >= 0.0 && isoValue - val2 < 0.0)) {
1251 fac = (isoValue - val1) / (val2 - val1);
1252 iTab[n] = points->len;
1253 at.at[0] = xu + fac*dBox[1];
1254 at.at[1] = yu + fac*dBox[2];
1255 at.at[2] = zu;
1256 vux = vxnu + fac*(visu_scalar_field_getGradAt(field, i, j+1, k, TOOL_XYZ_X) - vxnu);
1257 vuy = vynu + fac*(visu_scalar_field_getGradAt(field, i, j+1, k, TOOL_XYZ_Y) - vynu);
1258 vuz = vznu + fac*(visu_scalar_field_getGradAt(field, i, j+1, k, TOOL_XYZ_Z) - vznu);
1259 vux = vux*orthoBox[0]+vuy*orthoBox[1]+vuz*orthoBox[3];
1260 vuy = vuy*orthoBox[2]+vuz*orthoBox[4];
1261 vuz = vuz*orthoBox[5];
1262 s = sqrt(vux*vux+vuy*vuy+vuz*vuz);
1263 _setNormal(at.normal, s, vux, vuy, vuz);
1264 g_array_append_val(points, at);
1265 }
1266 else {
1267 iTab[n] = -1;
1268 }
1269 }
1270 else {
1271 iTab[n] = -1;
1272 }
1273 n++;
1274 }
1275 }
1276 }
1277 DBG_fprintf(stderr, " | found %d points.\n", points->len);
1278
1279 if (points->len == 0)
1280 {
1281 g_warning("no isosurface found.");
1282 g_array_unref(points);
1283 g_free(iTab);
1284 return FALSE;
1285 }
1286 status = Create_surf(nelez3, neleyz3, nelexyz3, sizem1, iTab,
1287 points, isoValue, field, scalarBox, name, surf);
1288
1289 DBG_fprintf(stderr, " | Surface successfully created.\n");
1290
1291 return status;
1292 }
1293
1294
1295 /**
1296 * create_fromSF_nonuniform:
1297 * @surf: a location on a #VisuSurface pointer ;
1298 * @field: the scalar field to create the surface from ;
1299 * @isoValue: the value of the isosurface ;
1300 * @id: an integer identifying the surface ;
1301 * @name: the name of the surface to use (can be NULL).
1302 *
1303 * Create on the fly a surface from the scalar field @field. If @name is given, the surface
1304 * is created with it, if not, "Isosurface @id + 1" is used. @surf can already
1305 * contains several surfaces, in that case, the new surface is added. If @surf is
1306 * NULL, then a new #VisuSurface object is created and returned.
1307 *
1308 * Returns: TRUE if the surface is created.
1309 */
1310
create_fromSF_nonuniform(VisuSurface ** surf,const VisuScalarField * field,double isoValue,const gchar * name)1311 static gboolean create_fromSF_nonuniform(VisuSurface **surf, const VisuScalarField *field,
1312 double isoValue, const gchar *name)
1313 {
1314
1315 /* I label local cell vertices as in ref. above
1316 and assigns x y z names like this :
1317
1318 y
1319 |
1320
1321 4---------------5
1322 /. /|
1323 7---------------6 |
1324 | . | |
1325 | . | |
1326 | 0.............|.1 --x
1327 |/ |/
1328 3---------------2
1329
1330 /
1331 z
1332
1333 */
1334
1335 /* Local variables */
1336
1337 register guint i, j, k;
1338 int n;
1339 int nelez3, neleyz3, nelexyz3;
1340 guint sizem1[3]; /*nx-1, ny-1 ,nz-1 : number of mesh intervals in the x,y and z direction*/
1341 guint scalarGrid[3]; /*nx, ny ,nz : number of mesh nodes in the x,y and z direction*/
1342 int *iTab;
1343 double fac;
1344 double xu, yu, zu, xui, xuij, yuj, dmesh;
1345 double vux, vuy, vuz, s;
1346 double vxnu, vynu, vznu, v;
1347 double orthoBox[6]; /* inverse length of the box*/
1348 GArray *points;
1349 VisuSurfacePoint at;
1350 double *meshx, *meshy, *meshz;
1351 double val1, val2;
1352 VisuBox *box;
1353 double scalarBox[6]; /*define the box edges and topology*/
1354 gboolean per[3], status;
1355
1356 /* Routine code*/
1357
1358 /* Ensure that the pointer is not zero */
1359 g_return_val_if_fail(surf, FALSE);
1360
1361 /* edges are labelled from each corner:
1362 x+ then z+ then y+
1363 for k varying fastest
1364 then j varying fastest
1365 then i varying fastest
1366 */
1367
1368 /* Get data from the field. */
1369 box = visu_boxed_getBox(VISU_BOXED(field));
1370 for (i = 0; i < VISU_BOX_N_VECTORS; i++)
1371 scalarBox[i] = visu_box_getGeometry(box, i);
1372 visu_box_getPeriodicity(box, per);
1373 meshx = visu_scalar_field_getMesh(field, TOOL_XYZ_X);
1374 meshy = visu_scalar_field_getMesh(field, TOOL_XYZ_Y);
1375 meshz = visu_scalar_field_getMesh(field, TOOL_XYZ_Z);
1376 visu_scalar_field_getGridSize(field, scalarGrid);
1377
1378 DBG_fprintf(stderr, "Pot2surf : compute isosurface at value %g from"
1379 " field %p.\n", isoValue, (gpointer)field);
1380 DBG_fprintf(stderr, " | periodic %d, %d, %d.\n", per[0], per[1], per[2]);
1381 DBG_fprintf(stderr, " | value %g.\n", isoValue);
1382 DBG_fprintf(stderr, " | size %d %d %d.\n", scalarGrid[0],
1383 scalarGrid[1], scalarGrid[2]);
1384 DBG_fprintf(stderr, " | box %g %g %g\n", scalarBox[0],
1385 scalarBox[1], scalarBox[2]);
1386 DBG_fprintf(stderr, " | %g %g %g.\n", scalarBox[3],
1387 scalarBox[4], scalarBox[5]);
1388
1389 /* Compute some local values. */
1390 if (per[0])
1391 scalarGrid[0] += 1;
1392 if (per[1])
1393 scalarGrid[1] += 1;
1394 if (per[2])
1395 scalarGrid[2] += 1;
1396 for (i = 0; i < 3; i++)
1397 sizem1[i] = scalarGrid[i] - 1;
1398 v = scalarBox[0] * scalarBox[2] * scalarBox[5]; /* volume of the box = Lx*Ly*Lz */
1399 orthoBox[0] = scalarBox[2] * scalarBox[5] / v; /* 1/Lx */
1400 orthoBox[1] = -scalarBox[1] * scalarBox[5] / v;
1401 orthoBox[2] = scalarBox[0] * scalarBox[5] / v; /* 1/Ly */
1402 orthoBox[3] = (scalarBox[1] * scalarBox[4] - scalarBox[2] * scalarBox[3]) / v;
1403 orthoBox[4] = -scalarBox[0] * scalarBox[4] / v;
1404 orthoBox[5] = scalarBox[0] * scalarBox[2] / v; /* 1/Lz */
1405 nelez3 = 3 * scalarGrid[2];
1406 neleyz3 = scalarGrid[1] * nelez3;
1407 nelexyz3 = scalarGrid[0] * neleyz3; /* 3*nx*ny*nz */
1408
1409 /* Allocate buffers. */
1410 points = g_array_sized_new(FALSE, FALSE, sizeof(VisuSurfacePoint), nelexyz3 / 10);
1411 /* Indexes. */
1412 iTab = g_malloc(nelexyz3 * sizeof(int));
1413
1414 n = 0;
1415 for(i=0; i<scalarGrid[0]; i++) {
1416 xui = ((per[0] && i == sizem1[0])?1.:meshx[i]) * scalarBox[0];
1417 for(j=0; j<scalarGrid[1]; j++) {
1418 xuij = xui + ((per[1] && j == sizem1[1])?1.:meshy[j]) * scalarBox[1];
1419 yuj = ((per[1] && j == sizem1[1])?1.:meshy[j]) * scalarBox[2];
1420 for(k=0; k<scalarGrid[2]; k++) {
1421 xu = xuij + ((per[2] && k == sizem1[2])?1.:meshz[k]) * scalarBox[3];
1422 yu = yuj + ((per[2] && k == sizem1[2])?1.:meshz[k]) * scalarBox[4];
1423 zu = ((per[2] && k == sizem1[2])?1.:meshz[k]) * scalarBox[5];
1424 /* xu ,yu ,zu coordinate in the mesh corresponding to index i ,j ,k */
1425 vxnu = visu_scalar_field_getGradAt(field, i, j, k, TOOL_XYZ_X);
1426 vynu = visu_scalar_field_getGradAt(field, i, j, k, TOOL_XYZ_Y);
1427 vznu = visu_scalar_field_getGradAt(field, i, j, k, TOOL_XYZ_Z);
1428 val1 = visu_scalar_field_getAt(field, i, j, k); /* v(i,j,k) */
1429 if(i<sizem1[0]) {
1430 val2 = visu_scalar_field_getAt(field, i + 1, j, k); /* v(i+1,j,k)*/
1431 if((isoValue - val1 < 0.0 && isoValue - val2 >= 0.0) ||
1432 (isoValue - val1 >= 0.0 && isoValue - val2 < 0.0)) {
1433 fac = (isoValue - val1) / (val2 - val1);
1434 iTab[n] = points->len;
1435 dmesh = getDeltaMesh(i, meshx, sizem1[0], per[0]);
1436 at.at[0] = xu + fac * dmesh * scalarBox[0];
1437 at.at[1] = yu;
1438 at.at[2] = zu;
1439 vux = vxnu + fac*(visu_scalar_field_getGradAt(field, i+1, j, k, TOOL_XYZ_X) - vxnu);
1440 vuy = vynu + fac*(visu_scalar_field_getGradAt(field, i+1, j, k, TOOL_XYZ_Y) - vynu);
1441 vuz = vznu + fac*(visu_scalar_field_getGradAt(field, i+1, j, k, TOOL_XYZ_Z) - vznu);
1442 vux = vux*orthoBox[0]+vuy*orthoBox[1]+vuz*orthoBox[3];
1443 vuy = vuy*orthoBox[2]+vuz*orthoBox[4];
1444 vuz = vuz*orthoBox[5];
1445 s = sqrt(vux*vux+vuy*vuy+vuz*vuz);
1446 _setNormal(at.normal, s, vux, vuy, vuz);
1447 g_array_append_val(points, at);
1448 }
1449 else {
1450 iTab[n] = -1;
1451 }
1452 }
1453 else {
1454 iTab[n] = -1;
1455 }
1456 n++;
1457 if(k<sizem1[2]) {
1458 val2 = visu_scalar_field_getAt(field, i, j, k + 1);
1459 if((isoValue - val1 < 0.0 && isoValue - val2 >= 0.0) ||
1460 (isoValue - val1 >= 0.0 && isoValue - val2 < 0.0)) {
1461 fac = (isoValue - val1) / (val2 - val1);
1462 iTab[n] = points->len;
1463 dmesh = getDeltaMesh(k, meshz, sizem1[2], per[2]);
1464 at.at[0] = xu + fac * dmesh * scalarBox[3];
1465 at.at[1] = yu + fac * dmesh * scalarBox[4];
1466 at.at[2] = zu + fac * dmesh * scalarBox[5];
1467 vux = vxnu + fac*(visu_scalar_field_getGradAt(field, i, j, k+1, TOOL_XYZ_X) - vxnu);
1468 vuy = vynu + fac*(visu_scalar_field_getGradAt(field, i, j, k+1, TOOL_XYZ_Y) - vynu);
1469 vuz = vznu + fac*(visu_scalar_field_getGradAt(field, i, j, k+1, TOOL_XYZ_Z) - vznu);
1470 vux = vux*orthoBox[0]+vuy*orthoBox[1]+vuz*orthoBox[3];
1471 vuy = vuy*orthoBox[2]+vuz*orthoBox[4];
1472 vuz = vuz*orthoBox[5];
1473 s = sqrt(vux*vux+vuy*vuy+vuz*vuz);
1474 _setNormal(at.normal, s, vux, vuy, vuz);
1475 g_array_append_val(points, at);
1476 }
1477 else {
1478 iTab[n] = -1;
1479 }
1480 }
1481 else {
1482 iTab[n] = -1;
1483 }
1484 n++;
1485 if(j<sizem1[1]) {
1486 val2 = visu_scalar_field_getAt(field, i, j + 1, k);
1487 if((isoValue - val1 < 0.0 && isoValue - val2 >= 0.0) ||
1488 (isoValue - val1 >= 0.0 && isoValue - val2 < 0.0)) {
1489 fac = (isoValue - val1) / (val2 - val1);
1490 iTab[n] = points->len;
1491 dmesh = getDeltaMesh(j, meshy, sizem1[1], per[1]);
1492 at.at[0] = xu + fac * dmesh * scalarBox[1];
1493 at.at[1] = yu + fac * dmesh * scalarBox[2];
1494 at.at[2] = zu;
1495 vux = vxnu + fac*(visu_scalar_field_getGradAt(field, i, j+1, k, TOOL_XYZ_X) - vxnu);
1496 vuy = vynu + fac*(visu_scalar_field_getGradAt(field, i, j+1, k, TOOL_XYZ_Y) - vynu);
1497 vuz = vznu + fac*(visu_scalar_field_getGradAt(field, i, j+1, k, TOOL_XYZ_Z) - vznu);
1498 vux = vux*orthoBox[0]+vuy*orthoBox[1]+vuz*orthoBox[3];
1499 vuy = vuy*orthoBox[2]+vuz*orthoBox[4];
1500 vuz = vuz*orthoBox[5];
1501 s = sqrt(vux*vux+vuy*vuy+vuz*vuz);
1502 _setNormal(at.normal, s, vux, vuy, vuz);
1503 g_array_append_val(points, at);
1504 }
1505 else {
1506 iTab[n] = -1;
1507 }
1508 }
1509 else {
1510 iTab[n] = -1;
1511 }
1512 n++;
1513 }
1514 }
1515 }
1516 DBG_fprintf(stderr, " | found %d points.\n", points->len);
1517
1518 if (points->len == 0)
1519 {
1520 g_warning("no isosurface found.");
1521 g_array_unref(points);
1522 g_free(iTab);
1523 return FALSE;
1524 }
1525 status = Create_surf(nelez3, neleyz3, nelexyz3, sizem1, iTab,
1526 points, isoValue, field, scalarBox, name, surf);
1527
1528 DBG_fprintf(stderr, " | Surface successfully created.\n");
1529
1530 return status;
1531 }
1532
1533 /**
1534 * Create_surf:
1535 * @id: an integer identifying the surface ;
1536 * @nelez3: an integer giving the number of element times 3 along z;
1537 * @neleyz3: an integer giving the number of element times 3 in plane y by z;
1538 * @nelexyz3: an integer giving the number of element times 3 in volume x by y by z;
1539 * @nPoints: an integer giving the number points of the surface;
1540 * @sizem1: the number of intervals in each direction;
1541 * @iTab: table containing the number of surface points if surface exists at this place otherwise -1;
1542 * @xsurf: x coordinate of the surface points;
1543 * @ysurf: y coordinate of the surface points;
1544 * @zsurf: z coordinate of the surface points;
1545 * @xnsurf: normal value of the surface points;
1546 * @ynsurf: normal of the surface points;
1547 * @znsurf: normal of the surface points;
1548 * @isoValue: the value of the isosurface;
1549 * @scalarData: the potential values;
1550 * @scalarBox: the box parameters;
1551 * @name: the name of the surface to use (can be NULL).
1552 * @per: boolean for periodicity;
1553 * @surf: a location on a #VisuSurface pointer ;
1554 *
1555 * Create on the fly a surface from the scalar field @field. If @name is given, the surface
1556 * is created with it, if not, "Isosurface @id + 1" is used. @surf can already
1557 * contains several surfaces, in that case, the new surface is added. If @surf is
1558 * NULL, then a new #VisuSurface object is created and returned.
1559 *
1560 * Returns: TRUE if the surface is created.
1561 */
1562
Create_surf(int nelez3,int neleyz3,int nelexyz3 _U_,guint sizem1[3],int * iTab,GArray * points,double isoValue,const VisuScalarField * field,double scalarBox[6],const gchar * name,VisuSurface ** surf)1563 static gboolean Create_surf(int nelez3, int neleyz3, int nelexyz3 _U_,
1564 guint sizem1[3], int *iTab, GArray *points,
1565 double isoValue, const VisuScalarField *field, double scalarBox[6],
1566 const gchar *name, VisuSurface **surf)
1567 {
1568
1569 /* Local variables */
1570
1571 register guint i, j, k;
1572 int cubeindex;
1573 int e, n;
1574 int m1, m2, m3;
1575 int vertlist[12];
1576 GArray *vTab;
1577 VisuSurfacePoly poly;
1578 VisuSurfacePoint *at1, *at2, *at3;
1579 double vx, vy, vz, wx, wy, wz;
1580 double ux, uy, uz, s;
1581 float* densityData;
1582 VisuBox *box;
1583
1584 /* Routine code */
1585
1586 /* Ensure that the pointer is not zero */
1587 g_return_val_if_fail(surf, FALSE);
1588
1589 /* Allocate buffers. The 16 coefficient is for the maximum number of
1590 polygons per grid points. */
1591 vTab = g_array_sized_new(FALSE, FALSE, sizeof(VisuSurfacePoly), points->len / 3);
1592 poly.nvertices = 3;
1593
1594 /* Main loop */
1595 for(i=0; i<sizem1[0]; i++) {
1596 for(j=0; j<sizem1[1]; j++) {
1597 for(k=0; k<sizem1[2]; k++) {
1598 cubeindex = 0;
1599 if (visu_scalar_field_getAt(field, i , j , k ) <= isoValue) cubeindex |= 1;
1600 if (visu_scalar_field_getAt(field, i+1, j , k ) <= isoValue) cubeindex |= 2;
1601 if (visu_scalar_field_getAt(field, i+1, j , k+1) <= isoValue) cubeindex |= 4;
1602 if (visu_scalar_field_getAt(field, i , j , k+1) <= isoValue) cubeindex |= 8;
1603 if (visu_scalar_field_getAt(field, i , j+1, k ) <= isoValue) cubeindex |= 16;
1604 if (visu_scalar_field_getAt(field, i+1, j+1, k ) <= isoValue) cubeindex |= 32;
1605 if (visu_scalar_field_getAt(field, i+1, j+1, k+1) <= isoValue) cubeindex |= 64;
1606 if (visu_scalar_field_getAt(field, i , j+1, k+1) <= isoValue) cubeindex |= 128;
1607
1608 e = edgeTable[cubeindex];
1609
1610 if (e == 0) continue;
1611
1612 n = i*neleyz3+j*nelez3+k*3;
1613
1614 if (e & 1 ) vertlist[0 ] = iTab[n];
1615 if (e & 2 ) vertlist[1 ] = iTab[n + neleyz3 + 1];
1616 if (e & 4 ) vertlist[2 ] = iTab[n + 3];
1617 if (e & 8 ) vertlist[3 ] = iTab[n + 1];
1618 if (e & 16 ) vertlist[4 ] = iTab[n + nelez3];
1619 if (e & 32 ) vertlist[5 ] = iTab[n + neleyz3 + 1 + nelez3];
1620 if (e & 64 ) vertlist[6 ] = iTab[n + 3 + nelez3];
1621 if (e & 128 ) vertlist[7 ] = iTab[n + 1 + nelez3];
1622 if (e & 256 ) vertlist[8 ] = iTab[n + 2];
1623 if (e & 512 ) vertlist[9 ] = iTab[n + neleyz3 + 2];
1624 if (e & 1024) vertlist[10] = iTab[n + neleyz3 + 3 + 2];
1625 if (e & 2048) vertlist[11] = iTab[n + 3 + 2];
1626
1627 for (n = 0; triTable[cubeindex][n]!= -1; n += 3) {
1628 m1 = vertlist[triTable[cubeindex][n ]];
1629 if(m1 == -1)
1630 {
1631 g_warning("m1 %d %d %d.", i, j, k);
1632 g_array_unref(points);
1633 g_free(iTab);
1634 g_array_unref(vTab);
1635 return FALSE;
1636 }
1637 m2 = vertlist[triTable[cubeindex][n+1]];
1638 if(m2 == -1)
1639 {
1640 g_warning("m2 %d %d %d.", i, j, k);
1641 g_array_unref(points);
1642 g_free(iTab);
1643 g_array_unref(vTab);
1644 return FALSE;
1645 }
1646 m3 = vertlist[triTable[cubeindex][n+2]];
1647 if(m3 == -1)
1648 {
1649 g_warning("m3 %d %d %d.", i, j, k);
1650 g_array_unref(points);
1651 g_free(iTab);
1652 g_array_unref(vTab);
1653 return FALSE;
1654 }
1655 at1 = &g_array_index(points, VisuSurfacePoint, m1);
1656 at2 = &g_array_index(points, VisuSurfacePoint, m2);
1657 at3 = &g_array_index(points, VisuSurfacePoint, m3);
1658 ux = at2->at[0] - at1->at[0];
1659 uy = at2->at[1] - at1->at[1];
1660 uz = at2->at[2] - at1->at[2];
1661 vx = at3->at[0] - at1->at[0];
1662 vy = at3->at[1] - at1->at[1];
1663 vz = at3->at[2] - at1->at[2];
1664 wx = uy*vz-uz*vy;
1665 wy = uz*vx-ux*vz;
1666 wz = ux*vy-uy*vx;
1667 s = sqrt(wx*wx+wy*wy+wz*wz);
1668 if(s <= 0.0) continue;
1669 poly.indices[0] = m1;
1670 poly.indices[1] = m2;
1671 poly.indices[2] = m3;
1672 g_array_append_val(vTab, poly);
1673 }
1674 }
1675 }
1676 }
1677 DBG_fprintf(stderr, " | found %d polygons.\n", vTab->len);
1678
1679 if (vTab->len == 0)
1680 {
1681 g_warning("no isosurface found.");
1682 g_array_unref(points);
1683 g_free(iTab);
1684 g_array_unref(vTab);
1685 return FALSE;
1686 }
1687
1688 /* Ok, try to create a VisuSurface object from here. */
1689 g_return_val_if_fail(*surf == (VisuSurface*)0, FALSE);
1690
1691 DBG_fprintf(stderr, " | create new VisuSurface.\n");
1692 *surf = visu_surface_new(name, points, vTab);
1693 box = visu_box_new(scalarBox, VISU_BOX_PERIODIC);
1694 visu_boxed_setBox(VISU_BOXED(*surf), VISU_BOXED(box));
1695 g_object_unref(box);
1696 densityData = visu_surface_addPropertyFloat(*surf, VISU_SURFACE_PROPERTY_POTENTIAL);
1697 densityData[0] = isoValue;
1698
1699 #if DEBUG == 1
1700 visu_surface_checkConsistency(*surf);
1701 #endif
1702
1703 g_array_unref(points);
1704 g_array_unref(vTab);
1705 g_free(iTab);
1706 return TRUE;
1707 }
1708
1709
1710 /*****************************/
1711 /* XML files for iso-values. */
1712 /*****************************/
1713
1714 /*
1715 <surfaces>
1716 <surface rendered="yes" iso-value="0.45" name="foo">
1717 <hidden-by-planes status="yes" />
1718 <color rgba="0.5 0.5 0.5 1." material="0.2 1. 0.5 0.5 0." />
1719 </surface>
1720 </surfaces>
1721 */
1722
1723 /* Known elements. */
1724 #define SURF_PARSER_ELEMENT_SURFACES "surfaces"
1725 #define SURF_PARSER_ELEMENT_SURFACE "surface"
1726 #define SURF_PARSER_ELEMENT_HIDE "hidden-by-planes"
1727 #define SURF_PARSER_ELEMENT_COLOR "color"
1728 /* Known attributes. */
1729 #define SURF_PARSER_ATTRIBUTES_RENDERED "rendered"
1730 #define SURF_PARSER_ATTRIBUTES_VALUE "iso-value"
1731 #define SURF_PARSER_ATTRIBUTES_NAME "name"
1732 #define SURF_PARSER_ATTRIBUTES_STATUS "status"
1733 #define SURF_PARSER_ATTRIBUTES_RGBA "rgba"
1734 #define SURF_PARSER_ATTRIBUTES_MATERIAL "material"
1735
1736 struct _surfaces_xml
1737 {
1738 gchar *name;
1739 float iso;
1740 gboolean rendered, masked;
1741 gboolean colorSet, materialSet;
1742 float color[4], material[5];
1743 };
1744
1745 static gboolean startVisuSurface;
1746
1747 /* This method is called for every element that is parsed.
1748 The user_data must be a GList of _surfaces_xml. When a 'surface'
1749 element, a new struct instance is created and prepend in the list.
1750 When 'hidden-by-planes' or other qualificative elements are
1751 found, the first surface of the list is modified accordingly. */
surfacesXML_element(GMarkupParseContext * context _U_,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,gpointer user_data,GError ** error)1752 static void surfacesXML_element(GMarkupParseContext *context _U_,
1753 const gchar *element_name,
1754 const gchar **attribute_names,
1755 const gchar **attribute_values,
1756 gpointer user_data,
1757 GError **error)
1758 {
1759 GList **surfacesList;
1760 struct _surfaces_xml *surf;
1761 int i;
1762
1763 g_return_if_fail(user_data);
1764 surfacesList = (GList **)user_data;
1765
1766 DBG_fprintf(stderr, "Surf parser: found '%s' element.\n", element_name);
1767 if (!strcmp(element_name, SURF_PARSER_ELEMENT_SURFACES))
1768 {
1769 /* Should have no attributes. */
1770 if (attribute_names[0])
1771 {
1772 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
1773 _("Unexpected attribute '%s' for element '%s'."),
1774 attribute_names[0], SURF_PARSER_ELEMENT_SURFACES);
1775 return;
1776 }
1777 /* Initialise the surfacesList. */
1778 if (*surfacesList)
1779 {
1780 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
1781 _("DTD error: element '%s' should appear only once."),
1782 SURF_PARSER_ELEMENT_SURFACES);
1783 return;
1784 }
1785 *surfacesList = (GList*)0;
1786 startVisuSurface = TRUE;
1787 }
1788 else if (!strcmp(element_name, SURF_PARSER_ELEMENT_SURFACE))
1789 {
1790 surf = g_malloc(sizeof(struct _surfaces_xml));
1791 surf->name = (gchar*)0;
1792 surf->rendered = TRUE;
1793 surf->masked = TRUE;
1794 surf->iso = 12345.6789f;
1795 surf->colorSet = FALSE;
1796 surf->materialSet = FALSE;
1797
1798 /* We parse the attributes. */
1799 for (i = 0; attribute_names[i]; i++)
1800 {
1801 if (!strcmp(attribute_names[i], SURF_PARSER_ATTRIBUTES_NAME))
1802 surf->name = g_strdup(attribute_values[i]);
1803 else if (!strcmp(attribute_names[i], SURF_PARSER_ATTRIBUTES_RENDERED))
1804 {
1805 if (!strcmp(attribute_values[i], "yes"))
1806 surf->rendered = TRUE;
1807 else if (!strcmp(attribute_values[i], "no"))
1808 surf->rendered = FALSE;
1809 else
1810 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1811 _("Invalid value '%s' for attribute '%s'."),
1812 attribute_values[i], SURF_PARSER_ATTRIBUTES_RENDERED);
1813 }
1814 else if (!strcmp(attribute_names[i], SURF_PARSER_ATTRIBUTES_VALUE))
1815 {
1816 if (!(sscanf(attribute_values[i], "%f", &surf->iso) == 1))
1817 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1818 _("Invalid value '%s' for attribute '%s'."),
1819 attribute_values[i], SURF_PARSER_ATTRIBUTES_VALUE);
1820 }
1821 else
1822 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
1823 _("Unexpected attribute '%s' for element '%s'."),
1824 attribute_names[i], SURF_PARSER_ELEMENT_SURFACE);
1825 if (*error)
1826 {
1827 g_free(surf->name);
1828 g_free(surf);
1829 return;
1830 }
1831 }
1832 /* We check the mandatory attribute. */
1833 if (surf->iso == 12345.6789f)
1834 {
1835 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
1836 _("Missing attribute '%s' for element '%s'."),
1837 SURF_PARSER_ATTRIBUTES_VALUE, SURF_PARSER_ELEMENT_SURFACE);
1838 g_free(surf->name);
1839 g_free(surf);
1840 return;
1841 }
1842 DBG_fprintf(stderr, "Surf parser: add a new surface '%s' %f %d.\n",
1843 (surf->name)?surf->name:"None", surf->iso, surf->rendered);
1844 *surfacesList = g_list_prepend(*surfacesList, (gpointer)surf);
1845 }
1846 else if (startVisuSurface && !strcmp(element_name, SURF_PARSER_ELEMENT_HIDE))
1847 {
1848 if (!*surfacesList)
1849 {
1850 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1851 _("DTD error: parent element '%s' of element '%s' is missing."),
1852 SURF_PARSER_ELEMENT_SURFACE, SURF_PARSER_ELEMENT_HIDE);
1853 return;
1854 }
1855 surf = (struct _surfaces_xml*)((*surfacesList)->data);
1856
1857 /* We read the mandatory attribute. */
1858 if (attribute_names[0])
1859 {
1860 if (!strcmp(attribute_names[0], SURF_PARSER_ATTRIBUTES_STATUS))
1861 {
1862 if (!strcmp(attribute_values[0], "yes"))
1863 surf->masked = TRUE;
1864 else if (!strcmp(attribute_values[0], "no"))
1865 surf->masked = FALSE;
1866 else
1867 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1868 _("Invalid value '%s' for attribute '%s'."),
1869 attribute_values[0], SURF_PARSER_ATTRIBUTES_STATUS);
1870 }
1871 else
1872 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
1873 _("Unexpected attribute '%s' for element '%s'."),
1874 attribute_names[0], SURF_PARSER_ELEMENT_HIDE);
1875 }
1876 else
1877 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
1878 _("Missing attribute '%s' for element '%s'."),
1879 SURF_PARSER_ATTRIBUTES_VALUE, SURF_PARSER_ELEMENT_SURFACE);
1880 if (*error)
1881 return;
1882
1883 }
1884 else if (startVisuSurface && !strcmp(element_name, SURF_PARSER_ELEMENT_COLOR))
1885 {
1886 if (!*surfacesList)
1887 {
1888 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1889 _("DTD error: parent element '%s' of element '%s' is missing."),
1890 SURF_PARSER_ELEMENT_SURFACE, SURF_PARSER_ELEMENT_COLOR);
1891 return;
1892 }
1893 surf = (struct _surfaces_xml*)((*surfacesList)->data);
1894
1895 for(i = 0; attribute_names[i]; i++)
1896 {
1897 if (!strcmp(attribute_names[i], SURF_PARSER_ATTRIBUTES_RGBA))
1898 {
1899 if (sscanf(attribute_values[i], "%g %g %g %g",
1900 surf->color, surf->color + 1,
1901 surf->color + 2, surf->color + 3) != 4)
1902 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1903 _("Invalid value '%s' for attribute '%s'."),
1904 attribute_values[i], SURF_PARSER_ATTRIBUTES_RGBA);
1905 else
1906 surf->colorSet = TRUE;
1907 }
1908 else if (!strcmp(attribute_names[i], SURF_PARSER_ATTRIBUTES_MATERIAL))
1909 {
1910 if (sscanf(attribute_values[i], "%g %g %g %g %g",
1911 surf->material, surf->material + 1, surf->material + 2,
1912 surf->material + 3, surf->material + 4) != 5)
1913 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1914 _("Invalid value '%s' for attribute '%s'."),
1915 attribute_values[i], SURF_PARSER_ATTRIBUTES_MATERIAL);
1916 else
1917 surf->materialSet = TRUE;
1918 }
1919 else
1920 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
1921 _("Unexpected attribute '%s' for element '%s'."),
1922 attribute_names[i], SURF_PARSER_ELEMENT_COLOR);
1923 if (*error)
1924 return;
1925 }
1926 }
1927 else if (startVisuSurface)
1928 {
1929 /* We silently ignore the element if surfacesList is unset, but
1930 raise an error if surfacesList has been set. */
1931 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
1932 _("Unexpected element '%s'."), element_name);
1933 }
1934 }
1935
1936 /* Check when a element is closed that everything required has been set. */
surfacesXML_end(GMarkupParseContext * context _U_,const gchar * element_name,gpointer user_data _U_,GError ** error _U_)1937 void surfacesXML_end(GMarkupParseContext *context _U_,
1938 const gchar *element_name,
1939 gpointer user_data _U_,
1940 GError **error _U_)
1941 {
1942 if (!strcmp(element_name, SURF_PARSER_ELEMENT_SURFACES))
1943 startVisuSurface = FALSE;
1944 }
1945
1946 /* What to do when an error is raised. */
surfacesXML_error(GMarkupParseContext * context _U_,GError * error,gpointer user_data)1947 static void surfacesXML_error(GMarkupParseContext *context _U_,
1948 GError *error,
1949 gpointer user_data)
1950 {
1951 GList *tmpLst;
1952
1953 DBG_fprintf(stderr, "Surf parser: error raised '%s'.\n", error->message);
1954 g_return_if_fail(user_data);
1955
1956 /* We free the current list of surfaces. */
1957 tmpLst = *(GList**)user_data;
1958 while (tmpLst)
1959 {
1960 g_free(((struct _surfaces_xml*)tmpLst->data)->name);
1961 g_free(tmpLst->data);
1962 tmpLst = g_list_next(tmpLst);
1963 }
1964 g_list_free(*(GList**)user_data);
1965 }
1966
1967 /**
1968 * visu_surface_parseXMLFile:
1969 * @filename: a path to a file.
1970 * @surfaces: (inout) (element-type VisuSurface*): a location on a
1971 * #VisuSurface pointer.
1972 * @field: the scalar field to create the surface from.
1973 * @error: a location to store a possible error.
1974 *
1975 * Parse the given XML file, looking for the <surfaces> tag and create
1976 * the given surfaces.
1977 *
1978 * Returns: FALSE if a error occured.
1979 */
visu_surface_parseXMLFile(const gchar * filename,GList ** surfaces,VisuScalarField * field,GError ** error)1980 gboolean visu_surface_parseXMLFile(const gchar* filename, GList **surfaces,
1981 VisuScalarField *field, GError **error)
1982 {
1983 GMarkupParseContext* xmlContext;
1984 GMarkupParser parser;
1985 gboolean status;
1986 gsize size;
1987 gchar *buffer;
1988 GList *list, *tmpLst;
1989 VisuSurface *surface;
1990 struct _surfaces_xml *surf;
1991 VisuSurfaceResource *res;
1992
1993 g_return_val_if_fail(filename && surfaces && field, FALSE);
1994
1995 buffer = (gchar*)0;
1996 if (!g_file_get_contents(filename, &buffer, &size, error))
1997 return FALSE;
1998
1999 /* Create context. */
2000 list = (GList*)0;
2001 parser.start_element = surfacesXML_element;
2002 parser.end_element = surfacesXML_end;
2003 parser.text = NULL;
2004 parser.passthrough = NULL;
2005 parser.error = surfacesXML_error;
2006 xmlContext = g_markup_parse_context_new(&parser, 0, &list, NULL);
2007
2008 /* Parse data. */
2009 startVisuSurface = FALSE;
2010 status = g_markup_parse_context_parse(xmlContext, buffer, size, error);
2011
2012 /* Free buffers. */
2013 g_markup_parse_context_free(xmlContext);
2014 g_free(buffer);
2015
2016 if (!status)
2017 return FALSE;
2018
2019 if (!list)
2020 {
2021 *error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY,
2022 _("No iso-value found."));
2023 return FALSE;
2024 }
2025
2026 /* Need to reverse the list since elements have been prepended. */
2027 list = g_list_reverse(list);
2028
2029 /* Convert the list to new isosurfaces. */
2030 DBG_fprintf(stderr, "Surf parser: create %d new surfaces for %p.\n",
2031 g_list_length(list), (gpointer)(*surfaces));
2032 tmpLst = list;
2033 while(tmpLst)
2034 {
2035 surf = (struct _surfaces_xml*)tmpLst->data;
2036 surface = visu_surface_new_fromScalarField(field, surf->iso, surf->name);
2037 if (surface)
2038 {
2039 res = visu_surface_getResource(surface);
2040 g_object_set(G_OBJECT(res), "rendered", surf->rendered,
2041 "maskable", surf->masked, NULL);
2042 if (surf->colorSet)
2043 g_object_set(G_OBJECT(res), "color", tool_color_addFloatRGBA(surf->color, NULL), NULL);
2044 if (surf->materialSet)
2045 g_object_set(G_OBJECT(res), "material", surf->material, NULL);
2046 *surfaces = g_list_append(*surfaces, surface);
2047 }
2048 g_free(surf->name);
2049 g_free(surf);
2050 tmpLst = g_list_next(tmpLst);
2051 }
2052 g_list_free(list);
2053
2054 return TRUE;
2055 }
2056
2057 /**
2058 * visu_surface_exportXMLFile:
2059 * @filename: a path to a file.
2060 * @values: an array of @n values.
2061 * @res: an array of @n #VisuSurfaceResource.
2062 * @n: number of surface resources to export.
2063 * @error: a location to store a possible error.
2064 *
2065 * Export the surface resources into an XML file.
2066 *
2067 * Returns: FALSE if a error occured.
2068 */
visu_surface_exportXMLFile(const gchar * filename,float * values,VisuSurfaceResource ** res,int n,GError ** error)2069 gboolean visu_surface_exportXMLFile(const gchar* filename, float *values,
2070 VisuSurfaceResource **res, int n, GError **error)
2071 {
2072 gboolean valid;
2073 GString *output;
2074 int i;
2075 gchar *lbl;
2076 gboolean rendered, maskable;
2077 ToolColor *color;
2078 float *mat;
2079
2080 /* We actually output the values. */
2081 output = g_string_new(" <surfaces>\n");
2082 for (i = 0; i < n; i++)
2083 {
2084 g_object_get(G_OBJECT(res[i]), "label", &lbl, "color", &color,
2085 "material", &mat, "rendered", &rendered,
2086 "maskable", &maskable, NULL);
2087 g_string_append_printf(output, " <surface rendered=\"%s\" iso-value=\"%g\"",
2088 (rendered)?"yes":"no", values[i]);
2089 if (lbl && lbl[0])
2090 g_string_append_printf(output, " name=\"%s\"", lbl);
2091 g_string_append(output, ">\n");
2092 g_string_append_printf(output, " <hidden-by-planes status=\"%s\" />\n",
2093 (maskable)?"yes":"no");
2094 g_string_append_printf(output, " <color rgba=\"%g %g %g %g\""
2095 " material=\"%g %g %g %g %g\" />\n",
2096 color->rgba[0], color->rgba[1],
2097 color->rgba[2], color->rgba[3],
2098 mat[0], mat[1], mat[2], mat[3], mat[4]);
2099 g_string_append(output, " </surface>\n");
2100 }
2101 g_string_append(output, " </surfaces>");
2102
2103 valid = tool_XML_substitute(output, filename, "surfaces", error);
2104 if (!valid)
2105 {
2106 g_string_free(output, TRUE);
2107 return FALSE;
2108 }
2109
2110 valid = g_file_set_contents(filename, output->str, -1, error);
2111 g_string_free(output, TRUE);
2112 return valid;
2113 }
2114