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

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

Use trace macros in image loader. Formatting fixes in libs

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