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