PageRenderTime 75ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/Post/PViewVertexArrays.cpp

https://bitbucket.org/lge/gmsh
C++ | 1501 lines | 1335 code | 138 blank | 28 comment | 453 complexity | 51fb2a52f991b5d607b78d77af840585 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. // Gmsh - Copyright (C) 1997-2012 C. Geuzaine, J.-F. Remacle
  2. //
  3. // See the LICENSE.txt file for license information. Please report all
  4. // bugs and problems to <gmsh@geuz.org>.
  5. #include <string.h>
  6. #include "GmshMessage.h"
  7. #include "GmshDefines.h"
  8. #include "onelab.h"
  9. #include "Iso.h"
  10. #include "MEdge.h"
  11. #include "MFace.h"
  12. #include "PView.h"
  13. #include "PViewOptions.h"
  14. #include "PViewData.h"
  15. #include "PViewDataRemote.h"
  16. #include "Numeric.h"
  17. #include "VertexArray.h"
  18. #include "SmoothData.h"
  19. #include "Context.h"
  20. #include "OpenFile.h"
  21. #include "mathEvaluator.h"
  22. #include "Options.h"
  23. #include "StringUtils.h"
  24. static void saturate(int nb, double **val, double vmin, double vmax,
  25. int i0=0, int i1=1, int i2=2, int i3=3,
  26. int i4=4, int i5=5, int i6=6, int i7=7)
  27. {
  28. int id[8] = {i0, i1, i2, i3, i4, i5, i6, i7};
  29. for(int i = 0; i < nb; i++){
  30. if(val[id[i]][0] > vmax) val[id[i]][0] = vmax;
  31. else if(val[id[i]][0] < vmin) val[id[i]][0] = vmin;
  32. }
  33. }
  34. static double saturateVector(double *val, int numComp2, double *val2,
  35. double min, double max)
  36. {
  37. double v = ComputeScalarRep(numComp2, val2); // v >= 0
  38. if (v < min && v > 1e-15) {
  39. double f = min / v;
  40. for (int iComp = 0; iComp < numComp2; ++iComp)
  41. val2[iComp] *= f;
  42. val[0] *= f;
  43. val[1] *= f;
  44. val[2] *= f;
  45. return min;
  46. }
  47. if (v > max && v > 1e-15) {
  48. double f = max / v;
  49. for (int iComp = 0; iComp < numComp2; ++iComp)
  50. val2[iComp] *= f;
  51. val[0] *= f;
  52. val[1] *= f;
  53. val[2] *= f;
  54. return max;
  55. }
  56. return v;
  57. }
  58. static SVector3 normal3(double **xyz, int i0=0, int i1=1, int i2=2)
  59. {
  60. SVector3 t1(xyz[i1][0] - xyz[i0][0],
  61. xyz[i1][1] - xyz[i0][1],
  62. xyz[i1][2] - xyz[i0][2]);
  63. SVector3 t2(xyz[i2][0] - xyz[i0][0],
  64. xyz[i2][1] - xyz[i0][1],
  65. xyz[i2][2] - xyz[i0][2]);
  66. SVector3 n = crossprod(t1, t2);
  67. n.normalize();
  68. return n;
  69. }
  70. static SVector3 getPointNormal(PView *p, double v)
  71. {
  72. PViewOptions *opt = p->getOptions();
  73. SVector3 n(0., 0., 0.);
  74. if(opt->pointType > 0){
  75. // when we draw spheres, we use the normalized value (between 0
  76. // and 1) stored in the first component of the normal to modulate
  77. // the radius
  78. double d = opt->tmpMax - opt->tmpMin;
  79. n[0] = (v - opt->tmpMin) / (d ? d : 1.);
  80. }
  81. return n;
  82. }
  83. static void getLineNormal(PView *p, double x[2], double y[2], double z[2],
  84. double *v, SVector3 n[2], bool computeNormal)
  85. {
  86. PViewOptions *opt = p->getOptions();
  87. if(opt->lineType > 0){
  88. if(v){
  89. // when we draw tapered cylinders, we use the normalized values
  90. // (between 0 and 1) stored in the first component of the
  91. // normals to modulate the width
  92. double d = opt->tmpMax - opt->tmpMin;
  93. n[0][0] = (v[0] - opt->tmpMin) / (d ? d : 1.);
  94. n[1][0] = (v[1] - opt->tmpMin) / (d ? d : 1.);
  95. }
  96. else{
  97. // when we don't have values we use maximum width cylinders
  98. n[0][0] = n[1][0] = 1.;
  99. }
  100. }
  101. else if(computeNormal){
  102. SBoundingBox3d bb = p->getData()->getBoundingBox();
  103. if(bb.min().z() == bb.max().z())
  104. n[0] = n[1] = SVector3(0., 0., 1.);
  105. else if(bb.min().y() == bb.max().y())
  106. n[0] = n[1] = SVector3(0., 1., 0.);
  107. else if(bb.min().x() == bb.max().x())
  108. n[0] = n[1] = SVector3(1., 0., 0.);
  109. else{
  110. // we don't have any info about the normal, just pick one
  111. SVector3 t(x[1] - x[0], y[1] - y[0], z[1] - z[0]);
  112. SVector3 ex(0., 0., 0.);
  113. if(t[0] == 0.)
  114. ex[0] = 1.;
  115. else if(t[1] == 0.)
  116. ex[1] = 1.;
  117. else
  118. ex[2] = 1.;
  119. n[0] = crossprod(t, ex);
  120. n[0].normalize();
  121. n[1] = n[0];
  122. }
  123. }
  124. }
  125. static bool getExternalValues(PView *p, int index, int ient, int iele,
  126. int numNodes, int numComp, double **val,
  127. int &numComp2, double **val2)
  128. {
  129. PViewOptions *opt = p->getOptions();
  130. // use self by default
  131. numComp2 = numComp;
  132. for(int i = 0; i < numNodes; i++)
  133. for(int j = 0; j < numComp; j++)
  134. val2[i][j] = val[i][j];
  135. opt->externalMin = opt->tmpMin;
  136. opt->externalMax = opt->tmpMax;
  137. if(index < 0 || index >= (int)PView::list.size()) return false;
  138. PView *p2 = PView::list[index];
  139. PViewData *data2 = p2->getData(true); // use adaptive data if available
  140. if(iele >= data2->getNumElements(opt->timeStep, ient)) return false;
  141. if(!data2->skipElement(opt->timeStep, ient, iele) &&
  142. data2->getNumNodes(opt->timeStep, ient, iele) == numNodes){
  143. numComp2 = data2->getNumComponents(opt->timeStep, ient, iele);
  144. for(int i = 0; i < numNodes; i++)
  145. for(int j = 0; j < numComp2; j++)
  146. data2->getValue(opt->timeStep, ient, iele, i, j, val2[i][j]);
  147. if(opt->rangeType == PViewOptions::Custom){
  148. opt->externalMin = opt->customMin;
  149. opt->externalMax = opt->customMax;
  150. }
  151. else if(opt->rangeType == PViewOptions::PerTimeStep){
  152. opt->externalMin = data2->getMin(opt->timeStep);
  153. opt->externalMax = data2->getMax(opt->timeStep);
  154. }
  155. else{
  156. opt->externalMin = data2->getMin();
  157. opt->externalMax = data2->getMax();
  158. }
  159. return true;
  160. }
  161. return false;
  162. }
  163. static void applyGeneralRaise(PView *p, int numNodes, int numComp,
  164. double **vals, double **xyz)
  165. {
  166. PViewOptions *opt = p->getOptions();
  167. if(!opt->genRaiseEvaluator) return;
  168. std::vector<double> values(12, 0.), res(3);
  169. for(int k = 0; k < numNodes; k++) {
  170. for(int i = 0; i < 3; i++) values[i] = xyz[k][i];
  171. for(int i = 0; i < std::min(numComp, 9); i++) values[3 + i] = vals[k][i];
  172. if(opt->genRaiseEvaluator->eval(values, res))
  173. for(int i = 0; i < 3; i++)
  174. xyz[k][i] += opt->genRaiseFactor * res[i];
  175. }
  176. }
  177. void changeCoordinates(PView *p, int ient, int iele,
  178. int numNodes, int type, int numComp,
  179. double **xyz, double **val)
  180. {
  181. PViewOptions *opt = p->getOptions();
  182. if(opt->explode != 1.) {
  183. double barycenter[3] = {0., 0., 0.};
  184. for(int i = 0; i < numNodes; i++)
  185. for(int j = 0; j < 3; j++)
  186. barycenter[j] += xyz[i][j];
  187. for(int j = 0; j < 3; j++)
  188. barycenter[j] /= (double)numNodes;
  189. for(int i = 0; i < numNodes; i++)
  190. for(int j = 0; j < 3; j++)
  191. xyz[i][j] = barycenter[j] + opt->explode * (xyz[i][j] - barycenter[j]);
  192. }
  193. if(opt->transform[0][0] != 1. || opt->transform[0][1] != 0. ||
  194. opt->transform[0][2] != 0. || opt->transform[1][0] != 0. ||
  195. opt->transform[1][1] != 1. || opt->transform[1][2] != 0. ||
  196. opt->transform[2][0] != 0. || opt->transform[2][1] != 0. ||
  197. opt->transform[2][2] != 1.){
  198. for(int i = 0; i < numNodes; i++) {
  199. double old[3] = {xyz[i][0], xyz[i][1], xyz[i][2]};
  200. for(int j = 0; j < 3; j++){
  201. xyz[i][j] = 0.;
  202. for(int k = 0; k < 3; k++)
  203. xyz[i][j] += opt->transform[j][k] * old[k];
  204. }
  205. }
  206. }
  207. if(opt->offset[0] || opt->offset[1] || opt->offset[2]){
  208. for(int i = 0; i < numNodes; i++)
  209. for(int j = 0; j < 3; j++)
  210. xyz[i][j] += opt->offset[j];
  211. }
  212. if(opt->raise[0] || opt->raise[1] || opt->raise[2]){
  213. for(int i = 0; i < numNodes; i++){
  214. double v = ComputeScalarRep(numComp, val[i]);
  215. for(int j = 0; j < 3; j++)
  216. xyz[i][j] += opt->raise[j] * v;
  217. }
  218. }
  219. if(opt->normalRaise && (type == TYPE_LIN || type == TYPE_TRI || type ==TYPE_QUA)){
  220. SVector3 n;
  221. if(type == TYPE_LIN){
  222. // assumes lines in z=const plane, and raises in that plane
  223. double x[2] = {xyz[0][0], xyz[1][0]};
  224. double y[2] = {xyz[0][1], xyz[1][1]};
  225. double z[2] = {xyz[0][2], xyz[1][2]};
  226. SVector3 p(0, 0, 1.);
  227. SVector3 t(x[1] - x[0], y[1] - y[0], z[1] - z[0]);
  228. n = crossprod(t, p);
  229. n.normalize();
  230. }
  231. else
  232. n = normal3(xyz);
  233. for(int i = 0; i < numNodes; i++){
  234. double v = ComputeScalarRep(numComp, val[i]);
  235. for(int j = 0; j < 3; j++)
  236. xyz[i][j] += n[j] * opt->normalRaise * v;
  237. }
  238. }
  239. if(numComp == 3 && opt->vectorType == PViewOptions::Displacement){
  240. for(int i = 0; i < numNodes; i++){
  241. for(int j = 0; j < 3; j++)
  242. xyz[i][j] += opt->displacementFactor * val[i][j];
  243. }
  244. }
  245. if(opt->useGenRaise){
  246. int numComp2;
  247. double **val2 = new double*[numNodes];
  248. for(int i = 0; i < numNodes; i++)
  249. val2[i] = new double[9];
  250. getExternalValues(p, opt->viewIndexForGenRaise, ient, iele, numNodes,
  251. numComp, val, numComp2, val2);
  252. applyGeneralRaise(p, numNodes, numComp2, val2, xyz);
  253. for(int i = 0; i < numNodes; i++)
  254. delete [] val2[i];
  255. delete [] val2;
  256. }
  257. }
  258. static double evalClipPlane(int clip, double x, double y, double z)
  259. {
  260. return CTX::instance()->clipPlane[clip][0] * x +
  261. CTX::instance()->clipPlane[clip][1] * y +
  262. CTX::instance()->clipPlane[clip][2] * z +
  263. CTX::instance()->clipPlane[clip][3];
  264. }
  265. static double intersectClipPlane(int clip, int numNodes, double **xyz)
  266. {
  267. double val = evalClipPlane(clip, xyz[0][0], xyz[0][1], xyz[0][2]);
  268. for(int i = 1; i < numNodes; i++){
  269. if(val * evalClipPlane(clip, xyz[i][0], xyz[i][1], xyz[i][2]) <= 0)
  270. return 0.; // the element intersects the cut plane
  271. }
  272. return val;
  273. }
  274. bool isElementVisible(PViewOptions *opt, int dim, int numNodes,
  275. double **xyz)
  276. {
  277. if(!CTX::instance()->clipWholeElements) return true;
  278. bool hidden = false;
  279. for(int clip = 0; clip < 6; clip++){
  280. if(opt->clip & (1 << clip)){
  281. if(dim < 3 && CTX::instance()->clipOnlyVolume){
  282. }
  283. else{
  284. double d = intersectClipPlane(clip, numNodes, xyz);
  285. if(dim == 3 && CTX::instance()->clipOnlyDrawIntersectingVolume && d){
  286. hidden = true;
  287. break;
  288. }
  289. else if(d < 0){
  290. hidden = true;
  291. break;
  292. }
  293. }
  294. }
  295. }
  296. return !hidden;
  297. }
  298. static void addOutlinePoint(PView *p, double **xyz, unsigned int color,
  299. bool pre, int i0=0)
  300. {
  301. if(pre) return;
  302. SVector3 n = getPointNormal(p, 1.);
  303. p->va_points->add(&xyz[i0][0], &xyz[i0][1], &xyz[i0][2], &n, &color, 0, true);
  304. }
  305. static void addScalarPoint(PView *p, double **xyz,
  306. double **val, bool pre, int i0=0,
  307. bool unique=false)
  308. {
  309. if(pre) return;
  310. PViewOptions *opt = p->getOptions();
  311. double vmin = opt->tmpMin, vmax = opt->tmpMax;
  312. if(opt->saturateValues) saturate(1, val, vmin, vmax, i0);
  313. if(val[i0][0] >= vmin && val[i0][0] <= vmax){
  314. unsigned int col = opt->getColor(val[i0][0], vmin, vmax, false,
  315. (opt->intervalsType == PViewOptions::Discrete) ?
  316. opt->nbIso : -1);
  317. SVector3 n = getPointNormal(p, val[i0][0]);
  318. p->va_points->add(&xyz[i0][0], &xyz[i0][1], &xyz[i0][2], &n, &col, 0, unique);
  319. }
  320. }
  321. static void addOutlineLine(PView *p, double **xyz, unsigned int color,
  322. bool pre, int i0=0, int i1=1)
  323. {
  324. if(pre) return;
  325. const int in[2] = {i0, i1};
  326. unsigned int col[2];
  327. double x[2], y[2], z[2];
  328. for(int i = 0; i < 2; i++){
  329. x[i] = xyz[in[i]][0]; y[i] = xyz[in[i]][1]; z[i] = xyz[in[i]][2];
  330. col[i] = color;
  331. }
  332. SVector3 n[2];
  333. getLineNormal(p, x, y, z, 0, n, true);
  334. p->va_lines->add(x, y, z, n, col, 0, true);
  335. }
  336. static void addScalarLine(PView *p, double **xyz,
  337. double **val, bool pre, int i0=0, int i1=1,
  338. bool unique=false)
  339. {
  340. if(pre) return;
  341. PViewOptions *opt = p->getOptions();
  342. if(opt->boundary > 0){
  343. opt->boundary--;
  344. addScalarPoint(p, xyz, val, pre, i0, true);
  345. addScalarPoint(p, xyz, val, pre, i1, true);
  346. opt->boundary++;
  347. return;
  348. }
  349. double vmin = opt->tmpMin, vmax = opt->tmpMax;
  350. if(opt->saturateValues) saturate(2, val, vmin, vmax, i0, i1);
  351. double x[2] = {xyz[i0][0], xyz[i1][0]};
  352. double y[2] = {xyz[i0][1], xyz[i1][1]};
  353. double z[2] = {xyz[i0][2], xyz[i1][2]};
  354. double v[2] = {val[i0][0], val[i1][0]};
  355. if(opt->intervalsType == PViewOptions::Continuous){
  356. SVector3 n[2];
  357. getLineNormal(p, x, y, z, v, n, true);
  358. if(val[i0][0] >= vmin && val[i0][0] <= vmax &&
  359. val[i1][0] >= vmin && val[i1][0] <= vmax){
  360. unsigned int col[2];
  361. for(int i = 0; i < 2; i++)
  362. col[i] = opt->getColor(v[i], vmin, vmax);
  363. p->va_lines->add(x, y, z, n, col, 0, unique);
  364. }
  365. else{
  366. double x2[2], y2[2], z2[2], v2[2];
  367. int nb = CutLine(x, y, z, v, vmin, vmax, x2, y2, z2, v2);
  368. if(nb == 2){
  369. unsigned int col[2];
  370. for(int i = 0; i < 2; i++)
  371. col[i] = opt->getColor(v2[i], vmin, vmax);
  372. p->va_lines->add(x2, y2, z2, n, col, 0, unique);
  373. }
  374. }
  375. }
  376. if(opt->intervalsType == PViewOptions::Discrete){
  377. for(int k = 0; k < opt->nbIso; k++){
  378. if(vmin == vmax) k = opt->nbIso / 2;
  379. double min = opt->getScaleValue(k, opt->nbIso + 1, vmin, vmax);
  380. double max = opt->getScaleValue(k + 1, opt->nbIso + 1, vmin, vmax);
  381. double x2[2], y2[2], z2[2], v2[2];
  382. int nb = CutLine(x, y, z, v, min, max, x2, y2, z2, v2);
  383. if(nb == 2){
  384. unsigned int color = opt->getColor(k, opt->nbIso);
  385. unsigned int col[2] = {color, color};
  386. SVector3 n[2];
  387. getLineNormal(p, x2, y2, z2, v2, n, true);
  388. p->va_lines->add(x2, y2, z2, n, col, 0, unique);
  389. }
  390. if(vmin == vmax) break;
  391. }
  392. }
  393. if(opt->intervalsType == PViewOptions::Iso){
  394. for(int k = 0; k < opt->nbIso; k++) {
  395. if(vmin == vmax) k = opt->nbIso / 2;
  396. double iso = opt->getScaleValue(k, opt->nbIso, vmin, vmax);
  397. double x2[1], y2[1], z2[1];
  398. int nb = IsoLine(x, y, z, v, iso, x2, y2, z2);
  399. if(nb == 1){
  400. unsigned int color = opt->getColor(k, opt->nbIso);
  401. SVector3 n = getPointNormal(p, iso);
  402. p->va_points->add(x2, y2, z2, &n, &color, 0, unique);
  403. }
  404. if(vmin == vmax) break;
  405. }
  406. }
  407. }
  408. static void addOutlineTriangle(PView *p, double **xyz,
  409. unsigned int color, bool pre, int i0=0,
  410. int i1=1, int i2=2)
  411. {
  412. PViewOptions *opt = p->getOptions();
  413. const int il[3][2] = {{i0, i1}, {i1, i2}, {i2, i0}};
  414. SVector3 nfac = normal3(xyz, i0, i1, i2);
  415. for(int i = 0; i < 3; i++){
  416. double x[2] = {xyz[il[i][0]][0], xyz[il[i][1]][0]};
  417. double y[2] = {xyz[il[i][0]][1], xyz[il[i][1]][1]};
  418. double z[2] = {xyz[il[i][0]][2], xyz[il[i][1]][2]};
  419. SVector3 n[2] = {nfac, nfac};
  420. unsigned int col[2] = {color, color};
  421. if(opt->smoothNormals){
  422. for(int j = 0; j < 2; j++){
  423. if(pre) p->normals->add(x[j], y[j], z[j], n[j][0], n[j][1], n[j][2]);
  424. else p->normals->get(x[j], y[j], z[j], n[j][0], n[j][1], n[j][2]);
  425. }
  426. }
  427. getLineNormal(p, x, y, z, 0, n, false);
  428. if(!pre) p->va_lines->add(x, y, z, n, col, 0, true);
  429. }
  430. }
  431. static void addScalarTriangle(PView *p, double **xyz, double **val,
  432. bool pre, int i0=0, int i1=1, int i2=2,
  433. bool unique=false, bool skin=false)
  434. {
  435. PViewOptions *opt = p->getOptions();
  436. const int il[3][2] = {{i0, i1}, {i1, i2}, {i2, i0}};
  437. if(opt->boundary > 0){
  438. opt->boundary--;
  439. for(int i = 0; i < 3; i++)
  440. addScalarLine(p, xyz, val, pre, il[i][0], il[i][1], true);
  441. opt->boundary++;
  442. return;
  443. }
  444. double vmin = opt->tmpMin, vmax = opt->tmpMax;
  445. if(opt->saturateValues) saturate(3, val, vmin, vmax, i0, i1, i2);
  446. double x[3] = {xyz[i0][0], xyz[i1][0], xyz[i2][0]};
  447. double y[3] = {xyz[i0][1], xyz[i1][1], xyz[i2][1]};
  448. double z[3] = {xyz[i0][2], xyz[i1][2], xyz[i2][2]};
  449. double v[3] = {val[i0][0], val[i1][0], val[i2][0]};
  450. SVector3 nfac = normal3(xyz, i0, i1, i2);
  451. if(opt->intervalsType == PViewOptions::Continuous){
  452. if(val[i0][0] >= vmin && val[i0][0] <= vmax &&
  453. val[i1][0] >= vmin && val[i1][0] <= vmax &&
  454. val[i2][0] >= vmin && val[i2][0] <= vmax){
  455. SVector3 n[3] = {nfac, nfac, nfac};
  456. unsigned int col[3];
  457. for(int i = 0; i < 3; i++){
  458. if(opt->smoothNormals){
  459. if(pre) p->normals->add(x[i], y[i], z[i], n[i][0], n[i][1], n[i][2]);
  460. else p->normals->get(x[i], y[i], z[i], n[i][0], n[i][1], n[i][2]);
  461. }
  462. col[i] = opt->getColor(v[i], vmin, vmax);
  463. }
  464. if(!pre) p->va_triangles->add(x, y, z, n, col, 0, unique, skin);
  465. }
  466. else{
  467. double x2[10], y2[10], z2[10], v2[10];
  468. int nb = CutTriangle(x, y, z, v, vmin, vmax, x2, y2, z2, v2);
  469. if(nb >= 3){
  470. for(int j = 2; j < nb; j++){
  471. double x3[3] = {x2[0], x2[j - 1], x2[j]};
  472. double y3[3] = {y2[0], y2[j - 1], y2[j]};
  473. double z3[3] = {z2[0], z2[j - 1], z2[j]};
  474. double v3[3] = {v2[0], v2[j - 1], v2[j]};
  475. SVector3 n[3] = {nfac, nfac, nfac};
  476. unsigned int col[3];
  477. for(int i = 0; i < 3; i++){
  478. if(opt->smoothNormals){
  479. if(pre) p->normals->add(x3[i], y3[i], z3[i], n[i][0], n[i][1], n[i][2]);
  480. else p->normals->get(x3[i], y3[i], z3[i], n[i][0], n[i][1], n[i][2]);
  481. }
  482. col[i] = opt->getColor(v3[i], vmin, vmax);
  483. }
  484. if(!pre) p->va_triangles->add(x3, y3, z3, n, col, 0, unique, skin);
  485. }
  486. }
  487. }
  488. }
  489. if(opt->intervalsType == PViewOptions::Discrete){
  490. for(int k = 0; k < opt->nbIso; k++){
  491. if(vmin == vmax) k = opt->nbIso / 2;
  492. double min = opt->getScaleValue(k, opt->nbIso + 1, vmin, vmax);
  493. double max = opt->getScaleValue(k + 1, opt->nbIso + 1, vmin, vmax);
  494. double x2[10], y2[10], z2[10], v2[10];
  495. int nb = CutTriangle(x, y, z, v, min, max, x2, y2, z2, v2);
  496. if(nb >= 3){
  497. unsigned int color = opt->getColor(k, opt->nbIso);
  498. unsigned int col[3] = {color, color, color};
  499. for(int j = 2; j < nb; j++){
  500. double x3[3] = {x2[0], x2[j - 1], x2[j]};
  501. double y3[3] = {y2[0], y2[j - 1], y2[j]};
  502. double z3[3] = {z2[0], z2[j - 1], z2[j]};
  503. SVector3 n[3] = {nfac, nfac, nfac};
  504. if(opt->smoothNormals){
  505. for(int i = 0; i < 3; i++){
  506. if(pre) p->normals->add(x3[i], y3[i], z3[i], n[i][0], n[i][1], n[i][2]);
  507. else p->normals->get(x3[i], y3[i], z3[i], n[i][0], n[i][1], n[i][2]);
  508. }
  509. }
  510. if(!pre) p->va_triangles->add(x3, y3, z3, n, col, 0, unique, skin);
  511. }
  512. }
  513. if(vmin == vmax) break;
  514. }
  515. }
  516. if(opt->intervalsType == PViewOptions::Iso){
  517. for(int k = 0; k < opt->nbIso; k++) {
  518. if(vmin == vmax) k = opt->nbIso / 2;
  519. double iso = opt->getScaleValue(k, opt->nbIso, vmin, vmax);
  520. double x2[3], y2[3], z2[3];
  521. int nb = IsoTriangle(x, y, z, v, iso, x2, y2, z2);
  522. if(nb == 2){
  523. unsigned int color = opt->getColor(k, opt->nbIso);
  524. unsigned int col[2] = {color, color};
  525. SVector3 n[2] = {nfac, nfac};
  526. if(opt->smoothNormals){
  527. for(int i = 0; i < 2; i++){
  528. if(pre) p->normals->add(x2[i], y2[i], z2[i], n[i][0], n[i][1], n[i][2]);
  529. else p->normals->get(x2[i], y2[i], z2[i], n[i][0], n[i][1], n[i][2]);
  530. }
  531. }
  532. double v[2] = {iso, iso};
  533. getLineNormal(p, x, y, z, v, n, false);
  534. if(!pre) p->va_lines->add(x2, y2, z2, n, col, 0, unique);
  535. }
  536. if(vmin == vmax) break;
  537. }
  538. }
  539. }
  540. static void addOutlineQuadrangle(PView *p, double **xyz,
  541. unsigned int color, bool pre, int i0=0, int i1=1,
  542. int i2=2, int i3=3)
  543. {
  544. PViewOptions *opt = p->getOptions();
  545. const int il[4][2] = {{i0, i1}, {i1, i2}, {i2, i3}, {i3, i0}};
  546. SVector3 nfac = normal3(xyz, i0, i1, i2);
  547. for(int i = 0; i < 4; i++){
  548. double x[2] = {xyz[il[i][0]][0], xyz[il[i][1]][0]};
  549. double y[2] = {xyz[il[i][0]][1], xyz[il[i][1]][1]};
  550. double z[2] = {xyz[il[i][0]][2], xyz[il[i][1]][2]};
  551. SVector3 n[2] = {nfac, nfac};
  552. unsigned int col[2] = {color, color};
  553. if(opt->smoothNormals){
  554. for(int j = 0; j < 2; j++){
  555. if(pre) p->normals->add(x[j], y[j], z[j], n[j][0], n[j][1], n[j][2]);
  556. else p->normals->get(x[j], y[j], z[j], n[j][0], n[j][1], n[j][2]);
  557. }
  558. }
  559. getLineNormal(p, x, y, z, 0, n, false);
  560. if(!pre) p->va_lines->add(x, y, z, n, col, 0, true);
  561. }
  562. }
  563. static void addScalarQuadrangle(PView *p, double **xyz,
  564. double **val, bool pre, int i0=0,
  565. int i1=1, int i2=2, int i3=3, bool unique=false)
  566. {
  567. PViewOptions *opt = p->getOptions();
  568. const int il[4][2] = {{i0, i1}, {i1, i2}, {i2, i3}, {i3, i0}};
  569. const int it[2][3] = {{i0, i1, i2}, {i0, i2, i3}};
  570. if(opt->boundary > 0){
  571. opt->boundary--;
  572. for(int i = 0; i < 4; i++)
  573. addScalarLine(p, xyz, val, pre, il[i][0], il[i][1], true);
  574. opt->boundary++;
  575. return;
  576. }
  577. for(int i = 0; i < 2; i++)
  578. addScalarTriangle(p, xyz, val, pre, it[i][0], it[i][1], it[i][2], unique);
  579. }
  580. static void addOutlinePolygon(PView *p, double **xyz,
  581. unsigned int color, bool pre, int numNodes)
  582. {
  583. for(int i = 0; i < numNodes / 3; i++)
  584. addOutlineTriangle(p, xyz, color, pre, 3*i, 3*i + 1, 3*i + 2);
  585. }
  586. static void addScalarPolygon(PView *p, double **xyz,
  587. double **val, bool pre, int numNodes)
  588. {
  589. PViewOptions *opt = p->getOptions();
  590. if(opt->boundary > 0){
  591. const int il[3][2] = {{0, 1}, {1, 2}, {2, 0}};
  592. std::map<MEdge, int, Less_Edge> edges;
  593. std::vector<MVertex *> verts;
  594. for(int i = 0; i < numNodes; i++)
  595. verts.push_back(new MVertex(xyz[i][0], xyz[i][1], xyz[i][2]));
  596. for(int i = 0; i < numNodes / 3; i++){
  597. for(int j = 0; j < 3; j++) {
  598. MEdge ed(verts[3*i+il[j][0]], verts[3*i+il[j][1]]);
  599. std::map<MEdge, int, Less_Edge>::iterator ite;
  600. for(ite = edges.begin(); ite != edges.end(); ite++)
  601. if((*ite).first == ed) break;
  602. if(ite == edges.end())
  603. edges[ed] = 100*i+j;
  604. else edges.erase(ite);
  605. }
  606. }
  607. opt->boundary--;
  608. for(std::map<MEdge, int, Less_Edge>::iterator ite = edges.begin();
  609. ite != edges.end(); ite++){
  610. int i = (int) (*ite).second / 100;
  611. int j = (*ite).second % 100;
  612. addScalarLine(p, xyz, val, pre, 3*i+il[j][0], 3*i+il[j][0], true);
  613. }
  614. opt->boundary++;
  615. for(int i = 0; i < numNodes; i++)
  616. delete verts[i];
  617. return;
  618. }
  619. for(int i = 0; i < numNodes / 3; i++)
  620. addScalarTriangle(p, xyz, val, pre, 3*i, 3*i+1, 3*i+2);
  621. }
  622. static void addOutlineTetrahedron(PView *p, double **xyz,
  623. unsigned int color, bool pre)
  624. {
  625. const int it[4][3] = {{0, 2, 1}, {0, 1, 3}, {0, 3, 2}, {3, 1, 2}};
  626. for(int i = 0; i < 4; i++)
  627. addOutlineTriangle(p, xyz, color, pre, it[i][0], it[i][1], it[i][2]);
  628. }
  629. static void addScalarTetrahedron(PView *p, double **xyz,
  630. double **val, bool pre, int i0=0,
  631. int i1=1, int i2=2, int i3=3)
  632. {
  633. PViewOptions *opt = p->getOptions();
  634. const int it[4][3] = {{i0, i2, i1}, {i0, i1, i3}, {i0, i3, i2}, {i3, i1, i2}};
  635. if(opt->boundary > 0 ||
  636. opt->intervalsType == PViewOptions::Continuous ||
  637. opt->intervalsType == PViewOptions::Discrete){
  638. bool skin = (opt->boundary > 0) ? false : opt->drawSkinOnly;
  639. opt->boundary--;
  640. for(int i = 0; i < 4; i++)
  641. addScalarTriangle(p, xyz, val, pre, it[i][0], it[i][1], it[i][2], true, skin);
  642. opt->boundary++;
  643. return;
  644. }
  645. double vmin = opt->tmpMin, vmax = opt->tmpMax;
  646. if(opt->saturateValues) saturate(4, val, vmin, vmax, i0, i1, i2, i3);
  647. double x[4] = {xyz[i0][0], xyz[i1][0], xyz[i2][0], xyz[i3][0]};
  648. double y[4] = {xyz[i0][1], xyz[i1][1], xyz[i2][1], xyz[i3][1]};
  649. double z[4] = {xyz[i0][2], xyz[i1][2], xyz[i2][2], xyz[i3][2]};
  650. double v[4] = {val[i0][0], val[i1][0], val[i2][0], val[i3][0]};
  651. if(opt->intervalsType == PViewOptions::Iso){
  652. for(int k = 0; k < opt->nbIso; k++) {
  653. if(vmin == vmax) k = opt->nbIso / 2;
  654. double iso = opt->getScaleValue(k, opt->nbIso, vmin, vmax);
  655. double x2[6], y2[6], z2[6], nn[3];
  656. int nb = IsoSimplex(x, y, z, v, iso, x2, y2, z2, nn);
  657. if(nb >= 3){
  658. unsigned int color = opt->getColor(k, opt->nbIso);
  659. unsigned int col[3] = {color, color, color};
  660. for(int j = 2; j < nb; j++){
  661. double x3[3] = {x2[0], x2[j - 1], x2[j]};
  662. double y3[3] = {y2[0], y2[j - 1], y2[j]};
  663. double z3[3] = {z2[0], z2[j - 1], z2[j]};
  664. SVector3 n[3];
  665. for(int i = 0; i < 3; i++){
  666. n[i][0] = nn[0]; n[i][1] = nn[1]; n[i][2] = nn[2];
  667. if(opt->smoothNormals){
  668. if(pre) p->normals->add(x3[i], y3[i], z3[i], n[i][0], n[i][1], n[i][2]);
  669. else p->normals->get(x3[i], y3[i], z3[i], n[i][0], n[i][1], n[i][2]);
  670. }
  671. }
  672. if(!pre) p->va_triangles->add(x3, y3, z3, n, col, 0, false, false);
  673. }
  674. }
  675. if(vmin == vmax) break;
  676. }
  677. }
  678. }
  679. static void addOutlineHexahedron(PView *p, double **xyz,
  680. unsigned int color, bool pre)
  681. {
  682. const int iq[6][4] = {{0, 3, 2, 1}, {0, 1, 5, 4}, {0, 4, 7, 3},
  683. {1, 2, 6, 5}, {2, 3, 7, 6}, {4, 5, 6, 7}};
  684. for(int i = 0; i < 6; i++)
  685. addOutlineQuadrangle(p, xyz, color, pre, iq[i][0], iq[i][1],
  686. iq[i][2], iq[i][3]);
  687. }
  688. static void addScalarHexahedron(PView *p, double **xyz,
  689. double **val, bool pre)
  690. {
  691. PViewOptions *opt = p->getOptions();
  692. const int iq[6][4] = {{0, 3, 2, 1}, {0, 1, 5, 4}, {0, 4, 7, 3},
  693. {1, 2, 6, 5}, {2, 3, 7, 6}, {4, 5, 6, 7}};
  694. const int is[6][4] = {{0, 1, 3, 4}, {1, 3, 4, 5}, {3, 4, 5, 7},
  695. {1, 2, 3, 6}, {3, 1, 6, 5}, {6, 3, 5, 7}};
  696. if(opt->boundary > 0){
  697. opt->boundary--;
  698. for(int i = 0; i < 6; i++)
  699. addScalarQuadrangle(p, xyz, val, pre, iq[i][0], iq[i][1], iq[i][2], iq[i][3], true);
  700. opt->boundary++;
  701. return;
  702. }
  703. for(int i = 0; i < 6; i++)
  704. addScalarTetrahedron(p, xyz, val, pre, is[i][0], is[i][1], is[i][2], is[i][3]);
  705. }
  706. static void addOutlinePrism(PView *p, double **xyz, unsigned int color,
  707. bool pre)
  708. {
  709. const int iq[3][4] = {{0, 1, 4, 3}, {0, 3, 5, 2}, {1, 2, 5, 4}};
  710. const int it[2][3] = {{0, 2, 1}, {3, 4, 5}};
  711. for(int i = 0; i < 3; i++)
  712. addOutlineQuadrangle(p, xyz, color, pre, iq[i][0], iq[i][1], iq[i][2], iq[i][3]);
  713. for(int i = 0; i < 2; i++)
  714. addOutlineTriangle(p, xyz, color, pre, it[i][0], it[i][1], it[i][2]);
  715. }
  716. static void addScalarPrism(PView *p, double **xyz, double **val, bool pre)
  717. {
  718. PViewOptions *opt = p->getOptions();
  719. const int iq[3][4] = {{0, 1, 4, 3}, {0, 3, 5, 2}, {1, 2, 5, 4}};
  720. const int it[2][3] = {{0, 2, 1}, {3, 4, 5}};
  721. const int is[3][4] = {{0, 1, 2, 3}, {3, 4, 5, 2}, {1, 2, 4, 3}};
  722. if(opt->boundary > 0){
  723. opt->boundary--;
  724. for(int i = 0; i < 3; i++)
  725. addScalarQuadrangle(p, xyz, val, pre, iq[i][0], iq[i][1], iq[i][2], iq[i][3], true);
  726. for(int i = 0; i < 2; i++)
  727. addScalarTriangle(p, xyz, val, pre, it[i][0], it[i][1], it[i][2], true);
  728. opt->boundary++;
  729. return;
  730. }
  731. for(int i = 0; i < 3; i++)
  732. addScalarTetrahedron(p, xyz, val, pre, is[i][0], is[i][1], is[i][2], is[i][3]);
  733. }
  734. static void addOutlinePyramid(PView *p, double **xyz,
  735. unsigned int color, bool pre)
  736. {
  737. const int it[4][3] = {{0, 1, 4}, {3, 0, 4}, {1, 2, 4}, {2, 3, 4}};
  738. addOutlineQuadrangle(p, xyz, color, pre, 0, 3, 2, 1);
  739. for(int i = 0; i < 4; i++)
  740. addOutlineTriangle(p, xyz, color, pre, it[i][0], it[i][1], it[i][2]);
  741. }
  742. static void addScalarPyramid(PView *p, double **xyz,
  743. double **val, bool pre)
  744. {
  745. PViewOptions *opt = p->getOptions();
  746. const int it[4][3] = {{0, 1, 4}, {3, 0, 4}, {1, 2, 4}, {2, 3, 4}};
  747. const int is[2][4] = {{0, 1, 2, 4}, {2, 3, 0, 4}};
  748. if(opt->boundary > 0){
  749. opt->boundary--;
  750. addScalarQuadrangle(p, xyz, val, pre, 0, 3, 2, 1, true);
  751. for(int i = 0; i < 4; i++)
  752. addScalarTriangle(p, xyz, val, pre, it[i][0], it[i][1], it[i][2], true);
  753. opt->boundary++;
  754. return;
  755. }
  756. for(int i = 0; i < 2; i++)
  757. addScalarTetrahedron(p, xyz, val, pre, is[i][0], is[i][1], is[i][2], is[i][3]);
  758. }
  759. static void addOutlinePolyhedron(PView *p, double **xyz,
  760. unsigned int color, bool pre, int numNodes)
  761. {
  762. const int it[4][3] = {{0, 2, 1}, {0, 1, 3}, {0, 3, 2}, {3, 1, 2}};
  763. std::map<MFace, int, Less_Face> triFaces;
  764. std::vector<MVertex *> verts;
  765. for(int i = 0; i < numNodes; i++)
  766. verts.push_back(new MVertex(xyz[i][0], xyz[i][1], xyz[i][2]));
  767. for(int i = 0; i < numNodes / 4; i++){
  768. for(int j = 0; j < 4; j++) {
  769. MFace f(verts[4*i+it[j][0]], verts[4*i+it[j][1]], verts[4*i+it[j][2]]);
  770. std::map<MFace, int, Less_Face>::iterator ite;
  771. for(ite = triFaces.begin(); ite != triFaces.end(); ite++)
  772. if((*ite).first == f) break;
  773. if(ite == triFaces.end())
  774. triFaces[f] = 100*i+j;
  775. else triFaces.erase(ite);
  776. }
  777. }
  778. for(std::map<MFace, int, Less_Face>::iterator ite = triFaces.begin();
  779. ite != triFaces.end(); ite++){
  780. int i = (int) (*ite).second / 100;
  781. int j = (*ite).second % 100;
  782. addOutlineTriangle(p, xyz, color, pre, 4*i+it[j][0], 4*i+it[j][1], 4*i+it[j][2]);
  783. }
  784. for(int i = 0; i < numNodes; i++)
  785. delete verts[i];
  786. }
  787. static void addScalarPolyhedron(PView *p, double **xyz,
  788. double **val, bool pre, int numNodes)
  789. {
  790. PViewOptions *opt = p->getOptions();
  791. if(opt->boundary > 0){
  792. return;
  793. }
  794. for(int i = 0; i < numNodes / 4; i++)
  795. addScalarTetrahedron(p, xyz, val, pre, 4*i, 4*i + 1, 4*i + 2, 4*i + 3);
  796. }
  797. static void addOutlineElement(PView *p, int type, double **xyz,
  798. bool pre, int numNodes)
  799. {
  800. PViewOptions *opt = p->getOptions();
  801. switch(type){
  802. case TYPE_PNT: addOutlinePoint(p, xyz, opt->color.point, pre); break;
  803. case TYPE_LIN: addOutlineLine(p, xyz, opt->color.line, pre); break;
  804. case TYPE_TRI: addOutlineTriangle(p, xyz, opt->color.triangle, pre); break;
  805. case TYPE_QUA: addOutlineQuadrangle(p, xyz, opt->color.quadrangle, pre); break;
  806. case TYPE_POLYG: addOutlinePolygon(p, xyz, opt->color.quadrangle, pre, numNodes); break;
  807. case TYPE_TET: addOutlineTetrahedron(p, xyz, opt->color.tetrahedron, pre); break;
  808. case TYPE_HEX: addOutlineHexahedron(p, xyz, opt->color.hexahedron, pre); break;
  809. case TYPE_PRI: addOutlinePrism(p, xyz, opt->color.prism, pre); break;
  810. case TYPE_PYR: addOutlinePyramid(p, xyz, opt->color.pyramid, pre); break;
  811. case TYPE_POLYH: addOutlinePolyhedron(p, xyz, opt->color.pyramid, pre, numNodes); break;
  812. }
  813. }
  814. static void addScalarElement(PView *p, int type, double **xyz,
  815. double **val, bool pre, int numNodes)
  816. {
  817. switch(type){
  818. case TYPE_PNT: addScalarPoint(p, xyz, val, pre); break;
  819. case TYPE_LIN: addScalarLine(p, xyz, val, pre); break;
  820. case TYPE_TRI: addScalarTriangle(p, xyz, val, pre); break;
  821. case TYPE_QUA: addScalarQuadrangle(p, xyz, val, pre); break;
  822. case TYPE_POLYG: addScalarPolygon(p, xyz, val, pre, numNodes); break;
  823. case TYPE_TET: addScalarTetrahedron(p, xyz, val, pre); break;
  824. case TYPE_HEX: addScalarHexahedron(p, xyz, val, pre); break;
  825. case TYPE_PRI: addScalarPrism(p, xyz, val, pre); break;
  826. case TYPE_PYR: addScalarPyramid(p, xyz, val, pre); break;
  827. case TYPE_POLYH: addScalarPolyhedron(p, xyz, val, pre, numNodes); break;
  828. }
  829. }
  830. static void addVectorElement(PView *p, int ient, int iele, int numNodes,
  831. int type, double **xyz,
  832. double **val, bool pre)
  833. {
  834. // use adaptive data if available
  835. PViewData *data = p->getData(true);
  836. PViewOptions *opt = p->getOptions();
  837. int numComp2;
  838. double **val2 = new double*[numNodes];
  839. for(int i = 0; i < numNodes; i++)
  840. val2[i] = new double[9];
  841. getExternalValues(p, opt->externalViewIndex, ient, iele, numNodes,
  842. 3, val, numComp2, val2);
  843. if(opt->vectorType == PViewOptions::Displacement){
  844. for(int i = 0; i < numNodes; i++)
  845. val2[i][0] = ComputeScalarRep(numComp2, val2[i]);
  846. // add scalar element with correct min/max
  847. double min = opt->tmpMin, max = opt->tmpMax;
  848. opt->tmpMin = opt->externalMin;
  849. opt->tmpMax = opt->externalMax;
  850. addScalarElement(p, type, xyz, val2, pre, numNodes);
  851. opt->tmpMin = min;
  852. opt->tmpMax = max;
  853. // add point trajectories
  854. if(!pre && numNodes == 1 && opt->timeStep > 0 && opt->lineWidth){
  855. for(int ts = 0; ts < opt->timeStep; ts++){
  856. int numComp = data->getNumComponents(ts, ient, iele);
  857. double xyz0[3], dxyz[3][2] = {{0., 0.}, {0., 0.}, {0., 0.}};
  858. data->getNode(ts, ient, iele, 0, xyz0[0], xyz0[1], xyz0[2]);
  859. for(int j = 0; j < 3; j++){
  860. int comp = opt->forceNumComponents ? opt->componentMap[j] : j;
  861. if(comp >= 0 && comp < numComp){
  862. data->getValue(ts, ient, iele, 0, comp, dxyz[j][0]);
  863. data->getValue(ts + 1, ient, iele, 0, comp, dxyz[j][1]);
  864. }
  865. }
  866. unsigned int col[2];
  867. double norm[2];
  868. for(int i = 0; i < 2; i++){
  869. norm[i] = sqrt(dxyz[0][i] * dxyz[0][i] +
  870. dxyz[1][i] * dxyz[1][i] +
  871. dxyz[2][i] * dxyz[2][i]);
  872. col[i] = opt->getColor(norm[i], opt->tmpMin, opt->tmpMax);
  873. }
  874. for(int j = 0; j < 3; j++){
  875. dxyz[j][0] = xyz0[j] + dxyz[j][0] * opt->displacementFactor;
  876. dxyz[j][1] = xyz0[j] + dxyz[j][1] * opt->displacementFactor;
  877. }
  878. SVector3 n[2];
  879. getLineNormal(p, dxyz[0], dxyz[1], dxyz[2], norm, n, true);
  880. p->va_lines->add(dxyz[0], dxyz[1], dxyz[2], n, col, 0, false);
  881. }
  882. }
  883. for(int i = 0; i < numNodes; i++)
  884. delete [] val2[i];
  885. delete [] val2;
  886. return;
  887. }
  888. if(pre){
  889. for(int i = 0; i < numNodes; i++)
  890. delete [] val2[i];
  891. delete [] val2;
  892. return;
  893. }
  894. if(opt->glyphLocation == PViewOptions::Vertex){
  895. for(int i = 0; i < numNodes; i++){
  896. double v2 = opt->saturateValues ?
  897. saturateVector(val[i], numComp2, val2[i], opt->externalMin, opt->externalMax) :
  898. ComputeScalarRep(numComp2, val2[i]);
  899. if(v2 >= opt->externalMin && v2 <= opt->externalMax){
  900. unsigned int color = opt->getColor(v2, opt->externalMin, opt->externalMax, false,
  901. (opt->intervalsType == PViewOptions::Discrete) ?
  902. opt->nbIso : -1);
  903. unsigned int col[2] = {color, color};
  904. double dxyz[3][2];
  905. for(int j = 0; j < 3; j++){
  906. dxyz[j][0] = xyz[i][j];
  907. dxyz[j][1] = val[i][j];
  908. }
  909. p->va_vectors->add(dxyz[0], dxyz[1], dxyz[2], 0, col, 0, false);
  910. }
  911. }
  912. }
  913. if(opt->glyphLocation == PViewOptions::COG){
  914. SPoint3 pc(0., 0., 0.);
  915. double d[3] = {0., 0., 0.};
  916. double d2[9] = {0., 0., 0., 0., 0., 0., 0., 0., 0.};
  917. for(int i = 0; i < numNodes; i++){
  918. pc += SPoint3(xyz[i][0], xyz[i][1], xyz[i][2]);
  919. for(int j = 0; j < 3; j++) d[j] += val[i][j];
  920. for(int j = 0; j < numComp2; j++) d2[j] += val2[i][j];
  921. }
  922. pc /= (double)numNodes;
  923. for(int j = 0; j < 3; j++) d[j] /= (double)numNodes;
  924. for(int j = 0; j < numComp2; j++) d2[j] /= (double)numNodes;
  925. // need tolerance since we compare computed results (the average)
  926. // instead of the raw data used to compute bounds
  927. double v2 = opt->saturateValues ?
  928. saturateVector(d, numComp2, d2, opt->externalMin, opt->externalMax) :
  929. ComputeScalarRep(numComp2, d2);
  930. if(v2 >= opt->externalMin * (1. - 1.e-15) &&
  931. v2 <= opt->externalMax * (1. + 1.e-15)){
  932. unsigned int color = opt->getColor(v2, opt->externalMin, opt->externalMax, false,
  933. (opt->intervalsType == PViewOptions::Discrete) ?
  934. opt->nbIso : -1);
  935. unsigned int col[2] = {color, color};
  936. double dxyz[3][2];
  937. for(int i = 0; i < 3; i++){
  938. dxyz[i][0] = pc[i];
  939. dxyz[i][1] = d[i];
  940. }
  941. p->va_vectors->add(dxyz[0], dxyz[1], dxyz[2], 0, col, 0, false);
  942. }
  943. }
  944. for(int i = 0; i < numNodes; i++)
  945. delete [] val2[i];
  946. delete [] val2;
  947. }
  948. static void addTensorElement(PView *p, int iEnt, int iEle, int numNodes, int type,
  949. double **xyz, double **val,
  950. bool pre)
  951. {
  952. PViewOptions *opt = p->getOptions();
  953. fullMatrix <double> tensor(3,3);
  954. fullVector<double> S(3), imS (3);
  955. fullMatrix<double> V(3,3);
  956. fullMatrix <double> rightV(3,3);
  957. if(opt->tensorType == PViewOptions::VonMises){
  958. for(int i = 0; i < numNodes; i++)
  959. val[i][0] = ComputeVonMises(val[i]);
  960. addScalarElement(p, type, xyz, val, pre, numNodes);
  961. }
  962. else if (opt->tensorType == PViewOptions::Ellipse ||
  963. opt->tensorType == PViewOptions::Ellipsoid) {
  964. if(opt->glyphLocation == PViewOptions::Vertex){
  965. double vval[3][4]= {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}};
  966. for(int i = 0; i < numNodes; i++){
  967. for (int j = 0; j < 3; j++) {
  968. tensor(j,0) = val [i][0+j*3];
  969. tensor(j,1) = val [i][1+j*3];
  970. tensor(j,2) = val [i][2+j*3];
  971. }
  972. tensor.eig(S, imS, V, rightV, false);
  973. for (int k = 0; k < 3; k++) {
  974. vval[k][0] = xyz[i][k];
  975. for (int j = 0; j < 3; j++) {
  976. vval[k][j+1] = V(k,j)*S(j);
  977. }
  978. }
  979. double lmax = std::max(S(0), std::max(S(1), S(2)));
  980. unsigned int color = opt->getColor
  981. (lmax, opt->tmpMin, opt->tmpMax, false,
  982. (opt->intervalsType == PViewOptions::Discrete) ? opt->nbIso : -1);
  983. unsigned int col[4] = {color, color, color, color};
  984. p->va_ellipses->add(vval[0], vval[1], vval[2], 0, col, 0, false);
  985. }
  986. }
  987. else if(opt->glyphLocation == PViewOptions::COG){
  988. double vval[3][4]= {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}};
  989. for(int i = 0; i < numNodes; i++) {
  990. for (int j = 0; j < 3; j++) {
  991. tensor(j,0) = val [i][0+j*3];
  992. tensor(j,1) = val [i][1+j*3];
  993. tensor(j,2) = val [i][2+j*3];
  994. }
  995. tensor.eig(S, imS, V, rightV, false);
  996. for (int j = 0; j < 3; j++) {
  997. vval[0][j+1] += V(0,j)*S(j)/numNodes;
  998. vval[1][j+1] += V(1,j)*S(j)/numNodes;
  999. vval[2][j+1] += V(2,j)*S(j)/numNodes;
  1000. }
  1001. vval[0][0] += xyz[i][0]/numNodes;
  1002. vval[1][0] += xyz[i][1]/numNodes;
  1003. vval[2][0] += xyz[i][2]/numNodes;
  1004. }
  1005. double lmax = std::max(S(0), std::max(S(1), S(2)));
  1006. unsigned int color = opt->getColor
  1007. (lmax, opt->tmpMin, opt->tmpMax, false,
  1008. (opt->intervalsType == PViewOptions::Discrete) ? opt->nbIso : -1);
  1009. unsigned int col[4] = {color, color, color, color};
  1010. p->va_ellipses->add(vval[0], vval[1], vval[2], 0, col, 0, false);
  1011. }
  1012. }
  1013. else {
  1014. double **vval[3] = {new double*[numNodes],
  1015. new double*[numNodes],
  1016. new double*[numNodes]};
  1017. for(int i = 0; i < 3; i++)
  1018. for(int j = 0; j < numNodes; j++)
  1019. vval[i][j] = new double[3];
  1020. for(int i = 0; i < numNodes; i++) {
  1021. for (int j = 0; j < 3; j++) {
  1022. tensor(j,0) = val [i][0+j*3];
  1023. tensor(j,1) = val [i][1+j*3];
  1024. tensor(j,2) = val [i][2+j*3];
  1025. }
  1026. tensor.eig(S, imS, V, rightV, opt->tensorType != PViewOptions::EigenVectors);
  1027. if (PViewOptions::MinEigenValue == opt->tensorType)
  1028. val[i][0] = S(0);
  1029. else if (PViewOptions::MaxEigenValue == opt->tensorType)
  1030. val[i][0] = S(2);
  1031. else if (PViewOptions::EigenVectors == opt->tensorType) {
  1032. for (int j = 0; j < 3; j++) {
  1033. vval[0][i][j] = V(j,0)*S(0);
  1034. vval[1][i][j] = V(j,1)*S(1);
  1035. vval[2][i][j] = V(j,2)*S(2);
  1036. }
  1037. }
  1038. }
  1039. if (PViewOptions::EigenVectors == opt->tensorType) {
  1040. addVectorElement(p, iEnt, iEle, numNodes, type, xyz, vval[0], pre);
  1041. addVectorElement(p, iEnt, iEle, numNodes, type, xyz, vval[1], pre);
  1042. addVectorElement(p, iEnt, iEle, numNodes, type, xyz, vval[2], pre);
  1043. }
  1044. else
  1045. addScalarElement(p, type, xyz, val, pre, numNodes);
  1046. for(int i = 0; i < 3; i++){
  1047. for(int j = 0; j < numNodes; j++)
  1048. delete [] vval[i][j];
  1049. delete [] vval[i];
  1050. }
  1051. }
  1052. }
  1053. static void addElementsInArrays(PView *p, bool preprocessNormalsOnly)
  1054. {
  1055. static int numNodesError = 0, numCompError = 0;
  1056. // use adaptive data if available
  1057. PViewData *data = p->getData(true);
  1058. PViewOptions *opt = p->getOptions();
  1059. opt->tmpBBox.reset();
  1060. int NMAX = PVIEW_NMAX;
  1061. double **xyz = new double*[NMAX];
  1062. double **val = new double*[NMAX];
  1063. for(int i = 0; i < NMAX; i++){
  1064. xyz[i] = new double[3];
  1065. val[i] = new double[9];
  1066. }
  1067. for(int ent = 0; ent < data->getNumEntities(opt->timeStep); ent++){
  1068. if(data->skipEntity(opt->timeStep, ent)) continue;
  1069. for(int i = 0; i < data->getNumElements(opt->timeStep, ent); i++){
  1070. if(data->skipElement(opt->timeStep, ent, i, true, opt->sampling)) continue;
  1071. int type = data->getType(opt->timeStep, ent, i);
  1072. if(opt->skipElement(type)) continue;
  1073. int numComp = data->getNumComponents(opt->timeStep, ent, i);
  1074. int numNodes = data->getNumNodes(opt->timeStep, ent, i);
  1075. if(numNodes > PVIEW_NMAX){
  1076. if(type == TYPE_POLYG || type == TYPE_POLYH){
  1077. if(numNodes > NMAX){
  1078. for(int j = 0; j < NMAX; j++){
  1079. delete [] xyz[j];
  1080. delete [] val[j];
  1081. }
  1082. delete [] xyz;
  1083. delete [] val;
  1084. NMAX = numNodes;
  1085. xyz = new double*[NMAX];
  1086. val = new double*[NMAX];
  1087. for(int j = 0; j < NMAX; j++){
  1088. xyz[j] = new double[3];
  1089. val[j] = new double[9];
  1090. }
  1091. }
  1092. }
  1093. else {
  1094. if(numNodesError != numNodes){
  1095. numNodesError = numNodes;
  1096. Msg::Error("You should never draw views with > %d nodes per element: use"
  1097. "'Adapt visualization grid' to view high-order datasets!",
  1098. PVIEW_NMAX);
  1099. }
  1100. continue;
  1101. }
  1102. }
  1103. if((numComp > 9 && !opt->forceNumComponents) || opt->forceNumComponents > 9){
  1104. if(numCompError != numComp) {
  1105. numCompError = numComp;
  1106. Msg::Error("You should never draw views with > 9 values per node: use"
  1107. "'Adapt visualization grid' to view high-order datasets!");
  1108. }
  1109. continue;
  1110. }
  1111. for(int j = 0; j < numNodes; j++){
  1112. data->getNode(opt->timeStep, ent, i, j, xyz[j][0], xyz[j][1], xyz[j][2]);
  1113. if(opt->forceNumComponents){
  1114. for(int k = 0; k < opt->forceNumComponents; k++){
  1115. int comp = opt->componentMap[k];
  1116. if(comp >= 0 && comp < numComp)
  1117. data->getValue(opt->timeStep, ent, i, j, comp, val[j][k]);
  1118. else
  1119. val[j][k] = 0.;
  1120. }
  1121. }
  1122. else
  1123. for(int k = 0; k < numComp; k++)
  1124. data->getValue(opt->timeStep, ent, i, j, k, val[j][k]);
  1125. }
  1126. if(opt->forceNumComponents) numComp = opt->forceNumComponents;
  1127. changeCoordinates(p, ent, i, numNodes, type, numComp, xyz, val);
  1128. int dim = data->getDimension(opt->timeStep, ent, i);
  1129. if(!isElementVisible(opt, dim, numNodes, xyz)) continue;
  1130. for(int j = 0; j < numNodes; j++)
  1131. opt->tmpBBox += SPoint3(xyz[j][0], xyz[j][1], xyz[j][2]);
  1132. if(opt->showElement && !data->useGaussPoints())
  1133. addOutlineElement(p, type, xyz, preprocessNormalsOnly, numNodes);
  1134. if(opt->intervalsType != PViewOptions::Numeric){
  1135. if(data->useGaussPoints()){
  1136. for(int j = 0; j < numNodes; j++){
  1137. double *x2 = new double[3]; double **xyz2 = &x2;
  1138. double *v2 = new double[9]; double **val2 = &v2;
  1139. xyz2[0][0] = xyz[j][0];
  1140. xyz2[0][1] = xyz[j][1];
  1141. xyz2[0][2] = xyz[j][2];
  1142. for(int k = 0; k < numComp; k++)
  1143. val2[0][k] = val[j][k];
  1144. if(numComp == 1 && opt->drawScalars)
  1145. addScalarElement(p, TYPE_PNT, xyz2, val2, preprocessNormalsOnly, numNodes);
  1146. else if(numComp == 3 && opt->drawVectors)
  1147. addVectorElement(p, ent, i, 1, TYPE_PNT, xyz2, val2, preprocessNormalsOnly);
  1148. else if(numComp == 9 && opt->drawTensors)
  1149. addTensorElement(p, ent, i, 1, TYPE_PNT, xyz2, val2, preprocessNormalsOnly);
  1150. delete [] xyz2[0];
  1151. delete [] val2[0];
  1152. }
  1153. }
  1154. else if(numComp == 1 && opt->drawScalars)
  1155. addScalarElement(p, type, xyz, val, preprocessNormalsOnly, numNodes);
  1156. else if(numComp == 3 && opt->drawVectors)
  1157. addVectorElement(p, ent, i, numNodes, type, xyz, val, preprocessNormalsOnly);
  1158. else if(numComp == 9 && opt->drawTensors)
  1159. addTensorElement(p, ent, i, numNodes, type, xyz, val, preprocessNormalsOnly);
  1160. }
  1161. }
  1162. }
  1163. for(int j = 0; j < NMAX; j++){
  1164. delete [] xyz[j];
  1165. delete [] val[j];
  1166. }
  1167. delete [] xyz;
  1168. delete [] val;
  1169. }
  1170. class initPView {
  1171. private:
  1172. // we try to estimate how many primitives will end up in the vertex
  1173. // arrays, since reallocating the arrays takes a huge amount of time
  1174. // on Windows/Cygwin
  1175. int _estimateIfClipped(PView *p, int num)
  1176. {
  1177. if(CTX::instance()->clipWholeElements &&
  1178. CTX::instance()->clipOnlyDrawIntersectingVolume){
  1179. PViewOptions *opt = p->getOptions();
  1180. for(int clip = 0; clip < 6; clip++){
  1181. if(opt->clip & (1 << clip))
  1182. return (int)sqrt((double)num);
  1183. }
  1184. }
  1185. return num;
  1186. }
  1187. int _estimateNumPoints(PView *p)
  1188. {
  1189. PViewData *data = p->getData(true);
  1190. PViewOptions *opt = p->getOptions();
  1191. int heuristic = data->getNumPoints(opt->timeStep);
  1192. return heuristic + 10000;
  1193. }
  1194. int _estimateNumLines(PView *p)
  1195. {
  1196. PViewData *data = p->getData(true);
  1197. PViewOptions *opt = p->getOptions();
  1198. int heuristic = data->getNumLines(opt->timeStep);
  1199. return heuristic + 10000;
  1200. }
  1201. int _estimateNumTriangles(PView *p)
  1202. {
  1203. PViewData *data = p->getData(true);
  1204. PViewOptions *opt = p->getOptions();
  1205. int tris = data->getNumTriangles(opt->timeStep);
  1206. int quads = data->getNumQuadrangles(opt->timeStep);
  1207. int polygs = data->getNumPolygons(opt->timeStep);
  1208. int tets = data->getNumTetrahedra(opt->timeStep);
  1209. int prisms = data->getNumPrisms(opt->timeStep);
  1210. int pyrs = data->getNumPyramids(opt->timeStep);
  1211. int hexas = data->getNumHexahedra(opt->timeStep);
  1212. int polyhs = data->getNumPolyhedra(opt->timeStep);
  1213. int heuristic = 0;
  1214. if(opt->intervalsType == PViewOptions::Iso)
  1215. heuristic = (tets + prisms + pyrs + hexas + polyhs) / 10;
  1216. else if(opt->intervalsType == PViewOptions::Continuous)
  1217. heuristic = (tris + 2 * quads + 3 * polygs + 6 * tets +
  1218. 8 * prisms + 6 * pyrs + 12 * hexas + 10 * polyhs);
  1219. else if(opt->intervalsType == PViewOptions::Discrete)
  1220. heuristic = (tris + 2 * quads + 3 * polygs + 6 * tets +
  1221. 8 * prisms + 6 * pyrs + 12 * hexas + 10 * polyhs) * 2;
  1222. heuristic = _estimateIfClipped(p, heuristic);
  1223. return heuristic + 10000;
  1224. }
  1225. int _estimateNumVectors(PView *p)
  1226. {
  1227. PViewData *data = p->getData(true);
  1228. PViewOptions *opt = p->getOptions();
  1229. int heuristic = data->getNumVectors(opt->timeStep);
  1230. heuristic = _estimateIfClipped(p, heuristic);
  1231. return heuristic + 1000;
  1232. }
  1233. int _estimateNumEllipses(PView *p)
  1234. {
  1235. PViewData *data = p->getData(true);
  1236. PViewOptions *opt = p->getOptions();
  1237. int heuristic = data->getNumTensors(opt->timeStep);
  1238. heuristic = _estimateIfClipped(p, heuristic);
  1239. return heuristic + 1000;
  1240. }
  1241. public:
  1242. void operator () (PView *p)
  1243. {
  1244. // use adaptive data if available
  1245. PViewData *data = p->getData(true);
  1246. PViewOptions *opt = p->getOptions();
  1247. if(data->getDirty() || !data->getNumTimeSteps() || !p->getChanged()) return;
  1248. if(!opt->visible || opt->type != PViewOptions::Plot3D) return;
  1249. p->deleteVertexArrays();
  1250. if(data->isRemote()){
  1251. // FIXME: need to rewrite option code and add nice serialization
  1252. std::string fileName = CTX::instance()->homeDir + CTX::instance()->tmpFileName;
  1253. PrintOptions(0, GMSH_FULLRC, 0, 0, fileName.c_str());
  1254. std::string options = ConvertFileToString(fileName);
  1255. data->fillRemoteVertexArrays(options);
  1256. return;
  1257. }
  1258. if(opt->useGenRaise) opt->createGeneralRaise();
  1259. if(opt->rangeType == PViewOptions::Custom){
  1260. opt->tmpMin = opt->customMin;
  1261. opt->tmpMax = opt->customMax;
  1262. }
  1263. else if(opt->rangeType == PViewOptions::PerTimeStep){
  1264. opt->tmpMin = data->getMin(opt->timeStep);
  1265. opt->tmpMax = data->getMax(opt->timeStep);
  1266. }
  1267. else{
  1268. // FIXME: this is not perfect for multi-step adaptive views, as
  1269. // we don't have the correct min/max info for the other steps
  1270. opt->tmpMin = data->getMin();
  1271. opt->tmpMax = data->getMax();
  1272. }
  1273. p->va_points = new VertexArray(1, _estimateNumPoints(p));
  1274. p->va_lines = new VertexArray(2, _estimateNumLines(p));
  1275. p->va_triangles = new VertexArray(3, _estimateNumTriangles(p));
  1276. p->va_vectors = new VertexArray(2, _estimateNumVectors(p));
  1277. p->va_ellipses = new VertexArray(4, _estimateNumEllipses(p));
  1278. if(p->normals) delete p->normals;
  1279. p->normals = new smooth_normals(opt->angleSmoothNormals);
  1280. if(opt->smoothNormals) addElementsInArrays(p, true);
  1281. addElementsInArrays(p, false);
  1282. p->va_points->finalize();
  1283. p->va_lines->finalize();
  1284. p->va_triangles->finalize();
  1285. p->va_vectors->finalize();
  1286. p->va_ellipses->finalize();
  1287. Msg::Debug("%d vertices in vertex arrays (%g Mb)", p->va_points->getNumVertices() +
  1288. p->va_lines->getNumVertices() + p->va_triangles->getNumVertices

Large files files are truncated, but you can click here to view the full file