From b85a292ce06475d560bfa1195b63a8bfe211f22d Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 11 Jul 2012 14:15:27 -0500 Subject: Add 0.2.7 release of qwtplot3d for future TQt3 conversion and use --- lib/tqwtplot3d/src/qwt3d_meshplot.cpp | 320 ++++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 lib/tqwtplot3d/src/qwt3d_meshplot.cpp (limited to 'lib/tqwtplot3d/src/qwt3d_meshplot.cpp') diff --git a/lib/tqwtplot3d/src/qwt3d_meshplot.cpp b/lib/tqwtplot3d/src/qwt3d_meshplot.cpp new file mode 100644 index 0000000..0c975fe --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_meshplot.cpp @@ -0,0 +1,320 @@ +#if defined(_MSC_VER) /* MSVC Compiler */ +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4786 ) +#endif + +#include "qwt3d_surfaceplot.h" +#include "qwt3d_enrichment_std.h" + +using namespace std; +using namespace Qwt3D; + + +///////////////////////////////////////////////////////////////////////////////// +// +// cell specific +// + + +void SurfacePlot::createDataC() +{ + createFloorDataC(); + + if (plotStyle() == NOPLOT) + return; + + if (plotStyle() == Qwt3D::POINTS) + { + createPoints(); + return; + } + else if (plotStyle() == Qwt3D::USER) + { + if (userplotstyle_p) + createEnrichment(*userplotstyle_p); + return; + } + + setDeviceLineWidth(meshLineWidth()); + GLStateBewarer sb(GL_POLYGON_OFFSET_FILL,true); + setDevicePolygonOffset(polygonOffset(),1.0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + int idx = 0; + if (plotStyle() != WIREFRAME) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS); + + bool hl = (plotStyle() == HIDDENLINE); + if (hl) + { + RGBA col = backgroundRGBAColor(); + glColor4d(col.r, col.g, col.b, col.a); + } + + for (unsigned i=0; i!=actualDataC_->cells.size(); ++i) + { + glBegin(GL_POLYGON); + for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j) + { + idx = actualDataC_->cells[i][j]; + setColorFromVertexC(idx, hl); + glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, actualDataC_->nodes[idx].z ); + glNormal3d( actualDataC_->normals[idx].x, actualDataC_->normals[idx].y, actualDataC_->normals[idx].z ); + } + glEnd(); + } + } + + if (plotStyle() == FILLEDMESH || plotStyle() == WIREFRAME || plotStyle() == HIDDENLINE) + { + glColor4d(meshColor().r, meshColor().g, meshColor().b, meshColor().a); + { + for (unsigned i=0; i!=actualDataC_->cells.size(); ++i) + { + glBegin(GL_LINE_LOOP); + for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j) + { + idx = actualDataC_->cells[i][j]; + glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, actualDataC_->nodes[idx].z ); + } + glEnd(); + } + } + } +} + +// ci = cell index +// cv = vertex index in cell ci +void SurfacePlot::setColorFromVertexC(int node, bool skip) +{ + if (skip) + return; + + RGBA col = (*datacolor_p)( + actualDataC_->nodes[node].x, actualDataC_->nodes[node].y, actualDataC_->nodes[node].z); + + glColor4d(col.r, col.g, col.b, col.a); +} + +void SurfacePlot::createFloorDataC() +{ + switch (floorStyle()) + { + case FLOORDATA: + Data2FloorC(); + break; + case FLOORISO: + Isolines2FloorC(); + break; + default: + break; + } +} + +void SurfacePlot::Data2FloorC() +{ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + double zshift = actualDataC_->hull().minVertex.z; + int idx; + + for (unsigned i = 0; i!=actualDataC_->cells.size(); ++i) + { + glBegin(GL_POLYGON); + for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j) + { + idx = actualDataC_->cells[i][j]; + setColorFromVertexC(idx); + glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, zshift ); + } + glEnd(); + } +} + +void SurfacePlot::Isolines2FloorC() +{ + if (isolines() <= 0 || actualData_p->empty()) + return; + + double step = (actualData_p->hull().maxVertex.z - actualData_p->hull().minVertex.z) / isolines(); + + RGBA col; + + double zshift = actualData_p->hull().minVertex.z; + + TripleField nodes; + TripleField intersection; + + double lambda = 0; + + GLStateBewarer sb2(GL_LINE_SMOOTH, false); + + for (int k = 0; k != isolines(); ++k) + { + double val = zshift + k * step; + + for (unsigned i=0; i!=actualDataC_->cells.size(); ++i) + { + nodes.clear(); + unsigned cellnodes = actualDataC_->cells[i].size(); + for (unsigned j=0; j!=cellnodes; ++j) + { + nodes.push_back(actualDataC_->nodes[actualDataC_->cells[i][j]]); + } + + double diff = 0; + for (unsigned m = 0; m!=cellnodes; ++m) + { + unsigned mm = (m+1)%cellnodes; + if ((val>=nodes[m].z && val<=nodes[mm].z) || (val>=nodes[mm].z && val<=nodes[m].z)) + { + diff = nodes[mm].z - nodes[m].z; + + if (isPracticallyZero(diff)) // degenerated + { + intersection.push_back(nodes[m]); + intersection.push_back(nodes[mm]); + continue; + } + + lambda = (val - nodes[m].z) / diff; + intersection.push_back(Triple(nodes[m].x + lambda * (nodes[mm].x-nodes[m].x), nodes[m].y + lambda * (nodes[mm].y-nodes[m].y), val)); + } + } + + if (!intersection.empty()) + { + col = (*datacolor_p)(nodes[0].x,nodes[0].y,nodes[0].z); + glColor4d(col.r, col.g, col.b, col.a); + if (intersection.size()>2) + { + glBegin(GL_LINE_STRIP); + for (unsigned dd = 0; dd!=intersection.size(); ++dd) + { + glVertex3d(intersection[dd].x, intersection[dd].y, zshift); + } + glEnd(); + glBegin(GL_POINTS); + glVertex3d(intersection[0].x,intersection[0].y,zshift); + glEnd(); + } + else if (intersection.size() == 2) + { + glBegin(GL_LINES); + glVertex3d(intersection[0].x,intersection[0].y,zshift); + glVertex3d(intersection[1].x,intersection[1].y,zshift); + + // small pixel gap problem (see OpenGL spec.) + glVertex3d(intersection[1].x,intersection[1].y,zshift); + glVertex3d(intersection[0].x,intersection[0].y,zshift); + glEnd(); + } + + intersection.clear(); + } + } + } +} + +void SurfacePlot::createNormalsC() +{ + if (!normals() || actualData_p->empty()) + return; + + if (actualDataC_->nodes.size() != actualDataC_->normals.size()) + return; + Arrow arrow; + arrow.setQuality(normalQuality()); + + Triple basev, topv, norm; + + double diag = (actualData_p->hull().maxVertex-actualData_p->hull().minVertex).length() * normalLength(); + + RGBA col; + arrow.assign(*this); + arrow.drawBegin(); + for (unsigned i = 0; i != actualDataC_->normals.size(); ++i) + { + basev = actualDataC_->nodes[i]; + topv = basev + actualDataC_->normals[i]; + + norm = topv-basev; + norm.normalize(); + norm *= diag; + + arrow.setTop(basev+norm); + arrow.setColor((*datacolor_p)(basev.x,basev.y,basev.z)); + arrow.draw(basev); + } + arrow.drawEnd(); +} + +/*! + Convert user (non-rectangular) mesh based data to internal structure. + See also Qwt3D::TripleField and Qwt3D::CellField +*/ +bool SurfacePlot::loadFromData(TripleField const& data, CellField const& poly) +{ + actualDataG_->clear(); + actualData_p = actualDataC_; + + actualDataC_->nodes = data; + actualDataC_->cells = poly; + actualDataC_->normals = TripleField(actualDataC_->nodes.size()); + + unsigned i; + +// normals for the moment + Triple n, u, v; + for ( i = 0; i < poly.size(); ++i) + { + if (poly[i].size() < 3) + n = Triple(0,0,0); + else + { + for (unsigned j = 0; j < poly[i].size(); ++j) + { + unsigned jj = (j+1) % poly[i].size(); + unsigned pjj = (j) ? j-1 : poly[i].size()-1; + u = actualDataC_->nodes[poly[i][jj]]-actualDataC_->nodes[poly[i][j]]; + v = actualDataC_->nodes[poly[i][pjj]]-actualDataC_->nodes[poly[i][j]]; + n = normalizedcross(u,v); + actualDataC_->normals[poly[i][j]] += n; + } + } + } + for ( i = 0; i != actualDataC_->normals.size(); ++i) + { + actualDataC_->normals[i].normalize(); + } + + ParallelEpiped hull(Triple(DBL_MAX,DBL_MAX,DBL_MAX),Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX)); + + for (i = 0; i!=data.size(); ++i) + { + if (data[i].x < hull.minVertex.x) + hull.minVertex.x = data[i].x; + if (data[i].y < hull.minVertex.y) + hull.minVertex.y = data[i].y; + if (data[i].z < hull.minVertex.z) + hull.minVertex.z = data[i].z; + + if (data[i].x > hull.maxVertex.x) + hull.maxVertex.x = data[i].x; + if (data[i].y > hull.maxVertex.y) + hull.maxVertex.y = data[i].y; + if (data[i].z > hull.maxVertex.z) + hull.maxVertex.z = data[i].z; + } + + actualDataC_->setHull(hull); + + updateData(); + updateNormals(); + createCoordinateSystem(); + + return true; +} + + -- cgit v1.2.3