1 : /******************************************************************************
2 : * $Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z rouault $
3 : *
4 : * Project: SEG-P1 / UKOOA P1-90 Translator
5 : * Purpose: Implements OGRUKOOAP190Layer class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, 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, DAMSEGUKOOAS 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_segukooa.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "ogr_p.h"
34 : #include "ogr_srs_api.h"
35 :
36 : CPL_CVSID("$Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z rouault $");
37 :
38 : /************************************************************************/
39 : /* ExtractField() */
40 : /************************************************************************/
41 :
42 135 : static void ExtractField(char* szField, const char* pszLine, int nOffset, int nLen)
43 : {
44 135 : memcpy(szField, pszLine + nOffset, nLen);
45 135 : szField[nLen] = '\0';
46 135 : }
47 :
48 : /************************************************************************/
49 : /* GetNextFeature() */
50 : /************************************************************************/
51 :
52 16 : OGRFeature *OGRSEGUKOOABaseLayer::GetNextFeature()
53 : {
54 : OGRFeature *poFeature;
55 :
56 0 : while(TRUE)
57 : {
58 16 : poFeature = GetNextRawFeature();
59 16 : if (poFeature == NULL)
60 2 : return NULL;
61 :
62 14 : if((m_poFilterGeom == NULL
63 : || FilterGeometry( poFeature->GetGeometryRef() ) )
64 : && (m_poAttrQuery == NULL
65 : || m_poAttrQuery->Evaluate( poFeature )) )
66 : {
67 14 : return poFeature;
68 : }
69 : else
70 0 : delete poFeature;
71 : }
72 : }
73 :
74 : /************************************************************************/
75 : /* OGRUKOOAP190Layer() */
76 : /************************************************************************/
77 :
78 : typedef struct
79 : {
80 : const char* pszName;
81 : OGRFieldType eType;
82 : } FieldDesc;
83 :
84 : static const FieldDesc UKOOAP190Fields[] =
85 : {
86 : { "LINENAME", OFTString },
87 : { "VESSEL_ID", OFTString },
88 : { "SOURCE_ID", OFTString },
89 : { "OTHER_ID", OFTString },
90 : { "POINTNUMBER", OFTInteger },
91 : { "LONGITUDE", OFTReal },
92 : { "LATITUDE", OFTReal },
93 : { "EASTING", OFTReal },
94 : { "NORTHING", OFTReal },
95 : { "DEPTH", OFTReal },
96 : { "DAYOFYEAR", OFTInteger },
97 : { "TIME", OFTTime },
98 : { "DATETIME", OFTDateTime }
99 : };
100 :
101 : #define FIELD_LINENAME 0
102 : #define FIELD_VESSEL_ID 1
103 : #define FIELD_SOURCE_ID 2
104 : #define FIELD_OTHER_ID 3
105 : #define FIELD_POINTNUMBER 4
106 : #define FIELD_LONGITUDE 5
107 : #define FIELD_LATITUDE 6
108 : #define FIELD_EASTING 7
109 : #define FIELD_NORTHING 8
110 : #define FIELD_DEPTH 9
111 : #define FIELD_DAYOFYEAR 10
112 : #define FIELD_TIME 11
113 : #define FIELD_DATETIME 12
114 :
115 4 : OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
116 4 : VSILFILE* fp )
117 :
118 : {
119 4 : this->fp = fp;
120 4 : nNextFID = 0;
121 4 : bEOF = FALSE;
122 4 : poSRS = NULL;
123 4 : nYear = 0;
124 :
125 4 : poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
126 4 : poFeatureDefn->Reference();
127 4 : poFeatureDefn->SetGeomType( wkbPoint );
128 :
129 56 : for(int i=0;i<(int)(sizeof(UKOOAP190Fields)/sizeof(UKOOAP190Fields[0]));i++)
130 : {
131 : OGRFieldDefn oField( UKOOAP190Fields[i].pszName,
132 52 : UKOOAP190Fields[i].eType );
133 52 : poFeatureDefn->AddFieldDefn( &oField );
134 : }
135 :
136 : bUseEastingNorthingAsGeometry =
137 4 : CSLTestBoolean(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
138 :
139 4 : ParseHeaders();
140 4 : }
141 :
142 : /************************************************************************/
143 : /* ~OGRUKOOAP190Layer() */
144 : /************************************************************************/
145 :
146 4 : OGRUKOOAP190Layer::~OGRUKOOAP190Layer()
147 :
148 : {
149 4 : poFeatureDefn->Release();
150 :
151 4 : VSIFCloseL( fp );
152 :
153 4 : if (poSRS)
154 4 : poSRS->Release();
155 4 : }
156 :
157 : /************************************************************************/
158 : /* ParseHeaders() */
159 : /************************************************************************/
160 :
161 52 : void OGRUKOOAP190Layer::ParseHeaders()
162 : {
163 48 : while(TRUE)
164 : {
165 52 : const char* pszLine = CPLReadLine2L(fp,81,NULL);
166 52 : if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
167 : {
168 0 : break;
169 : }
170 :
171 52 : int nLineLen = strlen(pszLine);
172 104 : while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
173 : {
174 0 : ((char*)pszLine)[nLineLen-1] = '\0';
175 0 : nLineLen --;
176 : }
177 :
178 52 : if (pszLine[0] != 'H')
179 4 : break;
180 :
181 48 : if (nLineLen < 33)
182 0 : continue;
183 :
184 52 : if (!bUseEastingNorthingAsGeometry &&
185 : strncmp(pszLine, "H1500", 5) == 0 && poSRS == NULL)
186 : {
187 8 : if (strncmp(pszLine + 33 - 1, "WGS84", 5) == 0 ||
188 : strncmp(pszLine + 33 - 1, "WGS-84", 6) == 0)
189 : {
190 4 : poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
191 : }
192 0 : else if (strncmp(pszLine + 33 - 1, "WGS72", 5) == 0)
193 : {
194 0 : poSRS = new OGRSpatialReference();
195 0 : poSRS->SetFromUserInput("WGS72");
196 : }
197 : }
198 44 : else if (!bUseEastingNorthingAsGeometry &&
199 : strncmp(pszLine, "H1501", 5) == 0 && poSRS != NULL &&
200 : nLineLen >= 32 + 6 * 6 + 10)
201 : {
202 : char aszParams[6][6+1];
203 : char szZ[10+1];
204 : int i;
205 0 : for(i=0;i<6;i++)
206 : {
207 0 : ExtractField(aszParams[i], pszLine, 33 - 1 + i * 6, 6);
208 : }
209 0 : ExtractField(szZ, pszLine, 33 - 1 + 6 * 6, 10);
210 : poSRS->SetTOWGS84(atof(aszParams[0]),
211 : atof(aszParams[1]),
212 : atof(aszParams[2]),
213 : atof(aszParams[3]),
214 : atof(aszParams[4]),
215 : atof(aszParams[5]),
216 0 : atof(szZ));
217 : }
218 44 : else if (strncmp(pszLine, "H0200", 5) == 0)
219 : {
220 4 : char** papszTokens = CSLTokenizeString(pszLine + 33 - 1);
221 16 : for(int i = 0; papszTokens[i] != NULL; i++)
222 : {
223 12 : if (strlen(papszTokens[i]) == 4)
224 : {
225 4 : int nVal = atoi(papszTokens[i]);
226 4 : if (nVal >= 1900)
227 : {
228 4 : if (nYear != 0 && nYear != nVal)
229 : {
230 : CPLDebug("SEGUKOOA",
231 0 : "Several years found in H0200. Ignoring them!");
232 0 : nYear = 0;
233 0 : break;
234 : }
235 4 : nYear = nVal;
236 : }
237 : }
238 : }
239 4 : CSLDestroy(papszTokens);
240 : }
241 : }
242 4 : VSIFSeekL( fp, 0, SEEK_SET );
243 4 : }
244 :
245 : /************************************************************************/
246 : /* ResetReading() */
247 : /************************************************************************/
248 :
249 0 : void OGRUKOOAP190Layer::ResetReading()
250 :
251 : {
252 0 : nNextFID = 0;
253 0 : bEOF = FALSE;
254 0 : VSIFSeekL( fp, 0, SEEK_SET );
255 0 : }
256 :
257 : /************************************************************************/
258 : /* GetNextRawFeature() */
259 : /************************************************************************/
260 :
261 6 : OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
262 : {
263 6 : if (bEOF)
264 0 : return NULL;
265 :
266 : const char* pszLine;
267 :
268 24 : while(TRUE)
269 : {
270 30 : pszLine = CPLReadLine2L(fp,81,NULL);
271 30 : if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
272 : {
273 1 : bEOF = TRUE;
274 1 : return NULL;
275 : }
276 :
277 29 : int nLineLen = strlen(pszLine);
278 58 : while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
279 : {
280 0 : ((char*)pszLine)[nLineLen-1] = '\0';
281 0 : nLineLen --;
282 : }
283 :
284 29 : if (pszLine[0] == 'H' || nLineLen < 46)
285 24 : continue;
286 :
287 5 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
288 5 : poFeature->SetFID(nNextFID ++);
289 :
290 : char szLineName[12 + 1];
291 5 : ExtractField(szLineName, pszLine, 2-1, 12);
292 5 : int i = 11;
293 23 : while (i >= 0)
294 : {
295 18 : if (szLineName[i] == ' ')
296 13 : szLineName[i] = '\0';
297 : else
298 5 : break;
299 13 : i --;
300 : }
301 5 : poFeature->SetField(FIELD_LINENAME, szLineName);
302 :
303 : char szVesselId[1+1];
304 5 : szVesselId[0] = pszLine[17-1];
305 5 : if (szVesselId[0] != ' ')
306 : {
307 0 : szVesselId[1] = '\0';
308 0 : poFeature->SetField(FIELD_VESSEL_ID, szVesselId);
309 : }
310 :
311 : char szSourceId[1+1];
312 5 : szSourceId[0] = pszLine[18-1];
313 5 : if (szSourceId[0] != ' ')
314 : {
315 0 : szSourceId[1] = '\0';
316 0 : poFeature->SetField(FIELD_SOURCE_ID, szSourceId);
317 : }
318 :
319 : char szOtherId[1+1];
320 5 : szOtherId[0] = pszLine[19-1];
321 5 : if (szOtherId[0] != ' ')
322 : {
323 0 : szOtherId[1] = '\0';
324 0 : poFeature->SetField(FIELD_OTHER_ID, szOtherId);
325 : }
326 :
327 : char szPointNumber[6+1];
328 5 : ExtractField(szPointNumber, pszLine, 20-1, 6);
329 5 : poFeature->SetField(4, atoi(szPointNumber));
330 :
331 : char szDeg[3+1];
332 : char szMin[2+1];
333 : char szSec[5+1];
334 :
335 5 : ExtractField(szDeg, pszLine, 26-1, 2);
336 5 : ExtractField(szMin, pszLine, 26+2-1, 2);
337 5 : ExtractField(szSec, pszLine, 26+2+2-1, 5);
338 5 : double dfLat = atoi(szDeg) + atoi(szMin) / 60.0 + atof(szSec) / 3600.0;
339 5 : if (pszLine[26+2+2+5-1] == 'S')
340 2 : dfLat = -dfLat;
341 5 : poFeature->SetField(FIELD_LATITUDE, dfLat);
342 :
343 5 : ExtractField(szDeg, pszLine, 36-1, 3);
344 5 : ExtractField(szMin, pszLine, 36+3-1, 2);
345 5 : ExtractField(szSec, pszLine, 36+3+2-1, 5);
346 5 : double dfLon = atoi(szDeg) + atoi(szMin) / 60.0 + atof(szSec) / 3600.0;
347 5 : if (pszLine[36+3+2+5-1] == 'W')
348 2 : dfLon = -dfLon;
349 5 : poFeature->SetField(FIELD_LONGITUDE, dfLon);
350 :
351 5 : OGRGeometry* poGeom = NULL;
352 5 : if (!bUseEastingNorthingAsGeometry)
353 5 : poGeom = new OGRPoint(dfLon, dfLat);
354 :
355 5 : if (nLineLen >= 64)
356 : {
357 : char szEasting[9+1];
358 5 : ExtractField(szEasting, pszLine, 47-1, 9);
359 5 : double dfEasting = atof(szEasting);
360 5 : poFeature->SetField(FIELD_EASTING, dfEasting);
361 :
362 : char szNorthing[9+1];
363 5 : ExtractField(szNorthing, pszLine, 56-1, 9);
364 5 : double dfNorthing = atof(szNorthing);
365 5 : poFeature->SetField(FIELD_NORTHING, dfNorthing);
366 :
367 5 : if (bUseEastingNorthingAsGeometry)
368 0 : poGeom = new OGRPoint(dfEasting, dfNorthing);
369 : }
370 :
371 5 : if (poGeom)
372 : {
373 5 : if (poSRS)
374 5 : poGeom->assignSpatialReference(poSRS);
375 5 : poFeature->SetGeometryDirectly(poGeom);
376 : }
377 :
378 5 : if (nLineLen >= 70)
379 : {
380 : char szDepth[6+1];
381 5 : ExtractField(szDepth, pszLine, 65-1, 6);
382 5 : double dfDepth = atof(szDepth);
383 5 : poFeature->SetField(FIELD_DEPTH, dfDepth);
384 : }
385 :
386 5 : int nDayOfYear = 0;
387 5 : if (nLineLen >= 73)
388 : {
389 : char szDayOfYear[3+1];
390 5 : ExtractField(szDayOfYear, pszLine, 71-1, 3);
391 5 : nDayOfYear = atoi(szDayOfYear);
392 5 : poFeature->SetField(FIELD_DAYOFYEAR, nDayOfYear);
393 : }
394 :
395 5 : if (nLineLen >= 79)
396 : {
397 : char szH[2+1], szM[2+1], szS[2+1];
398 5 : ExtractField(szH, pszLine, 74-1, 2);
399 5 : ExtractField(szM, pszLine, 74-1+2, 2);
400 5 : ExtractField(szS, pszLine, 74-1+2+2, 2);
401 5 : poFeature->SetField(FIELD_TIME, 0, 0, 0, atoi(szH), atoi(szM), atoi(szS) );
402 :
403 5 : if (nYear != 0)
404 : {
405 : #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
406 : static const int mon_lengths[2][12] = {
407 : {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
408 : {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
409 : } ;
410 5 : int bIsLeap = isleap(nYear);
411 5 : int nMonth = 0;
412 5 : int nDays = 0;
413 5 : if ((bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 366) ||
414 : (!bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 365))
415 : {
416 10 : while(nDayOfYear > nDays + mon_lengths[bIsLeap][nMonth])
417 : {
418 0 : nDays += mon_lengths[bIsLeap][nMonth];
419 0 : nMonth ++;
420 : }
421 5 : int nDayOfMonth = nDayOfYear - nDays;
422 5 : nMonth ++;
423 :
424 : poFeature->SetField(FIELD_DATETIME, nYear, nMonth, nDayOfMonth,
425 5 : atoi(szH), atoi(szM), atoi(szS) );
426 : }
427 :
428 : }
429 : }
430 :
431 5 : return poFeature;
432 : }
433 : }
434 :
435 : /************************************************************************/
436 : /* OGRSEGP1Layer() */
437 : /************************************************************************/
438 :
439 : static const FieldDesc SEGP1Fields[] =
440 : {
441 : { "LINENAME", OFTString },
442 : { "POINTNUMBER", OFTInteger },
443 : { "RESHOOTCODE", OFTString },
444 : { "LONGITUDE", OFTReal },
445 : { "LATITUDE", OFTReal },
446 : { "EASTING", OFTReal },
447 : { "NORTHING", OFTReal },
448 : { "DEPTH", OFTReal },
449 : #if 0
450 : { "YEAR", OFTInteger },
451 : { "DAYOFYEAR", OFTInteger },
452 : { "TIME", OFTTime },
453 : { "DATETIME", OFTDateTime }
454 : #endif
455 : };
456 :
457 : #define SEGP1_FIELD_LINENAME 0
458 : #define SEGP1_FIELD_POINTNUMBER 1
459 : #define SEGP1_FIELD_RESHOOTCODE 2
460 : #define SEGP1_FIELD_LONGITUDE 3
461 : #define SEGP1_FIELD_LATITUDE 4
462 : #define SEGP1_FIELD_EASTING 5
463 : #define SEGP1_FIELD_NORTHING 6
464 : #define SEGP1_FIELD_DEPTH 7
465 : #define SEGP1_FIELD_DAYOFYEAR 8
466 : #define SEGP1_FIELD_TIME 9
467 : #define SEGP1_FIELD_DATETIME 10
468 :
469 4 : OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
470 : VSILFILE* fp,
471 4 : int nLatitudeCol )
472 :
473 : {
474 4 : this->fp = fp;
475 4 : this->nLatitudeCol = nLatitudeCol;
476 4 : nNextFID = 0;
477 4 : bEOF = FALSE;
478 4 : poSRS = NULL;
479 :
480 4 : poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
481 4 : poFeatureDefn->Reference();
482 4 : poFeatureDefn->SetGeomType( wkbPoint );
483 :
484 36 : for(int i=0;i<(int)(sizeof(SEGP1Fields)/sizeof(SEGP1Fields[0]));i++)
485 : {
486 : OGRFieldDefn oField( SEGP1Fields[i].pszName,
487 32 : SEGP1Fields[i].eType );
488 32 : poFeatureDefn->AddFieldDefn( &oField );
489 : }
490 :
491 : bUseEastingNorthingAsGeometry =
492 4 : CSLTestBoolean(CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO"));
493 :
494 4 : ResetReading();
495 4 : }
496 :
497 : /************************************************************************/
498 : /* ~OGRSEGP1Layer() */
499 : /************************************************************************/
500 :
501 4 : OGRSEGP1Layer::~OGRSEGP1Layer()
502 :
503 : {
504 4 : poFeatureDefn->Release();
505 :
506 4 : VSIFCloseL( fp );
507 :
508 4 : if (poSRS)
509 0 : poSRS->Release();
510 4 : }
511 :
512 : /************************************************************************/
513 : /* ResetReading() */
514 : /************************************************************************/
515 :
516 4 : void OGRSEGP1Layer::ResetReading()
517 :
518 : {
519 4 : nNextFID = 0;
520 4 : bEOF = FALSE;
521 4 : VSIFSeekL( fp, 0, SEEK_SET );
522 :
523 : /* Skip first 20 header lines */
524 4 : const char* pszLine = NULL;
525 84 : for(int i=0; i<20;i++)
526 : {
527 80 : pszLine = CPLReadLine2L(fp,81,NULL);
528 80 : if (pszLine == NULL)
529 : {
530 0 : bEOF = TRUE;
531 0 : break;
532 : }
533 : }
534 4 : }
535 :
536 : /************************************************************************/
537 : /* GetNextRawFeature() */
538 : /************************************************************************/
539 :
540 6 : OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
541 : {
542 6 : if (bEOF)
543 0 : return NULL;
544 :
545 6 : const char* pszLine = NULL;
546 : while(TRUE)
547 : {
548 6 : pszLine = CPLReadLine2L(fp,81,NULL);
549 6 : if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
550 : {
551 1 : bEOF = TRUE;
552 1 : return NULL;
553 : }
554 :
555 5 : int nLineLen = strlen(pszLine);
556 10 : while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
557 : {
558 0 : ((char*)pszLine)[nLineLen-1] = '\0';
559 0 : nLineLen --;
560 : }
561 :
562 5 : char* pszExpandedLine = ExpandTabs(pszLine);
563 5 : pszLine = pszExpandedLine;
564 5 : nLineLen = strlen(pszLine);
565 :
566 5 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
567 5 : poFeature->SetFID(nNextFID ++);
568 :
569 5 : OGRGeometry* poGeom = NULL;
570 :
571 5 : if (nLatitudeCol-1 + 19 <= nLineLen)
572 : {
573 : char szDeg[3+1];
574 : char szMin[2+1];
575 : char szSec[4+1];
576 :
577 5 : ExtractField(szDeg, pszLine, nLatitudeCol-1, 2);
578 5 : ExtractField(szMin, pszLine, nLatitudeCol+2-1, 2);
579 5 : ExtractField(szSec, pszLine, nLatitudeCol+2+2-1, 4);
580 5 : double dfLat = atoi(szDeg) + atoi(szMin) / 60.0 + atoi(szSec) / 100.0 / 3600.0;
581 5 : if (pszLine[nLatitudeCol+2+2+4-1] == 'S')
582 2 : dfLat = -dfLat;
583 5 : poFeature->SetField(SEGP1_FIELD_LATITUDE, dfLat);
584 :
585 5 : ExtractField(szDeg, pszLine, nLatitudeCol+9-1, 3);
586 5 : ExtractField(szMin, pszLine, nLatitudeCol+9+3-1, 2);
587 5 : ExtractField(szSec, pszLine, nLatitudeCol+9+3+2-1, 4);
588 5 : double dfLon = atoi(szDeg) + atoi(szMin) / 60.0 + atoi(szSec) / 100.0 / 3600.0;
589 5 : if (pszLine[nLatitudeCol+9+3+2+4-1] == 'W')
590 2 : dfLon = -dfLon;
591 5 : poFeature->SetField(SEGP1_FIELD_LONGITUDE, dfLon);
592 :
593 5 : if (!bUseEastingNorthingAsGeometry)
594 5 : poGeom = new OGRPoint(dfLon, dfLat);
595 : }
596 :
597 : /* Normal layout -> extract other fields */
598 5 : if (nLatitudeCol == 27)
599 : {
600 : char szLineName[16 + 1];
601 5 : ExtractField(szLineName, pszLine, 2-1, 16);
602 5 : int i = 15;
603 43 : while (i >= 0)
604 : {
605 38 : if (szLineName[i] == ' ')
606 33 : szLineName[i] = '\0';
607 : else
608 5 : break;
609 33 : i --;
610 : }
611 5 : poFeature->SetField(SEGP1_FIELD_LINENAME, szLineName);
612 :
613 : char szPointNumber[8+1];
614 5 : ExtractField(szPointNumber, pszLine, 18-1, 8);
615 5 : poFeature->SetField(SEGP1_FIELD_POINTNUMBER, atoi(szPointNumber));
616 :
617 : char szReshootCode[1+1];
618 5 : ExtractField(szReshootCode, pszLine, 26-1, 1);
619 5 : poFeature->SetField(SEGP1_FIELD_RESHOOTCODE, szReshootCode);
620 :
621 5 : if (nLineLen >= 61)
622 : {
623 : char szEasting[8+1];
624 5 : ExtractField(szEasting, pszLine, 46-1, 8);
625 5 : double dfEasting = atof(szEasting);
626 5 : poFeature->SetField(SEGP1_FIELD_EASTING, dfEasting);
627 :
628 : char szNorthing[8+1];
629 5 : ExtractField(szNorthing, pszLine, 54-1, 8);
630 5 : double dfNorthing = atof(szNorthing);
631 5 : poFeature->SetField(SEGP1_FIELD_NORTHING, dfNorthing);
632 :
633 5 : if (bUseEastingNorthingAsGeometry)
634 0 : poGeom = new OGRPoint(dfEasting, dfNorthing);
635 : }
636 :
637 5 : if (nLineLen >= 66)
638 : {
639 : char szDepth[5+1];
640 5 : ExtractField(szDepth, pszLine, 62-1, 5);
641 5 : double dfDepth = atof(szDepth);
642 5 : poFeature->SetField(SEGP1_FIELD_DEPTH, dfDepth);
643 : }
644 : }
645 :
646 5 : if (poGeom)
647 : {
648 5 : if (poSRS)
649 0 : poGeom->assignSpatialReference(poSRS);
650 5 : poFeature->SetGeometryDirectly(poGeom);
651 : }
652 :
653 5 : CPLFree(pszExpandedLine);
654 :
655 5 : return poFeature;
656 : }
657 : }
658 :
659 : /************************************************************************/
660 : /* ExpandTabs() */
661 : /************************************************************************/
662 :
663 7 : char* OGRSEGP1Layer::ExpandTabs(const char* pszLine)
664 : {
665 7 : char* pszExpandedLine = (char*)CPLMalloc(strlen(pszLine) * 8 + 1);
666 7 : int j = 0;
667 469 : for(int i=0; pszLine[i] != '\0'; i++)
668 : {
669 : /* A tab must be space-expanded to reach the next column number */
670 : /* which is a multiple of 8 */
671 462 : if (pszLine[i] == 9)
672 : {
673 0 : do
674 : {
675 0 : pszExpandedLine[j ++] = ' ';
676 : } while ((j % 8) != 0);
677 : }
678 : else
679 462 : pszExpandedLine[j ++] = pszLine[i];
680 : }
681 7 : pszExpandedLine[j] = '\0';
682 :
683 7 : return pszExpandedLine;
684 : }
685 :
686 : /************************************************************************/
687 : /* DetectLatitudeColumn() */
688 : /************************************************************************/
689 :
690 : /* Some SEG-P1 files have unusual offsets for latitude/longitude, so */
691 : /* we try our best to identify it even in case of non-standard layout */
692 : /* Return non-0 if detection is successfull (column number starts at 1) */
693 :
694 2 : int OGRSEGP1Layer::DetectLatitudeColumn(const char* pszLine)
695 : {
696 2 : int nLen = strlen(pszLine);
697 6 : if (nLen >= 45 && pszLine[0] == ' ' &&
698 2 : (pszLine[35-1] == 'N' || pszLine[35-1] == 'S') &&
699 2 : (pszLine[45-1] == 'E' || pszLine[45-1] == 'W'))
700 2 : return 27;
701 :
702 0 : for(int i=8;i<nLen-10;i++)
703 : {
704 0 : if ((pszLine[i] == 'N' || pszLine[i] == 'S') &&
705 0 : (pszLine[i+10] == 'E' || pszLine[i+10] == 'W'))
706 0 : return i - 8 + 1;
707 : }
708 :
709 0 : return 0;
710 : }
711 :
712 :
713 : /************************************************************************/
714 : /* OGRSEGUKOOALineLayer() */
715 : /************************************************************************/
716 :
717 4 : OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
718 4 : OGRLayer *poBaseLayer)
719 : {
720 4 : nNextFID = 0;
721 4 : bEOF = FALSE;
722 :
723 : poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_lines",
724 4 : CPLGetBasename(pszFilename)) );
725 4 : poFeatureDefn->Reference();
726 4 : poFeatureDefn->SetGeomType( wkbLineString );
727 :
728 4 : OGRFieldDefn oField( "LINENAME", OFTString );
729 4 : poFeatureDefn->AddFieldDefn( &oField );
730 :
731 4 : this->poBaseLayer = poBaseLayer;
732 4 : poNextBaseFeature = NULL;
733 4 : }
734 :
735 : /************************************************************************/
736 : /* ~OGRSEGUKOOALineLayer() */
737 : /************************************************************************/
738 :
739 4 : OGRSEGUKOOALineLayer::~OGRSEGUKOOALineLayer()
740 : {
741 4 : delete poNextBaseFeature;
742 4 : delete poBaseLayer;
743 :
744 4 : poFeatureDefn->Release();
745 4 : }
746 :
747 : /************************************************************************/
748 : /* ResetReading() */
749 : /************************************************************************/
750 :
751 0 : void OGRSEGUKOOALineLayer::ResetReading()
752 :
753 : {
754 0 : nNextFID = 0;
755 0 : bEOF = FALSE;
756 0 : delete poNextBaseFeature;
757 0 : poNextBaseFeature = NULL;
758 0 : poBaseLayer->ResetReading();
759 0 : }
760 :
761 : /************************************************************************/
762 : /* GetNextRawFeature() */
763 : /************************************************************************/
764 :
765 4 : OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
766 : {
767 4 : if (bEOF)
768 0 : return NULL;
769 :
770 : /* Merge points of base layer that have same value for attribute(0) */
771 : /* into a single linestring */
772 :
773 4 : OGRFeature* poFeature = NULL;
774 4 : OGRLineString* poLS = NULL;
775 :
776 4 : if (poNextBaseFeature == NULL)
777 2 : poNextBaseFeature = poBaseLayer->GetNextFeature();
778 :
779 16 : while(poNextBaseFeature != NULL)
780 : {
781 20 : if (poNextBaseFeature->IsFieldSet(0) &&
782 10 : poNextBaseFeature->GetFieldAsString(0)[0] != '\0')
783 : {
784 10 : if (poFeature != NULL &&
785 : strcmp(poFeature->GetFieldAsString(0),
786 : poNextBaseFeature->GetFieldAsString(0)) != 0)
787 : {
788 2 : return poFeature;
789 : }
790 :
791 : OGRPoint* poPoint =
792 8 : (OGRPoint*) poNextBaseFeature->GetGeometryRef();
793 8 : if (poPoint != NULL)
794 : {
795 8 : if (poFeature == NULL)
796 : {
797 4 : poFeature = new OGRFeature(poFeatureDefn);
798 4 : poFeature->SetFID(nNextFID ++);
799 : poFeature->SetField(0,
800 4 : poNextBaseFeature->GetFieldAsString(0));
801 8 : poLS = new OGRLineString();
802 4 : if (poBaseLayer->GetSpatialRef())
803 : poLS->assignSpatialReference(
804 2 : poBaseLayer->GetSpatialRef());
805 4 : poFeature->SetGeometryDirectly(poLS);
806 : }
807 :
808 8 : poLS->addPoint(poPoint);
809 : }
810 : }
811 :
812 8 : delete poNextBaseFeature;
813 8 : poNextBaseFeature = poBaseLayer->GetNextFeature();
814 : }
815 :
816 2 : bEOF = TRUE;
817 2 : return poFeature;
818 : }
|