1 /*
2 Teem: Tools to process and visualize scientific data and images .
3 Copyright (C) 2012, 2011, 2010, 2009 University of Chicago
4 Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann
5 Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 (LGPL) as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 The terms of redistributing and/or modifying this software also
12 include exceptions to the LGPL that facilitate static linking.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this library; if not, write to Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24
25 #include "limn.h"
26
27 int
limnObjectCubeAdd(limnObject * obj,unsigned int lookIdx)28 limnObjectCubeAdd(limnObject *obj, unsigned int lookIdx) {
29 unsigned int vII[4], vII0, partIdx;
30
31 partIdx = limnObjectPartAdd(obj);
32 /* HEY: we have to set this first so that
33 obj->setVertexRGBAFromLook can do the right thing */
34 obj->part[partIdx]->lookIdx = lookIdx;
35 /*
36 7 6
37
38 z 4 5
39 | y
40 | / 3 2
41 | /
42 | / 0 1
43 ------ x
44 */
45 vII0 = limnObjectVertexAdd(obj, partIdx, -1, -1, -1);
46 limnObjectVertexAdd(obj, partIdx, 1, -1, -1);
47 limnObjectVertexAdd(obj, partIdx, 1, 1, -1);
48 limnObjectVertexAdd(obj, partIdx, -1, 1, -1);
49 limnObjectVertexAdd(obj, partIdx, -1, -1, 1);
50 limnObjectVertexAdd(obj, partIdx, 1, -1, 1);
51 limnObjectVertexAdd(obj, partIdx, 1, 1, 1);
52 limnObjectVertexAdd(obj, partIdx, -1, 1, 1);
53 ELL_4V_SET(vII, vII0+3, vII0+2, vII0+1, vII0+0);
54 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
55 ELL_4V_SET(vII, vII0+1, vII0+5, vII0+4, vII0+0);
56 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
57 ELL_4V_SET(vII, vII0+2, vII0+6, vII0+5, vII0+1);
58 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
59 ELL_4V_SET(vII, vII0+3, vII0+7, vII0+6, vII0+2);
60 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
61 ELL_4V_SET(vII, vII0+0, vII0+4, vII0+7, vII0+3);
62 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
63 ELL_4V_SET(vII, vII0+5, vII0+6, vII0+7, vII0+4);
64 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
65
66 return partIdx;
67 }
68
69 int
limnObjectSquareAdd(limnObject * obj,unsigned int lookIdx)70 limnObjectSquareAdd(limnObject *obj, unsigned int lookIdx) {
71 unsigned int vII0, vII[4], partIdx;
72
73 partIdx = limnObjectPartAdd(obj);
74 /* HEY: we have to set this first so that
75 obj->setVertexRGBAFromLook can do the right thing */
76 obj->part[partIdx]->lookIdx = lookIdx;
77 vII0 = limnObjectVertexAdd(obj, partIdx, 0, 0, 0);
78 limnObjectVertexAdd(obj, partIdx, 1, 0, 0);
79 limnObjectVertexAdd(obj, partIdx, 1, 1, 0);
80 limnObjectVertexAdd(obj, partIdx, 0, 1, 0);
81 ELL_4V_SET(vII, vII0+0, vII0+1, vII0+2, vII0+3);
82 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
83 return partIdx;
84 }
85
86 /*
87 ******** limnObjectCylinderAdd
88 **
89 ** adds a cylinder that fills up the bi-unit cube [-1,1]^3,
90 ** with axis "axis" (0:X, 1:Y, 2:Z), with discretization "res"
91 */
92 int
limnObjectCylinderAdd(limnObject * obj,unsigned int lookIdx,unsigned int axis,unsigned int res)93 limnObjectCylinderAdd(limnObject *obj, unsigned int lookIdx,
94 unsigned int axis, unsigned int res) {
95 unsigned int partIdx, ii, jj, tmp, vII0=0, *vII;
96 double theta;
97
98 partIdx = limnObjectPartAdd(obj);
99 /* HEY: we have to set this first so that
100 obj->setVertexRGBAFromLook can do the right thing */
101 obj->part[partIdx]->lookIdx = lookIdx;
102 vII = (unsigned int *)calloc(res, sizeof(unsigned int));
103
104 for (ii=0; ii<=res-1; ii++) {
105 theta = AIR_AFFINE(0, ii, res, 0, 2*AIR_PI);
106 switch(axis) {
107 case 0:
108 tmp = limnObjectVertexAdd(obj, partIdx,
109 1,
110 AIR_CAST(float, -sin(theta)),
111 AIR_CAST(float, cos(theta)));
112 limnObjectVertexAdd(obj, partIdx,
113 -1,
114 AIR_CAST(float, -sin(theta)),
115 AIR_CAST(float, cos(theta)));
116 break;
117 case 1:
118 tmp = limnObjectVertexAdd(obj, partIdx,
119 AIR_CAST(float, sin(theta)),
120 1,
121 AIR_CAST(float, cos(theta)));
122 limnObjectVertexAdd(obj, partIdx,
123 AIR_CAST(float, sin(theta)),
124 -1,
125 AIR_CAST(float, cos(theta)));
126 break;
127 case 2: default:
128 tmp = limnObjectVertexAdd(obj, partIdx,
129 AIR_CAST(float, cos(theta)),
130 AIR_CAST(float, sin(theta)),
131 1);
132 limnObjectVertexAdd(obj, partIdx,
133 AIR_CAST(float, cos(theta)),
134 AIR_CAST(float, sin(theta)),
135 -1);
136 break;
137 }
138 if (!ii) {
139 vII0 = tmp;
140 }
141 }
142 /* add all side faces */
143 for (ii=0; ii<=res-1; ii++) {
144 jj = (ii+1) % res;
145 ELL_4V_SET(vII, vII0 + 2*ii, vII0 + 2*ii + 1,
146 vII0 + 2*jj + 1, vII0 + 2*jj);
147 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
148 }
149 /* add top */
150 for (ii=0; ii<=res-1; ii++) {
151 vII[ii] = vII0 + 2*ii;
152 }
153 limnObjectFaceAdd(obj, partIdx, lookIdx, res, vII);
154 /* add bottom */
155 for (ii=0; ii<=res-1; ii++) {
156 vII[ii] = vII0 + 2*(res-1-ii) + 1;
157 }
158 limnObjectFaceAdd(obj, partIdx, lookIdx, res, vII);
159
160 free(vII);
161 return partIdx;
162 }
163
164 int
limnObjectConeAdd(limnObject * obj,unsigned int lookIdx,unsigned int axis,unsigned int res)165 limnObjectConeAdd(limnObject *obj, unsigned int lookIdx,
166 unsigned int axis, unsigned int res) {
167 double th;
168 unsigned int partIdx, tmp, vII0=0, ii, jj, *vII;
169
170 vII = (unsigned int *)calloc(res, sizeof(unsigned int));
171
172 partIdx = limnObjectPartAdd(obj);
173 /* HEY: we have to set this first so that
174 obj->setVertexRGBAFromLook can do the right thing */
175 obj->part[partIdx]->lookIdx = lookIdx;
176 for (ii=0; ii<=res-1; ii++) {
177 th = AIR_AFFINE(0, ii, res, 0, 2*AIR_PI);
178 switch(axis) {
179 case 0:
180 tmp = limnObjectVertexAdd(obj, partIdx,
181 0,
182 AIR_CAST(float, -sin(th)),
183 AIR_CAST(float, cos(th)));
184 break;
185 case 1:
186 tmp = limnObjectVertexAdd(obj, partIdx,
187 AIR_CAST(float, sin(th)),
188 0,
189 AIR_CAST(float, cos(th)));
190 break;
191 case 2: default:
192 tmp = limnObjectVertexAdd(obj, partIdx,
193 AIR_CAST(float, cos(th)),
194 AIR_CAST(float, sin(th)),
195 0);
196 break;
197 }
198 if (!ii) {
199 vII0 = tmp;
200 }
201 }
202 switch(axis) {
203 case 0:
204 limnObjectVertexAdd(obj, partIdx, 1, 0, 0);
205 break;
206 case 1:
207 limnObjectVertexAdd(obj, partIdx, 0, 1, 0);
208 break;
209 case 2: default:
210 limnObjectVertexAdd(obj, partIdx, 0, 0, 1);
211 break;
212 }
213 for (ii=0; ii<=res-1; ii++) {
214 jj = (ii+1) % res;
215 ELL_3V_SET(vII, vII0+ii, vII0+jj, vII0+res);
216 limnObjectFaceAdd(obj, partIdx, lookIdx, 3, vII);
217 }
218 for (ii=0; ii<=res-1; ii++) {
219 vII[ii] = vII0+res-1-ii;
220 }
221 limnObjectFaceAdd(obj, partIdx, lookIdx, res, vII);
222
223 free(vII);
224 return partIdx;
225 }
226
227 int
limnObjectPolarSphereAdd(limnObject * obj,unsigned int lookIdx,unsigned int axis,unsigned int thetaRes,unsigned int phiRes)228 limnObjectPolarSphereAdd(limnObject *obj, unsigned int lookIdx,
229 unsigned int axis, unsigned int thetaRes,
230 unsigned int phiRes) {
231 unsigned int partIdx, vII0, nti, ti, pi, vII[4], pl;
232 double t, p;
233
234 thetaRes = AIR_MAX(thetaRes, 3);
235 phiRes = AIR_MAX(phiRes, 2);
236
237 partIdx = limnObjectPartAdd(obj);
238 /* HEY: we have to set this first so that
239 obj->setVertexRGBAFromLook can do the right thing */
240 obj->part[partIdx]->lookIdx = lookIdx;
241 switch(axis) {
242 case 0:
243 vII0 = limnObjectVertexAdd(obj, partIdx, 1, 0, 0);
244 break;
245 case 1:
246 vII0 = limnObjectVertexAdd(obj, partIdx, 0, 1, 0);
247 break;
248 case 2: default:
249 vII0 = limnObjectVertexAdd(obj, partIdx, 0, 0, 1);
250 break;
251 }
252 for (pi=1; pi<=phiRes-1; pi++) {
253 p = AIR_AFFINE(0, pi, phiRes, 0, AIR_PI);
254 for (ti=0; ti<=thetaRes-1; ti++) {
255 t = AIR_AFFINE(0, ti, thetaRes, 0, 2*AIR_PI);
256 switch(axis) {
257 case 0:
258 limnObjectVertexAdd(obj, partIdx,
259 AIR_CAST(float, cos(p)),
260 AIR_CAST(float, -sin(t)*sin(p)),
261 AIR_CAST(float, cos(t)*sin(p)));
262 break;
263 case 1:
264 limnObjectVertexAdd(obj, partIdx,
265 AIR_CAST(float, sin(t)*sin(p)),
266 AIR_CAST(float, cos(p)),
267 AIR_CAST(float, cos(t)*sin(p)));
268 break;
269 case 2: default:
270 limnObjectVertexAdd(obj, partIdx,
271 AIR_CAST(float, cos(t)*sin(p)),
272 AIR_CAST(float, sin(t)*sin(p)),
273 AIR_CAST(float, cos(p)));
274 break;
275 }
276 }
277 }
278 switch(axis) {
279 case 0:
280 pl = limnObjectVertexAdd(obj, partIdx, -1, 0, 0);
281 break;
282 case 1:
283 pl = limnObjectVertexAdd(obj, partIdx, 0, -1, 0);
284 break;
285 case 2: default:
286 pl = limnObjectVertexAdd(obj, partIdx, 0, 0, -1);
287 break;
288 }
289 for (ti=1; ti<=thetaRes; ti++) {
290 nti = ti < thetaRes ? ti+1 : 1;
291 ELL_3V_SET(vII, vII0+ti, vII0+nti, vII0+0);
292 limnObjectFaceAdd(obj, partIdx, lookIdx, 3, vII);
293 }
294 for (pi=0; pi<=phiRes-3; pi++) {
295 for (ti=1; ti<=thetaRes; ti++) {
296 nti = ti < thetaRes ? ti+1 : 1;
297 ELL_4V_SET(vII, vII0+pi*thetaRes + ti, vII0+(pi+1)*thetaRes + ti,
298 vII0+(pi+1)*thetaRes + nti, vII0+pi*thetaRes + nti);
299 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
300 }
301 }
302 for (ti=1; ti<=thetaRes; ti++) {
303 nti = ti < thetaRes ? ti+1 : 1;
304 ELL_3V_SET(vII, vII0+pi*thetaRes + ti, pl, vII0+pi*thetaRes + nti);
305 limnObjectFaceAdd(obj, partIdx, lookIdx, 3, vII);
306 }
307
308 return partIdx;
309 }
310
311 int
limnObjectPolarSuperquadFancyAdd(limnObject * obj,unsigned int lookIdx,unsigned int axis,float A,float B,float C,float R,unsigned int thetaRes,unsigned int phiRes)312 limnObjectPolarSuperquadFancyAdd(limnObject *obj,
313 unsigned int lookIdx, unsigned int axis,
314 float A, float B, float C, float R,
315 unsigned int thetaRes, unsigned int phiRes) {
316 unsigned int partIdx, vII0, nti, ti, pi, vII[4], pl;
317 double x, y, z, t, p;
318
319 AIR_UNUSED(R);
320 thetaRes = AIR_MAX(thetaRes, 3);
321 phiRes = AIR_MAX(phiRes, 2);
322
323 partIdx = limnObjectPartAdd(obj);
324 /* HEY: we have to set this first so that
325 obj->setVertexRGBAFromLook can do the right thing */
326 obj->part[partIdx]->lookIdx = lookIdx;
327 switch(axis) {
328 case 0:
329 vII0 = limnObjectVertexAdd(obj, partIdx, 1, 0, 0);
330 break;
331 case 1:
332 vII0 = limnObjectVertexAdd(obj, partIdx, 0, 1, 0);
333 break;
334 case 2: default:
335 vII0 = limnObjectVertexAdd(obj, partIdx, 0, 0, 1);
336 break;
337 }
338 for (pi=1; pi<=phiRes-1; pi++) {
339 p = AIR_AFFINE(0, pi, phiRes, 0, AIR_PI);
340 for (ti=0; ti<=thetaRes-1; ti++) {
341 t = AIR_AFFINE(0, ti, thetaRes, 0, 2*AIR_PI);
342 switch(axis) {
343 case 0:
344 x = airSgnPow(cos(p),B);
345 y = -airSgnPow(sin(t),A) * airSgnPow(sin(p),B);
346 z = airSgnPow(cos(t),A) * airSgnPow(sin(p),B);
347 if (C != B) {
348 /* modify profile along y axis to create beta=C */
349 double yp, ymax;
350 yp = airSgnPow(sin(acos(airSgnPow(x, 1/C))), C);
351 ymax = airSgnPow(sin(p), B);
352 if (ymax) {
353 y *= yp/ymax;
354 }
355 }
356 break;
357 case 1:
358 x = airSgnPow(sin(t),A) * airSgnPow(sin(p),B);
359 y = airSgnPow(cos(p),B);
360 z = airSgnPow(cos(t),A) * airSgnPow(sin(p),B);
361 break;
362 case 2: default:
363 x = airSgnPow(cos(t),A) * airSgnPow(sin(p),B);
364 y = airSgnPow(sin(t),A) * airSgnPow(sin(p),B);
365 z = airSgnPow(cos(p),B);
366 if (C != B) {
367 /* modify profile along y axis to create beta=C */
368 double yp, ymax;
369 yp = airSgnPow(sin(acos(airSgnPow(z, 1/C))), C);
370 ymax = airSgnPow(sin(p), B);
371 if (ymax) {
372 y *= yp/ymax;
373 }
374 }
375 break;
376 }
377 limnObjectVertexAdd(obj, partIdx,
378 AIR_CAST(float, x),
379 AIR_CAST(float, y),
380 AIR_CAST(float, z));
381 }
382 }
383 switch(axis) {
384 case 0:
385 pl = limnObjectVertexAdd(obj, partIdx, -1, 0, 0);
386 break;
387 case 1:
388 pl = limnObjectVertexAdd(obj, partIdx, 0, -1, 0);
389 break;
390 case 2: default:
391 pl = limnObjectVertexAdd(obj, partIdx, 0, 0, -1);
392 break;
393 }
394 for (ti=1; ti<=thetaRes; ti++) {
395 nti = ti < thetaRes ? ti+1 : 1;
396 ELL_3V_SET(vII, vII0+ti, vII0+nti, vII0+0);
397 limnObjectFaceAdd(obj, partIdx, lookIdx, 3, vII);
398 }
399 for (pi=0; pi<=phiRes-3; pi++) {
400 for (ti=1; ti<=thetaRes; ti++) {
401 nti = ti < thetaRes ? ti+1 : 1;
402 ELL_4V_SET(vII, vII0+pi*thetaRes + ti, vII0+(pi+1)*thetaRes + ti,
403 vII0+(pi+1)*thetaRes + nti, vII0+pi*thetaRes + nti);
404 limnObjectFaceAdd(obj, partIdx, lookIdx, 4, vII);
405 }
406 }
407 for (ti=1; ti<=thetaRes; ti++) {
408 nti = ti < thetaRes ? ti+1 : 1;
409 ELL_3V_SET(vII, vII0+pi*thetaRes + ti, pl, vII0+pi*thetaRes + nti);
410 limnObjectFaceAdd(obj, partIdx, lookIdx, 3, vII);
411 }
412
413 return partIdx;
414 }
415
416 int
limnObjectPolarSuperquadAdd(limnObject * obj,unsigned int lookIdx,unsigned int axis,float A,float B,unsigned int thetaRes,unsigned int phiRes)417 limnObjectPolarSuperquadAdd(limnObject *obj,
418 unsigned int lookIdx, unsigned int axis,
419 float A, float B,
420 unsigned int thetaRes, unsigned int phiRes) {
421
422 return limnObjectPolarSuperquadFancyAdd(obj, lookIdx, axis,
423 A, B, B, 0,
424 thetaRes, phiRes);
425 }
426