/renderthread.cpp

http://nscow.googlecode.com/ · C++ · 246 lines · 209 code · 37 blank · 0 comment · 14 complexity · 5feaafdb9525dd16f79f8df24e5309e2 MD5 · raw file

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