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

Last change on this file since 1429 was 1429, checked in by gah, 15 years ago

Initial commit of new flow visualization command structure

File size: 50.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
47static INLINE char *
48skipspaces(char *string)
49{
50    while (isspace(*string)) {
51        string++;
52    }
53    return string;
54}
55
56static INLINE char *
57getline(char **stringPtr, char *endPtr)
58{
59    char *line, *p;
60
61    line = skipspaces(*stringPtr);
62    for (p = line; p < endPtr; p++) {
63        if (*p == '\n') {
64            *p++ = '\0';
65            *stringPtr = p;
66            return line;
67        }
68    }
69    *stringPtr = p;
70    return line;
71}
72
73Rappture::Unirect3d *
74ReadDxVectorFieldData(Rappture::Outcome &result, size_t length, char *string)
75{
76    int nx, ny, nz, npts;
77    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
78    char *p, *endPtr;
79
80
81    dx = dy = dz = 0.0;         // Suppress compiler warning.
82    x0 = y0 = z0 = 0.0;         // May not have an origin line.
83    for (p = string, endPtr = p + length; p < endPtr; /*empty*/) {
84        char *line;
85
86        line = getline(&p, endPtr);
87        if (line == endPtr) {
88            break;
89        }
90        if ((line[0] == '#') || (line == '\0')) {
91            continue;           // Skip blank or comment lines.
92        }
93        if (sscanf(line, "object %*d class gridpositions counts %d %d %d",
94                   &nx, &ny, &nz) == 3) {
95            printf("w:%d h:%d d:%d\n", nx, ny, nz);
96            // found grid size
97        } else if (sscanf(line, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
98            // found origin
99        } else if (sscanf(line, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
100            // found one of the delta lines
101            if (ddx != 0.0) {
102                dx = ddx;
103            } else if (ddy != 0.0) {
104                dy = ddy;
105            } else if (ddz != 0.0) {
106                dz = ddz;
107            }
108        } else if (sscanf(line, "object %*d class array type %*s shape 3"
109                " rank 1 items %d data follows", &npts) == 1) {
110            printf("point %d\n", npts);
111            if (npts != nx*ny*nz) {
112                result.addError("inconsistent data: expected %d points"
113                                " but found %d points", nx*ny*nz, npts);
114                return NULL;
115            }
116            break;
117        } else if (sscanf(line, "object %*d class array type %*s rank 0"
118                " times %d data follows", &npts) == 1) {
119            if (npts != nx*ny*nz) {
120                result.addError("inconsistent data: expected %d points"
121                                " but found %d points", nx*ny*nz, npts);
122                return NULL;
123            }
124            break;
125        }
126    }
127    if (npts != nx*ny*nz) {
128        result.addError("inconsistent data: expected %d points"
129                        " but found %d points", nx*ny*nz, npts);
130        return NULL;
131    }
132    float *values = new float[npts];
133    int nValues = 0;
134    for (int ix=0; ix < nx; ix++) {
135        for (int iy=0; iy < ny; iy++) {
136            for (int iz=0; iz < nz; iz++) {
137                char *line;
138                if ((p == endPtr) || (nValues > npts)) {
139                    break;
140                }
141                line = getline(&p, endPtr);
142                if ((line[0] == '#') || (line[0] == '\0')) {
143                    continue;   // Skip blank or comment lines.
144                }
145                double vx, vy, vz;
146                if (sscanf(line, "%lg %lg %lg", &vx, &vy, &vz) == 3) {
147                    int nindex = (iz*nx*ny + iy*nx + ix) * 3;
148                    values[nindex] = vx;
149                    values[nindex+1] = vy;
150                    values[nindex+2] = vz;
151                    nValues++;
152                }
153            }
154        }
155    }
156    // make sure that we read all of the expected points
157    if (nValues != npts) {
158        result.addError("inconsistent data: expected %d points"
159                        " but found %d points", npts, nValues);
160        delete values;
161        return NULL;
162    }
163    return new Rappture::Unirect3d(x0, x0 + dx * nx, nx, y0, y0 + dy * ny, ny,
164                                   z0, z0 + dz * nz, nz, nValues, values, 3);
165}
166
167
168#ifdef notdef
169/*
170 * Load a 3D vector field from a dx-format file
171 */
172bool
173load_vector_stream2(Rappture::Outcome &result, int ivol, size_t length,
174                    char *string)
175{
176    Rappture::Unirect3d *dataPtr;
177    dataPtr = ReadDxVectorFieldData(result, length, string);
178    if (dataPtr == NULL) {
179        return false;
180    }
181    Vector3 physicalMin;
182    Vector3 physicalMax;
183
184    physicalMin.set(dataPtr->xMin(), dataPtr->yMin(), dataPtr->zMin());
185    physicalMax.set(dataPtr->xMax(), dataPtr->yMax(), dataPtr->zMax());
186
187    double max_mag = -DBL_MAX, min_mag = DBL_MAX;
188    float *values = dataPtr->values();
189    for (size_t ix=0; ix < dataPtr->xNum(); ix++) {
190        for (size_t iy=0; iy < dataPtr->yNum(); iy++) {
191            for (size_t iz=0; iz < dataPtr->zNum(); iz++) {
192                double vx, vy, vz, vm;
193                vx = values[0];
194                vy = values[1];
195                vz = values[2];
196                vm = sqrt(vx*vx + vy*vy + vz*vz);
197                if (vm > max_mag) {
198                    max_mag = vm;
199                }
200                if (vm < min_mag) {
201                    min_mag = vm;
202                }
203                values += 3;
204            }
205        }
206    }
207   
208    float *data = new float[4*dataPtr->nValues()];
209    memset(data, 0, sizeof(float) * 4 * dataPtr->nValues());
210    fprintf(stderr, "generating %dx%dx%d = %d points\n",
211            dataPtr->xNum(), dataPtr->yNum(), dataPtr->zNum(),
212            dataPtr->nValues());
213
214    float *destPtr = data;
215    float *srcPtr = dataPtr->values();
216    for (size_t iz=0; iz < dataPtr->zNum(); iz++) {
217        for (size_t iy=0; iy < dataPtr->yNum(); iy++) {
218            for (size_t ix=0; ix < dataPtr->xNum(); ix++) {
219                double vx, vy, vz, vm;
220                vx = values[0];
221                vy = values[1];
222                vz = values[2];
223                vm = sqrt(vx*vx + vy*vy + vz*vz);
224                destPtr[0] = vm / max_mag;
225                destPtr[1] = vx /(2.0*max_mag) + 0.5;
226                destPtr[2] = vy /(2.0*max_mag) + 0.5;
227                destPtr[3] = vz /(2.0*max_mag) + 0.5;
228                srcPtr += 3;
229                destPtr += 4;
230            }
231        }
232    }
233   
234    Volume *volPtr;
235    volPtr = NanoVis::load_volume(ivol, dataPtr->xNum(), dataPtr->yNum(),
236                dataPtr->zNum(), 4, data, min_mag, max_mag, 0);
237    volPtr->xAxis.SetRange(dataPtr->xMin(), dataPtr->xMax());
238    volPtr->yAxis.SetRange(dataPtr->yMin(), dataPtr->yMax());
239    volPtr->zAxis.SetRange(dataPtr->zMin(), dataPtr->zMax());
240    volPtr->wAxis.SetRange(min_mag, max_mag);
241    volPtr->update_pending = true;
242    volPtr->setPhysicalBBox(physicalMin, physicalMax);
243    delete dataPtr;
244    delete data;
245    return true;
246}
247
248bool
249load_vector_stream(Rappture::Outcome result, int index, size_t length,
250                    char *string)
251{
252    Rappture::Unirect3d *dataPtr;
253    dataPtr = ReadDxVectorFieldData(result, length, string);
254    if (dataPtr == NULL) {
255        return false;
256    }
257    Vector3 physicalMin;
258    Vector3 physicalMax;
259
260    physicalMin.set(dataPtr->xMin(), dataPtr->yMin(), dataPtr->zMin());
261    physicalMax.set(dataPtr->xMax(), dataPtr->yMax(), dataPtr->zMax());
262
263    Rappture::Mesh1D xgrid(dataPtr->xMin(), dataPtr->yMin(), dataPtr->xNum());
264    Rappture::Mesh1D ygrid(dataPtr->yMin(), dataPtr->yMax(), dataPtr->yNum());
265    Rappture::Mesh1D zgrid(dataPtr->zMin(), dataPtr->zMax(), dataPtr->zNum());
266    Rappture::FieldRect3D xfield(xgrid, ygrid, zgrid);
267    Rappture::FieldRect3D yfield(xgrid, ygrid, zgrid);
268    Rappture::FieldRect3D zfield(xgrid, ygrid, zgrid);
269   
270    float *values = dataPtr->values();
271    size_t npts = 0;
272    for (size_t ix=0; ix < dataPtr->xNum(); ix++) {
273        for (size_t iy=0; iy < dataPtr->yNum(); iy++) {
274            for (size_t iz=0; iz < dataPtr->zNum(); iz++) {
275                xfield.define(npts, values[0]);
276                yfield.define(npts, values[1]);
277                zfield.define(npts, values[2]);
278                npts++;
279                values += 3;
280            }
281        }
282    }
283
284    double dx, dy, dz;
285    // figure out a good mesh spacing
286    int nsample = 30;
287    dx = xfield.rangeMax(Rappture::xaxis) - xfield.rangeMin(Rappture::xaxis);
288    dy = xfield.rangeMax(Rappture::yaxis) - xfield.rangeMin(Rappture::yaxis);
289    dz = xfield.rangeMax(Rappture::zaxis) - xfield.rangeMin(Rappture::zaxis);
290    double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
291
292    printf("dx:%lf dy:%lf dz:%lf dmin:%lf\n", dx, dy, dz, dmin);
293
294    size_t nx, ny, nz;
295    nx = (int)ceil(dx/dmin);
296    ny = (int)ceil(dy/dmin);
297    nz = (int)ceil(dz/dmin);
298   
299#ifndef NV40
300    // must be an even power of 2 for older cards
301    nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
302    ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
303    nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
304#endif
305   
306    float *data = new float[4*nx*ny*nz];
307    memset(data, 0, sizeof(float) * 4 * nx * ny * nz);
308   
309    std::cout << "generating " << nx << "x" << ny << "x" << nz << " = " << nx*ny*nz << " points" << std::endl;
310   
311    // generate the uniformly sampled data that we need for a volume
312    double vmin = 1e21;
313    double vmax = -1e21;
314    double nzero_min = 0.0;
315    size_t ngen = 0;
316    for (size_t iz=0; iz < nz; iz++) {
317        double zval = dataPtr->zMin() + iz*dmin;
318        for (size_t iy=0; iy < ny; iy++) {
319            double yval = dataPtr->yMin() + iy*dmin;
320            for (size_t ix=0; ix < nx; ix++) {
321                double xval = dataPtr->xMin() + ix*dmin;
322                double vx, vy, vz;
323
324                vx = xfield.value(xval,yval,zval);
325                vy = yfield.value(xval,yval,zval);
326                vz = zfield.value(xval,yval,zval);
327               
328                double vm;
329                vm = sqrt(vx*vx + vy*vy + vz*vz);
330                if (vm < vmin) {
331                    vmin = vm;
332                } else if (vm > vmax) {
333                    vmax = vm;
334                }
335                if ((vm != 0.0f) && (vm < nzero_min)) {
336                    nzero_min = vm;
337                }
338                data[ngen++] = vm;
339                data[ngen++] = vx;
340                data[ngen++] = vy;
341                data[ngen++] = vz;
342            }
343        }
344    }
345   
346    ngen = 0;
347    // scale should be accounted.
348    for (ngen=0; ngen < npts; /*empty*/) {
349        data[ngen] = data[ngen] / vmax; ++ngen;
350        data[ngen] = (data[ngen]/(2.0*vmax) + 0.5); ++ngen;
351        data[ngen] = (data[ngen]/(2.0*vmax) + 0.5); ++ngen;
352        data[ngen] = (data[ngen]/(2.0*vmax) + 0.5); ++ngen;
353    }
354    Volume *volPtr;
355    volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data, vmin, vmax,
356                                  nzero_min);
357   
358    volPtr->xAxis.SetRange(dataPtr->xMin(), dataPtr->xMin() + (nx * dx));
359    volPtr->yAxis.SetRange(dataPtr->yMin(), dataPtr->yMin() + (ny * dy));
360    volPtr->zAxis.SetRange(dataPtr->zMin(), dataPtr->zMin() + (nz * dz));
361    volPtr->wAxis.SetRange(vmin, vmax);
362    volPtr->update_pending = true;
363    delete [] data;
364    return true;
365}
366#endif
367
368/* Load a 3D volume from a dx-format file
369 */
370bool
371load_volume_stream2(Rappture::Outcome &result, int index, std::iostream& fin)
372{
373    printf("load_volume_stream2\n");
374    Rappture::MeshTri2D xymesh;
375    int dummy, nx, ny, nz, nxy, npts;
376    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
377    char line[128], type[128], *start;
378
379    int isrect = 1;
380    dx = dy = dz = 0.0;         // Suppress compiler warning.
381    x0 = y0 = z0 = 0.0;         // May not have an origin line.
382    do {
383        fin.getline(line,sizeof(line)-1);
384        for (start=&line[0]; *start == ' ' || *start == '\t'; start++)
385            ;  // skip leading blanks
386
387        if (*start != '#') {  // skip comment lines
388            if (sscanf(start, "object %d class gridpositions counts %d %d %d",
389                       &dummy, &nx, &ny, &nz) == 4) {
390                // found grid size
391                isrect = 1;
392            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
393                isrect = 0;
394                double xx, yy, zz;
395                for (int i=0; i < nxy; i++) {
396                    fin.getline(line,sizeof(line)-1);
397                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
398                        xymesh.addNode( Rappture::Node2D(xx,yy) );
399                    }
400                }
401
402                char fpts[128];
403                sprintf(fpts, "/tmp/tmppts%d", getpid());
404                char fcells[128];
405                sprintf(fcells, "/tmp/tmpcells%d", getpid());
406
407                std::ofstream ftmp(fpts);
408                // save corners of bounding box first, to work around meshing
409                // problems in voronoi utility
410                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
411                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
412                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
413                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
414                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
415                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
416                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
417                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
418                for (int i=0; i < nxy; i++) {
419                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
420                }
421                ftmp.close();
422
423                char cmdstr[512];
424                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
425                if (system(cmdstr) == 0) {
426                    int cx, cy, cz;
427                    std::ifstream ftri(fcells);
428                    while (!ftri.eof()) {
429                        ftri.getline(line,sizeof(line)-1);
430                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
431                            if (cx >= 4 && cy >= 4 && cz >= 4) {
432                                // skip first 4 boundary points
433                                xymesh.addCell(cx-4, cy-4, cz-4);
434                            }
435                        }
436                    }
437                    ftri.close();
438                } else {
439                    result.error("triangularization failed");
440                    return false;
441                }
442                unlink(fpts), unlink(fcells);
443            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
444                // found z-grid
445            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
446                // found origin
447            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
448        int count = 0;
449                // found one of the delta lines
450                if (ddx != 0.0) {
451            dx = ddx;
452            count++;
453        }
454        if (ddy != 0.0) {
455            dy = ddy;
456            count++;
457        }
458        if (ddz != 0.0) {
459            dz = ddz;
460            count++;
461        }
462        if (count > 1) {
463            result.addError("don't know how to handle multiple non-zero"
464                            " delta values");
465            return false;
466        }
467            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
468                if (isrect && (npts != nx*ny*nz)) {
469                    result.addError("inconsistent data: expected %d points "
470                                    " but found %d points", nx*ny*nz, npts);
471                    return false;
472                } else if (!isrect && (npts != nxy*nz)) {
473                    result.addError("inconsistent data: expected %d points "
474                                    " but found %d points", nxy*nz, npts);
475                    return false;
476                }
477                break;
478            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
479                if (npts != nx*ny*nz) {
480                    result.addError("inconsistent data: expected %d points "
481                                    " but found %d points", nx*ny*nz, npts);
482                    return false;
483                }
484                break;
485            }
486        }
487    } while (!fin.eof());
488
489    fprintf(stderr, "found nx=%d ny=%d, nz=%d, x0=%f, y0=%f, z0=%f\n",
490            nx, ny, nz, x0, y0, z0);
491    // read data points
492    if (fin.eof()) {
493        result.addError("EOF found: expecting %d points", npts);
494        return false;
495    }
496    if (isrect) {
497        double dval[6];
498        int nread = 0;
499        int ix = 0;
500        int iy = 0;
501        int iz = 0;
502        float* data = new float[nx *  ny *  nz * 4];
503        memset(data, 0, nx*ny*nz*4);
504        double vmin = 1e21;
505        double nzero_min = 1e21;
506        double vmax = -1e21;
507       
508       
509        while (!fin.eof() && nread < npts) {
510            fin.getline(line,sizeof(line)-1);
511            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
512           
513            for (int p=0; p < n; p++) {
514                int nindex = (iz*nx*ny + iy*nx + ix) * 4;
515                data[nindex] = dval[p];
516               
517                if (dval[p] < vmin) {
518                    vmin = dval[p];
519                } else if (dval[p] > vmax) {
520                    vmax = dval[p];
521                }
522                if (dval[p] != 0.0f && dval[p] < nzero_min) {
523                    nzero_min = dval[p];
524                }
525               
526                nread++;
527                if (++iz >= nz) {
528                    iz = 0;
529                    if (++iy >= ny) {
530                        iy = 0;
531                        ++ix;
532                    }
533                }
534            }
535        }
536       
537        // make sure that we read all of the expected points
538        if (nread != nx*ny*nz) {
539            result.addError("inconsistent data: expected %d points "
540                            " but found %d points", nx*ny*nz, nread);
541            return false;
542        }
543       
544        double dv = vmax - vmin;
545        int count = nx*ny*nz;
546        int ngen = 0;
547        double v;
548        if (dv == 0.0) {
549            dv = 1.0;
550        }
551       
552        for (int i = 0; i < count; ++i) {
553            v = data[ngen];
554            // scale all values [0-1], -1 => out of bounds
555            //
556            // INSOO
557            v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
558            data[ngen] = v;
559            ngen += 4;
560        }
561       
562        computeSimpleGradient(data, nx, ny, nz);
563       
564        dx = nx;
565        dy = ny;
566        dz = nz;
567       
568        Volume *volPtr;
569        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
570                                      vmin, vmax, nzero_min);
571        volPtr->xAxis.SetRange(x0, x0 + (nx * dx));
572        volPtr->yAxis.SetRange(y0, y0 + (ny * dy));
573        volPtr->zAxis.SetRange(z0, z0 + (nz * dz));
574        volPtr->wAxis.SetRange(vmin, vmax);
575        volPtr->update_pending = true;
576        delete [] data;
577       
578    } else {
579        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
580        Rappture::FieldPrism3D field(xymesh, zgrid);
581       
582        double dval;
583        int nread = 0;
584        int ixy = 0;
585        int iz = 0;
586        while (!fin.eof() && nread < npts) {
587            fin >> dval;
588            if (fin.fail()) {
589                result.addError("after %d of %d points: can't read number",
590                                nread, npts);
591                return false;
592            } else {
593                int nid = nxy*iz + ixy;
594                field.define(nid, dval);
595               
596                nread++;
597                if (++iz >= nz) {
598                    iz = 0;
599                    ixy++;
600                }
601            }
602        }
603       
604        // make sure that we read all of the expected points
605        if (nread != nxy*nz) {
606            result.addError("inconsistent data: expected %d points "
607                            "but found %d points", nxy*nz, nread);
608            return false;
609        }
610       
611        // figure out a good mesh spacing
612        int nsample = 30;
613        x0 = field.rangeMin(Rappture::xaxis);
614        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
615        y0 = field.rangeMin(Rappture::yaxis);
616        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
617        z0 = field.rangeMin(Rappture::zaxis);
618        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
619        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
620       
621        nx = (int)ceil(dx/dmin);
622        ny = (int)ceil(dy/dmin);
623        nz = (int)ceil(dz/dmin);
624#ifndef NV40
625        // must be an even power of 2 for older cards
626        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
627        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
628        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
629#endif
630        float *data = new float[4*nx*ny*nz];
631       
632        double vmin = field.valueMin();
633        double dv = field.valueMax() - field.valueMin();
634        if (dv == 0.0) {
635            dv = 1.0;
636        }
637        // generate the uniformly sampled data that we need for a volume
638        int ngen = 0;
639        double nzero_min = 0.0;
640        for (iz=0; iz < nz; iz++) {
641            double zval = z0 + iz*dmin;
642            for (int iy=0; iy < ny; iy++) {
643                double yval = y0 + iy*dmin;
644                for (int ix=0; ix < nx; ix++) {
645                    double xval = x0 + ix*dmin;
646                    double v = field.value(xval,yval,zval);
647                   
648                    if (v != 0.0f && v < nzero_min) {
649                        nzero_min = v;
650                    }
651                    // scale all values [0-1], -1 => out of bounds
652                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
653                    data[ngen] = v;
654                   
655                    ngen += 4;
656                }
657            }
658        }
659       
660        // FIXME: This next section of code should be replaced by a
661        // call to the computeSimpleGradient() function. There is a slight
662        // difference in the code below and the aforementioned function
663        // in that the commented out lines in the else statements are
664        // different.
665        //
666        // Compute the gradient of this data.  BE CAREFUL: center
667        // calculation on each node to avoid skew in either direction.
668        ngen = 0;
669        for (int iz=0; iz < nz; iz++) {
670            for (int iy=0; iy < ny; iy++) {
671                for (int ix=0; ix < nx; ix++) {
672                    // gradient in x-direction
673                    //double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
674                    //double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
675                    double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
676                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
677                    if (valm1 < 0 || valp1 < 0) {
678                        data[ngen+1] = 0.0;
679                    } else {
680                        data[ngen+1] = valp1-valm1; // assume dx=1
681                        //data[ngen+1] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
682                    }
683                   
684                    // gradient in y-direction
685                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
686                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
687                    if (valm1 < 0 || valp1 < 0) {
688                        data[ngen+2] = 0.0;
689                    } else {
690                        data[ngen+2] = valp1-valm1; // assume dy=1
691                        //data[ngen+2] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
692                    }
693                   
694                    // gradient in z-direction
695                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
696                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
697                    if (valm1 < 0 || valp1 < 0) {
698                        data[ngen+3] = 0.0;
699                    } else {
700                        data[ngen+3] = valp1-valm1; // assume dz=1
701                        //data[ngen+3] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
702                    }
703                   
704                    ngen += 4;
705                }
706            }
707        }
708       
709        Volume *volPtr;
710        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
711                                      field.valueMin(), field.valueMax(), nzero_min);
712        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
713                               field.rangeMax(Rappture::xaxis));
714        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
715                               field.rangeMax(Rappture::yaxis));
716        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
717                               field.rangeMax(Rappture::zaxis));
718        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
719        volPtr->update_pending = true;
720        delete [] data;
721    }
722    //
723    // Center this new volume on the origin.
724    //
725    float dx0 = -0.5;
726    float dy0 = -0.5*dy/dx;
727    float dz0 = -0.5*dz/dx;
728    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
729    return true;
730}
731
732bool
733load_volume_stream(Rappture::Outcome &result, int index, std::iostream& fin)
734{
735    printf("load_volume_stream\n");
736
737    Rappture::MeshTri2D xymesh;
738    int dummy, nx, ny, nz, nxy, npts;
739    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
740    char line[128], type[128], *start;
741
742    int isrect = 1;
743
744    dx = dy = dz = 0.0;         // Suppress compiler warning.
745    x0 = y0 = z0 = 0.0;         // May not have an origin line.
746    while (!fin.eof()) {
747        fin.getline(line, sizeof(line) - 1);
748        if (fin.fail()) {
749            result.error("error in data stream");
750            return false;
751        }
752        for (start=line; *start == ' ' || *start == '\t'; start++)
753            ;  // skip leading blanks
754
755        if (*start != '#') {  // skip comment lines
756            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
757                // found grid size
758                isrect = 1;
759            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
760                isrect = 0;
761
762                double xx, yy, zz;
763                for (int i=0; i < nxy; i++) {
764                    fin.getline(line,sizeof(line)-1);
765                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
766                        xymesh.addNode( Rappture::Node2D(xx,yy) );
767                    }
768                }
769
770                char fpts[128];
771                sprintf(fpts, "/tmp/tmppts%d", getpid());
772                char fcells[128];
773                sprintf(fcells, "/tmp/tmpcells%d", getpid());
774
775                std::ofstream ftmp(fpts);
776                // save corners of bounding box first, to work around meshing
777                // problems in voronoi utility
778                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
779                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
780                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
781                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
782                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
783                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
784                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
785                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
786                for (int i=0; i < nxy; i++) {
787                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
788
789                }
790                ftmp.close();
791
792                char cmdstr[512];
793                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
794                if (system(cmdstr) == 0) {
795                    int cx, cy, cz;
796                    std::ifstream ftri(fcells);
797                    while (!ftri.eof()) {
798                        ftri.getline(line,sizeof(line)-1);
799                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
800                            if (cx >= 4 && cy >= 4 && cz >= 4) {
801                                // skip first 4 boundary points
802                                xymesh.addCell(cx-4, cy-4, cz-4);
803                            }
804                        }
805                    }
806                    ftri.close();
807                } else {
808                    result.error("triangularization failed");
809                    return false;
810                }
811                unlink(fpts);
812                unlink(fcells);
813            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
814                // found z-grid
815            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
816                // found origin
817            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
818                // found one of the delta lines
819                if (ddx != 0.0) { dx = ddx; }
820                else if (ddy != 0.0) { dy = ddy; }
821                else if (ddz != 0.0) { dz = ddz; }
822            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
823                if (isrect && (npts != nx*ny*nz)) {
824                    result.addError("inconsistent data: expected %d points"
825                                    " but found %d points", nx*ny*nz, npts);
826                    return false;
827                } else if (!isrect && (npts != nxy*nz)) {
828                    result.addError("inconsistent data: expected %d points"
829                                    " but found %d points", nx*ny*nz, npts);
830                    return false;
831                }
832                break;
833            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
834                if (npts != nx*ny*nz) {
835                    result.addError("inconsistent data: expected %d points"
836                                    " but found %d points", nx*ny*nz, npts);
837                    return false;
838                }
839                break;
840            }
841        }
842    }
843    // read data points
844    if (fin.eof()) {
845        result.error("data not found in stream");
846        return false;
847    }
848    if (isrect) {
849        Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
850        Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
851        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
852        Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
853
854        double dval[6];
855        int nread = 0;
856        int ix = 0;
857        int iy = 0;
858        int iz = 0;
859        while (!fin.eof() && nread < npts) {
860            fin.getline(line,sizeof(line)-1);
861            if (fin.fail()) {
862                result.addError("error reading data points");
863                return false;
864            }
865            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
866           
867            for (int p=0; p < n; p++) {
868                int nindex = iz*nx*ny + iy*nx + ix;
869                field.define(nindex, dval[p]);
870                fflush(stderr);
871                nread++;
872                if (++iz >= nz) {
873                    iz = 0;
874                    if (++iy >= ny) {
875                        iy = 0;
876                        ++ix;
877                    }
878                }
879            }
880        }
881       
882        // make sure that we read all of the expected points
883        if (nread != nx*ny*nz) {
884            result.addError("inconsistent data: expected %d points"
885                            " but found %d points", nx*ny*nz, npts);
886            return false;
887        }
888       
889        // figure out a good mesh spacing
890        int nsample = 30;
891        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
892        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
893        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
894        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
895       
896        nx = (int)ceil(dx/dmin);
897        ny = (int)ceil(dy/dmin);
898        nz = (int)ceil(dz/dmin);
899       
900#ifndef NV40
901        // must be an even power of 2 for older cards
902        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
903        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
904        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
905#endif
906       
907        //#define _SOBEL
908#ifdef _SOBEL_
909        const int step = 1;
910        float *cdata = new float[nx*ny*nz * step];
911        int ngen = 0;
912        double nzero_min = 0.0;
913        for (int iz=0; iz < nz; iz++) {
914            double zval = z0 + iz*dmin;
915            for (int iy=0; iy < ny; iy++) {
916                double yval = y0 + iy*dmin;
917                for (int ix=0; ix < nx; ix++) {
918                    double xval = x0 + ix*dmin;
919                    double v = field.value(xval,yval,zval);
920                   
921                    if (v != 0.0f && v < nzero_min) {
922                        nzero_min = v;
923                    }
924                   
925                    // scale all values [0-1], -1 => out of bounds
926                    v = (isnan(v)) ? -1.0 : v;
927                   
928                    cdata[ngen] = v;
929                    ngen += step;
930                }
931            }
932        }
933       
934        float* data = computeGradient(cdata, nx, ny, nz, field.valueMin(),
935                                      field.valueMax());
936#else
937        double vmin = field.valueMin();
938        double vmax = field.valueMax();
939        double nzero_min = 0;
940        float *data = new float[nx*ny*nz * 4];
941        double dv = vmax - vmin;
942        int ngen = 0;
943        if (dv == 0.0)  dv = 1.0;
944       
945        for (int iz=0; iz < nz; iz++) {
946            double zval = z0 + iz*dmin;
947            for (int iy=0; iy < ny; iy++) {
948                double yval = y0 + iy*dmin;
949                for (int ix=0; ix < nx; ix++) {
950                    double xval = x0 + ix*dmin;
951                    double v = field.value(xval,yval,zval);
952                   
953                    // scale all values [0-1], -1 => out of bounds
954                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
955                   
956                    data[ngen] = v;
957                    ngen += 4;
958                }
959            }
960        }
961       
962        computeSimpleGradient(data, nx, ny, nz);
963#endif
964       
965        for (int i=0; i<nx*ny*nz; i++) {
966            fprintf(stderr,"enddata[%i] = %lg\n",i,data[i]);
967            fflush(stderr);
968        }
969       
970        fprintf(stdout,"End Data Stats index = %i\n",index);
971        fprintf(stdout,"nx = %i ny = %i nz = %i\n",nx,ny,nz);
972        fprintf(stdout,"dx = %lg dy = %lg dz = %lg\n",dx,dy,dz);
973        fprintf(stdout,"dataMin = %lg\tdataMax = %lg\tnzero_min = %lg\n", field.valueMin(),field.valueMax(),nzero_min);
974        fflush(stdout);
975       
976        Volume *volPtr;
977        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
978                                      field.valueMin(), field.valueMax(), nzero_min);
979        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
980                               field.rangeMax(Rappture::xaxis));
981        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
982                               field.rangeMax(Rappture::yaxis));
983        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
984                               field.rangeMax(Rappture::zaxis));
985        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
986        volPtr->update_pending = true;
987        // TBD..
988        // POINTSET
989        /*
990          PointSet* pset = new PointSet();
991          pset->initialize(volume[index], (float*) data);
992          pset->setVisible(true);
993          NanoVis::pointSet.push_back(pset);
994          updateColor(pset);
995          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
996        */
997       
998        delete [] data;
999       
1000    } else {
1001        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
1002        Rappture::FieldPrism3D field(xymesh, zgrid);
1003       
1004        double dval;
1005        int nread = 0;
1006        int ixy = 0;
1007        int iz = 0;
1008        while (!fin.eof() && nread < npts) {
1009            fin >> dval;
1010            if (fin.fail()) {
1011                result.addError("after %d of %d points: can't read number",
1012                                nread, npts);
1013                return false;
1014            } else {
1015                int nid = nxy*iz + ixy;
1016                field.define(nid, dval);
1017               
1018                nread++;
1019                if (++iz >= nz) {
1020                    iz = 0;
1021                    ixy++;
1022                }
1023            }
1024        }
1025       
1026        // make sure that we read all of the expected points
1027        if (nread != nxy*nz) {
1028            result.addError("inconsistent data: expected %d points"
1029                            " but found %d points", nx*ny*nz, npts);
1030            return false;
1031        }
1032       
1033        // figure out a good mesh spacing
1034        int nsample = 30;
1035        x0 = field.rangeMin(Rappture::xaxis);
1036        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
1037        y0 = field.rangeMin(Rappture::yaxis);
1038        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
1039        z0 = field.rangeMin(Rappture::zaxis);
1040        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
1041        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
1042       
1043        nx = (int)ceil(dx/dmin);
1044        ny = (int)ceil(dy/dmin);
1045        nz = (int)ceil(dz/dmin);
1046#ifndef NV40
1047        // must be an even power of 2 for older cards
1048        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
1049        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
1050        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
1051#endif
1052        float *data = new float[4*nx*ny*nz];
1053       
1054        double vmin = field.valueMin();
1055        double dv = field.valueMax() - field.valueMin();
1056        if (dv == 0.0) { dv = 1.0; }
1057       
1058        // generate the uniformly sampled data that we need for a volume
1059        int ngen = 0;
1060        double nzero_min = 0.0;
1061        for (iz=0; iz < nz; iz++) {
1062            double zval = z0 + iz*dmin;
1063            for (int iy=0; iy < ny; iy++) {
1064                double yval = y0 + iy*dmin;
1065                for (int ix=0; ix < nx; ix++) {
1066                    double xval = x0 + ix*dmin;
1067                    double v = field.value(xval,yval,zval);
1068                   
1069                    if (v != 0.0f && v < nzero_min) {
1070                        nzero_min = v;
1071                    }
1072                    // scale all values [0-1], -1 => out of bounds
1073                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
1074                    data[ngen] = v;
1075                   
1076                    ngen += 4;
1077                }
1078            }
1079        }
1080       
1081        // Compute the gradient of this data.  BE CAREFUL: center
1082        // calculation on each node to avoid skew in either direction.
1083        ngen = 0;
1084        for (int iz=0; iz < nz; iz++) {
1085            for (int iy=0; iy < ny; iy++) {
1086                for (int ix=0; ix < nx; ix++) {
1087                    // gradient in x-direction
1088                    double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
1089                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
1090                    if (valm1 < 0 || valp1 < 0) {
1091                        data[ngen+1] = 0.0;
1092                    } else {
1093                        data[ngen+1] = valp1-valm1; // assume dx=1
1094                        //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1 (ISO)
1095                    }
1096                   
1097                    // gradient in y-direction
1098                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
1099                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
1100                    if (valm1 < 0 || valp1 < 0) {
1101                        data[ngen+2] = 0.0;
1102                    } else {
1103                        data[ngen+2] = valp1-valm1; // assume dy=1
1104                        //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1 (ISO)
1105                    }
1106                   
1107                    // gradient in z-direction
1108                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
1109                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
1110                    if (valm1 < 0 || valp1 < 0) {
1111                        data[ngen+3] = 0.0;
1112                    } else {
1113                        data[ngen+3] = valp1-valm1; // assume dz=1
1114                        //data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1 (ISO)
1115                    }
1116                   
1117                    ngen += 4;
1118                }
1119            }
1120        }
1121       
1122        Volume *volPtr;
1123        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
1124                                      field.valueMin(), field.valueMax(), nzero_min);
1125        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
1126                               field.rangeMax(Rappture::xaxis));
1127        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
1128                               field.rangeMax(Rappture::yaxis));
1129        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
1130                               field.rangeMax(Rappture::zaxis));
1131        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
1132        volPtr->update_pending = true;
1133        // TBD..
1134        // POINTSET
1135        /*
1136          PointSet* pset = new PointSet();
1137          pset->initialize(volume[index], (float*) data);
1138          pset->setVisible(true);
1139          NanoVis::pointSet.push_back(pset);
1140          updateColor(pset);
1141          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
1142        */
1143       
1144       
1145        delete [] data;
1146    }
1147
1148    //
1149    // Center this new volume on the origin.
1150    //
1151    float dx0 = -0.5;
1152    float dy0 = -0.5*dy/dx;
1153    float dz0 = -0.5*dz/dx;
1154    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
1155    return true;
1156}
1157
1158
1159bool
1160load_volume_stream_insoo(Rappture::Outcome &result, int index,
1161                         std::iostream& fin)
1162{
1163    printf("load_volume_stream\n");
1164 
1165    Rappture::MeshTri2D xymesh;
1166    int dummy, nx, ny, nz, nxy, npts;
1167    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
1168    char line[128], type[128], *start;
1169
1170    int isrect = 1;
1171
1172    dx = dy = dz = 0.0;         // Suppress compiler warning.
1173    x0 = y0 = z0 = 0.0;         // May not have an origin line.
1174    while (!fin.eof()) {
1175        fin.getline(line, sizeof(line) - 1);
1176        if (fin.fail()) {
1177            result.addError("line \"%s\"error in data stream");
1178            return false;
1179        }
1180        for (start=line; *start == ' ' || *start == '\t'; start++)
1181            ;  // skip leading blanks
1182
1183        if (*start != '#') {  // skip comment lines
1184            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
1185                // found grid size
1186                isrect = 1;
1187            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
1188                isrect = 0;
1189
1190                double xx, yy, zz;
1191                for (int i=0; i < nxy; i++) {
1192                    fin.getline(line,sizeof(line)-1);
1193                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
1194                        xymesh.addNode( Rappture::Node2D(xx,yy) );
1195                    }
1196                }
1197
1198                char fpts[128];
1199                sprintf(fpts, "/tmp/tmppts%d", getpid());
1200                char fcells[128];
1201                sprintf(fcells, "/tmp/tmpcells%d", getpid());
1202
1203                std::ofstream ftmp(fpts);
1204                // save corners of bounding box first, to work around meshing
1205                // problems in voronoi utility
1206                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
1207                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
1208                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
1209                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
1210                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
1211                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
1212                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
1213                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
1214                for (int i=0; i < nxy; i++) {
1215                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
1216
1217                }
1218                ftmp.close();
1219
1220                char cmdstr[512];
1221                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
1222                if (system(cmdstr) == 0) {
1223                    int cx, cy, cz;
1224                    std::ifstream ftri(fcells);
1225                    while (!ftri.eof()) {
1226                        ftri.getline(line,sizeof(line)-1);
1227                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
1228                            if (cx >= 4 && cy >= 4 && cz >= 4) {
1229                                // skip first 4 boundary points
1230                                xymesh.addCell(cx-4, cy-4, cz-4);
1231                            }
1232                        }
1233                    }
1234                    ftri.close();
1235                } else {
1236                    result.error("triangularization failed");
1237                    return false;
1238                }
1239                unlink(fpts), unlink(fcells);
1240            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
1241                // found z-grid
1242            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
1243                // found origin
1244            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
1245                // found one of the delta lines
1246                if (ddx != 0.0) { dx = ddx; }
1247                else if (ddy != 0.0) { dy = ddy; }
1248                else if (ddz != 0.0) { dz = ddz; }
1249            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
1250                if (isrect && (npts != nx*ny*nz)) {
1251                    result.addError("inconsistent data: expected %d points"
1252                                    " but found %d points", nx*ny*nz, npts);
1253                    return false;
1254                } else if (!isrect && (npts != nxy*nz)) {
1255                    result.addError("inconsistent data: expected %d points"
1256                                    " but found %d points", nx*ny*nz, npts);
1257                    return false;
1258                }
1259                break;
1260            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
1261                if (npts != nx*ny*nz) {
1262                    result.addError("inconsistent data: expected %d points"
1263                                    " but found %d points", nx*ny*nz, npts);
1264                    return false;
1265                }
1266                break;
1267            }
1268        }
1269    }
1270
1271    // read data points
1272    if (fin.eof()) {
1273        result.error("data not found in stream");
1274        return false;
1275    }
1276
1277    if (isrect) {
1278        Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
1279        Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
1280        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
1281        Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
1282       
1283        double dval[6];
1284        int nread = 0;
1285        int ix = 0;
1286        int iy = 0;
1287        int iz = 0;
1288        while (!fin.eof() && nread < npts) {
1289            fin.getline(line,sizeof(line)-1);
1290            if (fin.fail()) {
1291                result.error("error reading data points");
1292                return false;
1293            }
1294            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
1295           
1296            for (int p=0; p < n; p++) {
1297                int nindex = iz*nx*ny + iy*nx + ix;
1298                field.define(nindex, dval[p]);
1299                fprintf(stderr,"nindex = %i\tdval[%i] = %lg\n", nindex, p,
1300                        dval[p]);
1301                fflush(stderr);
1302                nread++;
1303                if (++iz >= nz) {
1304                    iz = 0;
1305                    if (++iy >= ny) {
1306                        iy = 0;
1307                        ++ix;
1308                    }
1309                }
1310            }
1311        }
1312       
1313        // make sure that we read all of the expected points
1314        if (nread != nx*ny*nz) {
1315            result.addError("inconsistent data: expected %d points"
1316                            " but found %d points", nx*ny*nz, npts);
1317            return false;
1318        }
1319       
1320        // figure out a good mesh spacing
1321        int nsample = 30;
1322        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
1323        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
1324        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
1325        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
1326       
1327        nx = (int)ceil(dx/dmin);
1328        ny = (int)ceil(dy/dmin);
1329        nz = (int)ceil(dz/dmin);
1330       
1331#ifndef NV40
1332        // must be an even power of 2 for older cards
1333        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
1334        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
1335        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
1336#endif
1337       
1338        float *data = new float[4*nx*ny*nz];
1339       
1340        double vmin = field.valueMin();
1341        double dv = field.valueMax() - field.valueMin();
1342        if (dv == 0.0) { dv = 1.0; }
1343       
1344        int ngen = 0;
1345        double nzero_min = 0.0;
1346        for (iz=0; iz < nz; iz++) {
1347            double zval = z0 + iz*dmin;
1348            for (int iy=0; iy < ny; iy++) {
1349                double yval = y0 + iy*dmin;
1350                for (int ix=0; ix < nx; ix++) {
1351                    double xval = x0 + ix*dmin;
1352                    double v = field.value(xval,yval,zval);
1353                   
1354                    if (v != 0.0f && v < nzero_min) {
1355                        nzero_min = v;
1356                    }
1357                    // scale all values [0-1], -1 => out of bounds
1358                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
1359                    data[ngen] = v;
1360                   
1361                    ngen += 4;
1362                }
1363            }
1364        }
1365       
1366        // Compute the gradient of this data.  BE CAREFUL: center
1367        // calculation on each node to avoid skew in either direction.
1368        ngen = 0;
1369        for (int iz=0; iz < nz; iz++) {
1370            for (int iy=0; iy < ny; iy++) {
1371                for (int ix=0; ix < nx; ix++) {
1372                    // gradient in x-direction
1373                    double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
1374                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
1375                    if (valm1 < 0 || valp1 < 0) {
1376                        data[ngen+1] = 0.0;
1377                    } else {
1378                        data[ngen+1] = valp1-valm1; // assume dx=1
1379                        //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1 (ISO)
1380                    }
1381                   
1382                    // gradient in y-direction
1383                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
1384                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
1385                    if (valm1 < 0 || valp1 < 0) {
1386                        data[ngen+2] = 0.0;
1387                    } else {
1388                        data[ngen+2] = valp1-valm1; // assume dy=1
1389                        //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1 (ISO)
1390                    }
1391                   
1392                    // gradient in z-direction
1393                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
1394                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
1395                    if (valm1 < 0 || valp1 < 0) {
1396                        data[ngen+3] = 0.0;
1397                    } else {
1398                        data[ngen+3] = valp1-valm1; // assume dz=1
1399                        //data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1 (ISO)
1400                    }
1401                   
1402                    ngen += 4;
1403                }
1404            }
1405        }
1406       
1407        /*
1408          float *cdata = new float[nx*ny*nz];
1409          int ngen = 0;
1410          double nzero_min = 0.0;
1411          for (int iz=0; iz < nz; iz++) {
1412          double zval = z0 + iz*dmin;
1413          for (int iy=0; iy < ny; iy++) {
1414          double yval = y0 + iy*dmin;
1415          for (int ix=0; ix < nx; ix++) {
1416          double xval = x0 + ix*dmin;
1417          double v = field.value(xval,yval,zval);
1418         
1419          if (v != 0.0f && v < nzero_min) {
1420          nzero_min = v;
1421          }
1422         
1423          // scale all values [0-1], -1 => out of bounds
1424          v = (isnan(v)) ? -1.0 : v;
1425         
1426          cdata[ngen] = v;
1427          ++ngen;
1428          }
1429                }
1430            }
1431           
1432            float* data = computeGradient(cdata, nx, ny, nz, field.valueMin(),
1433                                          field.valueMax());
1434                                         
1435            for (int i=0; i<nx*ny*nz; i++) {
1436                fprintf(stderr,"enddata[%i] = %lg\n",i,data[i]);
1437                fflush(stderr);
1438            }
1439
1440            fprintf(stdout,"End Data Stats index = %i\n",index);
1441            fprintf(stdout,"nx = %i ny = %i nz = %i\n",nx,ny,nz);
1442            fprintf(stdout,"dx = %lg dy = %lg dz = %lg\n",dx,dy,dz);
1443            fprintf(stdout,"dataMin = %lg\tdataMax = %lg\tnzero_min = %lg\n", field.valueMin(),field.valueMax(),nzero_min);
1444            fflush(stdout);
1445            */
1446
1447        Volume *volPtr;
1448        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
1449                                      field.valueMin(), field.valueMax(), nzero_min);
1450        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
1451                               field.rangeMax(Rappture::xaxis));
1452        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
1453                               field.rangeMax(Rappture::yaxis));
1454        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
1455                               field.rangeMax(Rappture::zaxis));
1456        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
1457        volPtr->update_pending = true;
1458        // TBD..
1459        // POINTSET
1460        /*
1461          PointSet* pset = new PointSet();
1462          pset->initialize(volume[index], (float*) data);
1463          pset->setVisible(true);
1464          NanoVis::pointSet.push_back(pset);
1465          updateColor(pset);
1466          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
1467        */
1468       
1469        delete [] data;
1470       
1471    } else {
1472        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
1473        Rappture::FieldPrism3D field(xymesh, zgrid);
1474       
1475        double dval;
1476        int nread = 0;
1477        int ixy = 0;
1478        int iz = 0;
1479        while (!fin.eof() && nread < npts) {
1480            fin >> dval;
1481            if (fin.fail()) {
1482                char mesg[256];
1483                sprintf(mesg,"after %d of %d points: can't read number",
1484                        nread, npts);
1485                result.error(mesg);
1486                return false;
1487            } else {
1488                int nid = nxy*iz + ixy;
1489                field.define(nid, dval);
1490               
1491                nread++;
1492                if (++iz >= nz) {
1493                    iz = 0;
1494                    ixy++;
1495                }
1496            }
1497        }
1498       
1499        // make sure that we read all of the expected points
1500        if (nread != nxy*nz) {
1501            result.addError("inconsistent data: expected %d points"
1502                            " but found %d points", nx*ny*nz, npts);
1503            return false;
1504        }
1505       
1506        // figure out a good mesh spacing
1507        int nsample = 30;
1508        x0 = field.rangeMin(Rappture::xaxis);
1509        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
1510        y0 = field.rangeMin(Rappture::yaxis);
1511        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
1512        z0 = field.rangeMin(Rappture::zaxis);
1513        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
1514        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
1515       
1516        nx = (int)ceil(dx/dmin);
1517        ny = (int)ceil(dy/dmin);
1518        nz = (int)ceil(dz/dmin);
1519#ifndef NV40
1520        // must be an even power of 2 for older cards
1521        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
1522        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
1523        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
1524#endif
1525        float *data = new float[4*nx*ny*nz];
1526       
1527        double vmin = field.valueMin();
1528        double dv = field.valueMax() - field.valueMin();
1529        if (dv == 0.0) { dv = 1.0; }
1530       
1531        // generate the uniformly sampled data that we need for a volume
1532        int ngen = 0;
1533        double nzero_min = 0.0;
1534        for (iz=0; iz < nz; iz++) {
1535            double zval = z0 + iz*dmin;
1536            for (int iy=0; iy < ny; iy++) {
1537                double yval = y0 + iy*dmin;
1538                for (int ix=0; ix < nx; ix++) {
1539                    double xval = x0 + ix*dmin;
1540                    double v = field.value(xval,yval,zval);
1541                   
1542                    if (v != 0.0f && v < nzero_min) {
1543                        nzero_min = v;
1544                    }
1545                    // scale all values [0-1], -1 => out of bounds
1546                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
1547                    data[ngen] = v;
1548                   
1549                    ngen += 4;
1550                }
1551            }
1552        }
1553       
1554        // Compute the gradient of this data.  BE CAREFUL: center
1555        // calculation on each node to avoid skew in either direction.
1556        ngen = 0;
1557        for (int iz=0; iz < nz; iz++) {
1558            for (int iy=0; iy < ny; iy++) {
1559                for (int ix=0; ix < nx; ix++) {
1560                    // gradient in x-direction
1561                    double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
1562                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
1563                    if (valm1 < 0 || valp1 < 0) {
1564                        data[ngen+1] = 0.0;
1565                    } else {
1566                        data[ngen+1] = valp1-valm1; // assume dx=1
1567                        //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1 (ISO)
1568                    }
1569                   
1570                    // gradient in y-direction
1571                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
1572                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
1573                    if (valm1 < 0 || valp1 < 0) {
1574                        data[ngen+2] = 0.0;
1575                    } else {
1576                        data[ngen+2] = valp1-valm1; // assume dy=1
1577                        //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1 (ISO)
1578                    }
1579                   
1580                    // gradient in z-direction
1581                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
1582                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
1583                    if (valm1 < 0 || valp1 < 0) {
1584                        data[ngen+3] = 0.0;
1585                    } else {
1586                        data[ngen+3] = valp1-valm1; // assume dz=1
1587                        //data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1 (ISO)
1588                    }
1589                   
1590                    ngen += 4;
1591                }
1592            }
1593        }
1594       
1595        Volume *volPtr;
1596        volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
1597                                      field.valueMin(), field.valueMax(), nzero_min);
1598        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
1599                               field.rangeMax(Rappture::xaxis));
1600        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
1601                               field.rangeMax(Rappture::yaxis));
1602        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
1603                               field.rangeMax(Rappture::zaxis));
1604        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
1605        volPtr->update_pending = true;
1606        // TBD..
1607        // POINTSET
1608        /*
1609          PointSet* pset = new PointSet();
1610          pset->initialize(volume[index], (float*) data);
1611          pset->setVisible(true);
1612          NanoVis::pointSet.push_back(pset);
1613          updateColor(pset);
1614          NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
1615        */
1616       
1617       
1618        delete [] data;
1619    }
1620
1621    //
1622    // Center this new volume on the origin.
1623    //
1624    float dx0 = -0.5;
1625    float dy0 = -0.5*dy/dx;
1626    float dz0 = -0.5*dz/dx;
1627    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
1628    return true;
1629}
Note: See TracBrowser for help on using the repository browser.