diff options
Diffstat (limited to 'lib/tqwtplot3d/src/qwt3d_meshplot.cpp')
| -rw-r--r-- | lib/tqwtplot3d/src/qwt3d_meshplot.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
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;
+}
+
+
|
