PageRenderTime 66ms CodeModel.GetById 13ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/renderthread.cpp

http://nscow.googlecode.com/
C++ | 246 lines | 209 code | 37 blank | 0 comment | 13 complexity | 5feaafdb9525dd16f79f8df24e5309e2 MD5 | raw file
  1#include <QColor>
  2#include <cmath>
  3using namespace std;
  4
  5#include "ScalarField2D.h"
  6#include "VectorField2D.h"
  7#include "VectorOperators.h"
  8#include "NavierStokes.h"
  9#include "renderthread.h"
 10
 11RenderThread::RenderThread(QObject *parent)
 12    : QThread(parent), m_abort(false), m_hasAction(NONE), itsOutput(0)
 13{
 14}
 15
 16RenderThread::~RenderThread()
 17{
 18    mutex.lock();
 19    m_abort = true;
 20    mutex.unlock();
 21
 22    wait();
 23}
 24
 25void RenderThread::startSim(int xdim, int ydim)
 26{
 27    this->xdim = xdim;
 28    this->ydim = ydim;
 29    m_abort = false;
 30    start();
 31}
 32
 33void RenderThread::startSim(QImage& image)
 34{
 35    if(!image.isNull()) {
 36        m_image = image;
 37        xdim = m_image.width();
 38        ydim = m_image.height();
 39    } else {
 40        xdim = 50;
 41        ydim = 50;
 42    }
 43    m_abort = false;
 44    start();
 45}
 46
 47void RenderThread::run()
 48{
 49    m_image = QImage(xdim,ydim,QImage::Format_RGB32);
 50
 51    ScalarField2D p(xdim,ydim);
 52    p.fill(0.0);
 53
 54    ScalarField2D rho(xdim,ydim,1);
 55    rho.fill(0.0);
 56
 57    VectorField2D v(xdim,ydim,-1);
 58    v.fill(0.0);
 59
 60    while(!m_abort) {
 61        NavierStokes::advect(v);
 62        NavierStokes::diffuse(v);
 63
 64        switch (m_hasAction) {
 65        case FORCE:
 66            NavierStokes::addForces(v, xdim*m_fstart.x(), ydim*m_fstart.y(), xdim*m_fend.x(), ydim*m_fend.y());
 67            m_fstart = m_fend;
 68            m_hasAction = NONE;
 69            break;
 70        case DYE:
 71            NavierStokes::addDye(rho,m_xTool,m_yTool);
 72            break;
 73        case INFORCE:
 74            NavierStokes::addInOutForce(v,m_xTool,m_yTool,-1);
 75            break;
 76        case OUTFORCE:
 77            NavierStokes::addInOutForce(v,m_xTool,m_yTool);
 78        default:
 79            break;
 80        }
 81
 82        NavierStokes::computePressure(v,p);
 83        NavierStokes::subtractPressureGradient(v,p);
 84        NavierStokes::vorticityConfinement(v);
 85
 86        NavierStokes::advect(v,rho);
 87        NavierStokes::diffuse(v,rho);
 88
 89        NavierStokes::t += NavierStokes::dt;
 90
 91        switch (itsOutput) {
 92        case DENSITY:
 93            writeImage(rho,m_image);
 94            break;
 95        case VELOCITY:
 96            writeImage(v,m_image);
 97            break;
 98        case PRESSURE:
 99            writeImage(p,m_image);
100            break;
101        case VORTICITY:
102            ScalarField2D vorticity(xdim,ydim);
103            DelCross(vorticity,v);
104            writeImage(vorticity,m_image);
105            break;
106        }
107        emit sendImage(m_image);
108        msleep(50);
109    }
110}
111
112void RenderThread::stopProcess()
113{
114    mutex.lock();
115    m_abort = true;
116    mutex.unlock();
117}
118
119void RenderThread::writeImage(const ScalarField2D& data, QImage& image) {
120    int xdim = data.xdim;
121    int ydim = data.ydim;
122
123    double scale = 255 / max(fabs(data.min()), fabs(data.max()));
124    QRgb* ppixel = (QRgb*) image.bits();
125    for(int y = 0; y < ydim; y++) {
126        for(int x = 0; x < xdim; x++) {
127            if (data.value(x,y) < 0)
128                *ppixel = qRgb(-scale*data.value(x,y),0,0);
129            else
130                *ppixel = qRgb(0,0,scale*data.value(x,y));
131            ppixel++;
132        }
133    }
134}
135
136
137void RenderThread::writeImage(const VectorField2D& data, QImage& image) {
138    int xdim = data.xdim;
139    int ydim = data.ydim;
140
141    double scale = 255/max(fabs(data.max()),fabs(data.min()));;
142
143    QRgb* ppixel = (QRgb*) image.bits();
144    for(int y = 0; y < ydim; y++) {
145        for(int x = 0; x < xdim; x++) {
146            double g = 0.0;
147            if (data.value(x,y,0) < 0.0) g -= data.value(x,y,0);
148            if (data.value(x,y,1) < 0.0) g -= data.value(x,y,1);
149            *ppixel = qRgb(scale * fabs( data.value(x,y,0) ) , 0.5*scale*g , scale*fabs(data.value(x,y,1)) );
150            ppixel++;
151        }
152    }
153}
154
155void RenderThread::startForce(double x, double y) {
156    mutex.lock();
157    m_fstart = QPointF(x,y);
158    mutex.unlock();
159}
160
161void RenderThread::moreForce(double x, double y) {
162    mutex.lock();
163    if (m_fstart.x()!=x && m_fstart.y()!=y) {
164        m_fend = QPointF(x,y);
165        m_hasAction = FORCE;
166    }
167    mutex.unlock();
168}
169
170void RenderThread::addDye(double x, double y) {
171    mutex.lock();
172    m_xTool = x*xdim;
173    m_yTool = y*ydim;
174    m_hasAction = DYE;
175    mutex.unlock();
176}
177
178void RenderThread::stopAction(double, double) {
179    mutex.lock();
180    m_hasAction = NONE;
181    mutex.unlock();
182}
183
184void RenderThread::addInForce(double x, double y) {
185    mutex.lock();
186    m_xTool = x*xdim;
187    m_yTool = y*ydim;
188    m_hasAction = INFORCE;
189    mutex.unlock();
190}
191
192void RenderThread::addOutForce(double x, double y) {
193    mutex.lock();
194    m_xTool = x*xdim;
195    m_yTool = y*ydim;
196    m_hasAction = OUTFORCE;
197    mutex.unlock();
198}
199
200void RenderThread::setNu(double nu) {
201    mutex.lock();
202    NavierStokes::nu = nu;
203    mutex.unlock();
204}
205
206void RenderThread::setDt(double dt) {
207    mutex.lock();
208    NavierStokes::dt = dt;
209    mutex.unlock();
210}
211
212void RenderThread::setDx(double dx) {
213    mutex.lock();
214    NavierStokes::dx = dx;
215    mutex.unlock();
216}
217
218void RenderThread::setE(double e) {
219    mutex.lock();
220    NavierStokes::e = e;
221    mutex.unlock();
222}
223
224void RenderThread::setRTool(double rTool) {
225    mutex.lock();
226    NavierStokes::rTool = rTool;
227    mutex.unlock();
228}
229
230void RenderThread::setMagTool(double magTool) {
231    mutex.lock();
232    NavierStokes::magTool = magTool;
233    mutex.unlock();
234}
235
236void RenderThread::setDC(double dc) {
237    mutex.lock();
238    NavierStokes::dC = dc;
239    mutex.unlock();
240}
241
242void RenderThread::setOutput(int output) {
243    mutex.lock();
244    itsOutput = output;
245    mutex.unlock();
246}