Loading of landsat meta data file and coordinates, displays schematic cuboid
[tecorrec.git] / geo / tcGlobe.cpp
blob8886cccdd7398a45be0aa8ff03d706b2a54a3ff8
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()
46 addDataSet(new tcLandsatData("/home/james/cs/pro/data/LE71950281999206EDC01/"));
49 /// Destructor.
50 tcGlobe::~tcGlobe()
55 * Data sets
58 /// Add a dataset to the globe.
59 void tcGlobe::addDataSet(tcPhotographyData* data)
61 m_data.push_back(data);
65 * Rendering
68 /// Draw a line of latitude.
69 void tcGlobe::drawLineOfLatitude(double latitude) const
71 double z = sin(latitude) * m_meanRadius;
72 double xy = cos(latitude) * m_meanRadius;
73 glBegin(GL_LINE_LOOP);
75 for (int lon = 0; lon < 360; ++lon)
77 glVertex3d(xy*sin(M_PI/180*lon), xy*cos(M_PI/180*lon), z);
80 glEnd();
83 /// Render a cell.
84 void tcGlobe::renderCell(tcObserver* const observer, const tcGeo& swCorner, const tcGeo& neCorner) const
86 // Find the square distances to each corner
87 GLmat4d modelview;
88 glGetv(GL_MODELVIEW_MATRIX, &modelview);
89 tcGeo geoCorners[4] = {
90 tcGeo(swCorner.lon(), swCorner.lat()),
91 tcGeo(swCorner.lon(), neCorner.lat()),
92 tcGeo(neCorner.lon(), neCorner.lat()),
93 tcGeo(neCorner.lon(), swCorner.lat())
95 GLvec3d cartCorners[4];
96 float toCorners[4];
97 for (int i = 0; i < 4; ++i)
99 cartCorners[i] = (GLvec3d)geoCorners[i] * m_meanRadius;
100 toCorners[i] = (modelview*(cartCorners[i], 1.0)).slice<0,3>().sqr();
101 // Cull faces which are roughly backfacing
102 if ((modelview*(cartCorners[i], 0.0))[2] <= 0.0)
104 return;
108 // Decide whether to subdivide
109 float diagonal = (cartCorners[0]-cartCorners[2]).sqr()*4;
110 bool subdivide = true;
111 // If it is disproportionately tall, only subdivide horizontally
112 bool tall = (cartCorners[1] - cartCorners[0]) > (cartCorners[3] - cartCorners[0]).sqr()*4.0;
113 for (int i = 0; i < 4; ++i)
115 if (toCorners[i] > diagonal)
117 subdivide = false;
118 break;
122 if (subdivide)
124 glColor3f(0.0f, 0.0f, 1.0f);
126 else
128 glColor3f(1.0f, 0.5f, 0.0f);
131 #if 0
132 glBegin(GL_LINE_LOOP);
133 for (int i = 0; i < 4; ++i)
135 glVertex3(cartCorners[i]);
137 glEnd();
138 #endif
140 if (subdivide)
142 if (tall)
144 // bottom
145 renderCell(observer, geoCorners[0], (geoCorners[3] + geoCorners[2]) * 0.5);
146 // top
147 renderCell(observer, (geoCorners[0] + geoCorners[1]) * 0.5, geoCorners[2]);
149 else
151 // bottom left
152 renderCell(observer, geoCorners[0], (geoCorners[0] + geoCorners[2]) * 0.5);
153 // bottom right
154 renderCell(observer, (geoCorners[0] + geoCorners[3]) * 0.5, (geoCorners[3] + geoCorners[2]) * 0.5);
155 // top right
156 renderCell(observer, (geoCorners[0] + geoCorners[1]) * 0.5, (geoCorners[1] + geoCorners[2]) * 0.5);
157 // top right
158 renderCell(observer, (geoCorners[0] + geoCorners[2]) * 0.5, geoCorners[2]);
160 return;
163 // Render this cell
164 const int resolution = 16;
165 for (int i = 0; i < resolution; ++i)
167 glBegin(GL_TRIANGLE_STRIP);
169 for (int j = 0; j <= resolution; ++j)
171 for (int k = 0; k < 2; ++k)
173 double dlon = (neCorner.lon()-swCorner.lon()) / resolution;
174 double dlat = (neCorner.lat()-swCorner.lat()) / resolution;
175 tcGeo coord = swCorner + tcGeo((i+k) * dlon, j * dlat);
176 bool accurate = false;
177 double alt = m_elevation->altitudeAt(coord, &accurate);
178 if (!accurate)
180 glColor4f(0.0f, 0.0f, 0.5f, 0.5f);
182 else
184 glColor4f(1.0f, 1.0f-(float)alt/3278.0f, 0.0f, 1.0f);
186 GLvec3d dir = coord;
187 double rad = m_meanRadius + alt;
188 glVertex3(dir * rad);
192 glEnd();
196 /// Render from the POV of an observer.
197 void tcGlobe::render(tcObserver* const observer)
199 /// @todo use a really simple fragment shader to cull backfacing lines
200 #if 1
201 // Lines of latitude
202 glColor3f(0.0f, 1.0f, 0.0f);
203 for (int lat = -75; lat <= 75; lat += 15)
205 if (lat != 0)
207 drawLineOfLatitude(M_PI/180*lat);
211 double tropic = (23.0 + 26.0/60 + 22.0/3600) * M_PI/180;
212 // Equator
213 glColor3f(1.0f, 0.0f, 0.0f);
214 drawLineOfLatitude(0.0);
215 // Tropics (Capricorn and Cancer)
216 glColor3f(1.0f, 0.0f, 1.0f);
217 drawLineOfLatitude(-tropic);
218 glColor3f(1.0f, 1.0f, 0.0f);
219 drawLineOfLatitude(+tropic);
220 // Arctic and Antarctic Circles
221 glColor3f(1.0f, 1.0f, 1.0f);
222 drawLineOfLatitude(+M_PI/2 - tropic);
223 drawLineOfLatitude(-M_PI/2 + tropic);
225 // Lines of longitude
226 for (int lon = 0; lon < 360; lon += 15)
228 double x = sin(M_PI/180*lon) * m_meanRadius;
229 double y = -cos(M_PI/180*lon) * m_meanRadius;
230 int minLat = 15;
231 int maxLat = 165;
232 if (lon % 180 == 0)
234 glLineWidth(2.0f);
235 glColor3f(1.0f, lon/180, 0.0f);
237 if (lon % 90 == 0)
239 minLat = 0;
240 maxLat = 180;
242 glBegin(GL_LINE_STRIP);
244 for (int lat = minLat; lat <= maxLat; ++lat)
246 double z = cos(M_PI/180*lat) * m_meanRadius;
247 double xy = sin(M_PI/180*lat);
248 glVertex3d(xy*x, xy*y, z);
251 glEnd();
252 if (lon % 180 == 0)
254 glLineWidth(1.0f);
255 glColor3f(0.0f, 1.0f, 0.0f);
258 #endif
260 // Draw data diagramatically
261 foreach (tcPhotographyData* data, m_data)
263 data->renderSchematic(m_meanRadius, observer);
266 // Go through cells
267 const int dlon = 30;
268 const int dlat = 30;
269 for (int lon = -180; lon < 180; lon += dlon)
271 for (int lat = -90; lat < 90; lat += dlat)
273 tcGeo sw(M_PI/180 * (lon), M_PI/180 * (lat));
274 tcGeo ne(M_PI/180 * (lon+dlon), M_PI/180 * (lat+dlat));
275 renderCell(observer, sw, ne);
281 * Accessors
284 /// Get the mean radius.
285 double tcGlobe::meanRadius() const
287 return m_meanRadius;