1 #if defined(_MSC_VER) /* MSVC Compiler */
2 #pragma warning(disable : 4305)
3 #pragma warning(disable : 4786)
4 #endif
5
6 #include "qwt3d_surfaceplot.h"
7 #include "qwt3d_enrichment_std.h"
8
9 using namespace std;
10 using namespace Qwt3D;
11
12 /////////////////////////////////////////////////////////////////////////////////
13 //
14 // cell specific
15 //
16
createDataC()17 void SurfacePlot::createDataC()
18 {
19 createFloorDataC();
20
21 if (plotStyle() == NOPLOT)
22 return;
23
24 if (plotStyle() == Qwt3D::POINTS) {
25 createPoints();
26 return;
27 } else if (plotStyle() == Qwt3D::USER) {
28 if (userplotstyle_p)
29 createEnrichment(*userplotstyle_p);
30 return;
31 }
32
33 setDeviceLineWidth(meshLineWidth());
34 GLStateBewarer sb(GL_POLYGON_OFFSET_FILL, true);
35 setDevicePolygonOffset(polygonOffset(), 1.0);
36 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
37 int idx = 0;
38 if (plotStyle() != WIREFRAME) {
39 glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
40
41 bool hl = (plotStyle() == HIDDENLINE);
42 if (hl) {
43 RGBA col = backgroundRGBAColor();
44 glColor4d(col.r, col.g, col.b, col.a);
45 }
46
47 for (unsigned i = 0; i != actualDataC_->cells.size(); ++i) {
48 glBegin(GL_POLYGON);
49 for (unsigned j = 0; j != actualDataC_->cells[i].size(); ++j) {
50 idx = actualDataC_->cells[i][j];
51 setColorFromVertexC(idx, hl);
52 glVertex3d(actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y,
53 actualDataC_->nodes[idx].z);
54 glNormal3d(actualDataC_->normals[idx].x, actualDataC_->normals[idx].y,
55 actualDataC_->normals[idx].z);
56 }
57 glEnd();
58 }
59 }
60
61 if (plotStyle() == FILLEDMESH || plotStyle() == WIREFRAME || plotStyle() == HIDDENLINE) {
62 glColor4d(meshColor().r, meshColor().g, meshColor().b, meshColor().a);
63 {
64 for (unsigned i = 0; i != actualDataC_->cells.size(); ++i) {
65 glBegin(GL_LINE_LOOP);
66 for (unsigned j = 0; j != actualDataC_->cells[i].size(); ++j) {
67 idx = actualDataC_->cells[i][j];
68 glVertex3d(actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y,
69 actualDataC_->nodes[idx].z);
70 }
71 glEnd();
72 }
73 }
74 }
75 }
76
77 // ci = cell index
78 // cv = vertex index in cell ci
setColorFromVertexC(int node,bool skip)79 void SurfacePlot::setColorFromVertexC(int node, bool skip)
80 {
81 if (skip)
82 return;
83
84 RGBA col = (*datacolor_p)(actualDataC_->nodes[node].x, actualDataC_->nodes[node].y,
85 actualDataC_->nodes[node].z);
86
87 glColor4d(col.r, col.g, col.b, col.a);
88 }
89
createFloorDataC()90 void SurfacePlot::createFloorDataC()
91 {
92 switch (floorStyle()) {
93 case FLOORDATA:
94 Data2FloorC();
95 break;
96 case FLOORISO:
97 Isolines2FloorC();
98 break;
99 default:
100 break;
101 }
102 }
103
Data2FloorC()104 void SurfacePlot::Data2FloorC()
105 {
106 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
107 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
108
109 double zshift = actualDataC_->hull().minVertex.z;
110 int idx;
111
112 for (unsigned i = 0; i != actualDataC_->cells.size(); ++i) {
113 glBegin(GL_POLYGON);
114 for (unsigned j = 0; j != actualDataC_->cells[i].size(); ++j) {
115 idx = actualDataC_->cells[i][j];
116 setColorFromVertexC(idx);
117 glVertex3d(actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, zshift);
118 }
119 glEnd();
120 }
121 }
122
Isolines2FloorC()123 void SurfacePlot::Isolines2FloorC()
124 {
125 if (isolines() <= 0 || actualData_p->empty())
126 return;
127
128 double step =
129 (actualData_p->hull().maxVertex.z - actualData_p->hull().minVertex.z) / isolines();
130
131 RGBA col;
132
133 double zshift = actualData_p->hull().minVertex.z;
134
135 TripleField nodes;
136 TripleField intersection;
137
138 double lambda = 0;
139
140 GLStateBewarer sb2(GL_LINE_SMOOTH, false);
141
142 for (int k = 0; k != isolines(); ++k) {
143 double val = zshift + k * step;
144
145 for (unsigned i = 0; i != actualDataC_->cells.size(); ++i) {
146 nodes.clear();
147 size_t cellnodes = actualDataC_->cells[i].size();
148 for (size_t j = 0; j < cellnodes; ++j) {
149 nodes.push_back(actualDataC_->nodes[actualDataC_->cells[i][j]]);
150 }
151
152 double diff = 0;
153 for (unsigned m = 0; m != cellnodes; ++m) {
154 unsigned mm = (m + 1) % cellnodes;
155 if ((val >= nodes[m].z && val <= nodes[mm].z)
156 || (val >= nodes[mm].z && val <= nodes[m].z)) {
157 diff = nodes[mm].z - nodes[m].z;
158
159 if (isPracticallyZero(diff)) // degenerated
160 {
161 intersection.push_back(nodes[m]);
162 intersection.push_back(nodes[mm]);
163 continue;
164 }
165
166 lambda = (val - nodes[m].z) / diff;
167 intersection.push_back(Triple(nodes[m].x + lambda * (nodes[mm].x - nodes[m].x),
168 nodes[m].y + lambda * (nodes[mm].y - nodes[m].y),
169 val));
170 }
171 }
172
173 if (!intersection.empty()) {
174 col = (*datacolor_p)(nodes[0].x, nodes[0].y, nodes[0].z);
175 glColor4d(col.r, col.g, col.b, col.a);
176 if (intersection.size() > 2) {
177 glBegin(GL_LINE_STRIP);
178 for (unsigned dd = 0; dd != intersection.size(); ++dd) {
179 glVertex3d(intersection[dd].x, intersection[dd].y, zshift);
180 }
181 glEnd();
182 glBegin(GL_POINTS);
183 glVertex3d(intersection[0].x, intersection[0].y, zshift);
184 glEnd();
185 } else if (intersection.size() == 2) {
186 glBegin(GL_LINES);
187 glVertex3d(intersection[0].x, intersection[0].y, zshift);
188 glVertex3d(intersection[1].x, intersection[1].y, zshift);
189
190 // small pixel gap problem (see OpenGL spec.)
191 glVertex3d(intersection[1].x, intersection[1].y, zshift);
192 glVertex3d(intersection[0].x, intersection[0].y, zshift);
193 glEnd();
194 }
195
196 intersection.clear();
197 }
198 }
199 }
200 }
201
createNormalsC()202 void SurfacePlot::createNormalsC()
203 {
204 if (!normals() || actualData_p->empty())
205 return;
206
207 if (actualDataC_->nodes.size() != actualDataC_->normals.size())
208 return;
209 Arrow arrow;
210 arrow.setQuality(normalQuality());
211
212 Triple basev, topv, norm;
213
214 double diag = (actualData_p->hull().maxVertex - actualData_p->hull().minVertex).length()
215 * normalLength();
216
217 RGBA col;
218 arrow.assign(*this);
219 arrow.drawBegin();
220 for (unsigned i = 0; i != actualDataC_->normals.size(); ++i) {
221 basev = actualDataC_->nodes[i];
222 topv = basev + actualDataC_->normals[i];
223
224 norm = topv - basev;
225 norm.normalize();
226 norm *= diag;
227
228 arrow.setTop(basev + norm);
229 arrow.setColor((*datacolor_p)(basev.x, basev.y, basev.z));
230 arrow.draw(basev);
231 }
232 arrow.drawEnd();
233 }
234
235 /*!
236 Convert user (non-rectangular) mesh based data to internal structure.
237 See also Qwt3D::TripleField and Qwt3D::CellField
238 */
loadFromData(TripleField const & data,CellField const & poly)239 bool SurfacePlot::loadFromData(TripleField const &data, CellField const &poly)
240 {
241 actualDataG_->clear();
242 actualData_p = actualDataC_;
243
244 actualDataC_->nodes = data;
245 actualDataC_->cells = poly;
246 actualDataC_->normals = TripleField(actualDataC_->nodes.size());
247
248 unsigned i;
249
250 // normals for the moment
251 Triple n, u, v;
252 for (i = 0; i < poly.size(); ++i) {
253 if (poly[i].size() < 3)
254 n = Triple(0, 0, 0);
255 else {
256 for (size_t j = 0; j < poly[i].size(); ++j) {
257 size_t jj = (j + 1) % poly[i].size();
258 size_t pjj = (j) ? j - 1 : poly[i].size() - 1;
259 u = actualDataC_->nodes[poly[i][jj]] - actualDataC_->nodes[poly[i][j]];
260 v = actualDataC_->nodes[poly[i][pjj]] - actualDataC_->nodes[poly[i][j]];
261 n = normalizedcross(u, v);
262 actualDataC_->normals[poly[i][j]] += n;
263 }
264 }
265 }
266 for (i = 0; i != actualDataC_->normals.size(); ++i) {
267 actualDataC_->normals[i].normalize();
268 }
269
270 ParallelEpiped hull(Triple(DBL_MAX, DBL_MAX, DBL_MAX), Triple(-DBL_MAX, -DBL_MAX, -DBL_MAX));
271
272 for (i = 0; i != data.size(); ++i) {
273 if (data[i].x < hull.minVertex.x)
274 hull.minVertex.x = data[i].x;
275 if (data[i].y < hull.minVertex.y)
276 hull.minVertex.y = data[i].y;
277 if (data[i].z < hull.minVertex.z)
278 hull.minVertex.z = data[i].z;
279
280 if (data[i].x > hull.maxVertex.x)
281 hull.maxVertex.x = data[i].x;
282 if (data[i].y > hull.maxVertex.y)
283 hull.maxVertex.y = data[i].y;
284 if (data[i].z > hull.maxVertex.z)
285 hull.maxVertex.z = data[i].z;
286 }
287
288 actualDataC_->setHull(hull);
289
290 updateData();
291 updateNormals();
292 createCoordinateSystem();
293
294 return true;
295 }
296