void Curve::fillTriangleG(const TripleField& t, double* z, const std::vector<double>& stops) { std::sort(z, z + 3); double zmin = z[0], zmax = z[2]; std::vector<double> colorLevels = isocolors(stops, zmin, zmax); if (colorLevels.empty()){ RGBA col = (*datacolor_p)(0, 0, 0.5*(zmin + zmax)); glColor4d(col.r, col.g, col.b, col.a); glBegin(GL_TRIANGLES); for (int i = 0; i < 3; i++){ Triple p = t[i]; glVertex3d(p.x, p.y, p.z); } glEnd(); return; } bool searchFillColor = false; std::vector<double> untransformedColorLevels; Qwt3D::Axis zAxis = plot_p->coordinates()->axes[Z1]; if (zAxis.scaleType() != Qwt3D::LINEARSCALE){ searchFillColor = true; untransformedColorLevels = std::vector<double>(colorLevels); unsigned int colorCount = colorLevels.size(); for (unsigned int i = 0; i < colorCount; i++) colorLevels[i] = zAxis.transform(colorLevels[i]); } std::vector<TripleField> cells = isocolorCells(t, colorLevels); if (cells.empty()) return; if (searchFillColor){ colorLevels.push_back(zAxis.transform(zmax)); untransformedColorLevels.push_back(zmax); } unsigned int polygons = cells.size(); for (unsigned int i = 0; i < polygons; i++){ TripleField cell = cells[i]; setPolygonColor(cell, searchFillColor, colorLevels, untransformedColorLevels); unsigned int points = cell.size(); if (points > 3) fillPolygonG(cell); else { glBegin(GL_TRIANGLES); for (unsigned int j = 0; j < points; j++){ Triple p = cell[j]; glVertex3d(p.x, p.y, p.z); } glEnd(); } } }
void Curve::fillPolygonG(TripleField cell, int comp, double shift) { std::sort(cell.begin(), cell.end(), tripleLessThan); Triple left = cell.front(); cell.erase(cell.begin()); Triple right = cell.back(); cell.pop_back(); TripleField ccwPoints, cwPoints; ccwPoints.push_back(left); cwPoints.push_back(left); unsigned int points = cell.size(); for (unsigned int i = 0; i < points; i++){ Triple p = cell[i]; if (ccw(left, right, p)) ccwPoints.push_back(p); else cwPoints.push_back(p); } cwPoints.push_back(right); ccwPoints.push_back(right); std::sort(cwPoints.begin(), cwPoints.end(), tripleLessThan); std::sort(ccwPoints.begin(), ccwPoints.end(), tripleLessThan); bool projection = (comp >= 0); if (projection){ glBegin(GL_POLYGON); points = cwPoints.size(); for (unsigned int i = 0; i < points; i++) drawVertex(cwPoints[i], shift, comp); glEnd(); glBegin(GL_POLYGON); points = ccwPoints.size(); for (unsigned int i = 0; i < points; i++) drawVertex(ccwPoints[i], shift, comp); glEnd(); } else { glBegin(GL_POLYGON); points = cwPoints.size(); for (unsigned int i = 0; i < points; i++){ Triple p = cwPoints[i]; glVertex3d(p.x, p.y, p.z); } glEnd(); glBegin(GL_POLYGON); points = ccwPoints.size(); for (unsigned int i = 0; i < points; i++){ Triple p = ccwPoints[i]; glVertex3d(p.x, p.y, p.z); } glEnd(); } }
/*! Convert user (non-rectangular) mesh based data to internal structure. See also Qwt3D::TripleField and Qwt3D::CellField */ bool Curve::loadFromData(TripleField const& data, CellField const& poly, QString titlestr) { actualDataG_->clear(); actualData_p = actualDataC_; actualDataC_->datatype = Qwt3D::POLYGON; actualDataC_->nodes = data; actualDataC_->cells = poly; actualDataC_->normals = TripleField(actualDataC_->nodes.size()); if (!titlestr.isEmpty()) setTitle(titlestr); 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){ Triple t = data[i]; if (t.x < hull.minVertex.x) hull.minVertex.x = t.x; if (t.y < hull.minVertex.y) hull.minVertex.y = t.y; if (t.z < hull.minVertex.z) hull.minVertex.z = t.z; if (t.x > hull.maxVertex.x) hull.maxVertex.x = t.x; if (t.y > hull.maxVertex.y) hull.maxVertex.y = t.y; if (t.z > hull.maxVertex.z) hull.maxVertex.z = t.z; } actualDataC_->setHull(hull); emit readInFinished(title()->string()); updateData(); return true; }
void Curve::mapTriangleG(double *v1, double *v2, double *v3, const std::vector<double>& stops, int comp, double shift) { double z[] = {v1[2], v2[2], v3[2]}; std::sort(z, z + 3); double zmin = z[0], zmax = z[2]; std::vector<double> colorLevels = isocolors(stops, zmin, zmax); TripleField t; t.push_back(plot_p->transform(v1, comp)); t.push_back(plot_p->transform(v2, comp)); t.push_back(plot_p->transform(v3, comp)); if (colorLevels.empty()){ RGBA col = (*datacolor_p)(0, 0, 0.5*(zmin + zmax)); glColor4d(col.r, col.g, col.b, col.a); glBegin(GL_TRIANGLES); for (int i = 0; i < 3; i++) drawVertex(t[i], shift, comp); glEnd(); return; } std::vector<TripleField> cells = isocolorCells(t, colorLevels); if (cells.empty()) return; unsigned int polygons = cells.size(); for (unsigned int i = 0; i < polygons; i++){ TripleField cell = cells[i]; RGBA col = (*datacolor_p)(0, 0, 0.5*(cell[0].z + cell[2].z)); glColor4d(col.r, col.g, col.b, col.a); unsigned int points = cell.size(); if (points > 3) fillPolygonG(cell, comp, shift); else { glBegin(GL_TRIANGLES); for (unsigned int j = 0; j < points; j++) drawVertex(cell[j], shift, comp); glEnd(); } } }
void Curve::setPolygonColor(const TripleField& cell, bool search, const std::vector<double>& colorLevels, const std::vector<double>& untransformedColorLevels) { if (!search){ RGBA col = (*datacolor_p)(0, 0, 0.5*(cell[0].z + cell[2].z)); glColor4d(col.r, col.g, col.b, col.a); return; } unsigned int colors = colorLevels.size(); if (colors < 2) return; double color = colorLevels[0]; bool ok = true; unsigned int points = cell.size(); for (unsigned int j = 0; j < points; j++){ double z = cell[j].z; if (z > color){ ok = false; break; } } if (ok){ RGBA col = (*datacolor_p)(0, 0, 0.99*untransformedColorLevels[0]); glColor4d(col.r, col.g, col.b, col.a); return; } for (unsigned int i = 1; i < colors; i++){ double color = colorLevels[i]; double prevColor = colorLevels[i - 1]; bool ok = true; for (unsigned int j = 0; j < points; j++){ double z = cell[j].z; if (z < prevColor || z > color){ ok = false; break; } } if (ok){ RGBA col = (*datacolor_p)(0, 0, 0.5*(untransformedColorLevels[i] + untransformedColorLevels[i - 1])); glColor4d(col.r, col.g, col.b, col.a); return; } } }
std::vector<TripleField> isocolorCells(const TripleField& t, const std::vector<double>& colorLevels) { QList<Triple> intersections; unsigned int colorCount = colorLevels.size(), size = t.size(); for (unsigned int k = 0; k < colorCount; k++){ double val = colorLevels[k]; for (unsigned int i = 0; i < size; i++){ int ii = (i + 1)%size; Triple ti = t[i], tii = t[ii]; double zi = ti.z, zii = tii.z; if (val == zi){ if (!intersections.contains(ti)) intersections.push_back(ti); continue; } else if (val == zii){ if (!intersections.contains(tii)) intersections.push_back(tii); continue; } bool outer = (val > zii && val < zi); bool inner = (val > zi && val < zii); if (inner || outer){ Triple d = tii - ti; double f = (val - zi)/d(2); double component[3]; for (unsigned int j = 0; j < 3; j++) component[j] = ti(j) + f*d(j); intersections.push_back(Triple(component[0], component[1], val)); } } } std::vector<TripleField> cells; if (intersections.empty()) return cells; Triple p = intersections[0], pp = intersections[1]; TripleField firstCell, lastCell; firstCell.push_back(p); firstCell.push_back(pp); double level = p.z; for (unsigned int j = 0; j < size; j++){ Triple tj = t[j]; if (tj.z < level) firstCell.push_back(tj); } cells.push_back(firstCell); unsigned int intPairs = intersections.size()/2; for (unsigned int i = 1; i < intPairs; i++){ TripleField cell; cell.push_back(p); cell.push_back(pp); double prevLevel = p.z; unsigned int k = 2*i; p = intersections[k]; pp = intersections[k + 1]; level = p.z; for (unsigned int j = 0; j < size; j++){ Triple tj = t[j]; if (prevLevel < tj.z && tj.z < level) cell.push_back(tj); } cell.push_back(p); cell.push_back(pp); cells.push_back(cell); } lastCell.push_back(p); lastCell.push_back(pp); for (unsigned int j = 0; j < size; j++){ Triple tj = t[j]; if (tj.z > level) lastCell.push_back(tj); } cells.push_back(lastCell); return cells; }
/*! 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; }
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 Curve::IsolinesC(unsigned comp, bool projected) { if (isolines() <= 0 || actualDataC_->empty()) return; Triple tmax = actualDataC_->hull().maxVertex; Triple tmin = actualDataC_->hull().minVertex; double delta = tmax(comp) - tmin(comp); double shift = tmin(comp); double step = delta / isolines(); RGBA col; TripleField nodes; TripleField intersection; double lambda = 0; GLStateBewarer sb2(GL_LINE_SMOOTH, false); for (unsigned int k = 0; k != isolines(); ++k) { double val = shift + k * step; for (unsigned int i = 0; i != actualDataC_->cells.size(); ++i) { nodes.clear(); unsigned int cellnodes = actualDataC_->cells[i].size(); for (unsigned int j = 0; j != cellnodes; ++j) { nodes.push_back(actualDataC_->nodes[actualDataC_->cells[i][j]]); } double diff = 0; for (unsigned int m = 0; m != cellnodes; ++m) { unsigned int mm = (m+1) % cellnodes; bool outer = (val >= nodes[mm](comp) && val <= nodes[m](comp)); bool inner = (val >= nodes[m](comp) && val <= nodes[mm](comp)); if (inner || outer) { diff = nodes[mm](comp) - nodes[m](comp); if (isPracticallyZero(diff)) { // degenerated intersection.push_back(nodes[m]); intersection.push_back(nodes[mm]); continue; } Triple intersect; double component[3]; lambda = (val - nodes[m](comp)) / diff; for (unsigned int c = 0; c!=3; ++c) { component[c] = (nodes[m](c) + lambda * (nodes[mm](c)-nodes[m](c))); } switch (comp) { case 0: intersect = Triple(val, component[1], component[2]); break; case 1: intersect = Triple(component[0], val, component[2]); break; case 2: intersect = Triple(component[0], component[1], val); break; } intersection.push_back(intersect); } } col = (*datacolor_p)(nodes[0].x,nodes[0].y,nodes[0].z); glColor4d(col.r, col.g, col.b, col.a); drawIntersections(intersection, shift, comp, projected); } } }