~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
static void ExtractField(char* szField, const char* pszLine, int nOffset, int nLen)
 
43
{
 
44
    memcpy(szField, pszLine + nOffset, nLen);
 
45
    szField[nLen] = '\0';
 
46
}
 
47
 
 
48
/************************************************************************/
 
49
/*                           GetNextFeature()                           */
 
50
/************************************************************************/
 
51
 
 
52
OGRFeature *OGRSEGUKOOABaseLayer::GetNextFeature()
 
53
{
 
54
    OGRFeature  *poFeature;
 
55
 
 
56
    while(TRUE)
 
57
    {
 
58
        poFeature = GetNextRawFeature();
 
59
        if (poFeature == NULL)
 
60
            return NULL;
 
61
 
 
62
        if((m_poFilterGeom == NULL
 
63
            || FilterGeometry( poFeature->GetGeometryRef() ) )
 
64
        && (m_poAttrQuery == NULL
 
65
            || m_poAttrQuery->Evaluate( poFeature )) )
 
66
        {
 
67
            return poFeature;
 
68
        }
 
69
        else
 
70
            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
OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
 
116
                                      VSILFILE* fp )
 
117
 
 
118
{
 
119
    this->fp = fp;
 
120
    nNextFID = 0;
 
121
    bEOF = FALSE;
 
122
    poSRS = NULL;
 
123
    nYear = 0;
 
124
 
 
125
    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
 
126
    poFeatureDefn->Reference();
 
127
    poFeatureDefn->SetGeomType( wkbPoint );
 
128
 
 
129
    for(int i=0;i<(int)(sizeof(UKOOAP190Fields)/sizeof(UKOOAP190Fields[0]));i++)
 
130
    {
 
131
        OGRFieldDefn    oField( UKOOAP190Fields[i].pszName,
 
132
                                UKOOAP190Fields[i].eType );
 
133
        poFeatureDefn->AddFieldDefn( &oField );
 
134
    }
 
135
 
 
136
    bUseEastingNorthingAsGeometry =
 
137
        CSLTestBoolean(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
 
138
 
 
139
    ParseHeaders();
 
140
}
 
141
 
 
142
/************************************************************************/
 
143
/*                         ~OGRUKOOAP190Layer()                         */
 
144
/************************************************************************/
 
145
 
 
146
OGRUKOOAP190Layer::~OGRUKOOAP190Layer()
 
147
 
 
148
{
 
149
    poFeatureDefn->Release();
 
150
 
 
151
    VSIFCloseL( fp );
 
152
 
 
153
    if (poSRS)
 
154
        poSRS->Release();
 
155
}
 
156
 
 
157
/************************************************************************/
 
158
/*                          ParseHeaders()                              */
 
159
/************************************************************************/
 
160
 
 
161
void OGRUKOOAP190Layer::ParseHeaders()
 
162
{
 
163
    while(TRUE)
 
164
    {
 
165
        const char* pszLine = CPLReadLine2L(fp,81,NULL);
 
166
        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
 
167
        {
 
168
            break;
 
169
        }
 
170
 
 
171
        int nLineLen = strlen(pszLine);
 
172
        while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
 
173
        {
 
174
            ((char*)pszLine)[nLineLen-1] = '\0';
 
175
            nLineLen --;
 
176
        }
 
177
 
 
178
        if (pszLine[0] != 'H')
 
179
            break;
 
180
 
 
181
        if (nLineLen < 33)
 
182
            continue;
 
183
 
 
184
        if (!bUseEastingNorthingAsGeometry &&
 
185
            strncmp(pszLine, "H1500", 5) == 0 && poSRS == NULL)
 
186
        {
 
187
            if (strncmp(pszLine + 33 - 1, "WGS84", 5) == 0 ||
 
188
                strncmp(pszLine + 33 - 1, "WGS-84", 6) == 0)
 
189
            {
 
190
                poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
 
191
            }
 
192
            else if (strncmp(pszLine + 33 - 1, "WGS72", 5) == 0)
 
193
            {
 
194
                poSRS = new OGRSpatialReference();
 
195
                poSRS->SetFromUserInput("WGS72");
 
196
            }
 
197
        }
 
198
        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
            for(i=0;i<6;i++)
 
206
            {
 
207
                ExtractField(aszParams[i], pszLine, 33 - 1 + i * 6, 6);
 
208
            }
 
209
            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
                              atof(szZ));
 
217
        }
 
218
        else if (strncmp(pszLine, "H0200", 5) == 0)
 
219
        {
 
220
            char** papszTokens = CSLTokenizeString(pszLine + 33 - 1);
 
221
            for(int i = 0; papszTokens[i] != NULL; i++)
 
222
            {
 
223
                if (strlen(papszTokens[i]) == 4)
 
224
                {
 
225
                    int nVal = atoi(papszTokens[i]);
 
226
                    if (nVal >= 1900)
 
227
                    {
 
228
                        if (nYear != 0 && nYear != nVal)
 
229
                        {
 
230
                            CPLDebug("SEGUKOOA",
 
231
                                     "Several years found in H0200. Ignoring them!");
 
232
                            nYear = 0;
 
233
                            break;
 
234
                        }
 
235
                        nYear = nVal;
 
236
                    }
 
237
                }
 
238
            }
 
239
            CSLDestroy(papszTokens);
 
240
        }
 
241
    }
 
242
    VSIFSeekL( fp, 0, SEEK_SET );
 
243
}
 
244
 
 
245
/************************************************************************/
 
246
/*                            ResetReading()                            */
 
247
/************************************************************************/
 
248
 
 
249
void OGRUKOOAP190Layer::ResetReading()
 
250
 
 
251
{
 
252
    nNextFID = 0;
 
253
    bEOF = FALSE;
 
254
    VSIFSeekL( fp, 0, SEEK_SET );
 
255
}
 
256
 
 
257
/************************************************************************/
 
258
/*                         GetNextRawFeature()                          */
 
259
/************************************************************************/
 
260
 
 
261
OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
 
262
{
 
263
    if (bEOF)
 
264
        return NULL;
 
265
 
 
266
    const char* pszLine;
 
267
 
 
268
    while(TRUE)
 
269
    {
 
270
        pszLine = CPLReadLine2L(fp,81,NULL);
 
271
        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
 
272
        {
 
273
            bEOF = TRUE;
 
274
            return NULL;
 
275
        }
 
276
 
 
277
        int nLineLen = strlen(pszLine);
 
278
        while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
 
279
        {
 
280
            ((char*)pszLine)[nLineLen-1] = '\0';
 
281
            nLineLen --;
 
282
        }
 
283
 
 
284
        if (pszLine[0] == 'H' || nLineLen < 46)
 
285
            continue;
 
286
 
 
287
        OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
288
        poFeature->SetFID(nNextFID ++);
 
289
 
 
290
        char szLineName[12 + 1];
 
291
        ExtractField(szLineName, pszLine, 2-1, 12);
 
292
        int i = 11;
 
293
        while (i >= 0)
 
294
        {
 
295
            if (szLineName[i] == ' ')
 
296
                szLineName[i] = '\0';
 
297
            else
 
298
                break;
 
299
            i --;
 
300
        }
 
301
        poFeature->SetField(FIELD_LINENAME, szLineName);
 
302
 
 
303
        char szVesselId[1+1];
 
304
        szVesselId[0] = pszLine[17-1];
 
305
        if (szVesselId[0] != ' ')
 
306
        {
 
307
            szVesselId[1] = '\0';
 
308
            poFeature->SetField(FIELD_VESSEL_ID, szVesselId);
 
309
        }
 
310
 
 
311
        char szSourceId[1+1];
 
312
        szSourceId[0] = pszLine[18-1];
 
313
        if (szSourceId[0] != ' ')
 
314
        {
 
315
            szSourceId[1] = '\0';
 
316
            poFeature->SetField(FIELD_SOURCE_ID, szSourceId);
 
317
        }
 
318
 
 
319
        char szOtherId[1+1];
 
320
        szOtherId[0] = pszLine[19-1];
 
321
        if (szOtherId[0] != ' ')
 
322
        {
 
323
            szOtherId[1] = '\0';
 
324
            poFeature->SetField(FIELD_OTHER_ID, szOtherId);
 
325
        }
 
326
 
 
327
        char szPointNumber[6+1];
 
328
        ExtractField(szPointNumber, pszLine, 20-1, 6);
 
329
        poFeature->SetField(4, atoi(szPointNumber));
 
330
 
 
331
        char szDeg[3+1];
 
332
        char szMin[2+1];
 
333
        char szSec[5+1];
 
334
 
 
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')
 
340
            dfLat = -dfLat;
 
341
        poFeature->SetField(FIELD_LATITUDE, dfLat);
 
342
 
 
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')
 
348
            dfLon = -dfLon;
 
349
        poFeature->SetField(FIELD_LONGITUDE, dfLon);
 
350
 
 
351
        OGRGeometry* poGeom = NULL;
 
352
        if (!bUseEastingNorthingAsGeometry)
 
353
            poGeom = new OGRPoint(dfLon, dfLat);
 
354
 
 
355
        if (nLineLen >= 64)
 
356
        {
 
357
            char szEasting[9+1];
 
358
            ExtractField(szEasting, pszLine, 47-1, 9);
 
359
            double dfEasting = atof(szEasting);
 
360
            poFeature->SetField(FIELD_EASTING, dfEasting);
 
361
 
 
362
            char szNorthing[9+1];
 
363
            ExtractField(szNorthing, pszLine, 56-1, 9);
 
364
            double dfNorthing = atof(szNorthing);
 
365
            poFeature->SetField(FIELD_NORTHING, dfNorthing);
 
366
 
 
367
            if (bUseEastingNorthingAsGeometry)
 
368
                poGeom = new OGRPoint(dfEasting, dfNorthing);
 
369
        }
 
370
 
 
371
        if (poGeom)
 
372
        {
 
373
            if (poSRS)
 
374
                poGeom->assignSpatialReference(poSRS);
 
375
            poFeature->SetGeometryDirectly(poGeom);
 
376
        }
 
377
 
 
378
        if (nLineLen >= 70)
 
379
        {
 
380
            char szDepth[6+1];
 
381
            ExtractField(szDepth, pszLine, 65-1, 6);
 
382
            double dfDepth = atof(szDepth);
 
383
            poFeature->SetField(FIELD_DEPTH, dfDepth);
 
384
        }
 
385
 
 
386
        int nDayOfYear = 0;
 
387
        if (nLineLen >= 73)
 
388
        {
 
389
            char szDayOfYear[3+1];
 
390
            ExtractField(szDayOfYear, pszLine, 71-1, 3);
 
391
            nDayOfYear = atoi(szDayOfYear);
 
392
            poFeature->SetField(FIELD_DAYOFYEAR, nDayOfYear);
 
393
        }
 
394
 
 
395
        if (nLineLen >= 79)
 
396
        {
 
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) );
 
402
 
 
403
            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
                int bIsLeap = isleap(nYear);
 
411
                int nMonth = 0;
 
412
                int nDays = 0;
 
413
                if ((bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 366) ||
 
414
                    (!bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 365))
 
415
                {
 
416
                    while(nDayOfYear > nDays + mon_lengths[bIsLeap][nMonth])
 
417
                    {
 
418
                        nDays += mon_lengths[bIsLeap][nMonth];
 
419
                        nMonth ++;
 
420
                    }
 
421
                    int nDayOfMonth = nDayOfYear - nDays;
 
422
                    nMonth ++;
 
423
 
 
424
                    poFeature->SetField(FIELD_DATETIME, nYear, nMonth, nDayOfMonth,
 
425
                                        atoi(szH), atoi(szM), atoi(szS) );
 
426
                }
 
427
 
 
428
            }
 
429
        }
 
430
 
 
431
        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
OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
 
470
                              VSILFILE* fp,
 
471
                              int nLatitudeCol )
 
472
 
 
473
{
 
474
    this->fp = fp;
 
475
    this->nLatitudeCol = nLatitudeCol;
 
476
    nNextFID = 0;
 
477
    bEOF = FALSE;
 
478
    poSRS = NULL;
 
479
 
 
480
    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
 
481
    poFeatureDefn->Reference();
 
482
    poFeatureDefn->SetGeomType( wkbPoint );
 
483
 
 
484
    for(int i=0;i<(int)(sizeof(SEGP1Fields)/sizeof(SEGP1Fields[0]));i++)
 
485
    {
 
486
        OGRFieldDefn    oField( SEGP1Fields[i].pszName,
 
487
                                SEGP1Fields[i].eType );
 
488
        poFeatureDefn->AddFieldDefn( &oField );
 
489
    }
 
490
 
 
491
    bUseEastingNorthingAsGeometry =
 
492
        CSLTestBoolean(CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO"));
 
493
 
 
494
    ResetReading();
 
495
}
 
496
 
 
497
/************************************************************************/
 
498
/*                            ~OGRSEGP1Layer()                          */
 
499
/************************************************************************/
 
500
 
 
501
OGRSEGP1Layer::~OGRSEGP1Layer()
 
502
 
 
503
{
 
504
    poFeatureDefn->Release();
 
505
 
 
506
    VSIFCloseL( fp );
 
507
 
 
508
    if (poSRS)
 
509
        poSRS->Release();
 
510
}
 
511
 
 
512
/************************************************************************/
 
513
/*                            ResetReading()                            */
 
514
/************************************************************************/
 
515
 
 
516
void OGRSEGP1Layer::ResetReading()
 
517
 
 
518
{
 
519
    nNextFID = 0;
 
520
    bEOF = FALSE;
 
521
    VSIFSeekL( fp, 0, SEEK_SET );
 
522
 
 
523
    /* Skip first 20 header lines */
 
524
    const char* pszLine = NULL;
 
525
    for(int i=0; i<20;i++)
 
526
    {
 
527
        pszLine = CPLReadLine2L(fp,81,NULL);
 
528
        if (pszLine == NULL)
 
529
        {
 
530
            bEOF = TRUE;
 
531
            break;
 
532
        }
 
533
    }
 
534
}
 
535
 
 
536
/************************************************************************/
 
537
/*                         GetNextRawFeature()                          */
 
538
/************************************************************************/
 
539
 
 
540
OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
 
541
{
 
542
    if (bEOF)
 
543
        return NULL;
 
544
 
 
545
    const char* pszLine = NULL;
 
546
    while(TRUE)
 
547
    {
 
548
        pszLine = CPLReadLine2L(fp,81,NULL);
 
549
        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
 
550
        {
 
551
            bEOF = TRUE;
 
552
            return NULL;
 
553
        }
 
554
 
 
555
        int nLineLen = strlen(pszLine);
 
556
        while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
 
557
        {
 
558
            ((char*)pszLine)[nLineLen-1] = '\0';
 
559
            nLineLen --;
 
560
        }
 
561
 
 
562
        char* pszExpandedLine = ExpandTabs(pszLine);
 
563
        pszLine = pszExpandedLine;
 
564
        nLineLen = strlen(pszLine);
 
565
 
 
566
        OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
567
        poFeature->SetFID(nNextFID ++);
 
568
 
 
569
        OGRGeometry* poGeom = NULL;
 
570
 
 
571
        if (nLatitudeCol-1 + 19 <= nLineLen)
 
572
        {
 
573
            char szDeg[3+1];
 
574
            char szMin[2+1];
 
575
            char szSec[4+1];
 
576
 
 
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')
 
582
                dfLat = -dfLat;
 
583
            poFeature->SetField(SEGP1_FIELD_LATITUDE, dfLat);
 
584
 
 
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')
 
590
                dfLon = -dfLon;
 
591
            poFeature->SetField(SEGP1_FIELD_LONGITUDE, dfLon);
 
592
 
 
593
            if (!bUseEastingNorthingAsGeometry)
 
594
                poGeom = new OGRPoint(dfLon, dfLat);
 
595
        }
 
596
 
 
597
        /* Normal layout -> extract other fields */
 
598
        if (nLatitudeCol == 27)
 
599
        {
 
600
            char szLineName[16 + 1];
 
601
            ExtractField(szLineName, pszLine, 2-1, 16);
 
602
            int i = 15;
 
603
            while (i >= 0)
 
604
            {
 
605
                if (szLineName[i] == ' ')
 
606
                    szLineName[i] = '\0';
 
607
                else
 
608
                    break;
 
609
                i --;
 
610
            }
 
611
            poFeature->SetField(SEGP1_FIELD_LINENAME, szLineName);
 
612
 
 
613
            char szPointNumber[8+1];
 
614
            ExtractField(szPointNumber, pszLine, 18-1, 8);
 
615
            poFeature->SetField(SEGP1_FIELD_POINTNUMBER, atoi(szPointNumber));
 
616
 
 
617
            char szReshootCode[1+1];
 
618
            ExtractField(szReshootCode, pszLine, 26-1, 1);
 
619
            poFeature->SetField(SEGP1_FIELD_RESHOOTCODE, szReshootCode);
 
620
 
 
621
            if (nLineLen >= 61)
 
622
            {
 
623
                char szEasting[8+1];
 
624
                ExtractField(szEasting, pszLine, 46-1, 8);
 
625
                double dfEasting = atof(szEasting);
 
626
                poFeature->SetField(SEGP1_FIELD_EASTING, dfEasting);
 
627
 
 
628
                char szNorthing[8+1];
 
629
                ExtractField(szNorthing, pszLine, 54-1, 8);
 
630
                double dfNorthing = atof(szNorthing);
 
631
                poFeature->SetField(SEGP1_FIELD_NORTHING, dfNorthing);
 
632
 
 
633
                if (bUseEastingNorthingAsGeometry)
 
634
                    poGeom = new OGRPoint(dfEasting, dfNorthing);
 
635
            }
 
636
 
 
637
            if (nLineLen >= 66)
 
638
            {
 
639
                char szDepth[5+1];
 
640
                ExtractField(szDepth, pszLine, 62-1, 5);
 
641
                double dfDepth = atof(szDepth);
 
642
                poFeature->SetField(SEGP1_FIELD_DEPTH, dfDepth);
 
643
            }
 
644
        }
 
645
 
 
646
        if (poGeom)
 
647
        {
 
648
            if (poSRS)
 
649
                poGeom->assignSpatialReference(poSRS);
 
650
            poFeature->SetGeometryDirectly(poGeom);
 
651
        }
 
652
 
 
653
        CPLFree(pszExpandedLine);
 
654
 
 
655
        return poFeature;
 
656
    }
 
657
}
 
658
 
 
659
/************************************************************************/
 
660
/*                           ExpandTabs()                               */
 
661
/************************************************************************/
 
662
 
 
663
char* OGRSEGP1Layer::ExpandTabs(const char* pszLine)
 
664
{
 
665
    char* pszExpandedLine = (char*)CPLMalloc(strlen(pszLine) * 8 + 1);
 
666
    int j = 0;
 
667
    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
        if (pszLine[i] == 9)
 
672
        {
 
673
            do
 
674
            {
 
675
                pszExpandedLine[j ++] = ' ';
 
676
            } while ((j % 8) != 0);
 
677
        }
 
678
        else
 
679
            pszExpandedLine[j ++] = pszLine[i];
 
680
    }
 
681
    pszExpandedLine[j] = '\0';
 
682
 
 
683
    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
int OGRSEGP1Layer::DetectLatitudeColumn(const char* pszLine)
 
695
{
 
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'))
 
700
        return 27;
 
701
 
 
702
    for(int i=8;i<nLen-10;i++)
 
703
    {
 
704
        if ((pszLine[i] == 'N' || pszLine[i] == 'S') &&
 
705
            (pszLine[i+10] == 'E' || pszLine[i+10] == 'W'))
 
706
            return i - 8 + 1;
 
707
    }
 
708
 
 
709
    return 0;
 
710
}
 
711
 
 
712
 
 
713
/************************************************************************/
 
714
/*                        OGRSEGUKOOALineLayer()                        */
 
715
/************************************************************************/
 
716
 
 
717
OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
 
718
                                           OGRLayer *poBaseLayer)
 
719
{
 
720
    nNextFID = 0;
 
721
    bEOF = FALSE;
 
722
 
 
723
    poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_lines",
 
724
                                                   CPLGetBasename(pszFilename)) );
 
725
    poFeatureDefn->Reference();
 
726
    poFeatureDefn->SetGeomType( wkbLineString );
 
727
 
 
728
    OGRFieldDefn    oField( "LINENAME", OFTString );
 
729
    poFeatureDefn->AddFieldDefn( &oField );
 
730
 
 
731
    this->poBaseLayer = poBaseLayer;
 
732
    poNextBaseFeature = NULL;
 
733
}
 
734
 
 
735
/************************************************************************/
 
736
/*                       ~OGRSEGUKOOALineLayer()                        */
 
737
/************************************************************************/
 
738
 
 
739
OGRSEGUKOOALineLayer::~OGRSEGUKOOALineLayer()
 
740
{
 
741
    delete poNextBaseFeature;
 
742
    delete poBaseLayer;
 
743
 
 
744
    poFeatureDefn->Release();
 
745
}
 
746
 
 
747
/************************************************************************/
 
748
/*                            ResetReading()                            */
 
749
/************************************************************************/
 
750
 
 
751
void OGRSEGUKOOALineLayer::ResetReading()
 
752
 
 
753
{
 
754
    nNextFID = 0;
 
755
    bEOF = FALSE;
 
756
    delete poNextBaseFeature;
 
757
    poNextBaseFeature = NULL;
 
758
    poBaseLayer->ResetReading();
 
759
}
 
760
 
 
761
/************************************************************************/
 
762
/*                         GetNextRawFeature()                          */
 
763
/************************************************************************/
 
764
 
 
765
OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
 
766
{
 
767
    if (bEOF)
 
768
        return NULL;
 
769
 
 
770
    /* Merge points of base layer that have same value for attribute(0) */
 
771
    /* into a single linestring */
 
772
 
 
773
    OGRFeature* poFeature = NULL;
 
774
    OGRLineString* poLS = NULL;
 
775
 
 
776
    if (poNextBaseFeature == NULL)
 
777
        poNextBaseFeature = poBaseLayer->GetNextFeature();
 
778
 
 
779
    while(poNextBaseFeature != NULL)
 
780
    {
 
781
        if (poNextBaseFeature->IsFieldSet(0) &&
 
782
            poNextBaseFeature->GetFieldAsString(0)[0] != '\0')
 
783
        {
 
784
            if (poFeature != NULL &&
 
785
                strcmp(poFeature->GetFieldAsString(0),
 
786
                    poNextBaseFeature->GetFieldAsString(0)) != 0)
 
787
            {
 
788
                return poFeature;
 
789
            }
 
790
 
 
791
            OGRPoint* poPoint =
 
792
                (OGRPoint*) poNextBaseFeature->GetGeometryRef();
 
793
            if (poPoint != NULL)
 
794
            {
 
795
                if (poFeature == NULL)
 
796
                {
 
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);
 
806
                }
 
807
 
 
808
                poLS->addPoint(poPoint);
 
809
            }
 
810
        }
 
811
 
 
812
        delete poNextBaseFeature;
 
813
        poNextBaseFeature = poBaseLayer->GetNextFeature();
 
814
    }
 
815
 
 
816
    bEOF = TRUE;
 
817
    return poFeature;
 
818
}