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

Last change on this file since 2798 was 2798, checked in by ldelgass, 12 years ago

Add emacs mode magic line in preparation for indentation cleanup

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