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 1 : OGRSUALayer::OGRSUALayer( VSILFILE* fp )
44 :
45 : {
46 1 : fpSUA = fp;
47 1 : nNextFID = 0;
48 1 : bEOF = FALSE;
49 1 : bHasLastLine = FALSE;
50 :
51 1 : poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
52 :
53 2 : poFeatureDefn = new OGRFeatureDefn( "layer" );
54 1 : poFeatureDefn->Reference();
55 1 : poFeatureDefn->SetGeomType( wkbPolygon );
56 :
57 1 : OGRFieldDefn oField1( "TYPE", OFTString);
58 1 : poFeatureDefn->AddFieldDefn( &oField1 );
59 1 : OGRFieldDefn oField2( "CLASS", OFTString);
60 1 : poFeatureDefn->AddFieldDefn( &oField2 );
61 1 : OGRFieldDefn oField3( "TITLE", OFTString);
62 1 : poFeatureDefn->AddFieldDefn( &oField3 );
63 1 : OGRFieldDefn oField4( "TOPS", OFTString);
64 1 : poFeatureDefn->AddFieldDefn( &oField4 );
65 1 : OGRFieldDefn oField5( "BASE", OFTString);
66 1 : poFeatureDefn->AddFieldDefn( &oField5 );
67 1 : }
68 :
69 : /************************************************************************/
70 : /* ~OGRSUALayer() */
71 : /************************************************************************/
72 :
73 1 : OGRSUALayer::~OGRSUALayer()
74 :
75 : {
76 1 : if( poSRS != NULL )
77 1 : poSRS->Release();
78 :
79 1 : poFeatureDefn->Release();
80 :
81 1 : VSIFCloseL( fpSUA );
82 1 : }
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 2 : OGRFeature *OGRSUALayer::GetNextFeature()
104 : {
105 : OGRFeature *poFeature;
106 :
107 0 : while(TRUE)
108 : {
109 2 : poFeature = GetNextRawFeature();
110 2 : if (poFeature == NULL)
111 0 : return NULL;
112 :
113 2 : if((m_poFilterGeom == NULL
114 : || FilterGeometry( poFeature->GetGeometryRef() ) )
115 : && (m_poAttrQuery == NULL
116 : || m_poAttrQuery->Evaluate( poFeature )) )
117 : {
118 2 : return poFeature;
119 : }
120 : else
121 0 : delete poFeature;
122 : }
123 : }
124 :
125 :
126 :
127 : /************************************************************************/
128 : /* GetLatLon() */
129 : /************************************************************************/
130 :
131 12 : static int GetLatLon(const char* pszStr, double& dfLat, double& dfLon)
132 : {
133 12 : if (pszStr[7] != ' ')
134 0 : return FALSE;
135 12 : if (pszStr[0] != 'N' && pszStr[0] != 'S')
136 0 : return FALSE;
137 12 : if (pszStr[8] != 'E' && pszStr[8] != 'W')
138 0 : return FALSE;
139 :
140 : char szDeg[4], szMin[3], szSec[3];
141 12 : szDeg[0] = pszStr[1];
142 12 : szDeg[1] = pszStr[2];
143 12 : szDeg[2] = 0;
144 12 : szMin[0] = pszStr[3];
145 12 : szMin[1] = pszStr[4];
146 12 : szMin[2] = 0;
147 12 : szSec[0] = pszStr[5];
148 12 : szSec[1] = pszStr[6];
149 12 : szSec[2] = 0;
150 :
151 12 : dfLat = atoi(szDeg) + atoi(szMin) / 60. + atoi(szSec) / 3600.;
152 12 : if (pszStr[0] == 'S')
153 12 : dfLat = -dfLat;
154 :
155 12 : szDeg[0] = pszStr[9];
156 12 : szDeg[1] = pszStr[10];
157 12 : szDeg[2] = pszStr[11];
158 12 : szDeg[3] = 0;
159 12 : szMin[0] = pszStr[12];
160 12 : szMin[1] = pszStr[13];
161 12 : szMin[2] = 0;
162 12 : szSec[0] = pszStr[14];
163 12 : szSec[1] = pszStr[15];
164 12 : szSec[2] = 0;
165 :
166 12 : dfLon = atoi(szDeg) + atoi(szMin) / 60. + atoi(szSec) / 3600.;
167 12 : if (pszStr[8] == 'W')
168 0 : dfLon = -dfLon;
169 :
170 12 : return TRUE;
171 : }
172 :
173 : /************************************************************************/
174 : /* GetNextRawFeature() */
175 : /************************************************************************/
176 :
177 2 : OGRFeature *OGRSUALayer::GetNextRawFeature()
178 : {
179 : const char* pszLine;
180 2 : CPLString osTYPE, osCLASS, osTITLE, osTOPS, osBASE;
181 2 : OGRLinearRing oLR;
182 2 : double dfLastLat = 0, dfLastLon = 0;
183 2 : int bFirst = TRUE;
184 :
185 2 : if (bEOF)
186 0 : return NULL;
187 :
188 84 : while(TRUE)
189 : {
190 88 : if (bFirst && bHasLastLine)
191 : {
192 2 : pszLine = osLastLine.c_str();
193 2 : bFirst = FALSE;
194 : }
195 : else
196 : {
197 84 : pszLine = CPLReadLine2L(fpSUA, 1024, NULL);
198 84 : if (pszLine == NULL)
199 : {
200 1 : bEOF = TRUE;
201 1 : if (oLR.getNumPoints() == 0)
202 0 : return NULL;
203 1 : break;
204 : }
205 83 : osLastLine = pszLine;
206 83 : bHasLastLine = TRUE;
207 : }
208 :
209 85 : if (pszLine[0] == '#' || pszLine[0] == '\0')
210 63 : continue;
211 :
212 22 : if (EQUALN(pszLine, "TYPE=", 5))
213 : {
214 3 : if (osTYPE.size() != 0)
215 1 : break;
216 2 : osTYPE = pszLine + 5;
217 : }
218 19 : else if (EQUALN(pszLine, "CLASS=", 6))
219 : {
220 0 : if (osCLASS.size() != 0)
221 0 : break;
222 0 : osCLASS = pszLine + 6;
223 : }
224 19 : else if (EQUALN(pszLine, "TITLE=", 6))
225 : {
226 2 : if (osTITLE.size() != 0)
227 0 : break;
228 2 : osTITLE = pszLine + 6;
229 : }
230 17 : else if (EQUALN(pszLine, "TOPS=", 5))
231 2 : osTOPS = pszLine + 5;
232 15 : else if (EQUALN(pszLine, "BASE=", 5))
233 2 : osBASE = pszLine + 5;
234 13 : else if (EQUALN(pszLine, "POINT=", 6))
235 : {
236 7 : pszLine += 6;
237 7 : if (strlen(pszLine) != 16)
238 0 : continue;
239 :
240 : double dfLat, dfLon;
241 7 : if (!GetLatLon(pszLine, dfLat, dfLon))
242 0 : continue;
243 :
244 7 : oLR.addPoint(dfLon, dfLat);
245 7 : dfLastLat = dfLat;
246 7 : dfLastLon = dfLon;
247 : }
248 8 : else if (EQUALN(pszLine, "CLOCKWISE", 9) || EQUALN(pszLine, "ANTI-CLOCKWISE", 14))
249 : {
250 2 : if (oLR.getNumPoints() == 0)
251 0 : continue;
252 :
253 2 : 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 2 : const char* pszCENTRE = strstr(pszLine, "CENTRE=");
261 2 : if (pszCENTRE == NULL)
262 0 : continue;
263 2 : pszCENTRE += 7;
264 2 : if (strlen(pszCENTRE) < 17 || pszCENTRE[16] != ' ')
265 0 : continue;
266 : double dfCenterLat, dfCenterLon;
267 2 : if (!GetLatLon(pszCENTRE, dfCenterLat, dfCenterLon))
268 0 : continue;
269 :
270 2 : const char* pszTO = strstr(pszLine, "TO=");
271 2 : if (pszTO == NULL)
272 0 : continue;
273 2 : pszTO += 3;
274 2 : if (strlen(pszTO) != 16)
275 0 : continue;
276 : double dfToLat, dfToLon;
277 2 : if (!GetLatLon(pszTO, dfToLat, dfToLon))
278 0 : continue;
279 :
280 2 : double dfStartDistance = OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
281 2 : double dfEndDistance = OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
282 2 : double dfStartAngle = OGRXPlane_Track(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
283 2 : double dfEndAngle = OGRXPlane_Track(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
284 4 : if (bClockWise && dfEndAngle < dfStartAngle)
285 2 : dfEndAngle += 360;
286 0 : else if (!bClockWise && dfStartAngle < dfEndAngle)
287 0 : dfEndAngle -= 360;
288 :
289 2 : int nSign = (bClockWise) ? 1 : -1;
290 : double dfAngle;
291 394 : for(dfAngle = dfStartAngle; (dfAngle - dfEndAngle) * nSign < 0; dfAngle += nSign)
292 : {
293 : double dfLat, dfLon;
294 392 : double pct = (dfAngle - dfStartAngle) / (dfEndAngle - dfStartAngle);
295 392 : double dfDist = dfStartDistance * (1-pct) + dfEndDistance * pct;
296 392 : OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfDist, dfAngle, &dfLat, &dfLon);
297 392 : oLR.addPoint(dfLon, dfLat);
298 : }
299 2 : oLR.addPoint(dfToLon, dfToLat);
300 :
301 2 : dfLastLat = oLR.getY(oLR.getNumPoints() - 1);
302 2 : dfLastLon = oLR.getX(oLR.getNumPoints() - 1);
303 : }
304 4 : else if (EQUALN(pszLine, "CIRCLE", 6))
305 : {
306 1 : const char* pszRADIUS = strstr(pszLine, "RADIUS=");
307 1 : if (pszRADIUS == NULL)
308 0 : continue;
309 1 : double dfRADIUS = atof(pszRADIUS + 7) * 1852;
310 :
311 1 : const char* pszCENTRE = strstr(pszLine, "CENTRE=");
312 1 : if (pszCENTRE == NULL)
313 0 : continue;
314 1 : pszCENTRE += 7;
315 1 : if (strlen(pszCENTRE) != 16)
316 0 : continue;
317 : double dfCenterLat, dfCenterLon;
318 1 : if (!GetLatLon(pszCENTRE, dfCenterLat, dfCenterLon))
319 0 : continue;
320 :
321 : double dfAngle;
322 : double dfLat, dfLon;
323 361 : for(dfAngle = 0; dfAngle < 360; dfAngle += 1)
324 : {
325 360 : OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfRADIUS, dfAngle, &dfLat, &dfLon);
326 360 : oLR.addPoint(dfLon, dfLat);
327 : }
328 1 : OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfRADIUS, 0, &dfLat, &dfLon);
329 1 : oLR.addPoint(dfLon, dfLat);
330 :
331 1 : dfLastLat = oLR.getY(oLR.getNumPoints() - 1);
332 1 : dfLastLon = oLR.getX(oLR.getNumPoints() - 1);
333 : }
334 3 : 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 2 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
344 4 : poFeature->SetField(0, osTYPE.c_str());
345 2 : poFeature->SetField(1, osCLASS.c_str());
346 2 : poFeature->SetField(2, osTITLE.c_str());
347 2 : poFeature->SetField(3, osTOPS.c_str());
348 2 : poFeature->SetField(4, osBASE.c_str());
349 :
350 2 : OGRPolygon* poPoly = new OGRPolygon();
351 2 : poPoly->assignSpatialReference(poSRS);
352 2 : oLR.closeRings();
353 2 : poPoly->addRing(&oLR);
354 2 : poFeature->SetGeometryDirectly(poPoly);
355 2 : poFeature->SetFID(nNextFID++);
356 :
357 2 : return poFeature;
358 : }
359 : /************************************************************************/
360 : /* TestCapability() */
361 : /************************************************************************/
362 :
363 0 : int OGRSUALayer::TestCapability( const char * pszCap )
364 :
365 : {
366 0 : return FALSE;
367 : }
368 :
|