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

Last change on this file since 1363 was 1325, checked in by gah, 16 years ago

Clean up of warnings, outcomes

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