source: trunk/vizservers/nanovis/dxReader.cpp @ 928

Last change on this file since 928 was 928, checked in by gah, 17 years ago

collect limits for axes

File size: 41.5 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#include <stdio.h>
22#include <math.h>
23#include <fstream>
24#include <iostream>
25#include <sstream>
26#include <string>
27#include <sys/types.h>
28#include <unistd.h>
29
30#include "Nv.h"
31
32#include "nanovis.h"
33#include "RpField1D.h"
34#include "RpFieldRect3D.h"
35#include "RpFieldPrism3D.h"
36
37//transfer function headers
38#include "ZincBlendeVolume.h"
39#include "NvZincBlendeReconstructor.h"
40#include "GradientFilter.h"
41
42#define  _LOCAL_ZINC_TEST_ 0
43
44static float *
45merge(float* scalar, float* gradient, int size)
46{
47    float* data = (float*) malloc(sizeof(float) * 4 * size);
48
49    Vector3* g = (Vector3*) gradient;
50   
51    int ngen = 0, sindex = 0;
52    for (sindex = 0; sindex <size; ++sindex) {
53        data[ngen++] = scalar[sindex];
54        data[ngen++] = g[sindex].x;
55        data[ngen++] = g[sindex].y;
56        data[ngen++] = g[sindex].z;
57    }
58    return data;
59}
60
61static void
62normalizeScalar(float* fdata, int count, float min, float max)
63{
64    float v = max - min;
65    if (v != 0.0f) {
66        for (int i = 0; i < count; ++i) {
67            fdata[i] = fdata[i] / v;
68        }
69    }
70}
71
72static float*
73computeGradient(float* fdata, int width, int height, int depth,
74                float min, float max)
75{
76    float* gradients = (float *)malloc(width * height * depth * 3 *
77                                       sizeof(float));
78    float* tempGradients = (float *)malloc(width * height * depth * 3 *
79                                           sizeof(float));
80    int sizes[3] = { width, height, depth };
81    computeGradients(tempGradients, fdata, sizes, DATRAW_FLOAT);
82    filterGradients(tempGradients, sizes);
83    quantizeGradients(tempGradients, gradients, sizes, DATRAW_FLOAT);
84    normalizeScalar(fdata, width * height * depth, min, max);
85    float* data = merge(fdata, gradients, width * height * depth);
86    return data;
87}
88
89/*
90 * Load a 3D vector field from a dx-format file
91 */
92void
93load_vector_stream(int index, std::istream& fin)
94{
95    int dummy, nx, ny, nz, npts;
96    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
97    char line[128], type[128], *start;
98
99    dx = dy = dz = 0.0;         // Suppress compiler warning.
100    while (!fin.eof()) {
101        fin.getline(line, sizeof(line) - 1);
102        if (fin.fail()) {
103            //return result.error("error in data stream");
104            return;
105        }
106        for (start=&line[0]; *start == ' ' || *start == '\t'; start++)
107            ;  // skip leading blanks
108
109        if (*start != '#') {  // skip comment lines
110            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
111                // found grid size
112            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
113                // found origin
114            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
115                // found one of the delta lines
116                if (ddx != 0.0) {
117                    dx = ddx;
118                } else if (ddy != 0.0) {
119                    dy = ddy;
120                } else if (ddz != 0.0) {
121                    dz = ddz;
122                }
123            } else if (sscanf(start, "object %d class array type %s shape 3 rank 1 items %d data follows", &dummy, type, &npts) == 3) {
124                if (npts != nx*ny*nz) {
125                    std::cerr << "inconsistent data: expected " << nx*ny*nz << " points but found " << npts << " points" << std::endl;
126                    return;
127                }
128                break;
129            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
130                if (npts != nx*ny*nz) {
131                    std::cerr << "inconsistent data: expected " << nx*ny*nz << " points but found " << npts << " points" << std::endl;
132                    return;
133                }
134                break;
135            }
136        }
137    }
138
139    // read data points
140    if (!fin.eof()) {
141        Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
142        Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
143        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
144        Rappture::FieldRect3D xfield(xgrid, ygrid, zgrid);
145        Rappture::FieldRect3D yfield(xgrid, ygrid, zgrid);
146        Rappture::FieldRect3D zfield(xgrid, ygrid, zgrid);
147
148        double vx, vy, vz;
149        int nread = 0;
150        for (int ix=0; ix < nx; ix++) {
151            for (int iy=0; iy < ny; iy++) {
152                for (int iz=0; iz < nz; iz++) {
153                    if (fin.eof() || nread > npts) {
154                        break;
155                    }
156                    fin.getline(line,sizeof(line)-1);
157                    if (sscanf(line, "%lg %lg %lg", &vx, &vy, &vz) == 3) {
158                        int nindex = iz*nx*ny + iy*nx + ix;
159                        xfield.define(nindex, vx);
160                        yfield.define(nindex, vy);
161                        zfield.define(nindex, vz);
162                        nread++;
163                    }
164                }
165            }
166        }
167
168        // make sure that we read all of the expected points
169        if (nread != nx*ny*nz) {
170            std::cerr << "inconsistent data: expected " << nx*ny*nz << " points but found " << nread << " points" << std::endl;
171            return;
172        }
173
174        // figure out a good mesh spacing
175        int nsample = 30;
176        dx = xfield.rangeMax(Rappture::xaxis) - xfield.rangeMin(Rappture::xaxis);
177        dy = xfield.rangeMax(Rappture::yaxis) - xfield.rangeMin(Rappture::yaxis);
178        dz = xfield.rangeMax(Rappture::zaxis) - xfield.rangeMin(Rappture::zaxis);
179        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
180
181        nx = (int)ceil(dx/dmin);
182        ny = (int)ceil(dy/dmin);
183        nz = (int)ceil(dz/dmin);
184
185#ifndef NV40
186        // must be an even power of 2 for older cards
187        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
188        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
189        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
190#endif
191
192        float *data = new float[3*nx*ny*nz];
193        memset(data, 0, sizeof(float) * 3 * nx * ny * nz);
194
195        std::cout << "generating " << nx << "x" << ny << "x" << nz << " = " << nx*ny*nz << " points" << std::endl;
196
197        // generate the uniformly sampled data that we need for a volume
198        double vmin = 1e21;
199        double vmax = -1e21;
200        double nzero_min = 0.0;
201        int ngen = 0;
202        for (int iz=0; iz < nz; iz++) {
203            double zval = z0 + iz*dmin;
204            for (int iy=0; iy < ny; iy++) {
205                double yval = y0 + iy*dmin;
206                for (int ix=0; ix < nx; ix++) {
207                    double xval = x0 + ix*dmin;
208
209                    vx = xfield.value(xval,yval,zval);
210                    vy = yfield.value(xval,yval,zval);
211                    vz = zfield.value(xval,yval,zval);
212
213                    double vm;
214                    vm = sqrt(vx*vx + vy*vy + vz*vz);
215                    if (vm < vmin) {
216                        vmin = vm;
217                    } else if (vm > vmax) {
218                        vmax = vm;
219                    }
220                    if ((vm != 0.0f) && (vm < nzero_min)) {
221                        nzero_min = vm;
222                    }
223                    data[ngen++] = vx;
224                    data[ngen++] = vy;
225                    data[ngen++] = vz;
226                }
227            }
228        }
229
230        ngen = 0;
231
232        // scale should be accounted.
233        for (ngen=0; ngen < npts; ngen++) {
234            data[ngen] = (data[ngen]/(2.0*vmax) + 0.5);
235        }
236        Volume *volPtr;
237        volPtr = NanoVis::load_volume(index, nx, ny, nz, 3, data, vmin, vmax,
238                nzero_min);
239        volPtr->set_limits(NanoVis::X, x0, x0 + (nx * ddx));
240        volPtr->set_limits(NanoVis::Y, y0, y0 + (ny * ddy));
241        volPtr->set_limits(NanoVis::Z, z0, z0 + (nz * ddz));
242        delete [] data;
243    } else {
244        std::cerr << "WARNING: data not found in stream" << std::endl;
245    }
246}
247
248
249/* Load a 3D volume from a dx-format file
250 */
251Rappture::Outcome
252load_volume_stream2(int index, std::iostream& fin)
253{
254    Rappture::Outcome result;
255
256    Rappture::MeshTri2D xymesh;
257    int dummy, nx, ny, nz, nxy, npts;
258    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
259    char line[128], type[128], *start;
260
261    int isrect = 1;
262    dx = dy = dz = 0.0;         // Suppress compiler warning.
263    do {
264        fin.getline(line,sizeof(line)-1);
265        for (start=&line[0]; *start == ' ' || *start == '\t'; start++)
266            ;  // skip leading blanks
267
268        if (*start != '#') {  // skip comment lines
269            printf("%s\n", line);
270            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
271                // found grid size
272                isrect = 1;
273            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
274                isrect = 0;
275                double xx, yy, zz;
276                for (int i=0; i < nxy; i++) {
277                    fin.getline(line, sizeof(line));
278                    fin.getline(line,sizeof(line)-1);
279                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
280                        xymesh.addNode( Rappture::Node2D(xx,yy) );
281                    }
282                }
283                char mesg[256];
284                sprintf(mesg,"test");
285                result.error(mesg);
286                return result;
287
288                char fpts[128];
289                sprintf(fpts, "/tmp/tmppts%d", getpid());
290                char fcells[128];
291                sprintf(fcells, "/tmp/tmpcells%d", getpid());
292
293                std::ofstream ftmp(fpts);
294                // save corners of bounding box first, to work around meshing
295                // problems in voronoi utility
296                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
297                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
298                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
299                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
300                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
301                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
302                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
303                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
304                for (int i=0; i < nxy; i++) {
305                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
306               
307                }
308                ftmp.close();
309
310                char cmdstr[512];
311                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
312                if (system(cmdstr) == 0) {
313                    int cx, cy, cz;
314                    std::ifstream ftri(fcells);
315                    while (!ftri.eof()) {
316                        ftri.getline(line,sizeof(line)-1);
317                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
318                            if (cx >= 4 && cy >= 4 && cz >= 4) {
319                                // skip first 4 boundary points
320                                xymesh.addCell(cx-4, cy-4, cz-4);
321                            }
322                        }
323                    }
324                    ftri.close();
325                } else {
326                    return result.error("triangularization failed");
327                }
328
329                sprintf(cmdstr, "rm -f %s %s", fpts, fcells);
330                system(cmdstr);
331            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
332                // found z-grid
333            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
334                // found origin
335            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
336                int count = 0;
337                // found one of the delta lines
338                if (ddx != 0.0) {
339                    dx = ddx;
340                    count++;
341                }
342                if (ddy != 0.0) {
343                    dy = ddy;
344                    count++;
345                }
346                if (ddz != 0.0) {
347                    dz = ddz;
348                    count++;
349                }
350                if (count > 1) {
351                    return result.error(
352                        "don't know how to handle multiple non-zero delta values");
353                }
354            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
355                if (isrect && (npts != nx*ny*nz)) {
356                    char mesg[256];
357                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
358                    return result.error(mesg);
359                } else if (!isrect && (npts != nxy*nz)) {
360                    char mesg[256];
361                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, npts);
362                    return result.error(mesg);
363                }
364                break;
365            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
366                if (npts != nx*ny*nz) {
367                    char mesg[256];
368                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
369                    return result.error(mesg);
370                }
371                break;
372            }
373        }
374    } while (!fin.eof());
375
376    // read data points
377    if (!fin.eof()) {
378        if (isrect) {
379            double dval[6];
380            int nread = 0;
381            int ix = 0;
382            int iy = 0;
383            int iz = 0;
384            float* data = new float[nx *  ny *  nz * 4];
385            memset(data, 0, nx*ny*nz*4);
386            double vmin = 1e21;
387            double nzero_min = 1e21;
388            double vmax = -1e21;
389
390
391            while (!fin.eof() && nread < npts) {
392                fin.getline(line,sizeof(line)-1);
393                int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
394
395                for (int p=0; p < n; p++) {
396                    int nindex = (iz*nx*ny + iy*nx + ix) * 4;
397                    data[nindex] = dval[p];
398
399                    if (dval[p] < vmin) {
400                        vmin = dval[p];
401                    } else if (dval[p] > vmax) {
402                        vmax = dval[p];
403                    }
404                    if (dval[p] != 0.0f && dval[p] < nzero_min) {
405                        nzero_min = dval[p];
406                    }
407
408                    nread++;
409                    if (++iz >= nz) {
410                        iz = 0;
411                        if (++iy >= ny) {
412                            iy = 0;
413                            ++ix;
414                        }
415                    }
416                }
417            }
418
419            // make sure that we read all of the expected points
420            if (nread != nx*ny*nz) {
421                char mesg[256];
422                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, nread);
423                result.error(mesg);
424                return result;
425            }
426
427            double dv = vmax - vmin;
428            int count = nx*ny*nz;
429            int ngen = 0;
430            double v;
431            printf("test2\n");
432            fflush(stdout);
433            if (dv == 0.0) {
434                dv = 1.0;
435            }
436            for (int i = 0; i < count; ++i) {
437                v = data[ngen];
438                // scale all values [0-1], -1 => out of bounds
439                v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
440                data[ngen] = v;
441                ngen += 4;
442            }
443            // Compute the gradient of this data.  BE CAREFUL: center
444            // calculation on each node to avoid skew in either direction.
445            ngen = 0;
446            for (int iz=0; iz < nz; iz++) {
447                for (int iy=0; iy < ny; iy++) {
448                    for (int ix=0; ix < nx; ix++) {
449                        // gradient in x-direction
450                        double valm1 = (ix == 0) ? 0.0 : data[ngen - 4];
451                        double valp1 = (ix == nx-1) ? 0.0 : data[ngen + 4];
452                        if (valm1 < 0 || valp1 < 0) {
453                            data[ngen+1] = 0.0;
454                        } else {
455                            data[ngen+1] = valp1-valm1; // assume dx=1
456                            //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
457                        }
458
459                        // gradient in y-direction
460                        valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
461                        valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
462                        if (valm1 < 0 || valp1 < 0) {
463                            data[ngen+2] = 0.0;
464                        } else {
465                            data[ngen+2] = valp1-valm1; // assume dx=1
466                            //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1
467                        }
468
469                        // gradient in z-direction
470                        valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
471                        valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
472                        if (valm1 < 0 || valp1 < 0) {
473                            data[ngen+3] = 0.0;
474                        } else {
475                            data[ngen+3] = valp1-valm1; // assume dx=1
476                            //data[ngen+3] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
477                        }
478
479                        ngen += 4;
480                    }
481                }
482            }
483
484            dx = nx;
485            dy = ny;
486            dz = nz;
487            Volume *volPtr;
488            volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
489                                          vmin, vmax, nzero_min);
490            volPtr->set_limits(NanoVis::X, x0, x0 + (nx * ddx));
491            volPtr->set_limits(NanoVis::Y, y0, y0 + (ny * ddy));
492            volPtr->set_limits(NanoVis::Z, z0, z0 + (nz * ddz));
493            delete [] data;
494
495        } else {
496            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
497            Rappture::FieldPrism3D field(xymesh, zgrid);
498
499            double dval;
500            int nread = 0;
501            int ixy = 0;
502            int iz = 0;
503            while (!fin.eof() && nread < npts) {
504                fin >> dval;
505                if (fin.fail()) {
506                    char mesg[256];
507                    sprintf(mesg,"after %d of %d points: can't read number",
508                            nread, npts);
509                    return result.error(mesg);
510                } else {
511                    int nid = nxy*iz + ixy;
512                    field.define(nid, dval);
513
514                    nread++;
515                    if (++iz >= nz) {
516                        iz = 0;
517                        ixy++;
518                    }
519                }
520            }
521
522            // make sure that we read all of the expected points
523            if (nread != nxy*nz) {
524                char mesg[256];
525                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, nread);
526                return result.error(mesg);
527            }
528
529            // figure out a good mesh spacing
530            int nsample = 30;
531            x0 = field.rangeMin(Rappture::xaxis);
532            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
533            y0 = field.rangeMin(Rappture::yaxis);
534            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
535            z0 = field.rangeMin(Rappture::zaxis);
536            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
537            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
538
539            nx = (int)ceil(dx/dmin);
540            ny = (int)ceil(dy/dmin);
541            nz = (int)ceil(dz/dmin);
542#ifndef NV40
543            // must be an even power of 2 for older cards
544            nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
545            ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
546            nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
547#endif
548            float *data = new float[4*nx*ny*nz];
549
550            double vmin = field.valueMin();
551            double dv = field.valueMax() - field.valueMin();
552            if (dv == 0.0) {
553                dv = 1.0;
554            }
555            // generate the uniformly sampled data that we need for a volume
556            int ngen = 0;
557            double nzero_min = 0.0;
558            for (iz=0; iz < nz; iz++) {
559                double zval = z0 + iz*dmin;
560                for (int iy=0; iy < ny; iy++) {
561                    double yval = y0 + iy*dmin;
562                    for (int ix=0; ix < nx; ix++) {
563                        double xval = x0 + ix*dmin;
564                        double v = field.value(xval,yval,zval);
565
566                        if (v != 0.0f && v < nzero_min)
567                            {
568                                nzero_min = v;
569                            }
570                        // scale all values [0-1], -1 => out of bounds
571                        v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
572                        data[ngen] = v;
573
574                        ngen += 4;
575                    }
576                }
577            }
578
579            // Compute the gradient of this data.  BE CAREFUL: center
580            // calculation on each node to avoid skew in either direction.
581            ngen = 0;
582            for (int iz=0; iz < nz; iz++) {
583                for (int iy=0; iy < ny; iy++) {
584                    for (int ix=0; ix < nx; ix++) {
585                        // gradient in x-direction
586                        double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
587                        double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
588                        if (valm1 < 0 || valp1 < 0) {
589                            data[ngen+1] = 0.0;
590                        } else {
591                            //data[ngen+1] = valp1-valm1; // assume dx=1
592                            data[ngen+1] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
593                        }
594
595                        // gradient in y-direction
596                        valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
597                        valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
598                        if (valm1 < 0 || valp1 < 0) {
599                            data[ngen+2] = 0.0;
600                        } else {
601                            //data[ngen+2] = valp1-valm1; // assume dy=1
602                            data[ngen+2] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
603                        }
604
605                        // gradient in z-direction
606                        valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
607                        valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
608                        if (valm1 < 0 || valp1 < 0) {
609                            data[ngen+3] = 0.0;
610                        } else {
611                            //data[ngen+3] = valp1-valm1; // assume dz=1
612                            data[ngen+3] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
613                        }
614
615                        ngen += 4;
616                    }
617                }
618            }
619
620            Volume *volPtr;
621            volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
622                field.valueMin(), field.valueMax(), nzero_min);
623            volPtr->set_limits(NanoVis::X, field.rangeMin(Rappture::xaxis),
624                               field.rangeMax(Rappture::xaxis));
625            volPtr->set_limits(NanoVis::Y, field.rangeMin(Rappture::yaxis),
626                               field.rangeMax(Rappture::yaxis));
627            volPtr->set_limits(NanoVis::Z, field.rangeMin(Rappture::zaxis),
628                               field.rangeMax(Rappture::zaxis));
629            delete [] data;
630        }
631    } else {
632        return result.error("data not found in stream");
633    }
634
635    //
636    // Center this new volume on the origin.
637    //
638    float dx0 = -0.5;
639    float dy0 = -0.5*dy/dx;
640    float dz0 = -0.5*dz/dx;
641    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
642
643    return result;
644}
645
646Rappture::Outcome
647load_volume_stream(int index, std::iostream& fin)
648{
649    Rappture::Outcome result;
650
651    Rappture::MeshTri2D xymesh;
652    int dummy, nx, ny, nz, nxy, npts;
653    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
654    char line[128], type[128], *start;
655
656    int isrect = 1;
657
658    dx = dy = dz = 0.0;         // Suppress compiler warning.
659    while (!fin.eof()) {
660        fin.getline(line, sizeof(line) - 1);
661        if (fin.fail()) {
662            return result.error("error in data stream");
663        }
664        for (start=line; *start == ' ' || *start == '\t'; start++)
665            ;  // skip leading blanks
666
667        if (*start != '#') {  // skip comment lines
668            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
669                // found grid size
670                isrect = 1;
671            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
672                isrect = 0;
673
674                double xx, yy, zz;
675                for (int i=0; i < nxy; i++) {
676                    fin.getline(line,sizeof(line)-1);
677                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
678                        xymesh.addNode( Rappture::Node2D(xx,yy) );
679                    }
680                }
681
682                char fpts[128];
683                sprintf(fpts, "/tmp/tmppts%d", getpid());
684                char fcells[128];
685                sprintf(fcells, "/tmp/tmpcells%d", getpid());
686
687                std::ofstream ftmp(fpts);
688                // save corners of bounding box first, to work around meshing
689                // problems in voronoi utility
690                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
691                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
692                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
693                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
694                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
695                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
696                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
697                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
698                for (int i=0; i < nxy; i++) {
699                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
700               
701                }
702                ftmp.close();
703
704                char cmdstr[512];
705                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
706                if (system(cmdstr) == 0) {
707                    int cx, cy, cz;
708                    std::ifstream ftri(fcells);
709                    while (!ftri.eof()) {
710                        ftri.getline(line,sizeof(line)-1);
711                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
712                            if (cx >= 4 && cy >= 4 && cz >= 4) {
713                                // skip first 4 boundary points
714                                xymesh.addCell(cx-4, cy-4, cz-4);
715                            }
716                        }
717                    }
718                    ftri.close();
719                } else {
720                    return result.error("triangularization failed");
721                }
722
723                sprintf(cmdstr, "rm -f %s %s", fpts, fcells);
724                system(cmdstr);
725            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
726                // found z-grid
727            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
728                // found origin
729            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
730                // found one of the delta lines
731                if (ddx != 0.0) { dx = ddx; }
732                else if (ddy != 0.0) { dy = ddy; }
733                else if (ddz != 0.0) { dz = ddz; }
734            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
735                if (isrect && (npts != nx*ny*nz)) {
736                    char mesg[256];
737                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
738                    return result.error(mesg);
739                } else if (!isrect && (npts != nxy*nz)) {
740                    char mesg[256];
741                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, npts);
742                    return result.error(mesg);
743                }
744                break;
745            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
746                if (npts != nx*ny*nz) {
747                    char mesg[256];
748                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
749                    return result.error(mesg);
750                }
751                break;
752            }
753        }
754    }
755
756    // read data points
757    if (!fin.eof()) {
758        if (isrect) {
759            Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
760            Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
761            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
762            Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
763
764            double dval[6];
765            int nread = 0;
766            int ix = 0;
767            int iy = 0;
768            int iz = 0;
769            while (!fin.eof() && nread < npts) {
770                fin.getline(line,sizeof(line)-1);
771                if (fin.fail()) {
772                    return result.error("error reading data points");
773                }
774                int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
775
776                for (int p=0; p < n; p++) {
777                    int nindex = iz*nx*ny + iy*nx + ix;
778                    field.define(nindex, dval[p]);
779                    nread++;
780                    if (++iz >= nz) {
781                        iz = 0;
782                        if (++iy >= ny) {
783                            iy = 0;
784                            ++ix;
785                        }
786                    }
787                }
788            }
789
790            // make sure that we read all of the expected points
791            if (nread != nx*ny*nz) {
792                char mesg[256];
793                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, nread);
794                result.error(mesg);
795                return result;
796            }
797
798            // figure out a good mesh spacing
799            int nsample = 30;
800            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
801            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
802            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
803            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
804
805            nx = (int)ceil(dx/dmin);
806            ny = (int)ceil(dy/dmin);
807            nz = (int)ceil(dz/dmin);
808
809#ifndef NV40
810            // must be an even power of 2 for older cards
811            nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
812            ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
813            nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
814#endif
815
816            float *cdata = new float[nx*ny*nz];
817            int ngen = 0;
818            double nzero_min = 0.0;
819            for (int iz=0; iz < nz; iz++) {
820                double zval = z0 + iz*dmin;
821                for (int iy=0; iy < ny; iy++) {
822                    double yval = y0 + iy*dmin;
823                    for (int ix=0; ix < nx; ix++) {
824                        double xval = x0 + ix*dmin;
825                        double v = field.value(xval,yval,zval);
826
827                        if (v != 0.0f && v < nzero_min) {
828                            nzero_min = v;
829                        }
830
831                        // scale all values [0-1], -1 => out of bounds
832                        v = (isnan(v)) ? -1.0 : v;
833
834                        cdata[ngen] = v;
835                        ++ngen;
836                    }
837                }
838            }
839
840            float* data = computeGradient(cdata, nx, ny, nz, field.valueMin(),
841                                          field.valueMax());
842
843            // Compute the gradient of this data.  BE CAREFUL: center
844            /*
845              float *data = new float[4*nx*ny*nz];
846
847              double vmin = field.valueMin();
848              double dv = field.valueMax() - field.valueMin();
849              if (dv == 0.0) { dv = 1.0; }
850
851              // generate the uniformly sampled data that we need for a volume
852              int ngen = 0;
853              double nzero_min = 0.0;
854              for (int iz=0; iz < nz; iz++) {
855              double zval = z0 + iz*dmin;
856              for (int iy=0; iy < ny; iy++) {
857              double yval = y0 + iy*dmin;
858              for (int ix=0; ix < nx; ix++) {
859              double xval = x0 + ix*dmin;
860              double v = field.value(xval,yval,zval);
861
862              if (v != 0.0f && v < nzero_min)
863              {
864              nzero_min = v;
865              }
866
867              // scale all values [0-1], -1 => out of bounds
868              v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
869
870              data[ngen] = v;
871              ngen += 4;
872              }
873              }
874              }
875              // Compute the gradient of this data.  BE CAREFUL: center
876              // calculation on each node to avoid skew in either direction.
877              ngen = 0;
878              for (int iz=0; iz < nz; iz++) {
879              for (int iy=0; iy < ny; iy++) {
880              for (int ix=0; ix < nx; ix++) {
881              // gradient in x-direction
882              double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
883              double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
884              if (valm1 < 0 || valp1 < 0) {
885              data[ngen+1] = 0.0;
886              } else {
887              data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
888              }
889
890              // gradient in y-direction
891              valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
892              valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
893              if (valm1 < 0 || valp1 < 0) {
894              data[ngen+2] = 0.0;
895              } else {
896              //data[ngen+2] = valp1-valm1; // assume dy=1
897              data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
898              }
899
900              // gradient in z-direction
901              valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
902              valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
903              if (valm1 < 0 || valp1 < 0) {
904              data[ngen+3] = 0.0;
905              } else {
906              //data[ngen+3] = valp1-valm1; // assume dz=1
907              data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1
908              }
909
910              ngen += 4;
911              }
912              }
913              }
914            */
915
916            Volume *volPtr;
917            volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
918                field.valueMin(), field.valueMax(), nzero_min);
919            volPtr->set_limits(NanoVis::X, field.rangeMin(Rappture::xaxis),
920                               field.rangeMax(Rappture::xaxis));
921            volPtr->set_limits(NanoVis::Y, field.rangeMin(Rappture::yaxis),
922                               field.rangeMax(Rappture::yaxis));
923            volPtr->set_limits(NanoVis::Z, field.rangeMin(Rappture::zaxis),
924                               field.rangeMax(Rappture::zaxis));
925            // TBD..
926            // POINTSET
927            /*
928              PointSet* pset = new PointSet();
929              pset->initialize(volume[index], (float*) data);
930              pset->setVisible(true);
931              NanoVis::pointSet.push_back(pset);
932              updateColor(pset);
933              NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
934            */
935 
936            delete [] data;
937
938        } else {
939            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
940            Rappture::FieldPrism3D field(xymesh, zgrid);
941
942            double dval;
943            int nread = 0;
944            int ixy = 0;
945            int iz = 0;
946            while (!fin.eof() && nread < npts) {
947                fin >> dval;
948                if (fin.fail()) {
949                    char mesg[256];
950                    sprintf(mesg,"after %d of %d points: can't read number",
951                            nread, npts);
952                    return result.error(mesg);
953                } else {
954                    int nid = nxy*iz + ixy;
955                    field.define(nid, dval);
956
957                    nread++;
958                    if (++iz >= nz) {
959                        iz = 0;
960                        ixy++;
961                    }
962                }
963            }
964
965            // make sure that we read all of the expected points
966            if (nread != nxy*nz) {
967                char mesg[256];
968                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, nread);
969                return result.error(mesg);
970            }
971
972            // figure out a good mesh spacing
973            int nsample = 30;
974            x0 = field.rangeMin(Rappture::xaxis);
975            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
976            y0 = field.rangeMin(Rappture::yaxis);
977            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
978            z0 = field.rangeMin(Rappture::zaxis);
979            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
980            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
981
982            nx = (int)ceil(dx/dmin);
983            ny = (int)ceil(dy/dmin);
984            nz = (int)ceil(dz/dmin);
985#ifndef NV40
986            // must be an even power of 2 for older cards
987            nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
988            ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
989            nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
990#endif
991            float *data = new float[4*nx*ny*nz];
992
993            double vmin = field.valueMin();
994            double dv = field.valueMax() - field.valueMin();
995            if (dv == 0.0) { dv = 1.0; }
996
997            // generate the uniformly sampled data that we need for a volume
998            int ngen = 0;
999            double nzero_min = 0.0;
1000            for (iz=0; iz < nz; iz++) {
1001                double zval = z0 + iz*dmin;
1002                for (int iy=0; iy < ny; iy++) {
1003                    double yval = y0 + iy*dmin;
1004                    for (int ix=0; ix < nx; ix++) {
1005                        double xval = x0 + ix*dmin;
1006                        double v = field.value(xval,yval,zval);
1007
1008                        if (v != 0.0f && v < nzero_min)
1009                            {
1010                                nzero_min = v;
1011                            }
1012                        // scale all values [0-1], -1 => out of bounds
1013                        v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
1014                        data[ngen] = v;
1015
1016                        ngen += 4;
1017                    }
1018                }
1019            }
1020
1021            // Compute the gradient of this data.  BE CAREFUL: center
1022            // calculation on each node to avoid skew in either direction.
1023            ngen = 0;
1024            for (int iz=0; iz < nz; iz++) {
1025                for (int iy=0; iy < ny; iy++) {
1026                    for (int ix=0; ix < nx; ix++) {
1027                        // gradient in x-direction
1028                        double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
1029                        double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
1030                        if (valm1 < 0 || valp1 < 0) {
1031                            data[ngen+1] = 0.0;
1032                        } else {
1033                            //data[ngen+1] = valp1-valm1; // assume dx=1
1034                            data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
1035                        }
1036
1037                        // gradient in y-direction
1038                        valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
1039                        valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
1040                        if (valm1 < 0 || valp1 < 0) {
1041                            data[ngen+2] = 0.0;
1042                        } else {
1043                            //data[ngen+2] = valp1-valm1; // assume dy=1
1044                            data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1
1045                        }
1046
1047                        // gradient in z-direction
1048                        valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
1049                        valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
1050                        if (valm1 < 0 || valp1 < 0) {
1051                            data[ngen+3] = 0.0;
1052                        } else {
1053                            //data[ngen+3] = valp1-valm1; // assume dz=1
1054                            data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1
1055                        }
1056
1057                        ngen += 4;
1058                    }
1059                }
1060            }
1061
1062            Volume *volPtr;
1063            volPtr = NanoVis::load_volume(index, nx, ny, nz, 4, data,
1064                field.valueMin(), field.valueMax(), nzero_min);
1065            volPtr->set_limits(NanoVis::X, field.rangeMin(Rappture::xaxis),
1066                               field.rangeMax(Rappture::xaxis));
1067            volPtr->set_limits(NanoVis::Y, field.rangeMin(Rappture::yaxis),
1068                               field.rangeMax(Rappture::yaxis));
1069            volPtr->set_limits(NanoVis::Z, field.rangeMin(Rappture::zaxis),
1070                               field.rangeMax(Rappture::zaxis));
1071
1072            // TBD..
1073            // POINTSET
1074            /*
1075              PointSet* pset = new PointSet();
1076              pset->initialize(volume[index], (float*) data);
1077              pset->setVisible(true);
1078              NanoVis::pointSet.push_back(pset);
1079              updateColor(pset);
1080              NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
1081            */
1082 
1083
1084            delete [] data;
1085        }
1086    } else {
1087        return result.error("data not found in stream");
1088    }
1089
1090    //
1091    // Center this new volume on the origin.
1092    //
1093    float dx0 = -0.5;
1094    float dy0 = -0.5*dy/dx;
1095    float dz0 = -0.5*dz/dx;
1096    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
1097    return result;
1098}
Note: See TracBrowser for help on using the repository browser.