Remove elevation model. implemented correction adjustment using gui
[tecorrec.git] / geo / tcGlobe.cpp
blob8d59b5038c12fc4488b6a1dfc3a07f76a307e138
1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * Tecorrec is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * Tecorrec is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with Tecorrec. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 /**
21 * @file tcGlobe.cpp
22 * @brief Manages data for a globe.
25 #include "tcGlobe.h"
26 #include "tcPhotographyData.h"
27 #include "tcLandsatData.h"
28 #include "tcSrtmModel.h"
29 #include <glMatrix.h>
30 #include <glVector.h>
32 #include <GL/gl.h>
34 #include <cmath>
37 * Constructors + destructor
40 /// Primary constructor.
41 tcGlobe::tcGlobe(double meanRadius)
42 : m_meanRadius(meanRadius)
43 , m_elevation(new tcSrtmModel())
44 , m_data()
45 , m_elevationMode(RawElevation)
46 , m_elevationCorrection(0.0f)
48 addDataSet(new tcLandsatData("/home/james/cs/pro/data/LE71950281999206EDC01/"));
51 /// Destructor.
52 tcGlobe::~tcGlobe()
57 * Data sets
60 /// Add a dataset to the globe.
61 void tcGlobe::addDataSet(tcPhotographyData* data)
63 m_data.push_back(data);
67 * Rendering
70 /// Draw a line of latitude.
71 void tcGlobe::drawLineOfLatitude(double latitude) const
73 double z = sin(latitude) * m_meanRadius;
74 double xy = cos(latitude) * m_meanRadius;
75 glBegin(GL_LINE_LOOP);
77 for (int lon = 0; lon < 360; ++lon)
79 glVertex3d(xy*sin(M_PI/180*lon), xy*cos(M_PI/180*lon), z);
82 glEnd();
85 /// Render a cell.
86 void tcGlobe::renderCell(tcObserver* const observer, const tcGeo& swCorner, const tcGeo& neCorner) const
88 // Find the square distances to each corner
89 GLmat4d modelview;
90 glGetv(GL_MODELVIEW_MATRIX, &modelview);
91 tcGeo geoCorners[4] = {
92 tcGeo(swCorner.lon(), swCorner.lat()),
93 tcGeo(swCorner.lon(), neCorner.lat()),
94 tcGeo(neCorner.lon(), neCorner.lat()),
95 tcGeo(neCorner.lon(), swCorner.lat())
97 GLvec3d cartCorners[4];
98 float toCorners[4];
99 for (int i = 0; i < 4; ++i)
101 cartCorners[i] = (GLvec3d)geoCorners[i] * m_meanRadius;
102 toCorners[i] = (modelview*(cartCorners[i], 1.0)).slice<0,3>().sqr();
103 // Cull faces which are roughly backfacing
104 if ((modelview*(cartCorners[i], 0.0))[2] <= 0.0)
106 return;
110 // Decide whether to subdivide
111 float diagonal = (cartCorners[0]-cartCorners[2]).sqr()*4;
112 bool subdivide = true;
113 // If it is disproportionately tall, only subdivide horizontally
114 bool tall = (cartCorners[1] - cartCorners[0]) > (cartCorners[3] - cartCorners[0]).sqr()*4.0;
115 for (int i = 0; i < 4; ++i)
117 if (toCorners[i] > diagonal)
119 subdivide = false;
120 break;
124 if (subdivide)
126 glColor3f(0.0f, 0.0f, 1.0f);
128 else
130 glColor3f(1.0f, 0.5f, 0.0f);
133 #if 0
134 glBegin(GL_LINE_LOOP);
135 for (int i = 0; i < 4; ++i)
137 glVertex3(cartCorners[i]);
139 glEnd();
140 #endif
142 if (subdivide)
144 if (tall)
146 // bottom
147 renderCell(observer, geoCorners[0], (geoCorners[3] + geoCorners[2]) * 0.5);
148 // top
149 renderCell(observer, (geoCorners[0] + geoCorners[1]) * 0.5, geoCorners[2]);
151 else
153 // bottom left
154 renderCell(observer, geoCorners[0], (geoCorners[0] + geoCorners[2]) * 0.5);
155 // bottom right
156 renderCell(observer, (geoCorners[0] + geoCorners[3]) * 0.5, (geoCorners[3] + geoCorners[2]) * 0.5);
157 // top right
158 renderCell(observer, (geoCorners[0] + geoCorners[1]) * 0.5, (geoCorners[1] + geoCorners[2]) * 0.5);
159 // top right
160 renderCell(observer, (geoCorners[0] + geoCorners[2]) * 0.5, geoCorners[2]);
162 return;
165 // Render this cell
166 const int resolution = 32;
167 for (int i = 0; i < resolution; ++i)
169 glBegin(GL_TRIANGLE_STRIP);
171 for (int j = 0; j <= resolution; ++j)
173 for (int k = 0; k < 2; ++k)
175 double dlon = (neCorner.lon()-swCorner.lon()) / resolution;
176 double dlat = (neCorner.lat()-swCorner.lat()) / resolution;
177 tcGeo coord = swCorner + tcGeo((i+k) * dlon, j * dlat);
178 bool accurate = true;
179 double alt = 0.0;
180 switch (m_elevationMode)
182 case NoElevation:
184 // get accurate set
185 m_elevation->altitudeAt(coord, true, &accurate);
187 break;
188 case RawElevation:
190 alt = m_elevation->altitudeAt(coord, false, &accurate);
191 if (!accurate)
193 alt = 0.0;
196 break;
197 case CorrectedElevation:
199 // get accurate set
200 m_elevation->altitudeAt(coord, true, &accurate);
201 if (m_elevationCorrection <= 0.0f)
203 alt = m_elevation->altitudeAt(coord, false, 0);
205 else if (m_elevationCorrection >= 1.0f)
207 alt = m_elevation->altitudeAt(coord, true, 0);
209 else
211 double alt1 = m_elevation->altitudeAt(coord, false, 0);
212 double alt2 = m_elevation->altitudeAt(coord, true, 0);
213 alt = alt1*(1.0-m_elevationCorrection) + alt2*m_elevationCorrection;
216 break;
217 default:
218 break;
221 // Get colour
222 float intensity = 0.0;
223 foreach (tcPhotographyData* data, m_data)
225 intensity += data->sampleIntensity(coord);
228 if (!accurate)
230 glColor4f(intensity, intensity, intensity, 0.5f);
232 else
234 glColor4f(intensity, intensity, intensity, 1.0f);
235 //glColor4f(1.0f, 1.0f-(float)alt/3278.0f, 0.0f, 1.0f);
237 GLvec3d dir = coord;
238 double rad = m_meanRadius + alt;
239 glVertex3(dir * rad);
243 glEnd();
247 /// Render from the POV of an observer.
248 void tcGlobe::render(tcObserver* const observer)
250 /// @todo use a really simple fragment shader to cull backfacing lines
251 #if 1
252 // Lines of latitude
253 glColor3f(0.0f, 1.0f, 0.0f);
254 for (int lat = -75; lat <= 75; lat += 15)
256 if (lat != 0)
258 drawLineOfLatitude(M_PI/180*lat);
262 double tropic = (23.0 + 26.0/60 + 22.0/3600) * M_PI/180;
263 // Equator
264 glColor3f(1.0f, 0.0f, 0.0f);
265 drawLineOfLatitude(0.0);
266 // Tropics (Capricorn and Cancer)
267 glColor3f(1.0f, 0.0f, 1.0f);
268 drawLineOfLatitude(-tropic);
269 glColor3f(1.0f, 1.0f, 0.0f);
270 drawLineOfLatitude(+tropic);
271 // Arctic and Antarctic Circles
272 glColor3f(1.0f, 1.0f, 1.0f);
273 drawLineOfLatitude(+M_PI/2 - tropic);
274 drawLineOfLatitude(-M_PI/2 + tropic);
276 // Lines of longitude
277 for (int lon = 0; lon < 360; lon += 15)
279 double x = sin(M_PI/180*lon) * m_meanRadius;
280 double y = -cos(M_PI/180*lon) * m_meanRadius;
281 int minLat = 15;
282 int maxLat = 165;
283 if (lon % 180 == 0)
285 glLineWidth(2.0f);
286 glColor3f(1.0f, lon/180, 0.0f);
288 if (lon % 90 == 0)
290 minLat = 0;
291 maxLat = 180;
293 glBegin(GL_LINE_STRIP);
295 for (int lat = minLat; lat <= maxLat; ++lat)
297 double z = cos(M_PI/180*lat) * m_meanRadius;
298 double xy = sin(M_PI/180*lat);
299 glVertex3d(xy*x, xy*y, z);
302 glEnd();
303 if (lon % 180 == 0)
305 glLineWidth(1.0f);
306 glColor3f(0.0f, 1.0f, 0.0f);
309 #endif
311 // Draw data diagramatically
312 foreach (tcPhotographyData* data, m_data)
314 data->renderSchematic(m_meanRadius, observer);
317 // Go through cells
318 const int dlon = 30;
319 const int dlat = 30;
320 for (int lon = -180; lon < 180; lon += dlon)
322 for (int lat = -90; lat < 90; lat += dlat)
324 tcGeo sw(M_PI/180 * (lon), M_PI/180 * (lat));
325 tcGeo ne(M_PI/180 * (lon+dlon), M_PI/180 * (lat+dlat));
326 renderCell(observer, sw, ne);
331 /// Set the elevation mode to render in.
332 void tcGlobe::setElevationMode(ElevationMode mode)
334 m_elevationMode = mode;
337 /// Set the level of correction to show.
338 void tcGlobe::setElevationCorrection(float correction)
340 m_elevationCorrection = correction;
344 * Accessors
347 /// Get the mean radius.
348 double tcGlobe::meanRadius() const
350 return m_meanRadius;