source: trunk/packages/vizservers/nanovis/dxReader.cpp @ 1474

Last change on this file since 1474 was 1474, checked in by gah, 15 years ago
File size: 41.4 KB
Line 
1 
2/*
3 * ----------------------------------------------------------------------
4 * Nanovis: Visualization of Nanoelectronics Data
5 *
6 *  dxReader.cpp
7 *      This module contains openDX readers for 2D and 3D volumes.
8 *
9 * ======================================================================
10 *  AUTHOR:  Wei Qiao <qiaow@purdue.edu>
11 *           Michael McLennan <mmclennan@purdue.edu>
12 *           Purdue Rendering and Perceptualization Lab (PURPL)
13 *
14 *  Copyright (c) 2004-2006  Purdue Research Foundation
15 *
16 *  See the file "license.terms" for information on usage and
17 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
18 * ======================================================================
19 */
20
21// common dx functions
22#include "dxReaderCommon.h"
23
24#include <stdio.h>
25#include <math.h>
26#include <fstream>
27#include <iostream>
28#include <sstream>
29#include <string>
30#include <sys/types.h>
31#include <unistd.h>
32
33#include "Nv.h"
34
35#include "nanovis.h"
36#include "RpField1D.h"
37#include "RpFieldRect3D.h"
38#include "RpFieldPrism3D.h"
39#include <Unirect.h>
40
41//transfer function headers
42#include "ZincBlendeVolume.h"
43#include "NvZincBlendeReconstructor.h"
44
45#define  _LOCAL_ZINC_TEST_ 0
46
47/* Load a 3D volume from a dx-format file
48 */
49bool
50load_volume_stream2(Rappture::Outcome &result, int index, std::iostream& fin)
51{
52    printf("load_volume_stream2\n");
53    Rappture::MeshTri2D xymesh;
54    int dummy, nx, ny, nz, nxy, npts;
55    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
56    char line[128], type[128], *start;
57
58    int isrect = 1;
59    dx = dy = dz = 0.0;         // Suppress compiler warning.
60    x0 = y0 = z0 = 0.0;         // May not have an origin line.
61    nx = ny = nz = npts = nxy = 0;
62    do {
63        fin.getline(line,sizeof(line)-1);
64        for (start=&line[0]; *start == ' ' || *start == '\t'; start++)
65            ;  // skip leading blanks
66
67        if (*start != '#') {  // skip comment lines
68            if (sscanf(start, "object %d class gridpositions counts %d %d %d",
69                       &dummy, &nx, &ny, &nz) == 4) {
70                // found grid size
71                isrect = 1;
72            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
73                isrect = 0;
74                double xx, yy, zz;
75                for (int i=0; i < nxy; i++) {
76                    fin.getline(line,sizeof(line)-1);
77                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
78                        xymesh.addNode( Rappture::Node2D(xx,yy) );
79                    }
80                }
81
82                char fpts[128];
83                sprintf(fpts, "/tmp/tmppts%d", getpid());
84                char fcells[128];
85                sprintf(fcells, "/tmp/tmpcells%d", getpid());
86
87                std::ofstream ftmp(fpts);
88                // save corners of bounding box first, to work around meshing
89                // problems in voronoi utility
90                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
91                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
92                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
93                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
94                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
95                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
96                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
97                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
98                for (int i=0; i < nxy; i++) {
99                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
100                }
101                ftmp.close();
102
103                char cmdstr[512];
104                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
105                if (system(cmdstr) == 0) {
106                    int cx, cy, cz;
107                    std::ifstream ftri(fcells);
108                    while (!ftri.eof()) {
109                        ftri.getline(line,sizeof(line)-1);
110                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
111                            if (cx >= 4 && cy >= 4 && cz >= 4) {
112                                // skip first 4 boundary points
113                                xymesh.addCell(cx-4, cy-4, cz-4);
114                            }
115                        }
116                    }
117                    ftri.close();
118                } else {
119                    result.error("triangularization failed");
120                    return false;
121                }
122                unlink(fpts), unlink(fcells);
123            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
124                // found z-grid
125            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
126                // found origin
127            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
128        int count = 0;
129                // found one of the delta lines
130                if (ddx != 0.0) {
131            dx = ddx;
132            count++;
133        }
134        if (ddy != 0.0) {
135            dy = ddy;
136            count++;
137        }
138        if (ddz != 0.0) {
139            dz = ddz;
140            count++;
141        }
142        if (count > 1) {
143            result.addError("don't know how to handle multiple non-zero"
144                            " delta values");
145            return false;
146        }
147            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
148                if (isrect && (npts != nx*ny*nz)) {
149                    result.addError("inconsistent data: expected %d points "
150                                    " but found %d points", nx*ny*nz, npts);
151                    return false;
152                } else if (!isrect && (npts != nxy*nz)) {
153                    result.addError("inconsistent data: expected %d points "
154                                    " but found %d points", nxy*nz, npts);
155                    return false;
156                }
157                break;
158            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
159                if (npts != nx*ny*nz) {
160                    result.addError("inconsistent data: expected %d points "
161                                    " but found %d points", nx*ny*nz, npts);
162                    return false;
163                }
164                break;
165            }
166        }
167    } while (!fin.eof());
168
169    fprintf(stderr, "found nx=%d ny=%d, nz=%d, x0=%f, y0=%f, z0=%f\n",
170            nx, ny, nz, x0, y0, z0);
171    // read data points
172    if (fin.eof()) {
173        result.addError("EOF found: expecting %d points", npts);
174        return false;
175    }
176    if (isrect) {
177        double dval[6];
178        int nread = 0;
179        int ix = 0;
180        int iy = 0;
181        int iz = 0;
182        float* data = new float[nx *  ny *  nz * 4];
183        memset(data, 0, nx*ny*nz*4);
184        double vmin = 1e21;
185        double nzero_min = 1e21;
186        double vmax = -1e21;
187       
188       
189        while (!fin.eof() && nread < npts) {
190            fin.getline(line,sizeof(line)-1);
191            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
192           
193            for (int p=0; p < n; p++) {
194                int nindex = (iz*nx*ny + iy*nx + ix) * 4;
195                data[nindex] = dval[p];
196               
197                if (dval[p] < vmin) {
198                    vmin = dval[p];
199                } else if (dval[p] > vmax) {
200                    vmax = dval[p];
201                }
202                if (dval[p] != 0.0f && dval[p] < nzero_min) {
203                    nzero_min = dval[p];
204                }
205               
206                nread++;
207                if (++iz >= nz) {
208                    iz = 0;
209                    if (++iy >= ny) {
210                        iy = 0;
211                        ++ix;
212                    }
213                }
214            }
215        }
216       
217        // make sure that we read all of the expected points
218        if (nread != nx*ny*nz) {
219            result.addError("inconsistent data: expected %d points "
220                            " but found %d points", nx*ny*nz, nread);
221            return false;
222        }
223       
224        double dv = vmax - vmin;
225        int count = nx*ny*nz;
226        int ngen = 0;
227        double v;
228        if (dv == 0.0) {
229            dv = 1.0;
230        }
231       
232        for (int i = 0; i < count; ++i) {
233            v = data[ngen];
234            // scale all values [0-1], -1 => out of bounds
235            //
236            // INSOO
237            v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
238            data[ngen] = v;
239            ngen += 4;
240        }
241       
242        computeSimpleGradient(data, nx, ny, nz);
243       
244        dx = nx;
245        dy = ny;
246        dz = nz;
247       
248        Volume *volPtr;
249        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
250                                      vmin, vmax, nzero_min);
251        volPtr->xAxis.SetRange(x0, x0 + (nx * dx));
252        volPtr->yAxis.SetRange(y0, y0 + (ny * dy));
253        volPtr->zAxis.SetRange(z0, z0 + (nz * dz));
254        volPtr->wAxis.SetRange(vmin, vmax);
255        volPtr->update_pending = true;
256        delete [] data;
257       
258    } else {
259        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
260        Rappture::FieldPrism3D field(xymesh, zgrid);
261       
262        double dval;
263        int nread = 0;
264        int ixy = 0;
265        int iz = 0;
266        while (!fin.eof() && nread < npts) {
267            fin >> dval;
268            if (fin.fail()) {
269                result.addError("after %d of %d points: can't read number",
270                                nread, npts);
271                return false;
272            } else {
273                int nid = nxy*iz + ixy;
274                field.define(nid, dval);
275               
276                nread++;
277                if (++iz >= nz) {
278                    iz = 0;
279                    ixy++;
280                }
281            }
282        }
283       
284        // make sure that we read all of the expected points
285        if (nread != nxy*nz) {
286            result.addError("inconsistent data: expected %d points "
287                            "but found %d points", nxy*nz, nread);
288            return false;
289        }
290       
291        // figure out a good mesh spacing
292        int nsample = 30;
293        x0 = field.rangeMin(Rappture::xaxis);
294        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
295        y0 = field.rangeMin(Rappture::yaxis);
296        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
297        z0 = field.rangeMin(Rappture::zaxis);
298        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
299        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
300       
301        nx = (int)ceil(dx/dmin);
302        ny = (int)ceil(dy/dmin);
303        nz = (int)ceil(dz/dmin);
304#ifndef NV40
305        // must be an even power of 2 for older cards
306        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
307        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
308        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
309#endif
310        float *data = new float[4*nx*ny*nz];
311       
312        double vmin = field.valueMin();
313        double dv = field.valueMax() - field.valueMin();
314        if (dv == 0.0) {
315            dv = 1.0;
316        }
317        // generate the uniformly sampled data that we need for a volume
318        int ngen = 0;
319        double nzero_min = 0.0;
320        for (iz=0; iz < nz; iz++) {
321            double zval = z0 + iz*dmin;
322            for (int iy=0; iy < ny; iy++) {
323                double yval = y0 + iy*dmin;
324                for (int ix=0; ix < nx; ix++) {
325                    double xval = x0 + ix*dmin;
326                    double v = field.value(xval,yval,zval);
327                   
328                    if (v != 0.0f && v < nzero_min) {
329                        nzero_min = v;
330                    }
331                    // scale all values [0-1], -1 => out of bounds
332                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
333                    data[ngen] = v;
334                   
335                    ngen += 4;
336                }
337            }
338        }
339       
340        // FIXME: This next section of code should be replaced by a
341        // call to the computeSimpleGradient() function. There is a slight
342        // difference in the code below and the aforementioned function
343        // in that the commented out lines in the else statements are
344        // different.
345        //
346        // Compute the gradient of this data.  BE CAREFUL: center
347        // calculation on each node to avoid skew in either direction.
348        ngen = 0;
349        for (int iz=0; iz < nz; iz++) {
350            for (int iy=0; iy < ny; iy++) {
351                for (int ix=0; ix < nx; ix++) {
352                    // gradient in x-direction
353                    //double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
354                    //double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
355                    double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
356                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
357                    if (valm1 < 0 || valp1 < 0) {
358                        data[ngen+1] = 0.0;
359                    } else {
360                        data[ngen+1] = valp1-valm1; // assume dx=1
361                        //data[ngen+1] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
362                    }
363                   
364                    // gradient in y-direction
365                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
366                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
367                    if (valm1 < 0 || valp1 < 0) {
368                        data[ngen+2] = 0.0;
369                    } else {
370                        data[ngen+2] = valp1-valm1; // assume dy=1
371                        //data[ngen+2] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
372                    }
373                   
374                    // gradient in z-direction
375                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
376                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
377                    if (valm1 < 0 || valp1 < 0) {
378                        data[ngen+3] = 0.0;
379                    } else {
380                        data[ngen+3] = valp1-valm1; // assume dz=1
381                        //data[ngen+3] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
382                    }
383                   
384                    ngen += 4;
385                }
386            }
387        }
388       
389        Volume *volPtr;
390        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
391                                      field.valueMin(), field.valueMax(), nzero_min);
392        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
393                               field.rangeMax(Rappture::xaxis));
394        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
395                               field.rangeMax(Rappture::yaxis));
396        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
397                               field.rangeMax(Rappture::zaxis));
398        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
399        volPtr->update_pending = true;
400        delete [] data;
401    }
402    //
403    // Center this new volume on the origin.
404    //
405    float dx0 = -0.5;
406    float dy0 = -0.5*dy/dx;
407    float dz0 = -0.5*dz/dx;
408    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
409    return true;
410}
411
412bool
413load_volume_stream(Rappture::Outcome &result, int index, std::iostream& fin)
414{
415    printf("load_volume_stream\n");
416
417    Rappture::MeshTri2D xymesh;
418    int dummy, nx, ny, nz, nxy, npts;
419    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
420    char line[128], type[128], *start;
421
422    int isrect = 1;
423
424    dx = dy = dz = 0.0;         // Suppress compiler warning.
425    x0 = y0 = z0 = 0.0;         // May not have an origin line.
426    nx = ny = nz = npts = nxy = 0;
427    while (!fin.eof()) {
428        fin.getline(line, sizeof(line) - 1);
429        if (fin.fail()) {
430            result.error("error in data stream");
431            return false;
432        }
433        for (start=line; *start == ' ' || *start == '\t'; start++)
434            ;  // skip leading blanks
435
436        if (*start != '#') {  // skip comment lines
437            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
438                // found grid size
439                isrect = 1;
440            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
441                isrect = 0;
442
443                double xx, yy, zz;
444                for (int i=0; i < nxy; i++) {
445                    fin.getline(line,sizeof(line)-1);
446                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
447                        xymesh.addNode( Rappture::Node2D(xx,yy) );
448                    }
449                }
450
451                char fpts[128];
452                sprintf(fpts, "/tmp/tmppts%d", getpid());
453                char fcells[128];
454                sprintf(fcells, "/tmp/tmpcells%d", getpid());
455
456                std::ofstream ftmp(fpts);
457                // save corners of bounding box first, to work around meshing
458                // problems in voronoi utility
459                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
460                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
461                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
462                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
463                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
464                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
465                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
466                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
467                for (int i=0; i < nxy; i++) {
468                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
469
470                }
471                ftmp.close();
472
473                char cmdstr[512];
474                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
475                if (system(cmdstr) == 0) {
476                    int cx, cy, cz;
477                    std::ifstream ftri(fcells);
478                    while (!ftri.eof()) {
479                        ftri.getline(line,sizeof(line)-1);
480                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
481                            if (cx >= 4 && cy >= 4 && cz >= 4) {
482                                // skip first 4 boundary points
483                                xymesh.addCell(cx-4, cy-4, cz-4);
484                            }
485                        }
486                    }
487                    ftri.close();
488                } else {
489                    result.error("triangularization failed");
490                    return false;
491                }
492                unlink(fpts);
493                unlink(fcells);
494            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
495                // found z-grid
496            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
497                // found origin
498            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
499                // found one of the delta lines
500                if (ddx != 0.0) { dx = ddx; }
501                else if (ddy != 0.0) { dy = ddy; }
502                else if (ddz != 0.0) { dz = ddz; }
503            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
504                if (isrect && (npts != nx*ny*nz)) {
505                    result.addError("inconsistent data: expected %d points"
506                                    " but found %d points", nx*ny*nz, npts);
507                    return false;
508                } else if (!isrect && (npts != nxy*nz)) {
509                    result.addError("inconsistent data: expected %d points"
510                                    " but found %d points", nx*ny*nz, npts);
511                    return false;
512                }
513                break;
514            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
515                if (npts != nx*ny*nz) {
516                    result.addError("inconsistent data: expected %d points"
517                                    " but found %d points", nx*ny*nz, npts);
518                    return false;
519                }
520                break;
521            }
522        }
523    }
524    // read data points
525    if (fin.eof()) {
526        result.error("data not found in stream");
527        return false;
528    }
529    if (isrect) {
530        Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
531        Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
532        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
533        Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
534
535        double dval[6];
536        int nread = 0;
537        int ix = 0;
538        int iy = 0;
539        int iz = 0;
540        while (!fin.eof() && nread < npts) {
541            fin.getline(line,sizeof(line)-1);
542            if (fin.fail()) {
543                result.addError("error reading data points");
544                return false;
545            }
546            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
547           
548            for (int p=0; p < n; p++) {
549                int nindex = iz*nx*ny + iy*nx + ix;
550                field.define(nindex, dval[p]);
551                fflush(stderr);
552                nread++;
553                if (++iz >= nz) {
554                    iz = 0;
555                    if (++iy >= ny) {
556                        iy = 0;
557                        ++ix;
558                    }
559                }
560            }
561        }
562       
563        // make sure that we read all of the expected points
564        if (nread != nx*ny*nz) {
565            result.addError("inconsistent data: expected %d points"
566                            " but found %d points", nx*ny*nz, npts);
567            return false;
568        }
569       
570        // figure out a good mesh spacing
571        int nsample = 30;
572        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
573        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
574        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
575        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
576       
577        nx = (int)ceil(dx/dmin);
578        ny = (int)ceil(dy/dmin);
579        nz = (int)ceil(dz/dmin);
580       
581#ifndef NV40
582        // must be an even power of 2 for older cards
583        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
584        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
585        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
586#endif
587       
588        //#define _SOBEL
589#ifdef _SOBEL_
590        const int step = 1;
591        float *cdata = new float[nx*ny*nz * step];
592        int ngen = 0;
593        double nzero_min = 0.0;
594        for (int iz=0; iz < nz; iz++) {
595            double zval = z0 + iz*dmin;
596            for (int iy=0; iy < ny; iy++) {
597                double yval = y0 + iy*dmin;
598                for (int ix=0; ix < nx; ix++) {
599                    double xval = x0 + ix*dmin;
600                    double v = field.value(xval,yval,zval);
601                   
602                    if (v != 0.0f && v < nzero_min) {
603                        nzero_min = v;
604                    }
605                   
606                    // scale all values [0-1], -1 => out of bounds
607                    v = (isnan(v)) ? -1.0 : v;
608                   
609                    cdata[ngen] = v;
610                    ngen += step;
611                }
612            }
613        }
614       
615        float* data = computeGradient(cdata, nx, ny, nz, field.valueMin(),
616                                      field.valueMax());
617#else
618        double vmin = field.valueMin();
619        double vmax = field.valueMax();
620        double nzero_min = 0;
621        float *data = new float[nx*ny*nz * 4];
622        double dv = vmax - vmin;
623        int ngen = 0;
624        if (dv == 0.0)  dv = 1.0;
625       
626        for (int iz=0; iz < nz; iz++) {
627            double zval = z0 + iz*dmin;
628            for (int iy=0; iy < ny; iy++) {
629                double yval = y0 + iy*dmin;
630                for (int ix=0; ix < nx; ix++) {
631                    double xval = x0 + ix*dmin;
632                    double v = field.value(xval,yval,zval);
633                   
634                    // scale all values [0-1], -1 => out of bounds
635                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
636                   
637                    data[ngen] = v;
638                    ngen += 4;
639                }
640            }
641        }
642       
643        computeSimpleGradient(data, nx, ny, nz);
644#endif
645       
646#ifdef notdef
647        for (int i=0; i<nx*ny*nz; i++) {
648            fprintf(stderr,"enddata[%i] = %lg\n",i,data[i]);
649            fflush(stderr);
650        }
651#endif 
652        fprintf(stdout,"End Data Stats index = %i\n",index);
653        fprintf(stdout,"nx = %i ny = %i nz = %i\n",nx,ny,nz);
654        fprintf(stdout,"dx = %lg dy = %lg dz = %lg\n",dx,dy,dz);
655        fprintf(stdout,"dataMin = %lg\tdataMax = %lg\tnzero_min = %lg\n", field.valueMin(),field.valueMax(),nzero_min);
656        fflush(stdout);
657       
658        Volume *volPtr;
659        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
660                                      field.valueMin(), field.valueMax(), nzero_min);
661        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
662                               field.rangeMax(Rappture::xaxis));
663        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
664                               field.rangeMax(Rappture::yaxis));
665        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
666                               field.rangeMax(Rappture::zaxis));
667        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
668        volPtr->update_pending = true;
669        // TBD..
670        // POINTSET
671        /*
672          PointSet* pset = new PointSet();
673          pset->initialize(volume[index], (float*) data);
674          pset->setVisible(true);
675          NanoVis::pointSet.push_back(pset);
676          updateColor(pset);
677          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
678        */
679       
680        delete [] data;
681       
682    } else {
683        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
684        Rappture::FieldPrism3D field(xymesh, zgrid);
685       
686        double dval;
687        int nread = 0;
688        int ixy = 0;
689        int iz = 0;
690        while (!fin.eof() && nread < npts) {
691            fin >> dval;
692            if (fin.fail()) {
693                result.addError("after %d of %d points: can't read number",
694                                nread, npts);
695                return false;
696            } else {
697                int nid = nxy*iz + ixy;
698                field.define(nid, dval);
699               
700                nread++;
701                if (++iz >= nz) {
702                    iz = 0;
703                    ixy++;
704                }
705            }
706        }
707       
708        // make sure that we read all of the expected points
709        if (nread != nxy*nz) {
710            result.addError("inconsistent data: expected %d points"
711                            " but found %d points", nx*ny*nz, npts);
712            return false;
713        }
714       
715        // figure out a good mesh spacing
716        int nsample = 30;
717        x0 = field.rangeMin(Rappture::xaxis);
718        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
719        y0 = field.rangeMin(Rappture::yaxis);
720        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
721        z0 = field.rangeMin(Rappture::zaxis);
722        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
723        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
724       
725        nx = (int)ceil(dx/dmin);
726        ny = (int)ceil(dy/dmin);
727        nz = (int)ceil(dz/dmin);
728#ifndef NV40
729        // must be an even power of 2 for older cards
730        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
731        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
732        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
733#endif
734        float *data = new float[4*nx*ny*nz];
735       
736        double vmin = field.valueMin();
737        double dv = field.valueMax() - field.valueMin();
738        if (dv == 0.0) { dv = 1.0; }
739       
740        // generate the uniformly sampled data that we need for a volume
741        int ngen = 0;
742        double nzero_min = 0.0;
743        for (iz=0; iz < nz; iz++) {
744            double zval = z0 + iz*dmin;
745            for (int iy=0; iy < ny; iy++) {
746                double yval = y0 + iy*dmin;
747                for (int ix=0; ix < nx; ix++) {
748                    double xval = x0 + ix*dmin;
749                    double v = field.value(xval,yval,zval);
750                   
751                    if (v != 0.0f && v < nzero_min) {
752                        nzero_min = v;
753                    }
754                    // scale all values [0-1], -1 => out of bounds
755                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
756                    data[ngen] = v;
757                   
758                    ngen += 4;
759                }
760            }
761        }
762       
763        // Compute the gradient of this data.  BE CAREFUL: center
764        // calculation on each node to avoid skew in either direction.
765        ngen = 0;
766        for (int iz=0; iz < nz; iz++) {
767            for (int iy=0; iy < ny; iy++) {
768                for (int ix=0; ix < nx; ix++) {
769                    // gradient in x-direction
770                    double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
771                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
772                    if (valm1 < 0 || valp1 < 0) {
773                        data[ngen+1] = 0.0;
774                    } else {
775                        data[ngen+1] = valp1-valm1; // assume dx=1
776                        //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1 (ISO)
777                    }
778                   
779                    // gradient in y-direction
780                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
781                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
782                    if (valm1 < 0 || valp1 < 0) {
783                        data[ngen+2] = 0.0;
784                    } else {
785                        data[ngen+2] = valp1-valm1; // assume dy=1
786                        //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1 (ISO)
787                    }
788                   
789                    // gradient in z-direction
790                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
791                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
792                    if (valm1 < 0 || valp1 < 0) {
793                        data[ngen+3] = 0.0;
794                    } else {
795                        data[ngen+3] = valp1-valm1; // assume dz=1
796                        //data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1 (ISO)
797                    }
798                   
799                    ngen += 4;
800                }
801            }
802        }
803       
804        Volume *volPtr;
805        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
806                                      field.valueMin(), field.valueMax(), nzero_min);
807        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
808                               field.rangeMax(Rappture::xaxis));
809        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
810                               field.rangeMax(Rappture::yaxis));
811        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
812                               field.rangeMax(Rappture::zaxis));
813        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
814        volPtr->update_pending = true;
815        // TBD..
816        // POINTSET
817        /*
818          PointSet* pset = new PointSet();
819          pset->initialize(volume[index], (float*) data);
820          pset->setVisible(true);
821          NanoVis::pointSet.push_back(pset);
822          updateColor(pset);
823          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
824        */
825       
826       
827        delete [] data;
828    }
829
830    //
831    // Center this new volume on the origin.
832    //
833    float dx0 = -0.5;
834    float dy0 = -0.5*dy/dx;
835    float dz0 = -0.5*dz/dx;
836    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
837    return true;
838}
839
840
841bool
842load_volume_stream_insoo(Rappture::Outcome &result, int index,
843                         std::iostream& fin)
844{
845    printf("load_volume_stream\n");
846 
847    Rappture::MeshTri2D xymesh;
848    int dummy, nx, ny, nz, nxy, npts;
849    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
850    char line[128], type[128], *start;
851
852    int isrect = 1;
853
854    dx = dy = dz = 0.0;         // Suppress compiler warning.
855    x0 = y0 = z0 = 0.0;         // May not have an origin line.
856    nx = ny = nz = npts = nxy = 0;
857    while (!fin.eof()) {
858        fin.getline(line, sizeof(line) - 1);
859        if (fin.fail()) {
860            result.addError("line \"%s\"error in data stream");
861            return false;
862        }
863        for (start=line; *start == ' ' || *start == '\t'; start++)
864            ;  // skip leading blanks
865
866        if (*start != '#') {  // skip comment lines
867            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
868                // found grid size
869                isrect = 1;
870            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
871                isrect = 0;
872
873                double xx, yy, zz;
874                for (int i=0; i < nxy; i++) {
875                    fin.getline(line,sizeof(line)-1);
876                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
877                        xymesh.addNode( Rappture::Node2D(xx,yy) );
878                    }
879                }
880
881                char fpts[128];
882                sprintf(fpts, "/tmp/tmppts%d", getpid());
883                char fcells[128];
884                sprintf(fcells, "/tmp/tmpcells%d", getpid());
885
886                std::ofstream ftmp(fpts);
887                // save corners of bounding box first, to work around meshing
888                // problems in voronoi utility
889                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
890                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
891                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
892                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
893                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
894                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
895                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
896                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
897                for (int i=0; i < nxy; i++) {
898                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
899
900                }
901                ftmp.close();
902
903                char cmdstr[512];
904                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
905                if (system(cmdstr) == 0) {
906                    int cx, cy, cz;
907                    std::ifstream ftri(fcells);
908                    while (!ftri.eof()) {
909                        ftri.getline(line,sizeof(line)-1);
910                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
911                            if (cx >= 4 && cy >= 4 && cz >= 4) {
912                                // skip first 4 boundary points
913                                xymesh.addCell(cx-4, cy-4, cz-4);
914                            }
915                        }
916                    }
917                    ftri.close();
918                } else {
919                    result.error("triangularization failed");
920                    return false;
921                }
922                unlink(fpts), unlink(fcells);
923            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
924                // found z-grid
925            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
926                // found origin
927            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
928                // found one of the delta lines
929                if (ddx != 0.0) { dx = ddx; }
930                else if (ddy != 0.0) { dy = ddy; }
931                else if (ddz != 0.0) { dz = ddz; }
932            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
933                if (isrect && (npts != nx*ny*nz)) {
934                    result.addError("inconsistent data: expected %d points"
935                                    " but found %d points", nx*ny*nz, npts);
936                    return false;
937                } else if (!isrect && (npts != nxy*nz)) {
938                    result.addError("inconsistent data: expected %d points"
939                                    " but found %d points", nx*ny*nz, npts);
940                    return false;
941                }
942                break;
943            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
944                if (npts != nx*ny*nz) {
945                    result.addError("inconsistent data: expected %d points"
946                                    " but found %d points", nx*ny*nz, npts);
947                    return false;
948                }
949                break;
950            }
951        }
952    }
953
954    // read data points
955    if (fin.eof()) {
956        result.error("data not found in stream");
957        return false;
958    }
959
960    if (isrect) {
961        Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
962        Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
963        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
964        Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
965       
966        double dval[6];
967        int nread = 0;
968        int ix = 0;
969        int iy = 0;
970        int iz = 0;
971        while (!fin.eof() && nread < npts) {
972            fin.getline(line,sizeof(line)-1);
973            if (fin.fail()) {
974                result.error("error reading data points");
975                return false;
976            }
977            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
978           
979            for (int p=0; p < n; p++) {
980                int nindex = iz*nx*ny + iy*nx + ix;
981                field.define(nindex, dval[p]);
982                fprintf(stderr,"nindex = %i\tdval[%i] = %lg\n", nindex, p,
983                        dval[p]);
984                fflush(stderr);
985                nread++;
986                if (++iz >= nz) {
987                    iz = 0;
988                    if (++iy >= ny) {
989                        iy = 0;
990                        ++ix;
991                    }
992                }
993            }
994        }
995       
996        // make sure that we read all of the expected points
997        if (nread != nx*ny*nz) {
998            result.addError("inconsistent data: expected %d points"
999                            " but found %d points", nx*ny*nz, npts);
1000            return false;
1001        }
1002       
1003        // figure out a good mesh spacing
1004        int nsample = 30;
1005        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
1006        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
1007        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
1008        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
1009       
1010        nx = (int)ceil(dx/dmin);
1011        ny = (int)ceil(dy/dmin);
1012        nz = (int)ceil(dz/dmin);
1013       
1014#ifndef NV40
1015        // must be an even power of 2 for older cards
1016        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
1017        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
1018        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
1019#endif
1020       
1021        float *data = new float[4*nx*ny*nz];
1022       
1023        double vmin = field.valueMin();
1024        double dv = field.valueMax() - field.valueMin();
1025        if (dv == 0.0) { dv = 1.0; }
1026       
1027        int ngen = 0;
1028        double nzero_min = 0.0;
1029        for (iz=0; iz < nz; iz++) {
1030            double zval = z0 + iz*dmin;
1031            for (int iy=0; iy < ny; iy++) {
1032                double yval = y0 + iy*dmin;
1033                for (int ix=0; ix < nx; ix++) {
1034                    double xval = x0 + ix*dmin;
1035                    double v = field.value(xval,yval,zval);
1036                   
1037                    if (v != 0.0f && v < nzero_min) {
1038                        nzero_min = v;
1039                    }
1040                    // scale all values [0-1], -1 => out of bounds
1041                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
1042                    data[ngen] = v;
1043                   
1044                    ngen += 4;
1045                }
1046            }
1047        }
1048       
1049        // Compute the gradient of this data.  BE CAREFUL: center
1050        // calculation on each node to avoid skew in either direction.
1051        ngen = 0;
1052        for (int iz=0; iz < nz; iz++) {
1053            for (int iy=0; iy < ny; iy++) {
1054                for (int ix=0; ix < nx; ix++) {
1055                    // gradient in x-direction
1056                    double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
1057                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
1058                    if (valm1 < 0 || valp1 < 0) {
1059                        data[ngen+1] = 0.0;
1060                    } else {
1061                        data[ngen+1] = valp1-valm1; // assume dx=1
1062                        //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1 (ISO)
1063                    }
1064                   
1065                    // gradient in y-direction
1066                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
1067                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
1068                    if (valm1 < 0 || valp1 < 0) {
1069                        data[ngen+2] = 0.0;
1070                    } else {
1071                        data[ngen+2] = valp1-valm1; // assume dy=1
1072                        //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1 (ISO)
1073                    }
1074                   
1075                    // gradient in z-direction
1076                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
1077                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
1078                    if (valm1 < 0 || valp1 < 0) {
1079                        data[ngen+3] = 0.0;
1080                    } else {
1081                        data[ngen+3] = valp1-valm1; // assume dz=1
1082                        //data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1 (ISO)
1083                    }
1084                   
1085                    ngen += 4;
1086                }
1087            }
1088        }
1089       
1090        /*
1091          float *cdata = new float[nx*ny*nz];
1092          int ngen = 0;
1093          double nzero_min = 0.0;
1094          for (int iz=0; iz < nz; iz++) {
1095          double zval = z0 + iz*dmin;
1096          for (int iy=0; iy < ny; iy++) {
1097          double yval = y0 + iy*dmin;
1098          for (int ix=0; ix < nx; ix++) {
1099          double xval = x0 + ix*dmin;
1100          double v = field.value(xval,yval,zval);
1101         
1102          if (v != 0.0f && v < nzero_min) {
1103          nzero_min = v;
1104          }
1105         
1106          // scale all values [0-1], -1 => out of bounds
1107          v = (isnan(v)) ? -1.0 : v;
1108         
1109          cdata[ngen] = v;
1110          ++ngen;
1111          }
1112                }
1113            }
1114           
1115            float* data = computeGradient(cdata, nx, ny, nz, field.valueMin(),
1116                                          field.valueMax());
1117                                         
1118            for (int i=0; i<nx*ny*nz; i++) {
1119                fprintf(stderr,"enddata[%i] = %lg\n",i,data[i]);
1120                fflush(stderr);
1121            }
1122
1123            fprintf(stdout,"End Data Stats index = %i\n",index);
1124            fprintf(stdout,"nx = %i ny = %i nz = %i\n",nx,ny,nz);
1125            fprintf(stdout,"dx = %lg dy = %lg dz = %lg\n",dx,dy,dz);
1126            fprintf(stdout,"dataMin = %lg\tdataMax = %lg\tnzero_min = %lg\n", field.valueMin(),field.valueMax(),nzero_min);
1127            fflush(stdout);
1128            */
1129
1130        Volume *volPtr;
1131        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
1132                                      field.valueMin(), field.valueMax(), nzero_min);
1133        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
1134                               field.rangeMax(Rappture::xaxis));
1135        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
1136                               field.rangeMax(Rappture::yaxis));
1137        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
1138                               field.rangeMax(Rappture::zaxis));
1139        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
1140        volPtr->update_pending = true;
1141        // TBD..
1142        // POINTSET
1143        /*
1144          PointSet* pset = new PointSet();
1145          pset->initialize(volume[index], (float*) data);
1146          pset->setVisible(true);
1147          NanoVis::pointSet.push_back(pset);
1148          updateColor(pset);
1149          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
1150        */
1151       
1152        delete [] data;
1153       
1154    } else {
1155        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
1156        Rappture::FieldPrism3D field(xymesh, zgrid);
1157       
1158        double dval;
1159        int nread = 0;
1160        int ixy = 0;
1161        int iz = 0;
1162        while (!fin.eof() && nread < npts) {
1163            fin >> dval;
1164            if (fin.fail()) {
1165                char mesg[256];
1166                sprintf(mesg,"after %d of %d points: can't read number",
1167                        nread, npts);
1168                result.error(mesg);
1169                return false;
1170            } else {
1171                int nid = nxy*iz + ixy;
1172                field.define(nid, dval);
1173               
1174                nread++;
1175                if (++iz >= nz) {
1176                    iz = 0;
1177                    ixy++;
1178                }
1179            }
1180        }
1181       
1182        // make sure that we read all of the expected points
1183        if (nread != nxy*nz) {
1184            result.addError("inconsistent data: expected %d points"
1185                            " but found %d points", nx*ny*nz, npts);
1186            return false;
1187        }
1188       
1189        // figure out a good mesh spacing
1190        int nsample = 30;
1191        x0 = field.rangeMin(Rappture::xaxis);
1192        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
1193        y0 = field.rangeMin(Rappture::yaxis);
1194        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
1195        z0 = field.rangeMin(Rappture::zaxis);
1196        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
1197        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
1198       
1199        nx = (int)ceil(dx/dmin);
1200        ny = (int)ceil(dy/dmin);
1201        nz = (int)ceil(dz/dmin);
1202#ifndef NV40
1203        // must be an even power of 2 for older cards
1204        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
1205        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
1206        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
1207#endif
1208        float *data = new float[4*nx*ny*nz];
1209       
1210        double vmin = field.valueMin();
1211        double dv = field.valueMax() - field.valueMin();
1212        if (dv == 0.0) { dv = 1.0; }
1213       
1214        // generate the uniformly sampled data that we need for a volume
1215        int ngen = 0;
1216        double nzero_min = 0.0;
1217        for (iz=0; iz < nz; iz++) {
1218            double zval = z0 + iz*dmin;
1219            for (int iy=0; iy < ny; iy++) {
1220                double yval = y0 + iy*dmin;
1221                for (int ix=0; ix < nx; ix++) {
1222                    double xval = x0 + ix*dmin;
1223                    double v = field.value(xval,yval,zval);
1224                   
1225                    if (v != 0.0f && v < nzero_min) {
1226                        nzero_min = v;
1227                    }
1228                    // scale all values [0-1], -1 => out of bounds
1229                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
1230                    data[ngen] = v;
1231                   
1232                    ngen += 4;
1233                }
1234            }
1235        }
1236       
1237        // Compute the gradient of this data.  BE CAREFUL: center
1238        // calculation on each node to avoid skew in either direction.
1239        ngen = 0;
1240        for (int iz=0; iz < nz; iz++) {
1241            for (int iy=0; iy < ny; iy++) {
1242                for (int ix=0; ix < nx; ix++) {
1243                    // gradient in x-direction
1244                    double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
1245                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
1246                    if (valm1 < 0 || valp1 < 0) {
1247                        data[ngen+1] = 0.0;
1248                    } else {
1249                        data[ngen+1] = valp1-valm1; // assume dx=1
1250                        //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1 (ISO)
1251                    }
1252                   
1253                    // gradient in y-direction
1254                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
1255                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
1256                    if (valm1 < 0 || valp1 < 0) {
1257                        data[ngen+2] = 0.0;
1258                    } else {
1259                        data[ngen+2] = valp1-valm1; // assume dy=1
1260                        //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1 (ISO)
1261                    }
1262                   
1263                    // gradient in z-direction
1264                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
1265                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
1266                    if (valm1 < 0 || valp1 < 0) {
1267                        data[ngen+3] = 0.0;
1268                    } else {
1269                        data[ngen+3] = valp1-valm1; // assume dz=1
1270                        //data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1 (ISO)
1271                    }
1272                   
1273                    ngen += 4;
1274                }
1275            }
1276        }
1277       
1278        Volume *volPtr;
1279        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
1280                                      field.valueMin(), field.valueMax(), nzero_min);
1281        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
1282                               field.rangeMax(Rappture::xaxis));
1283        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
1284                               field.rangeMax(Rappture::yaxis));
1285        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
1286                               field.rangeMax(Rappture::zaxis));
1287        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
1288        volPtr->update_pending = true;
1289        // TBD..
1290        // POINTSET
1291        /*
1292          PointSet* pset = new PointSet();
1293          pset->initialize(volume[index], (float*) data);
1294          pset->setVisible(true);
1295          NanoVis::pointSet.push_back(pset);
1296          updateColor(pset);
1297          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
1298        */
1299       
1300       
1301        delete [] data;
1302    }
1303
1304    //
1305    // Center this new volume on the origin.
1306    //
1307    float dx0 = -0.5;
1308    float dy0 = -0.5*dy/dx;
1309    float dz0 = -0.5*dz/dx;
1310    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
1311    return true;
1312}
Note: See TracBrowser for help on using the repository browser.