1
/******************************************************************************
2
* $Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z rouault $
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>
8
******************************************************************************
9
* Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
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:
18
* The above copyright notice and this permission notice shall be included
19
* in all copies or substantial portions of the Software.
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
****************************************************************************/
30
#include "ogr_segukooa.h"
32
#include "cpl_string.h"
34
#include "ogr_srs_api.h"
36
CPL_CVSID("$Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z rouault $");
38
/************************************************************************/
40
/************************************************************************/
42
static void ExtractField(char* szField, const char* pszLine, int nOffset, int nLen)
44
memcpy(szField, pszLine + nOffset, nLen);
48
/************************************************************************/
49
/* GetNextFeature() */
50
/************************************************************************/
52
OGRFeature *OGRSEGUKOOABaseLayer::GetNextFeature()
54
OGRFeature *poFeature;
58
poFeature = GetNextRawFeature();
59
if (poFeature == NULL)
62
if((m_poFilterGeom == NULL
63
|| FilterGeometry( poFeature->GetGeometryRef() ) )
64
&& (m_poAttrQuery == NULL
65
|| m_poAttrQuery->Evaluate( poFeature )) )
74
/************************************************************************/
75
/* OGRUKOOAP190Layer() */
76
/************************************************************************/
84
static const FieldDesc UKOOAP190Fields[] =
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 },
96
{ "DAYOFYEAR", OFTInteger },
98
{ "DATETIME", OFTDateTime }
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
115
OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
125
poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
126
poFeatureDefn->Reference();
127
poFeatureDefn->SetGeomType( wkbPoint );
129
for(int i=0;i<(int)(sizeof(UKOOAP190Fields)/sizeof(UKOOAP190Fields[0]));i++)
131
OGRFieldDefn oField( UKOOAP190Fields[i].pszName,
132
UKOOAP190Fields[i].eType );
133
poFeatureDefn->AddFieldDefn( &oField );
136
bUseEastingNorthingAsGeometry =
137
CSLTestBoolean(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
142
/************************************************************************/
143
/* ~OGRUKOOAP190Layer() */
144
/************************************************************************/
146
OGRUKOOAP190Layer::~OGRUKOOAP190Layer()
149
poFeatureDefn->Release();
157
/************************************************************************/
159
/************************************************************************/
161
void OGRUKOOAP190Layer::ParseHeaders()
165
const char* pszLine = CPLReadLine2L(fp,81,NULL);
166
if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
171
int nLineLen = strlen(pszLine);
172
while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
174
((char*)pszLine)[nLineLen-1] = '\0';
178
if (pszLine[0] != 'H')
184
if (!bUseEastingNorthingAsGeometry &&
185
strncmp(pszLine, "H1500", 5) == 0 && poSRS == NULL)
187
if (strncmp(pszLine + 33 - 1, "WGS84", 5) == 0 ||
188
strncmp(pszLine + 33 - 1, "WGS-84", 6) == 0)
190
poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
192
else if (strncmp(pszLine + 33 - 1, "WGS72", 5) == 0)
194
poSRS = new OGRSpatialReference();
195
poSRS->SetFromUserInput("WGS72");
198
else if (!bUseEastingNorthingAsGeometry &&
199
strncmp(pszLine, "H1501", 5) == 0 && poSRS != NULL &&
200
nLineLen >= 32 + 6 * 6 + 10)
202
char aszParams[6][6+1];
207
ExtractField(aszParams[i], pszLine, 33 - 1 + i * 6, 6);
209
ExtractField(szZ, pszLine, 33 - 1 + 6 * 6, 10);
210
poSRS->SetTOWGS84(atof(aszParams[0]),
218
else if (strncmp(pszLine, "H0200", 5) == 0)
220
char** papszTokens = CSLTokenizeString(pszLine + 33 - 1);
221
for(int i = 0; papszTokens[i] != NULL; i++)
223
if (strlen(papszTokens[i]) == 4)
225
int nVal = atoi(papszTokens[i]);
228
if (nYear != 0 && nYear != nVal)
231
"Several years found in H0200. Ignoring them!");
239
CSLDestroy(papszTokens);
242
VSIFSeekL( fp, 0, SEEK_SET );
245
/************************************************************************/
247
/************************************************************************/
249
void OGRUKOOAP190Layer::ResetReading()
254
VSIFSeekL( fp, 0, SEEK_SET );
257
/************************************************************************/
258
/* GetNextRawFeature() */
259
/************************************************************************/
261
OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
270
pszLine = CPLReadLine2L(fp,81,NULL);
271
if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
277
int nLineLen = strlen(pszLine);
278
while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
280
((char*)pszLine)[nLineLen-1] = '\0';
284
if (pszLine[0] == 'H' || nLineLen < 46)
287
OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
288
poFeature->SetFID(nNextFID ++);
290
char szLineName[12 + 1];
291
ExtractField(szLineName, pszLine, 2-1, 12);
295
if (szLineName[i] == ' ')
296
szLineName[i] = '\0';
301
poFeature->SetField(FIELD_LINENAME, szLineName);
303
char szVesselId[1+1];
304
szVesselId[0] = pszLine[17-1];
305
if (szVesselId[0] != ' ')
307
szVesselId[1] = '\0';
308
poFeature->SetField(FIELD_VESSEL_ID, szVesselId);
311
char szSourceId[1+1];
312
szSourceId[0] = pszLine[18-1];
313
if (szSourceId[0] != ' ')
315
szSourceId[1] = '\0';
316
poFeature->SetField(FIELD_SOURCE_ID, szSourceId);
320
szOtherId[0] = pszLine[19-1];
321
if (szOtherId[0] != ' ')
324
poFeature->SetField(FIELD_OTHER_ID, szOtherId);
327
char szPointNumber[6+1];
328
ExtractField(szPointNumber, pszLine, 20-1, 6);
329
poFeature->SetField(4, atoi(szPointNumber));
335
ExtractField(szDeg, pszLine, 26-1, 2);
336
ExtractField(szMin, pszLine, 26+2-1, 2);
337
ExtractField(szSec, pszLine, 26+2+2-1, 5);
338
double dfLat = atoi(szDeg) + atoi(szMin) / 60.0 + atof(szSec) / 3600.0;
339
if (pszLine[26+2+2+5-1] == 'S')
341
poFeature->SetField(FIELD_LATITUDE, dfLat);
343
ExtractField(szDeg, pszLine, 36-1, 3);
344
ExtractField(szMin, pszLine, 36+3-1, 2);
345
ExtractField(szSec, pszLine, 36+3+2-1, 5);
346
double dfLon = atoi(szDeg) + atoi(szMin) / 60.0 + atof(szSec) / 3600.0;
347
if (pszLine[36+3+2+5-1] == 'W')
349
poFeature->SetField(FIELD_LONGITUDE, dfLon);
351
OGRGeometry* poGeom = NULL;
352
if (!bUseEastingNorthingAsGeometry)
353
poGeom = new OGRPoint(dfLon, dfLat);
358
ExtractField(szEasting, pszLine, 47-1, 9);
359
double dfEasting = atof(szEasting);
360
poFeature->SetField(FIELD_EASTING, dfEasting);
362
char szNorthing[9+1];
363
ExtractField(szNorthing, pszLine, 56-1, 9);
364
double dfNorthing = atof(szNorthing);
365
poFeature->SetField(FIELD_NORTHING, dfNorthing);
367
if (bUseEastingNorthingAsGeometry)
368
poGeom = new OGRPoint(dfEasting, dfNorthing);
374
poGeom->assignSpatialReference(poSRS);
375
poFeature->SetGeometryDirectly(poGeom);
381
ExtractField(szDepth, pszLine, 65-1, 6);
382
double dfDepth = atof(szDepth);
383
poFeature->SetField(FIELD_DEPTH, dfDepth);
389
char szDayOfYear[3+1];
390
ExtractField(szDayOfYear, pszLine, 71-1, 3);
391
nDayOfYear = atoi(szDayOfYear);
392
poFeature->SetField(FIELD_DAYOFYEAR, nDayOfYear);
397
char szH[2+1], szM[2+1], szS[2+1];
398
ExtractField(szH, pszLine, 74-1, 2);
399
ExtractField(szM, pszLine, 74-1+2, 2);
400
ExtractField(szS, pszLine, 74-1+2+2, 2);
401
poFeature->SetField(FIELD_TIME, 0, 0, 0, atoi(szH), atoi(szM), atoi(szS) );
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}
410
int bIsLeap = isleap(nYear);
413
if ((bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 366) ||
414
(!bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 365))
416
while(nDayOfYear > nDays + mon_lengths[bIsLeap][nMonth])
418
nDays += mon_lengths[bIsLeap][nMonth];
421
int nDayOfMonth = nDayOfYear - nDays;
424
poFeature->SetField(FIELD_DATETIME, nYear, nMonth, nDayOfMonth,
425
atoi(szH), atoi(szM), atoi(szS) );
435
/************************************************************************/
436
/* OGRSEGP1Layer() */
437
/************************************************************************/
439
static const FieldDesc SEGP1Fields[] =
441
{ "LINENAME", OFTString },
442
{ "POINTNUMBER", OFTInteger },
443
{ "RESHOOTCODE", OFTString },
444
{ "LONGITUDE", OFTReal },
445
{ "LATITUDE", OFTReal },
446
{ "EASTING", OFTReal },
447
{ "NORTHING", OFTReal },
448
{ "DEPTH", OFTReal },
450
{ "YEAR", OFTInteger },
451
{ "DAYOFYEAR", OFTInteger },
453
{ "DATETIME", OFTDateTime }
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
469
OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
475
this->nLatitudeCol = nLatitudeCol;
480
poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
481
poFeatureDefn->Reference();
482
poFeatureDefn->SetGeomType( wkbPoint );
484
for(int i=0;i<(int)(sizeof(SEGP1Fields)/sizeof(SEGP1Fields[0]));i++)
486
OGRFieldDefn oField( SEGP1Fields[i].pszName,
487
SEGP1Fields[i].eType );
488
poFeatureDefn->AddFieldDefn( &oField );
491
bUseEastingNorthingAsGeometry =
492
CSLTestBoolean(CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO"));
497
/************************************************************************/
498
/* ~OGRSEGP1Layer() */
499
/************************************************************************/
501
OGRSEGP1Layer::~OGRSEGP1Layer()
504
poFeatureDefn->Release();
512
/************************************************************************/
514
/************************************************************************/
516
void OGRSEGP1Layer::ResetReading()
521
VSIFSeekL( fp, 0, SEEK_SET );
523
/* Skip first 20 header lines */
524
const char* pszLine = NULL;
525
for(int i=0; i<20;i++)
527
pszLine = CPLReadLine2L(fp,81,NULL);
536
/************************************************************************/
537
/* GetNextRawFeature() */
538
/************************************************************************/
540
OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
545
const char* pszLine = NULL;
548
pszLine = CPLReadLine2L(fp,81,NULL);
549
if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
555
int nLineLen = strlen(pszLine);
556
while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
558
((char*)pszLine)[nLineLen-1] = '\0';
562
char* pszExpandedLine = ExpandTabs(pszLine);
563
pszLine = pszExpandedLine;
564
nLineLen = strlen(pszLine);
566
OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
567
poFeature->SetFID(nNextFID ++);
569
OGRGeometry* poGeom = NULL;
571
if (nLatitudeCol-1 + 19 <= nLineLen)
577
ExtractField(szDeg, pszLine, nLatitudeCol-1, 2);
578
ExtractField(szMin, pszLine, nLatitudeCol+2-1, 2);
579
ExtractField(szSec, pszLine, nLatitudeCol+2+2-1, 4);
580
double dfLat = atoi(szDeg) + atoi(szMin) / 60.0 + atoi(szSec) / 100.0 / 3600.0;
581
if (pszLine[nLatitudeCol+2+2+4-1] == 'S')
583
poFeature->SetField(SEGP1_FIELD_LATITUDE, dfLat);
585
ExtractField(szDeg, pszLine, nLatitudeCol+9-1, 3);
586
ExtractField(szMin, pszLine, nLatitudeCol+9+3-1, 2);
587
ExtractField(szSec, pszLine, nLatitudeCol+9+3+2-1, 4);
588
double dfLon = atoi(szDeg) + atoi(szMin) / 60.0 + atoi(szSec) / 100.0 / 3600.0;
589
if (pszLine[nLatitudeCol+9+3+2+4-1] == 'W')
591
poFeature->SetField(SEGP1_FIELD_LONGITUDE, dfLon);
593
if (!bUseEastingNorthingAsGeometry)
594
poGeom = new OGRPoint(dfLon, dfLat);
597
/* Normal layout -> extract other fields */
598
if (nLatitudeCol == 27)
600
char szLineName[16 + 1];
601
ExtractField(szLineName, pszLine, 2-1, 16);
605
if (szLineName[i] == ' ')
606
szLineName[i] = '\0';
611
poFeature->SetField(SEGP1_FIELD_LINENAME, szLineName);
613
char szPointNumber[8+1];
614
ExtractField(szPointNumber, pszLine, 18-1, 8);
615
poFeature->SetField(SEGP1_FIELD_POINTNUMBER, atoi(szPointNumber));
617
char szReshootCode[1+1];
618
ExtractField(szReshootCode, pszLine, 26-1, 1);
619
poFeature->SetField(SEGP1_FIELD_RESHOOTCODE, szReshootCode);
624
ExtractField(szEasting, pszLine, 46-1, 8);
625
double dfEasting = atof(szEasting);
626
poFeature->SetField(SEGP1_FIELD_EASTING, dfEasting);
628
char szNorthing[8+1];
629
ExtractField(szNorthing, pszLine, 54-1, 8);
630
double dfNorthing = atof(szNorthing);
631
poFeature->SetField(SEGP1_FIELD_NORTHING, dfNorthing);
633
if (bUseEastingNorthingAsGeometry)
634
poGeom = new OGRPoint(dfEasting, dfNorthing);
640
ExtractField(szDepth, pszLine, 62-1, 5);
641
double dfDepth = atof(szDepth);
642
poFeature->SetField(SEGP1_FIELD_DEPTH, dfDepth);
649
poGeom->assignSpatialReference(poSRS);
650
poFeature->SetGeometryDirectly(poGeom);
653
CPLFree(pszExpandedLine);
659
/************************************************************************/
661
/************************************************************************/
663
char* OGRSEGP1Layer::ExpandTabs(const char* pszLine)
665
char* pszExpandedLine = (char*)CPLMalloc(strlen(pszLine) * 8 + 1);
667
for(int i=0; pszLine[i] != '\0'; i++)
669
/* A tab must be space-expanded to reach the next column number */
670
/* which is a multiple of 8 */
675
pszExpandedLine[j ++] = ' ';
676
} while ((j % 8) != 0);
679
pszExpandedLine[j ++] = pszLine[i];
681
pszExpandedLine[j] = '\0';
683
return pszExpandedLine;
686
/************************************************************************/
687
/* DetectLatitudeColumn() */
688
/************************************************************************/
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) */
694
int OGRSEGP1Layer::DetectLatitudeColumn(const char* pszLine)
696
int nLen = strlen(pszLine);
697
if (nLen >= 45 && pszLine[0] == ' ' &&
698
(pszLine[35-1] == 'N' || pszLine[35-1] == 'S') &&
699
(pszLine[45-1] == 'E' || pszLine[45-1] == 'W'))
702
for(int i=8;i<nLen-10;i++)
704
if ((pszLine[i] == 'N' || pszLine[i] == 'S') &&
705
(pszLine[i+10] == 'E' || pszLine[i+10] == 'W'))
713
/************************************************************************/
714
/* OGRSEGUKOOALineLayer() */
715
/************************************************************************/
717
OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
718
OGRLayer *poBaseLayer)
723
poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_lines",
724
CPLGetBasename(pszFilename)) );
725
poFeatureDefn->Reference();
726
poFeatureDefn->SetGeomType( wkbLineString );
728
OGRFieldDefn oField( "LINENAME", OFTString );
729
poFeatureDefn->AddFieldDefn( &oField );
731
this->poBaseLayer = poBaseLayer;
732
poNextBaseFeature = NULL;
735
/************************************************************************/
736
/* ~OGRSEGUKOOALineLayer() */
737
/************************************************************************/
739
OGRSEGUKOOALineLayer::~OGRSEGUKOOALineLayer()
741
delete poNextBaseFeature;
744
poFeatureDefn->Release();
747
/************************************************************************/
749
/************************************************************************/
751
void OGRSEGUKOOALineLayer::ResetReading()
756
delete poNextBaseFeature;
757
poNextBaseFeature = NULL;
758
poBaseLayer->ResetReading();
761
/************************************************************************/
762
/* GetNextRawFeature() */
763
/************************************************************************/
765
OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
770
/* Merge points of base layer that have same value for attribute(0) */
771
/* into a single linestring */
773
OGRFeature* poFeature = NULL;
774
OGRLineString* poLS = NULL;
776
if (poNextBaseFeature == NULL)
777
poNextBaseFeature = poBaseLayer->GetNextFeature();
779
while(poNextBaseFeature != NULL)
781
if (poNextBaseFeature->IsFieldSet(0) &&
782
poNextBaseFeature->GetFieldAsString(0)[0] != '\0')
784
if (poFeature != NULL &&
785
strcmp(poFeature->GetFieldAsString(0),
786
poNextBaseFeature->GetFieldAsString(0)) != 0)
792
(OGRPoint*) poNextBaseFeature->GetGeometryRef();
795
if (poFeature == NULL)
797
poFeature = new OGRFeature(poFeatureDefn);
798
poFeature->SetFID(nNextFID ++);
799
poFeature->SetField(0,
800
poNextBaseFeature->GetFieldAsString(0));
801
poLS = new OGRLineString();
802
if (poBaseLayer->GetSpatialRef())
803
poLS->assignSpatialReference(
804
poBaseLayer->GetSpatialRef());
805
poFeature->SetGeometryDirectly(poLS);
808
poLS->addPoint(poPoint);
812
delete poNextBaseFeature;
813
poNextBaseFeature = poBaseLayer->GetNextFeature();