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

Last change on this file since 2852 was 2850, checked in by ldelgass, 12 years ago

Do what the FIXME says and replace gradient computation block with common
function. No functional change.

  • Property svn:eol-style set to native
File size: 29.5 KB
Line 
1 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
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#include <stdio.h>
21#include <math.h>
22#include <fstream>
23#include <iostream>
24#include <sstream>
25#include <string>
26#include <sys/types.h>
27#include <unistd.h>
28
29#include <RpOutcome.h>
30#include <RpField1D.h>
31#include <RpFieldRect3D.h>
32#include <RpFieldPrism3D.h>
33
34// common dx functions
35#include "dxReaderCommon.h"
36
37#include "nanovis.h"
38#include "Unirect.h"
39#include "Volume.h"
40#include "ZincBlendeVolume.h"
41#include "NvZincBlendeReconstructor.h"
42#ifdef USE_POINTSET_RENDERER
43#include "PointSet.h"
44#endif
45
46/**
47 * \brief Load a 3D volume from a dx-format file
48 */
49Volume *
50load_volume_stream2(Rappture::Outcome& result, const char *tag,
51                    std::iostream& fin)
52{
53    TRACE("load_volume_stream2 %s\n", tag);
54
55    Rappture::MeshTri2D xymesh;
56    int dummy, nx, ny, nz, nxy, npts;
57    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
58    char line[128], type[128], *start;
59
60    int isrect = 1;
61
62    dx = dy = dz = 0.0;
63    x0 = y0 = z0 = 0.0; // May not have an origin line.
64    nx = ny = nz = npts = nxy = 0;
65    do {
66        fin.getline(line, sizeof(line) - 1);
67        for (start = line; *start == ' ' || *start == '\t'; start++)
68            ;  // skip leading blanks
69
70        if (*start != '#') {  // skip comment lines
71            if (sscanf(start, "object %d class gridpositions counts %d %d %d",
72                       &dummy, &nx, &ny, &nz) == 4) {
73                // found grid size
74                isrect = 1;
75            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows",
76                              &dummy, &nxy) == 2) {
77                isrect = 0;
78
79                double xx, yy, zz;
80                for (int i = 0; i < nxy; i++) {
81                    fin.getline(line,sizeof(line)-1);
82                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
83                        xymesh.addNode( Rappture::Node2D(xx,yy) );
84                    }
85                }
86
87                char fpts[128];
88                sprintf(fpts, "/tmp/tmppts%d", getpid());
89                char fcells[128];
90                sprintf(fcells, "/tmp/tmpcells%d", getpid());
91
92                std::ofstream ftmp(fpts);
93                // save corners of bounding box first, to work around meshing
94                // problems in voronoi utility
95                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
96                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
97                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
98                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
99                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
100                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
101                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
102                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
103                for (int i = 0; i < nxy; i++) {
104                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
105                }
106                ftmp.close();
107
108                char cmdstr[512];
109                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
110                if (system(cmdstr) == 0) {
111                    int cx, cy, cz;
112                    std::ifstream ftri(fcells);
113                    while (!ftri.eof()) {
114                        ftri.getline(line,sizeof(line)-1);
115                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
116                            if (cx >= 4 && cy >= 4 && cz >= 4) {
117                                // skip first 4 boundary points
118                                xymesh.addCell(cx-4, cy-4, cz-4);
119                            }
120                        }
121                    }
122                    ftri.close();
123                } else {
124                    result.error("triangularization failed");
125                    return NULL;
126                }
127                unlink(fpts);
128                unlink(fcells);
129            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
130                // found z-grid
131            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
132                // found origin
133            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
134                int count = 0;
135                // found one of the delta lines
136                if (ddx != 0.0) {
137                    dx = ddx;
138                    count++;
139                }
140                if (ddy != 0.0) {
141                    dy = ddy;
142                    count++;
143                }
144                if (ddz != 0.0) {
145                    dz = ddz;
146                    count++;
147                }
148                if (count > 1) {
149                    result.addError("don't know how to handle multiple non-zero"
150                                    " delta values");
151                    return NULL;
152                }
153            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows",
154                              &dummy, type, &npts) == 3) {
155                if (isrect && (npts != nx*ny*nz)) {
156                    result.addError("inconsistent data: expected %d points"
157                                    " but found %d points", nx*ny*nz, npts);
158                    return NULL;
159                } else if (!isrect && (npts != nxy*nz)) {
160                    result.addError("inconsistent data: expected %d points"
161                                    " but found %d points", nxy*nz, npts);
162                    return NULL;
163                }
164                break;
165            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows",
166                              &dummy, type, &npts) == 3) {
167                if (npts != nx*ny*nz) {
168                    result.addError("inconsistent data: expected %d points"
169                                    " but found %d points", nx*ny*nz, npts);
170                    return NULL;
171                }
172                break;
173            }
174        }
175    } while (!fin.eof());
176
177    TRACE("found nx=%d ny=%d, nz=%d, x0=%f, y0=%f, z0=%f\n",
178           nx, ny, nz, x0, y0, z0);
179    // read data points
180    if (fin.eof() && (npts > 0)) {
181        result.addError("EOF found: expecting %d points", npts);
182        return NULL;
183    }
184    Volume *volPtr = NULL;
185    if (isrect) {
186        float *data = new float[nx *  ny *  nz * 4];
187        memset(data, 0, nx*ny*nz*4);
188
189        double vmin = 1e21;
190        double nzero_min = 1e21;
191        double vmax = -1e21;
192
193        double dval[6];
194        int nread = 0;
195        int ix = 0;
196        int iy = 0;
197        int iz = 0;
198
199        while (!fin.eof() && nread < npts) {
200            fin.getline(line,sizeof(line)-1);
201            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg",
202                           &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
203
204            for (int p = 0; p < n; p++) {
205                int nindex = (iz*nx*ny + iy*nx + ix) * 4;
206                data[nindex] = dval[p];
207
208                if (dval[p] < vmin) {
209                    vmin = dval[p];
210                } else if (dval[p] > vmax) {
211                    vmax = dval[p];
212                }
213                if (dval[p] != 0.0 && dval[p] < nzero_min) {
214                    nzero_min = dval[p];
215                }
216
217                nread++;
218                if (++iz >= nz) {
219                    iz = 0;
220                    if (++iy >= ny) {
221                        iy = 0;
222                        ++ix;
223                    }
224                }
225            }
226        }
227
228        // make sure that we read all of the expected points
229        if (nread != nx*ny*nz) {
230            result.addError("inconsistent data: expected %d points"
231                            " but found %d points", nx*ny*nz, nread);
232            return NULL;
233        }
234
235        double dv = vmax - vmin;
236        int count = nx*ny*nz;
237        int ngen = 0;
238        double v;
239        if (dv == 0.0) {
240            dv = 1.0;
241        }
242
243        for (int i = 0; i < count; ++i) {
244            v = data[ngen];
245            // scale all values [0-1], -1 => out of bounds
246            v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
247
248            data[ngen] = v;
249            ngen += 4;
250        }
251
252        computeSimpleGradient(data, nx, ny, nz);
253
254        dx = nx;
255        dy = ny;
256        dz = nz;
257
258        volPtr = NanoVis::load_volume(tag, nx, ny, nz, 4, data,
259                                      vmin, vmax, nzero_min);
260        volPtr->xAxis.SetRange(x0, x0 + (nx * dx));
261        volPtr->yAxis.SetRange(y0, y0 + (ny * dy));
262        volPtr->zAxis.SetRange(z0, z0 + (nz * dz));
263        volPtr->wAxis.SetRange(vmin, vmax);
264        volPtr->update_pending = true;
265        delete [] data;
266    } else {
267        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
268        Rappture::FieldPrism3D field(xymesh, zgrid);
269
270        double dval;
271        int nread = 0;
272        int ixy = 0;
273        int iz = 0;
274        while (!fin.eof() && nread < npts) {
275            fin >> dval;
276            if (fin.fail()) {
277                result.addError("after %d of %d points: can't read number",
278                                nread, npts);
279                return NULL;
280            } else {
281                int nid = nxy*iz + ixy;
282                field.define(nid, dval);
283
284                nread++;
285                if (++iz >= nz) {
286                    iz = 0;
287                    ixy++;
288                }
289            }
290        }
291
292        // make sure that we read all of the expected points
293        if (nread != nxy*nz) {
294            result.addError("inconsistent data: expected %d points"
295                            " but found %d points", nxy*nz, nread);
296            return NULL;
297        }
298
299        // figure out a good mesh spacing
300        int nsample = 30;
301        x0 = field.rangeMin(Rappture::xaxis);
302        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
303        y0 = field.rangeMin(Rappture::yaxis);
304        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
305        z0 = field.rangeMin(Rappture::zaxis);
306        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
307        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
308
309        nx = (int)ceil(dx/dmin);
310        ny = (int)ceil(dy/dmin);
311        nz = (int)ceil(dz/dmin);
312#ifndef NV40
313        // must be an even power of 2 for older cards
314        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
315        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
316        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
317#endif
318        float *data = new float[4*nx*ny*nz];
319
320        double vmin = field.valueMin();
321        double dv = field.valueMax() - field.valueMin();
322        if (dv == 0.0) {
323            dv = 1.0;
324        }
325
326        // generate the uniformly sampled data that we need for a volume
327        int ngen = 0;
328        double nzero_min = 0.0;
329        for (int iz = 0; iz < nz; iz++) {
330            double zval = z0 + iz*dmin;
331            for (int iy = 0; iy < ny; iy++) {
332                double yval = y0 + iy*dmin;
333                for (int ix = 0; ix < nx; ix++) {
334                    double xval = x0 + ix*dmin;
335                    double v = field.value(xval, yval, zval);
336
337                    if (v != 0.0 && v < nzero_min) {
338                        nzero_min = v;
339                    }
340                    // scale all values [0-1], -1 => out of bounds
341                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
342                    data[ngen] = v;
343
344                    ngen += 4;
345                }
346            }
347        }
348
349        computeSimpleGradient(data, nx, ny, nz);
350
351        volPtr = NanoVis::load_volume(tag, nx, ny, nz, 4, data,
352                                      field.valueMin(), field.valueMax(),
353                                      nzero_min);
354        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
355                               field.rangeMax(Rappture::xaxis));
356        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
357                               field.rangeMax(Rappture::yaxis));
358        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
359                               field.rangeMax(Rappture::zaxis));
360        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
361        volPtr->update_pending = true;
362        delete [] data;
363    }
364
365    //
366    // Center this new volume on the origin.
367    //
368    float dx0 = -0.5;
369    float dy0 = -0.5*dy/dx;
370    float dz0 = -0.5*dz/dx;
371    if (volPtr) {
372        volPtr->location(Vector3(dx0, dy0, dz0));
373        TRACE("volume moved\n");
374    }
375    return volPtr;
376}
377
378/**
379 * \brief Load a 3D volume from a dx-format file
380 */
381Volume *
382load_volume_stream(Rappture::Outcome& result, const char *tag,
383                   std::iostream& fin)
384{
385    TRACE("load_volume_stream %s\n", tag);
386
387    Rappture::MeshTri2D xymesh;
388    int dummy, nx, ny, nz, nxy, npts;
389    double x0, y0, z0, dx, dy, dz, ddx, ddy, ddz;
390    char line[128], type[128], *start;
391
392    int isrect = 1;
393
394    dx = dy = dz = 0.0;
395    x0 = y0 = z0 = 0.0; // May not have an origin line.
396    nx = ny = nz = npts = nxy = 0;
397    while (!fin.eof()) {
398        fin.getline(line, sizeof(line) - 1);
399        if (fin.fail()) {
400            result.error("error in data stream");
401            return NULL;
402        }
403        for (start = line; *start == ' ' || *start == '\t'; start++)
404            ;  // skip leading blanks
405
406        if (*start != '#') {  // skip comment lines
407            if (sscanf(start, "object %d class gridpositions counts %d %d %d",
408                       &dummy, &nx, &ny, &nz) == 4) {
409                // found grid size
410                isrect = 1;
411            } else if (sscanf(start, "object %d class array type float rank 1 shape 3 items %d data follows",
412                              &dummy, &nxy) == 2) {
413                isrect = 0;
414
415                double xx, yy, zz;
416                for (int i = 0; i < nxy; i++) {
417                    fin.getline(line,sizeof(line)-1);
418                    if (sscanf(line, "%lg %lg %lg", &xx, &yy, &zz) == 3) {
419                        xymesh.addNode( Rappture::Node2D(xx,yy) );
420                    }
421                }
422
423                char fpts[128];
424                sprintf(fpts, "/tmp/tmppts%d", getpid());
425                char fcells[128];
426                sprintf(fcells, "/tmp/tmpcells%d", getpid());
427
428                std::ofstream ftmp(fpts);
429                // save corners of bounding box first, to work around meshing
430                // problems in voronoi utility
431                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
432                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
433                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
434                     << xymesh.rangeMin(Rappture::yaxis) << std::endl;
435                ftmp << xymesh.rangeMax(Rappture::xaxis) << " "
436                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
437                ftmp << xymesh.rangeMin(Rappture::xaxis) << " "
438                     << xymesh.rangeMax(Rappture::yaxis) << std::endl;
439                for (int i = 0; i < nxy; i++) {
440                    ftmp << xymesh.atNode(i).x() << " " << xymesh.atNode(i).y() << std::endl;
441                }
442                ftmp.close();
443
444                char cmdstr[512];
445                sprintf(cmdstr, "voronoi -t < %s > %s", fpts, fcells);
446                if (system(cmdstr) == 0) {
447                    int cx, cy, cz;
448                    std::ifstream ftri(fcells);
449                    while (!ftri.eof()) {
450                        ftri.getline(line,sizeof(line)-1);
451                        if (sscanf(line, "%d %d %d", &cx, &cy, &cz) == 3) {
452                            if (cx >= 4 && cy >= 4 && cz >= 4) {
453                                // skip first 4 boundary points
454                                xymesh.addCell(cx-4, cy-4, cz-4);
455                            }
456                        }
457                    }
458                    ftri.close();
459                } else {
460                    result.error("triangularization failed");
461                    return NULL;
462                }
463                unlink(fpts);
464                unlink(fcells);
465            } else if (sscanf(start, "object %d class regulararray count %d", &dummy, &nz) == 2) {
466                // found z-grid
467            } else if (sscanf(start, "origin %lg %lg %lg", &x0, &y0, &z0) == 3) {
468                // found origin
469            } else if (sscanf(start, "delta %lg %lg %lg", &ddx, &ddy, &ddz) == 3) {
470                // found one of the delta lines
471                if (ddx != 0.0) {
472                    dx = ddx;
473                } else if (ddy != 0.0) {
474                    dy = ddy;
475                } else if (ddz != 0.0) {
476                    dz = ddz;
477                }
478            } else if (sscanf(start, "object %d class array type %s rank 0 items %d data follows",
479                              &dummy, type, &npts) == 3) {
480                if (isrect && (npts != nx*ny*nz)) {
481                    result.addError("inconsistent data: expected %d points"
482                                    " but found %d points", nx*ny*nz, npts);
483                    return NULL;
484                } else if (!isrect && (npts != nxy*nz)) {
485                    result.addError("inconsistent data: expected %d points"
486                                    " but found %d points", nx*ny*nz, npts);
487                    return NULL;
488                }
489                break;
490            } else if (sscanf(start, "object %d class array type %s rank 0 times %d data follows",
491                              &dummy, type, &npts) == 3) {
492                if (npts != nx*ny*nz) {
493                    result.addError("inconsistent data: expected %d points"
494                                    " but found %d points", nx*ny*nz, npts);
495                    return NULL;
496                }
497                break;
498            }
499        }
500    }
501    // read data points
502    if (fin.eof()) {
503        result.error("data not found in stream");
504        return NULL;
505    }
506    Volume *volPtr = NULL;
507    if (isrect) {
508        Rappture::Mesh1D xgrid(x0, x0+nx*dx, nx);
509        Rappture::Mesh1D ygrid(y0, y0+ny*dy, ny);
510        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
511        Rappture::FieldRect3D field(xgrid, ygrid, zgrid);
512
513        double dval[6];
514        int nread = 0;
515        int ix = 0;
516        int iy = 0;
517        int iz = 0;
518
519        while (!fin.eof() && nread < npts) {
520            fin.getline(line,sizeof(line)-1);
521            if (fin.fail()) {
522                result.addError("error reading data points");
523                return NULL;
524            }
525            int n = sscanf(line, "%lg %lg %lg %lg %lg %lg",
526                           &dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[5]);
527            for (int p = 0; p < n; p++) {
528                int nindex = iz*nx*ny + iy*nx + ix;
529                field.define(nindex, dval[p]);
530                nread++;
531                if (++iz >= nz) {
532                    iz = 0;
533                    if (++iy >= ny) {
534                        iy = 0;
535                        ++ix;
536                    }
537                }
538            }
539        }
540
541        // make sure that we read all of the expected points
542        if (nread != nx*ny*nz) {
543            result.addError("inconsistent data: expected %d points"
544                            " but found %d points", nx*ny*nz, npts);
545            return NULL;
546        }
547
548        // figure out a good mesh spacing
549        int nsample = 30;
550        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
551        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
552        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
553        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
554
555        nx = (int)ceil(dx/dmin);
556        ny = (int)ceil(dy/dmin);
557        nz = (int)ceil(dz/dmin);
558
559#ifndef NV40
560        // must be an even power of 2 for older cards
561        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
562        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
563        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
564#endif
565
566//#define _SOBEL
567#ifdef _SOBEL_
568        const int step = 1;
569        float *cdata = new float[nx*ny*nz * step];
570        int ngen = 0;
571        double nzero_min = 0.0;
572        for (int iz = 0; iz < nz; iz++) {
573            double zval = z0 + iz*dmin;
574            for (int iy = 0; iy < ny; iy++) {
575                double yval = y0 + iy*dmin;
576                for (int ix = 0; ix < nx; ix++) {
577                    double xval = x0 + ix*dmin;
578                    double v = field.value(xval, yval, zval);
579
580                    if (v != 0.0 && v < nzero_min) {
581                        nzero_min = v;
582                    }
583
584                    // scale all values [0-1], -1 => out of bounds
585                    v = (isnan(v)) ? -1.0 : v;
586
587                    cdata[ngen] = v;
588                    ngen += step;
589                }
590            }
591        }
592
593        float *data = computeGradient(cdata, nx, ny, nz,
594                                      field.valueMin(),
595                                      field.valueMax());
596#else
597        double vmin = field.valueMin();
598        double vmax = field.valueMax();
599        double nzero_min = 0.0;
600        float *data = new float[nx*ny*nz * 4];
601        double dv = vmax - vmin;
602        int ngen = 0;
603        if (dv == 0.0) {
604            dv = 1.0;
605        }
606
607        for (int iz = 0; iz < nz; iz++) {
608            double zval = z0 + iz*dmin;
609            for (int iy = 0; iy < ny; iy++) {
610                double yval = y0 + iy*dmin;
611                for (int ix = 0; ix < nx; ix++) {
612                    double xval = x0 + ix*dmin;
613                    double v = field.value(xval,yval,zval);
614
615                    // scale all values [0-1], -1 => out of bounds
616                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
617
618                    data[ngen] = v;
619                    ngen += 4;
620                }
621            }
622        }
623
624        computeSimpleGradient(data, nx, ny, nz);
625#endif
626
627        TRACE("nx = %i ny = %i nz = %i\n",nx,ny,nz);
628        TRACE("dx = %lg dy = %lg dz = %lg\n",dx,dy,dz);
629        TRACE("dataMin = %lg\tdataMax = %lg\tnzero_min = %lg\n",
630              field.valueMin(), field.valueMax(), nzero_min);
631
632        volPtr = NanoVis::load_volume(tag, nx, ny, nz, 4, data,
633                                      field.valueMin(), field.valueMax(),
634                                      nzero_min);
635        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
636                               field.rangeMax(Rappture::xaxis));
637        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
638                               field.rangeMax(Rappture::yaxis));
639        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
640                               field.rangeMax(Rappture::zaxis));
641        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
642        volPtr->update_pending = true;
643        // TBD..
644        // POINTSET
645        /*
646          PointSet *pset = new PointSet();
647          pset->initialize(volPtr, (float*)data);
648          pset->setVisible(true);
649          NanoVis::pointSet.push_back(pset);
650          updateColor(pset);
651          volPtr->pointsetIndex = NanoVis::pointSet.size() - 1;
652        */
653
654        delete [] data;
655    } else {
656        Rappture::Mesh1D zgrid(z0, z0+nz*dz, nz);
657        Rappture::FieldPrism3D field(xymesh, zgrid);
658
659        double dval;
660        int nread = 0;
661        int ixy = 0;
662        int iz = 0;
663        while (!fin.eof() && nread < npts) {
664            fin >> dval;
665            if (fin.fail()) {
666                result.addError("after %d of %d points: can't read number",
667                                nread, npts);
668                return NULL;
669            } else {
670                int nid = nxy*iz + ixy;
671                field.define(nid, dval);
672
673                nread++;
674                if (++iz >= nz) {
675                    iz = 0;
676                    ixy++;
677                }
678            }
679        }
680
681        // make sure that we read all of the expected points
682        if (nread != nxy*nz) {
683            result.addError("inconsistent data: expected %d points"
684                            " but found %d points", nx*ny*nz, npts);
685            return NULL;
686        }
687
688        // figure out a good mesh spacing
689        int nsample = 30;
690        x0 = field.rangeMin(Rappture::xaxis);
691        dx = field.rangeMax(Rappture::xaxis) - field.rangeMin(Rappture::xaxis);
692        y0 = field.rangeMin(Rappture::yaxis);
693        dy = field.rangeMax(Rappture::yaxis) - field.rangeMin(Rappture::yaxis);
694        z0 = field.rangeMin(Rappture::zaxis);
695        dz = field.rangeMax(Rappture::zaxis) - field.rangeMin(Rappture::zaxis);
696        double dmin = pow((dx*dy*dz)/(nsample*nsample*nsample), 0.333);
697
698        nx = (int)ceil(dx/dmin);
699        ny = (int)ceil(dy/dmin);
700        nz = (int)ceil(dz/dmin);
701#ifndef NV40
702        // must be an even power of 2 for older cards
703        nx = (int)pow(2.0, ceil(log10((double)nx)/log10(2.0)));
704        ny = (int)pow(2.0, ceil(log10((double)ny)/log10(2.0)));
705        nz = (int)pow(2.0, ceil(log10((double)nz)/log10(2.0)));
706#endif
707        float *data = new float[4*nx*ny*nz];
708
709        double vmin = field.valueMin();
710        double dv = field.valueMax() - field.valueMin();
711        if (dv == 0.0) {
712            dv = 1.0;
713        }
714
715        // generate the uniformly sampled data that we need for a volume
716        int ngen = 0;
717        double nzero_min = 0.0;
718        for (int iz = 0; iz < nz; iz++) {
719            double zval = z0 + iz*dmin;
720            for (int iy = 0; iy < ny; iy++) {
721                double yval = y0 + iy*dmin;
722                for (int ix = 0; ix < nx; ix++) {
723                    double xval = x0 + ix*dmin;
724                    double v = field.value(xval, yval, zval);
725
726                    if (v != 0.0 && v < nzero_min) {
727                        nzero_min = v;
728                    }
729                    // scale all values [0-1], -1 => out of bounds
730                    v = (isnan(v)) ? -1.0 : (v - vmin)/dv;
731                    data[ngen] = v;
732
733                    ngen += 4;
734                }
735            }
736        }
737
738        // Compute the gradient of this data.  BE CAREFUL: center
739        // calculation on each node to avoid skew in either direction.
740        ngen = 0;
741        for (int iz=0; iz < nz; iz++) {
742            for (int iy=0; iy < ny; iy++) {
743                for (int ix=0; ix < nx; ix++) {
744                    // gradient in x-direction
745                    double valm1 = (ix == 0) ? 0.0 : data[ngen-1];
746                    double valp1 = (ix == nx-1) ? 0.0 : data[ngen+1];
747                    if (valm1 < 0 || valp1 < 0) {
748                        data[ngen+1] = 0.0;
749                    } else {
750                        data[ngen+1] = valp1-valm1; // assume dx=1
751                        //data[ngen+1] = ((valp1-valm1) + 1.0) * 0.5; // assume dx=1 (ISO)
752                    }
753                   
754                    // gradient in y-direction
755                    valm1 = (iy == 0) ? 0.0 : data[ngen-4*nx];
756                    valp1 = (iy == ny-1) ? 0.0 : data[ngen+4*nx];
757                    if (valm1 < 0 || valp1 < 0) {
758                        data[ngen+2] = 0.0;
759                    } else {
760                        data[ngen+2] = valp1-valm1; // assume dy=1
761                        //data[ngen+2] = ((valp1-valm1) + 1.0) * 0.5; // assume dy=1 (ISO)
762                    }
763                   
764                    // gradient in z-direction
765                    valm1 = (iz == 0) ? 0.0 : data[ngen-4*nx*ny];
766                    valp1 = (iz == nz-1) ? 0.0 : data[ngen+4*nx*ny];
767                    if (valm1 < 0 || valp1 < 0) {
768                        data[ngen+3] = 0.0;
769                    } else {
770                        data[ngen+3] = valp1-valm1; // assume dz=1
771                        //data[ngen+3] = ((valp1-valm1) + 1.0) * 0.5; // assume dz=1 (ISO)
772                    }
773                   
774                    ngen += 4;
775                }
776            }
777        }
778
779        volPtr = NanoVis::load_volume(tag, nx, ny, nz, 4, data,
780                                      field.valueMin(), field.valueMax(),
781                                      nzero_min);
782        volPtr->xAxis.SetRange(field.rangeMin(Rappture::xaxis),
783                               field.rangeMax(Rappture::xaxis));
784        volPtr->yAxis.SetRange(field.rangeMin(Rappture::yaxis),
785                               field.rangeMax(Rappture::yaxis));
786        volPtr->zAxis.SetRange(field.rangeMin(Rappture::zaxis),
787                               field.rangeMax(Rappture::zaxis));
788        volPtr->wAxis.SetRange(field.valueMin(), field.valueMax());
789        volPtr->update_pending = true;
790        // TBD..
791        // POINTSET
792        /*
793          PointSet *pset = new PointSet();
794          pset->initialize(volPtr, (float*)data);
795          pset->setVisible(true);
796          NanoVis::pointSet.push_back(pset);
797          updateColor(pset);
798          volPtr->pointsetIndex = NanoVis::pointSet.size() - 1;
799        */
800
801        delete [] data;
802    }
803
804    //
805    // Center this new volume on the origin.
806    //
807    float dx0 = -0.5;
808    float dy0 = -0.5*dy/dx;
809    float dz0 = -0.5*dz/dx;
810    if (volPtr) {
811        volPtr->location(Vector3(dx0, dy0, dz0));
812    }
813    return volPtr;
814}
Note: See TracBrowser for help on using the repository browser.