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

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

More clean up. Added dxReader.cpp

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