source: nanovis/branches/1.2/Flow.cpp @ 5500

Last change on this file since 5500 was 5489, checked in by ldelgass, 9 years ago

Move cumulative flow min/max magnitude to Flow.

  • Property svn:eol-style set to native
File size: 10.6 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 *
5 * Authors:
6 *   Wei Qiao <qiaow@purdue.edu>
7 *   Insoo Woo <iwoo@purdue.edu>
8 *   George A. Howlett <gah@purdue.edu>
9 *   Leif Delgass <ldelgass@purdue.edu>
10 */
11
12#include <float.h>
13
14#include <tcl.h>
15
16#include <vrmath/BBox.h>
17#include <vrmath/Vector3f.h>
18
19#include "nanovis.h"
20#include "Flow.h"
21#include "FlowCmd.h"
22#include "FlowTypes.h"
23#include "FlowParticles.h"
24#include "FlowBox.h"
25#include "LIC.h"
26#include "VelocityArrowsSlice.h"
27#include "Switch.h"
28#include "Unirect.h"
29#include "Volume.h"
30#include "Trace.h"
31#include "TransferFunction.h"
32
33using namespace nv;
34using namespace vrmath;
35
36bool Flow::updatePending = false;
37double Flow::magMin = DBL_MAX;
38double Flow::magMax = -DBL_MAX;
39
40Flow::Flow(Tcl_Interp *interp, const char *name) :
41    _interp(interp),
42    _name(name),
43    _data(NULL),
44    _volume(NULL)
45{
46    memset(&_sv, 0, sizeof(FlowValues));
47    _sv.sliceVisible = 1;
48    _sv.transferFunction = NanoVis::getTransferFunction("default");
49
50    _cmdToken = Tcl_CreateObjCommand(_interp, (char *)name,
51                                     (Tcl_ObjCmdProc *)FlowInstObjCmd,
52                                     this, FlowInstDeleteProc);
53}
54
55Flow::~Flow()
56{
57    TRACE("Enter");
58
59    FreeSwitches(_switches, &_sv, 0);
60
61    if (_data != NULL) {
62        delete _data;
63    }
64    if (_volume != NULL) {
65        NanoVis::removeVolume(_volume);
66        _volume = NULL;
67    }
68    for (BoxHashmap::iterator itr = _boxTable.begin();
69         itr != _boxTable.end(); ++itr) {
70        delete itr->second;
71    }
72    _boxTable.clear();
73    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
74         itr != _particlesTable.end(); ++itr) {
75        delete itr->second;
76    }
77    _particlesTable.clear();
78}
79
80void
81Flow::getBounds(Vector3f& min,
82                Vector3f& max,
83                bool onlyVisible)
84{
85    TRACE("Enter");
86
87    if (onlyVisible && !visible())
88        return;
89
90    BBox allBounds;
91    for (BoxHashmap::iterator itr = _boxTable.begin();
92         itr != _boxTable.end(); ++itr) {
93        FlowBox *box = itr->second;
94        if (!onlyVisible || box->visible()) {
95            BBox bbox;
96            box->getWorldSpaceBounds(bbox.min, bbox.max,
97                                     getVolume());
98            allBounds.extend(bbox);
99        }
100    }
101    min = allBounds.min;
102    max = allBounds.max;
103}
104
105float
106Flow::getRelativePosition(FlowPosition *position)
107{
108    if (position->flags == RELPOS) {
109        return position->value;
110    }
111    switch (position->axis) {
112    case AXIS_X: 
113        return (position->value - NanoVis::xMin) /
114            (NanoVis::xMax - NanoVis::xMin);
115    case AXIS_Y: 
116        return (position->value - NanoVis::yMin) /
117            (NanoVis::yMax - NanoVis::yMin);
118    case AXIS_Z: 
119        return (position->value - NanoVis::zMin) /
120            (NanoVis::zMax - NanoVis::zMin);
121    }
122    return 0.0;
123}
124
125void
126Flow::resetParticles()
127{
128    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
129         itr != _particlesTable.end(); ++itr) {
130        itr->second->reset();
131    }
132}
133
134void
135Flow::advect()
136{
137    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
138         itr != _particlesTable.end(); ++itr) {
139        if (itr->second->visible()) {
140            itr->second->advect();
141        }
142    }
143}
144
145void
146Flow::render()
147{
148    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
149         itr != _particlesTable.end(); ++itr) {
150        if (itr->second->visible()) {
151            itr->second->render();
152        }
153    }
154    renderBoxes();
155}
156
157FlowParticles *
158Flow::createParticles(const char *particlesName)
159{
160    ParticlesHashmap::iterator itr = _particlesTable.find(particlesName);
161    if (itr != _particlesTable.end()) {
162        TRACE("Deleting existing particle injection plane '%s'", particlesName);
163        delete itr->second;
164        _particlesTable.erase(itr);
165    }
166    FlowParticles *particles = new FlowParticles(particlesName);
167    _particlesTable[particlesName] = particles;
168    return particles;
169}
170
171FlowParticles *
172Flow::getParticles(const char *particlesName)
173{
174    ParticlesHashmap::iterator itr;
175    itr = _particlesTable.find(particlesName);
176    if (itr == _particlesTable.end()) {
177        TRACE("Can't find particle injection plane '%s' in '%s'", particlesName, name());
178        return NULL;
179    }
180    return itr->second;
181}
182
183void
184Flow::deleteParticles(const char *particlesName)
185{
186    ParticlesHashmap::iterator itr = _particlesTable.find(particlesName);
187    if (itr == _particlesTable.end()) {
188        TRACE("Can't find particle injection plane '%s' in '%s'", particlesName, name());
189        return;
190    }
191    delete itr->second;
192    _particlesTable.erase(itr);
193}
194
195void
196Flow::getParticlesNames(std::vector<std::string>& names)
197{
198    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
199         itr != _particlesTable.end(); ++itr) {
200        names.push_back(std::string(itr->second->name()));
201    }
202}
203
204FlowBox *
205Flow::createBox(const char *boxName)
206{
207    BoxHashmap::iterator itr = _boxTable.find(boxName);
208    if (itr != _boxTable.end()) {
209        TRACE("Deleting existing box '%s'", boxName);
210        delete itr->second;
211        _boxTable.erase(itr);
212    }
213    FlowBox *box = new FlowBox(boxName);
214    _boxTable[boxName] = box;
215    return box;
216}
217
218FlowBox *
219Flow::getBox(const char *boxName)
220{
221    BoxHashmap::iterator itr = _boxTable.find(boxName);
222    if (itr == _boxTable.end()) {
223        TRACE("Can't find box '%s' in '%s'", boxName, name());
224        return NULL;
225    }
226    return itr->second;
227}
228
229void
230Flow::deleteBox(const char *boxName)
231{
232    BoxHashmap::iterator itr = _boxTable.find(boxName);
233    if (itr == _boxTable.end()) {
234        TRACE("Can't find box '%s' in '%s'", boxName, name());
235        return;
236    }
237    delete itr->second;
238    _boxTable.erase(itr);
239}
240
241void Flow::getBoxNames(std::vector<std::string>& names)
242{
243    for (BoxHashmap::iterator itr = _boxTable.begin();
244         itr != _boxTable.end(); ++itr) {
245        names.push_back(std::string(itr->second->name()));
246    }
247}
248
249void
250Flow::initializeParticles()
251{
252    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
253         itr != _particlesTable.end(); ++itr) {
254        itr->second->initialize();
255    }
256}
257
258bool
259Flow::scaleVectorField()
260{
261    if (_volume != NULL) {
262        TRACE("Removing existing volume: %s", _volume->name());
263        NanoVis::removeVolume(_volume);
264        _volume = NULL;
265    }
266    float *vdata = getScaledVector();
267    if (vdata == NULL) {
268        return false;
269    }
270    Volume *volume = makeVolume(vdata);
271    delete [] vdata;
272    if (volume == NULL) {
273        return false;
274    }
275    _volume = volume;
276
277    Vector3f scale = volume->getPhysicalScaling();
278    Vector3f pos = _volume->getPosition();
279
280    if (NanoVis::licRenderer != NULL) {
281        NanoVis::licRenderer->
282            setVectorField(_volume->textureID(),
283                           pos,
284                           scale.x,
285                           scale.y,
286                           scale.z,
287                           _volume->wAxis.max());
288        NanoVis::licRenderer->setSliceAxis(_sv.slicePos.axis);
289        NanoVis::licRenderer->setSlicePosition(_sv.slicePos.value);
290        NanoVis::licRenderer->visible(_sv.sliceVisible);
291    }
292
293    if (NanoVis::velocityArrowsSlice != NULL) {
294        NanoVis::velocityArrowsSlice->
295            setVectorField(_volume->textureID(),
296                           pos,
297                           scale.x,
298                           scale.y,
299                           scale.z,
300                           _volume->wAxis.max());
301        NanoVis::velocityArrowsSlice->setSliceAxis(_sv.slicePos.axis);
302        NanoVis::velocityArrowsSlice->setSlicePosition(_sv.slicePos.value);
303        NanoVis::velocityArrowsSlice->visible(_sv.showArrows);
304    }
305
306    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
307         itr != _particlesTable.end(); ++itr) {
308        itr->second->setVectorField(_volume,
309                                    pos,
310                                    scale.x,
311                                    scale.y,
312                                    scale.z,
313                                    _volume->wAxis.max());
314    }
315    return true;
316}
317
318void
319Flow::renderBoxes()
320{
321    for (BoxHashmap::iterator itr = _boxTable.begin();
322         itr != _boxTable.end(); ++itr) {
323        if (itr->second->visible()) {
324            itr->second->render(_volume);
325        }
326    }
327}
328
329float *
330Flow::getScaledVector()
331{
332    assert(_data->nComponents() == 3);
333    size_t n = _data->nValues() / _data->nComponents() * 4;
334    float *data = new float[n];
335    if (data == NULL) {
336        return NULL;
337    }
338    memset(data, 0, sizeof(float) * n);
339    float *dest = data;
340    const float *values = _data->values();
341    for (size_t iz = 0; iz < _data->zNum(); iz++) {
342        for (size_t iy = 0; iy < _data->yNum(); iy++) {
343            for (size_t ix = 0; ix < _data->xNum(); ix++) {
344                double vx, vy, vz, vm;
345                vx = values[0];
346                vy = values[1];
347                vz = values[2];
348                vm = sqrt(vx*vx + vy*vy + vz*vz);
349                dest[0] = vm / magMax;
350                dest[1] = vx /(2.0 * magMax) + 0.5;
351                dest[2] = vy /(2.0 * magMax) + 0.5;
352                dest[3] = vz /(2.0 * magMax) + 0.5;
353                values += 3;
354                dest += 4;
355            }
356        }
357    }
358    return data;
359}
360
361Volume *
362Flow::makeVolume(float *data)
363{
364    Volume *volume =
365        NanoVis::loadVolume(_name.c_str(),
366                            _data->xNum(),
367                            _data->yNum(),
368                            _data->zNum(),
369                            4, data,
370                            magMin,
371                            magMax,
372                            0);
373    volume->xAxis.setRange(_data->xMin(), _data->xMax());
374    volume->yAxis.setRange(_data->yMin(), _data->yMax());
375    volume->zAxis.setRange(_data->zMin(), _data->zMax());
376
377    TRACE("mag=%g %g", magMin, magMax);
378
379    volume->disableCutplane(0);
380    volume->disableCutplane(1);
381    volume->disableCutplane(2);
382
383    /* Initialize the volume with the previously configured values. */
384    volume->transferFunction(_sv.transferFunction);
385    volume->dataEnabled(_sv.showVolume);
386    volume->twoSidedLighting(_sv.twoSidedLighting);
387    volume->outline(_sv.showOutline);
388    volume->opacityScale(_sv.opacity);
389    volume->ambient(_sv.ambient);
390    volume->diffuse(_sv.diffuse);
391    volume->specularLevel(_sv.specular);
392    volume->specularExponent(_sv.specularExp);
393    volume->visible(_sv.showVolume);
394
395    Vector3f volScaling = volume->getPhysicalScaling();
396    Vector3f pos(volScaling);
397    pos *= -0.5;
398    volume->setPosition(pos);
399
400    Volume::updatePending = true;
401    return volume;
402}
Note: See TracBrowser for help on using the repository browser.