You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
7.8 KiB
C++
321 lines
7.8 KiB
C++
#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;
|
|
}
|
|
|
|
|