1 : /******************************************************************************
2 : * $Id: ogrsualayer.cpp 23066 2011-09-05 21:10:19Z rouault $
3 : *
4 : * Project: SUA Translator
5 : * Purpose: Implements OGRSUALayer class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_sua.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "ogr_p.h"
34 : #include "ogr_xplane_geo_utils.h"
35 : #include "ogr_srs_api.h"
36 :
37 : CPL_CVSID("$Id: ogrsualayer.cpp 23066 2011-09-05 21:10:19Z rouault $");
38 :
39 : /************************************************************************/
40 : /* OGRSUALayer() */
41 : /************************************************************************/
42 :
43 2 : OGRSUALayer::OGRSUALayer( VSILFILE* fp )
44 :
45 : {
46 2 : fpSUA = fp;
47 2 : nNextFID = 0;
48 2 : bEOF = FALSE;
49 2 : bHasLastLine = FALSE;
50 :
51 2 : poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
52 :
53 4 : poFeatureDefn = new OGRFeatureDefn( "layer" );
54 2 : poFeatureDefn->Reference();
55 2 : poFeatureDefn->SetGeomType( wkbPolygon );
56 :
57 2 : OGRFieldDefn oField1( "TYPE", OFTString);
58 2 : poFeatureDefn->AddFieldDefn( &oField1 );
59 2 : OGRFieldDefn oField2( "CLASS", OFTString);
60 2 : poFeatureDefn->AddFieldDefn( &oField2 );
61 2 : OGRFieldDefn oField3( "TITLE", OFTString);
62 2 : poFeatureDefn->AddFieldDefn( &oField3 );
63 2 : OGRFieldDefn oField4( "TOPS", OFTString);
64 2 : poFeatureDefn->AddFieldDefn( &oField4 );
65 2 : OGRFieldDefn oField5( "BASE", OFTString);
66 2 : poFeatureDefn->AddFieldDefn( &oField5 );
67 2 : }
68 :
69 : /************************************************************************/
70 : /* ~OGRSUALayer() */
71 : /************************************************************************/
72 :
73 2 : OGRSUALayer::~OGRSUALayer()
74 :
75 : {
76 2 : if( poSRS != NULL )
77 2 : poSRS->Release();
78 :
79 2 : poFeatureDefn->Release();
80 :
81 2 : VSIFCloseL( fpSUA );
82 2 : }
83 :
84 :
85 : /************************************************************************/
86 : /* ResetReading() */
87 : /************************************************************************/
88 :
89 0 : void OGRSUALayer::ResetReading()
90 :
91 : {
92 0 : nNextFID = 0;
93 0 : bEOF = FALSE;
94 0 : bHasLastLine = FALSE;
95 0 : VSIFSeekL( fpSUA, 0, SEEK_SET );
96 0 : }
97 :
98 :
99 : /************************************************************************/
100 : /* GetNextFeature() */
101 : /************************************************************************/
102 :
103 4 : OGRFeature *OGRSUALayer::GetNextFeature()
104 : {
105 : OGRFeature *poFeature;
106 :
107 0 : while(TRUE)
108 : {
109 4 : poFeature = GetNextRawFeature();
110 4 : if (poFeature == NULL)
111 0 : return NULL;
112 :
113 4 : if((m_poFilterGeom == NULL
114 : || FilterGeometry( poFeature->GetGeometryRef() ) )
115 : && (m_poAttrQuery == NULL
116 : || m_poAttrQuery->Evaluate( poFeature )) )
117 : {
118 4 : return poFeature;
119 : }
120 : else
121 0 : delete poFeature;
122 : }
123 : }
124 :
125 :
126 :
127 : /************************************************************************/
128 : /* GetLatLon() */
129 : /************************************************************************/
130 :
131 24 : static int GetLatLon(const char* pszStr, double& dfLat, double& dfLon)
132 : {
133 24 : if (pszStr[7] != ' ')
134 0 : return FALSE;
135 24 : if (pszStr[0] != 'N' && pszStr[0] != 'S')
136 0 : return FALSE;
137 24 : if (pszStr[8] != 'E' && pszStr[8] != 'W')
138 0 : return FALSE;
139 :
140 : char szDeg[4], szMin[3], szSec[3];
141 24 : szDeg[0] = pszStr[1];
142 24 : szDeg[1] = pszStr[2];
143 24 : szDeg[2] = 0;
144 24 : szMin[0] = pszStr[3];
145 24 : szMin[1] = pszStr[4];
146 24 : szMin[2] = 0;
147 24 : szSec[0] = pszStr[5];
148 24 : szSec[1] = pszStr[6];
149 24 : szSec[2] = 0;
150 :
151 24 : dfLat = atoi(szDeg) + atoi(szMin) / 60. + atoi(szSec) / 3600.;
152 24 : if (pszStr[0] == 'S')
153 24 : dfLat = -dfLat;
154 :
155 24 : szDeg[0] = pszStr[9];
156 24 : szDeg[1] = pszStr[10];
157 24 : szDeg[2] = pszStr[11];
158 24 : szDeg[3] = 0;
159 24 : szMin[0] = pszStr[12];
160 24 : szMin[1] = pszStr[13];
161 24 : szMin[2] = 0;
162 24 : szSec[0] = pszStr[14];
163 24 : szSec[1] = pszStr[15];
164 24 : szSec[2] = 0;
165 :
166 24 : dfLon = atoi(szDeg) + atoi(szMin) / 60. + atoi(szSec) / 3600.;
167 24 : if (pszStr[8] == 'W')
168 0 : dfLon = -dfLon;
169 :
170 24 : return TRUE;
171 : }
172 :
173 : /************************************************************************/
174 : /* GetNextRawFeature() */
175 : /************************************************************************/
176 :
177 4 : OGRFeature *OGRSUALayer::GetNextRawFeature()
178 : {
179 : const char* pszLine;
180 4 : CPLString osTYPE, osCLASS, osTITLE, osTOPS, osBASE;
181 4 : OGRLinearRing oLR;
182 4 : double dfLastLat = 0, dfLastLon = 0;
183 4 : int bFirst = TRUE;
184 :
185 4 : if (bEOF)
186 0 : return NULL;
187 :
188 168 : while(TRUE)
189 : {
190 176 : if (bFirst && bHasLastLine)
191 : {
192 4 : pszLine = osLastLine.c_str();
193 4 : bFirst = FALSE;
194 : }
195 : else
196 : {
197 168 : pszLine = CPLReadLine2L(fpSUA, 1024, NULL);
198 168 : if (pszLine == NULL)
199 : {
200 2 : bEOF = TRUE;
201 2 : if (oLR.getNumPoints() == 0)
202 0 : return NULL;
203 2 : break;
204 : }
205 166 : osLastLine = pszLine;
206 166 : bHasLastLine = TRUE;
207 : }
208 :
209 170 : if (pszLine[0] == '#' || pszLine[0] == '\0')
210 126 : continue;
211 :
212 44 : if (EQUALN(pszLine, "TYPE=", 5))
213 : {
214 6 : if (osTYPE.size() != 0)
215 2 : break;
216 4 : osTYPE = pszLine + 5;
217 : }
218 38 : else if (EQUALN(pszLine, "CLASS=", 6))
219 : {
220 0 : if (osCLASS.size() != 0)
221 0 : break;
222 0 : osCLASS = pszLine + 6;
223 : }
224 38 : else if (EQUALN(pszLine, "TITLE=", 6))
225 : {
226 4 : if (osTITLE.size() != 0)
227 0 : break;
228 4 : osTITLE = pszLine + 6;
229 : }
230 34 : else if (EQUALN(pszLine, "TOPS=", 5))
231 4 : osTOPS = pszLine + 5;
232 30 : else if (EQUALN(pszLine, "BASE=", 5))
233 4 : osBASE = pszLine + 5;
234 26 : else if (EQUALN(pszLine, "POINT=", 6))
235 : {
236 14 : pszLine += 6;
237 14 : if (strlen(pszLine) != 16)
238 0 : continue;
239 :
240 : double dfLat, dfLon;
241 14 : if (!GetLatLon(pszLine, dfLat, dfLon))
242 0 : continue;
243 :
244 14 : oLR.addPoint(dfLon, dfLat);
245 14 : dfLastLat = dfLat;
246 14 : dfLastLon = dfLon;
247 : }
248 16 : else if (EQUALN(pszLine, "CLOCKWISE", 9) || EQUALN(pszLine, "ANTI-CLOCKWISE", 14))
249 : {
250 4 : if (oLR.getNumPoints() == 0)
251 0 : continue;
252 :
253 4 : int bClockWise = EQUALN(pszLine, "CLOCKWISE", 9);
254 :
255 : /*const char* pszRADIUS = strstr(pszLine, "RADIUS=");
256 : if (pszRADIUS == NULL)
257 : continue;
258 : double dfRADIUS = atof(pszRADIUS + 7) * 1852;*/
259 :
260 4 : const char* pszCENTRE = strstr(pszLine, "CENTRE=");
261 4 : if (pszCENTRE == NULL)
262 0 : continue;
263 4 : pszCENTRE += 7;
264 4 : if (strlen(pszCENTRE) < 17 || pszCENTRE[16] != ' ')
265 0 : continue;
266 : double dfCenterLat, dfCenterLon;
267 4 : if (!GetLatLon(pszCENTRE, dfCenterLat, dfCenterLon))
268 0 : continue;
269 :
270 4 : const char* pszTO = strstr(pszLine, "TO=");
271 4 : if (pszTO == NULL)
272 0 : continue;
273 4 : pszTO += 3;
274 4 : if (strlen(pszTO) != 16)
275 0 : continue;
276 : double dfToLat, dfToLon;
277 4 : if (!GetLatLon(pszTO, dfToLat, dfToLon))
278 0 : continue;
279 :
280 4 : double dfStartDistance = OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
281 4 : double dfEndDistance = OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
282 4 : double dfStartAngle = OGRXPlane_Track(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
283 4 : double dfEndAngle = OGRXPlane_Track(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
284 8 : if (bClockWise && dfEndAngle < dfStartAngle)
285 4 : dfEndAngle += 360;
286 0 : else if (!bClockWise && dfStartAngle < dfEndAngle)
287 0 : dfEndAngle -= 360;
288 :
289 4 : int nSign = (bClockWise) ? 1 : -1;
290 : double dfAngle;
291 788 : for(dfAngle = dfStartAngle; (dfAngle - dfEndAngle) * nSign < 0; dfAngle += nSign)
292 : {
293 : double dfLat, dfLon;
294 784 : double pct = (dfAngle - dfStartAngle) / (dfEndAngle - dfStartAngle);
295 784 : double dfDist = dfStartDistance * (1-pct) + dfEndDistance * pct;
296 784 : OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfDist, dfAngle, &dfLat, &dfLon);
297 784 : oLR.addPoint(dfLon, dfLat);
298 : }
299 4 : oLR.addPoint(dfToLon, dfToLat);
300 :
301 4 : dfLastLat = oLR.getY(oLR.getNumPoints() - 1);
302 4 : dfLastLon = oLR.getX(oLR.getNumPoints() - 1);
303 : }
304 8 : else if (EQUALN(pszLine, "CIRCLE", 6))
305 : {
306 2 : const char* pszRADIUS = strstr(pszLine, "RADIUS=");
307 2 : if (pszRADIUS == NULL)
308 0 : continue;
309 2 : double dfRADIUS = atof(pszRADIUS + 7) * 1852;
310 :
311 2 : const char* pszCENTRE = strstr(pszLine, "CENTRE=");
312 2 : if (pszCENTRE == NULL)
313 0 : continue;
314 2 : pszCENTRE += 7;
315 2 : if (strlen(pszCENTRE) != 16)
316 0 : continue;
317 : double dfCenterLat, dfCenterLon;
318 2 : if (!GetLatLon(pszCENTRE, dfCenterLat, dfCenterLon))
319 0 : continue;
320 :
321 : double dfAngle;
322 : double dfLat, dfLon;
323 722 : for(dfAngle = 0; dfAngle < 360; dfAngle += 1)
324 : {
325 720 : OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfRADIUS, dfAngle, &dfLat, &dfLon);
326 720 : oLR.addPoint(dfLon, dfLat);
327 : }
328 2 : OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfRADIUS, 0, &dfLat, &dfLon);
329 2 : oLR.addPoint(dfLon, dfLat);
330 :
331 2 : dfLastLat = oLR.getY(oLR.getNumPoints() - 1);
332 2 : dfLastLon = oLR.getX(oLR.getNumPoints() - 1);
333 : }
334 6 : else if (EQUALN(pszLine, "INCLUDE", 7) || EQUALN(pszLine, "END", 3))
335 : {
336 : }
337 : else
338 : {
339 0 : CPLDebug("SUA", "Unexpected content : %s", pszLine);
340 : }
341 : }
342 :
343 4 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
344 8 : poFeature->SetField(0, osTYPE.c_str());
345 4 : poFeature->SetField(1, osCLASS.c_str());
346 4 : poFeature->SetField(2, osTITLE.c_str());
347 4 : poFeature->SetField(3, osTOPS.c_str());
348 4 : poFeature->SetField(4, osBASE.c_str());
349 :
350 4 : OGRPolygon* poPoly = new OGRPolygon();
351 4 : poPoly->assignSpatialReference(poSRS);
352 4 : oLR.closeRings();
353 4 : poPoly->addRing(&oLR);
354 4 : poFeature->SetGeometryDirectly(poPoly);
355 4 : poFeature->SetFID(nNextFID++);
356 :
357 4 : return poFeature;
358 : }
359 : /************************************************************************/
360 : /* TestCapability() */
361 : /************************************************************************/
362 :
363 0 : int OGRSUALayer::TestCapability( const char * pszCap )
364 :
365 : {
366 0 : return FALSE;
367 : }
368 :
|