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

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

turned on ISO_TEST

File size: 39.7 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 = sqrt(vx*vx + vy*vy + vz*vz);
214
215                    if (vm < vmin) { vmin = vm; }
216                    if (vm > vmax) { vmax = vm; }
217                    if (vm != 0.0f && vm < nzero_min)
218                    {
219                        nzero_min = vm;
220                    }
221
222                    data[ngen++] = vx;
223                    data[ngen++] = vy;
224                    data[ngen++] = vz;
225                }
226            }
227        }
228
229        ngen = 0;
230
231        // scale should be accounted.
232        for (ngen=0; ngen < npts; ngen++) {
233            data[ngen] = (data[ngen]/(2.0*vmax) + 0.5);
234        }
235        NanoVis::load_volume(index, nx, ny, nz, 3, data, vmin, vmax, nzero_min);
236        delete [] data;
237    } else {
238        std::cerr << "WARNING: data not found in stream" << std::endl;
239    }
240}
241
242
243/* Load a 3D volume from a dx-format file
244 */
245Rappture::Outcome
246load_volume_stream2(int index, std::iostream& fin)
247{
248    Rappture::Outcome result;
249
250    Rappture::MeshTri2D xymesh;
251    int dummy, nx, ny, nz, nxy, npts;
252    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
253    char line[128], type[128], *start;
254
255    int isrect = 1;
256    dx = dy = dz = 0.0;         // Suppress compiler warning.
257    do {
258        fin.getline(line,sizeof(line)-1);
259        for (start=&line[0]; *start == ' ' || *start == '\t'; start++)
260            ;  // skip leading blanks
261
262        if (*start != '#') {  // skip comment lines
263            printf("%s\n", line);
264            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
265                // found grid size
266                isrect = 1;
267            }
268            else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
269                isrect = 0;
270                double xx, yy, zz;
271                for (int i=0; i < nxy; i++) {
272                    fin.getline(line, sizeof(line));
273                    fin.getline(line,sizeof(line)-1);
274                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
275                        xymesh.addNode( Rappture::Node2D(xx,yy) );
276                    }
277                }
278                char mesg[256];
279                sprintf(mesg,"test");
280                result.error(mesg);
281                return result;
282
283                char fpts[128];
284                sprintf(fpts, "/tmp/tmppts%d", getpid());
285                char fcells[128];
286                sprintf(fcells, "/tmp/tmpcells%d", getpid());
287
288                std::ofstream ftmp(fpts);
289                // save corners of bounding box first, to work around meshing
290                // problems in voronoi utility
291                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
292                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
293                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
294                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
295                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
296                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
297                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
298                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
299                for (int i=0; i < nxy; i++) {
300                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
301               
302                }
303                ftmp.close();
304
305                char cmdstr[512];
306                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
307                if (system(cmdstr) == 0) {
308                    int cx, cy, cz;
309                    std::ifstream ftri(fcells);
310                    while (!ftri.eof()) {
311                        ftri.getline(line,sizeof(line)-1);
312                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
313                            if (cx >= 4 && cy >= 4 && cz >= 4) {
314                                // skip first 4 boundary points
315                                xymesh.addCell(cx-4, cy-4, cz-4);
316                            }
317                        }
318                    }
319                    ftri.close();
320                } else {
321                    return result.error("triangularization failed");
322                }
323
324                sprintf(cmdstr, "rm -f %s %s", fpts, fcells);
325                system(cmdstr);
326            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
327                // found z-grid
328            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
329                // found origin
330            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
331                // found one of the delta lines
332                if (ddx != 0.0) { dx = ddx; }
333                else if (ddy != 0.0) { dy = ddy; }
334                else if (ddz != 0.0) { dz = ddz; }
335            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
336                if (isrect && (npts != nx*ny*nz)) {
337                    char mesg[256];
338                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
339                    return result.error(mesg);
340                } else if (!isrect && (npts != nxy*nz)) {
341                    char mesg[256];
342                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, npts);
343                    return result.error(mesg);
344                }
345                break;
346            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
347                if (npts != nx*ny*nz) {
348                    char mesg[256];
349                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
350                    return result.error(mesg);
351                }
352                break;
353            }
354        }
355    } while (!fin.eof());
356
357    // read data points
358    if (!fin.eof()) {
359        if (isrect) {
360            double dval[6];
361            int nread = 0;
362            int ix = 0;
363            int iy = 0;
364            int iz = 0;
365            float* data = new float[nx *  ny *  nz * 4];
366            memset(data, 0, nx*ny*nz*4);
367            double vmin = 1e21;
368            double nzero_min = 1e21;
369            double vmax = -1e21;
370
371
372            while (!fin.eof() && nread < npts) {
373                fin.getline(line,sizeof(line)-1);
374                int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
375
376                for (int p=0; p < n; p++) {
377                    int nindex = (iz*nx*ny + iy*nx + ix) * 4;
378                    data[nindex] = dval[p];
379
380                    if (dval[p] < vmin) vmin = dval[p];
381                    if (dval[p] > vmax) vmax = dval[p];
382                    if (dval[p] != 0.0f && dval[p] < nzero_min) {
383                         nzero_min = dval[p];
384                    }
385
386                    nread++;
387                    if (++iz >= nz) {
388                        iz = 0;
389                        if (++iy >= ny) {
390                            iy = 0;
391                            ++ix;
392                        }
393                    }
394                }
395            }
396
397            // make sure that we read all of the expected points
398            if (nread != nx*ny*nz) {
399                char mesg[256];
400                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, nread);
401                result.error(mesg);
402                return result;
403            }
404
405            double dv = vmax - vmin;
406            int count = nx*ny*nz;
407            int ngen = 0;
408            double v;
409            printf("test2\n");
410                        fflush(stdout);
411            if (dv == 0.0) { dv = 1.0; }
412            for (int i = 0; i < count; ++i)
413            {
414                v = data[ngen];
415                // scale all values [0-1], -1 => out of bounds
416                v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
417                data[ngen] = v;
418                ngen += 4;
419            }
420
421            // Compute the gradient of this data.  BE CAREFUL: center
422            // calculation on each node to avoid skew in either direction.
423            ngen = 0;
424            for (int iz=0; iz < nz; iz++) {
425                for (int iy=0; iy < ny; iy++) {
426                    for (int ix=0; ix < nx; ix++) {
427                        // gradient in x-direction
428                        double valm1 = (ix == 0) ? 0.0 : data[ngen - 4];
429                        double valp1 = (ix == nx-1) ? 0.0 : data[ngen + 4];
430                        if (valm1 < 0 || valp1 < 0) {
431                            data[ngen+1] = 0.0;
432                        } else {
433                            data[ngen+1] = valp1-valm1; // assume dx=1
434                            //data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
435                        }
436
437                        // gradient in y-direction
438                        valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
439                        valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
440                        if (valm1 < 0 || valp1 < 0) {
441                            data[ngen+2] = 0.0;
442                        } else {
443                            data[ngen+2] = valp1-valm1; // assume dx=1
444                            //data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1
445                        }
446
447                        // gradient in z-direction
448                        valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
449                        valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
450                        if (valm1 < 0 || valp1 < 0) {
451                            data[ngen+3] = 0.0;
452                        } else {
453                            data[ngen+3] = valp1-valm1; // assume dx=1
454                            //data[ngen+3] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
455                        }
456
457                        ngen += 4;
458                    }
459                }
460            }
461
462            dx = nx;
463            dy = ny;
464            dz = nz;
465            NanoVis::load_volume(index, nx, ny, nz, 4, data,
466                vmin, vmax, nzero_min);
467
468            delete [] data;
469
470        } else {
471            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
472            Rappture::FieldPrism3D field(xymesh, zgrid);
473
474            double dval;
475            int nread = 0;
476            int ixy = 0;
477            int iz = 0;
478            while (!fin.eof() && nread < npts) {
479                fin >> dval;
480                if (fin.fail()) {
481                    char mesg[256];
482                    sprintf(mesg,"after %d of %d points: can't read number",
483                            nread, npts);
484                    return result.error(mesg);
485                } else {
486                    int nid = nxy*iz + ixy;
487                    field.define(nid, dval);
488
489                    nread++;
490                    if (++iz >= nz) {
491                        iz = 0;
492                        ixy++;
493                    }
494                }
495            }
496
497            // make sure that we read all of the expected points
498            if (nread != nxy*nz) {
499                char mesg[256];
500                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, nread);
501                return result.error(mesg);
502            }
503
504            // figure out a good mesh spacing
505            int nsample = 30;
506            x0 = field.rangeMin(Rappture::xaxis);
507            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
508            y0 = field.rangeMin(Rappture::yaxis);
509            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
510            z0 = field.rangeMin(Rappture::zaxis);
511            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
512            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
513
514            nx = (int)ceil(dx/dmin);
515            ny = (int)ceil(dy/dmin);
516            nz = (int)ceil(dz/dmin);
517#ifndef NV40
518            // must be an even power of 2 for older cards
519                nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
520                ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
521                nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
522#endif
523            float *data = new float[4*nx*ny*nz];
524
525            double vmin = field.valueMin();
526            double dv = field.valueMax() - field.valueMin();
527            if (dv == 0.0) { dv = 1.0; }
528
529            // generate the uniformly sampled data that we need for a volume
530            int ngen = 0;
531            double nzero_min = 0.0;
532            for (iz=0; iz < nz; iz++) {
533                double zval = z0 + iz*dmin;
534                for (int iy=0; iy < ny; iy++) {
535                    double yval = y0 + iy*dmin;
536                    for (int ix=0; ix < nx; ix++) {
537                        double xval = x0 + ix*dmin;
538                        double v = field.value(xval,yval,zval);
539
540                        if (v != 0.0f && v < nzero_min)
541                        {
542                            nzero_min = v;
543                        }
544                        // scale all values [0-1], -1 => out of bounds
545                        v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
546                        data[ngen] = v;
547
548                        ngen += 4;
549                    }
550                }
551            }
552
553            // Compute the gradient of this data.  BE CAREFUL: center
554            // calculation on each node to avoid skew in either direction.
555            ngen = 0;
556            for (int iz=0; iz < nz; iz++) {
557                for (int iy=0; iy < ny; iy++) {
558                    for (int ix=0; ix < nx; ix++) {
559                        // gradient in x-direction
560                        double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
561                        double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
562                        if (valm1 < 0 || valp1 < 0) {
563                            data[ngen+1] = 0.0;
564                        } else {
565                            //data[ngen+1] = valp1-valm1; // assume dx=1
566                            data[ngen+1] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
567                        }
568
569                        // gradient in y-direction
570                        valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
571                        valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
572                        if (valm1 < 0 || valp1 < 0) {
573                            data[ngen+2] = 0.0;
574                        } else {
575                            //data[ngen+2] = valp1-valm1; // assume dy=1
576                            data[ngen+2] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
577                        }
578
579                        // gradient in z-direction
580                        valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
581                        valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
582                        if (valm1 < 0 || valp1 < 0) {
583                            data[ngen+3] = 0.0;
584                        } else {
585                            //data[ngen+3] = valp1-valm1; // assume dz=1
586                            data[ngen+3] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1
587                        }
588
589                        ngen += 4;
590                    }
591                }
592            }
593
594            NanoVis::load_volume(index, nx, ny, nz, 4, data,
595                field.valueMin(), field.valueMax(), nzero_min);
596
597            delete [] data;
598        }
599    } else {
600        return result.error("data not found in stream");
601    }
602
603    //
604    // Center this new volume on the origin.
605    //
606    float dx0 = -0.5;
607    float dy0 = -0.5*dy/dx;
608    float dz0 = -0.5*dz/dx;
609    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
610
611    return result;
612}
613
614Rappture::Outcome
615load_volume_stream(int index, std::iostream& fin)
616{
617    Rappture::Outcome result;
618
619    Rappture::MeshTri2D xymesh;
620    int dummy, nx, ny, nz, nxy, npts;
621    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
622    char line[128], type[128], *start;
623
624    int isrect = 1;
625
626    dx = dy = dz = 0.0;         // Suppress compiler warning.
627    while (!fin.eof()) {
628        fin.getline(line, sizeof(line) - 1);
629        if (fin.fail()) {
630            return result.error("error in data stream");
631        }
632        for (start=line; *start == ' ' || *start == '\t'; start++)
633            ;  // skip leading blanks
634
635        if (*start != '#') {  // skip comment lines
636            if (sscanf(start, "object %d class gridpositions counts %d %d %d", &dummy, &nx, &ny, &nz) == 4) {
637                // found grid size
638                isrect = 1;
639            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows", &dummy, &nxy) == 2) {
640                isrect = 0;
641
642                double xx, yy, zz;
643                for (int i=0; i < nxy; i++) {
644                    fin.getline(line,sizeof(line)-1);
645                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
646                        xymesh.addNode( Rappture::Node2D(xx,yy) );
647                    }
648                }
649
650                char fpts[128];
651                sprintf(fpts, "/tmp/tmppts%d", getpid());
652                char fcells[128];
653                sprintf(fcells, "/tmp/tmpcells%d", getpid());
654
655                std::ofstream ftmp(fpts);
656                // save corners of bounding box first, to work around meshing
657                // problems in voronoi utility
658                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
659                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
660                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
661                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
662                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
663                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
664                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
665                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
666                for (int i=0; i < nxy; i++) {
667                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
668               
669                }
670                ftmp.close();
671
672                char cmdstr[512];
673                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
674                if (system(cmdstr) == 0) {
675                    int cx, cy, cz;
676                    std::ifstream ftri(fcells);
677                    while (!ftri.eof()) {
678                        ftri.getline(line,sizeof(line)-1);
679                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
680                            if (cx >= 4 && cy >= 4 && cz >= 4) {
681                                // skip first 4 boundary points
682                                xymesh.addCell(cx-4, cy-4, cz-4);
683                            }
684                        }
685                    }
686                    ftri.close();
687                } else {
688                    return result.error("triangularization failed");
689                }
690
691                sprintf(cmdstr, "rm -f %s %s", fpts, fcells);
692                system(cmdstr);
693            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
694                // found z-grid
695            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
696                // found origin
697            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
698                // found one of the delta lines
699                if (ddx != 0.0) { dx = ddx; }
700                else if (ddy != 0.0) { dy = ddy; }
701                else if (ddz != 0.0) { dz = ddz; }
702            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows", &dummy, type, &npts) == 3) {
703                if (isrect && (npts != nx*ny*nz)) {
704                    char mesg[256];
705                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
706                    return result.error(mesg);
707                } else if (!isrect && (npts != nxy*nz)) {
708                    char mesg[256];
709                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, npts);
710                    return result.error(mesg);
711                }
712                break;
713            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows", &dummy, type, &npts) == 3) {
714                if (npts != nx*ny*nz) {
715                    char mesg[256];
716                    sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, npts);
717                    return result.error(mesg);
718                }
719                break;
720            }
721        }
722    }
723
724    // read data points
725    if (!fin.eof()) {
726        if (isrect) {
727            Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
728            Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
729            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
730            Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
731
732            double dval[6];
733            int nread = 0;
734            int ix = 0;
735            int iy = 0;
736            int iz = 0;
737            while (!fin.eof() && nread < npts) {
738                fin.getline(line,sizeof(line)-1);
739                if (fin.fail()) {
740                    return result.error("error reading data points");
741                }
742                int n = sscanf(line, "%lg %lg %lg %lg %lg %lg", &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
743
744                for (int p=0; p < n; p++) {
745                    int nindex = iz*nx*ny + iy*nx + ix;
746                    field.define(nindex, dval[p]);
747                    nread++;
748                    if (++iz >= nz) {
749                        iz = 0;
750                        if (++iy >= ny) {
751                            iy = 0;
752                            ++ix;
753                        }
754                    }
755                }
756            }
757
758            // make sure that we read all of the expected points
759            if (nread != nx*ny*nz) {
760                char mesg[256];
761                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nx*ny*nz, nread);
762                result.error(mesg);
763                return result;
764            }
765
766            // figure out a good mesh spacing
767            int nsample = 30;
768            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
769            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
770            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
771            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
772
773            nx = (int)ceil(dx/dmin);
774            ny = (int)ceil(dy/dmin);
775            nz = (int)ceil(dz/dmin);
776
777#ifndef NV40
778            // must be an even power of 2 for older cards
779                nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
780                ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
781                nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
782#endif
783
784            float *cdata = new float[nx*ny*nz];
785            int ngen = 0;
786            double nzero_min = 0.0;
787            for (int iz=0; iz < nz; iz++) {
788                double zval = z0 + iz*dmin;
789                for (int iy=0; iy < ny; iy++) {
790                    double yval = y0 + iy*dmin;
791                    for (int ix=0; ix < nx; ix++) {
792                        double xval = x0 + ix*dmin;
793                        double v = field.value(xval,yval,zval);
794
795                        if (v != 0.0f && v < nzero_min) {
796                            nzero_min = v;
797                        }
798
799                        // scale all values [0-1], -1 => out of bounds
800                        v = (isnan(v)) ? -1.0 : v;
801
802                        cdata[ngen] = v;
803                        ++ngen;
804                    }
805                }
806            }
807
808            float* data = computeGradient(cdata, nx, ny, nz, field.valueMin(),
809                                          field.valueMax());
810
811            // Compute the gradient of this data.  BE CAREFUL: center
812            /*
813            float *data = new float[4*nx*ny*nz];
814
815            double vmin = field.valueMin();
816            double dv = field.valueMax() - field.valueMin();
817            if (dv == 0.0) { dv = 1.0; }
818
819            // generate the uniformly sampled data that we need for a volume
820            int ngen = 0;
821            double nzero_min = 0.0;
822            for (int iz=0; iz < nz; iz++) {
823                double zval = z0 + iz*dmin;
824                for (int iy=0; iy < ny; iy++) {
825                    double yval = y0 + iy*dmin;
826                    for (int ix=0; ix < nx; ix++) {
827                        double xval = x0 + ix*dmin;
828                        double v = field.value(xval,yval,zval);
829
830                        if (v != 0.0f && v < nzero_min)
831                        {
832                            nzero_min = v;
833                        }
834
835                        // scale all values [0-1], -1 => out of bounds
836                        v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
837
838                        data[ngen] = v;
839                        ngen += 4;
840                    }
841                }
842            }
843            // Compute the gradient of this data.  BE CAREFUL: center
844            // calculation on each node to avoid skew in either direction.
845            ngen = 0;
846            for (int iz=0; iz < nz; iz++) {
847                for (int iy=0; iy < ny; iy++) {
848                    for (int ix=0; ix < nx; ix++) {
849                        // gradient in x-direction
850                        double valm1 = (ix == 0) ? 0.0 : data[ngen-4];
851                        double valp1 = (ix == nx-1) ? 0.0 : data[ngen+4];
852                        if (valm1 < 0 || valp1 < 0) {
853                            data[ngen+1] = 0.0;
854                        } else {
855                            data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
856                        }
857
858                        // gradient in y-direction
859                        valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
860                        valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
861                        if (valm1 < 0 || valp1 < 0) {
862                            data[ngen+2] = 0.0;
863                        } else {
864                            //data[ngen+2] = valp1-valm1; // assume dy=1
865                            data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
866                        }
867
868                        // gradient in z-direction
869                        valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
870                        valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
871                        if (valm1 < 0 || valp1 < 0) {
872                            data[ngen+3] = 0.0;
873                        } else {
874                            //data[ngen+3] = valp1-valm1; // assume dz=1
875                            data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1
876                        }
877
878                        ngen += 4;
879                    }
880                }
881            }
882            */
883
884            NanoVis::load_volume(index, nx, ny, nz, 4, data,
885                field.valueMin(), field.valueMax(), nzero_min);
886
887            // TBD..
888            // POINTSET
889            /*
890            PointSet* pset = new PointSet();
891            pset->initialize(volume[index], (float*) data);
892            pset->setVisible(true);
893            NanoVis::pointSet.push_back(pset);
894            updateColor(pset);
895            NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
896            */
897 
898            delete [] data;
899
900        } else {
901            Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
902            Rappture::FieldPrism3D field(xymesh, zgrid);
903
904            double dval;
905            int nread = 0;
906            int ixy = 0;
907            int iz = 0;
908            while (!fin.eof() && nread < npts) {
909                fin >> dval;
910                if (fin.fail()) {
911                    char mesg[256];
912                    sprintf(mesg,"after %d of %d points: can't read number",
913                            nread, npts);
914                    return result.error(mesg);
915                } else {
916                    int nid = nxy*iz + ixy;
917                    field.define(nid, dval);
918
919                    nread++;
920                    if (++iz >= nz) {
921                        iz = 0;
922                        ixy++;
923                    }
924                }
925            }
926
927            // make sure that we read all of the expected points
928            if (nread != nxy*nz) {
929                char mesg[256];
930                sprintf(mesg,"inconsistent data: expected %d points but found %d points", nxy*nz, nread);
931                return result.error(mesg);
932            }
933
934            // figure out a good mesh spacing
935            int nsample = 30;
936            x0 = field.rangeMin(Rappture::xaxis);
937            dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
938            y0 = field.rangeMin(Rappture::yaxis);
939            dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
940            z0 = field.rangeMin(Rappture::zaxis);
941            dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
942            double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
943
944            nx = (int)ceil(dx/dmin);
945            ny = (int)ceil(dy/dmin);
946            nz = (int)ceil(dz/dmin);
947#ifndef NV40
948            // must be an even power of 2 for older cards
949                nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
950                ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
951                nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
952#endif
953            float *data = new float[4*nx*ny*nz];
954
955            double vmin = field.valueMin();
956            double dv = field.valueMax() - field.valueMin();
957            if (dv == 0.0) { dv = 1.0; }
958
959            // generate the uniformly sampled data that we need for a volume
960            int ngen = 0;
961            double nzero_min = 0.0;
962            for (iz=0; iz < nz; iz++) {
963                double zval = z0 + iz*dmin;
964                for (int iy=0; iy < ny; iy++) {
965                    double yval = y0 + iy*dmin;
966                    for (int ix=0; ix < nx; ix++) {
967                        double xval = x0 + ix*dmin;
968                        double v = field.value(xval,yval,zval);
969
970                        if (v != 0.0f && v < nzero_min)
971                        {
972                            nzero_min = v;
973                        }
974                        // scale all values [0-1], -1 => out of bounds
975                        v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
976                        data[ngen] = v;
977
978                        ngen += 4;
979                    }
980                }
981            }
982
983            // Compute the gradient of this data.  BE CAREFUL: center
984            // calculation on each node to avoid skew in either direction.
985            ngen = 0;
986            for (int iz=0; iz < nz; iz++) {
987                for (int iy=0; iy < ny; iy++) {
988                    for (int ix=0; ix < nx; ix++) {
989                        // gradient in x-direction
990                        double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
991                        double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
992                        if (valm1 < 0 || valp1 < 0) {
993                            data[ngen+1] = 0.0;
994                        } else {
995                            //data[ngen+1] = valp1-valm1; // assume dx=1
996                            data[ngen+1] = ((valp1-valm1) + 1) *  0.5; // assume dx=1
997                        }
998
999                        // gradient in y-direction
1000                        valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
1001                        valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
1002                        if (valm1 < 0 || valp1 < 0) {
1003                            data[ngen+2] = 0.0;
1004                        } else {
1005                            //data[ngen+2] = valp1-valm1; // assume dy=1
1006                            data[ngen+2] = ((valp1-valm1) + 1) *  0.5; // assume dy=1
1007                        }
1008
1009                        // gradient in z-direction
1010                        valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
1011                        valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
1012                        if (valm1 < 0 || valp1 < 0) {
1013                            data[ngen+3] = 0.0;
1014                        } else {
1015                            //data[ngen+3] = valp1-valm1; // assume dz=1
1016                            data[ngen+3] = ((valp1-valm1) + 1) *  0.5; // assume dz=1
1017                        }
1018
1019                        ngen += 4;
1020                    }
1021                }
1022            }
1023
1024                NanoVis::load_volume(index, nx, ny, nz, 4, data,
1025                field.valueMin(), field.valueMax(), nzero_min);
1026
1027            // TBD..
1028            // POINTSET
1029            /*
1030            PointSet* pset = new PointSet();
1031            pset->initialize(volume[index], (float*) data);
1032            pset->setVisible(true);
1033            NanoVis::pointSet.push_back(pset);
1034            updateColor(pset);
1035            NanoVis::volume[index]->pointsetIndex = NanoVis::pointSet.size() - 1;
1036            */
1037 
1038
1039            delete [] data;
1040        }
1041    } else {
1042        return result.error("data not found in stream");
1043    }
1044
1045    //
1046    // Center this new volume on the origin.
1047    //
1048    float dx0 = -0.5;
1049    float dy0 = -0.5*dy/dx;
1050    float dz0 = -0.5*dz/dx;
1051    NanoVis::volume[index]->move(Vector3(dx0, dy0, dz0));
1052    return result;
1053}
Note: See TracBrowser for help on using the repository browser.