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

« back to all changes in this revision

Viewing changes to ogr/ogrgeomediageometry.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: ogrgeomediageometry.cpp 21561 2011-01-23 12:22:58Z rouault $
 
3
 *
 
4
 * Project:  OpenGIS Simple Features Reference Implementation
 
5
 * Purpose:  Implements decoder of geomedia geometry blobs
 
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, 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 "ogrgeomediageometry.h"
 
31
#include "cpl_string.h"
 
32
 
 
33
CPL_CVSID("$Id: ogrgeomediageometry.cpp 21561 2011-01-23 12:22:58Z rouault $");
 
34
 
 
35
#define GEOMEDIA_POINT          0xC0
 
36
#define GEOMEDIA_ORIENTED_POINT 0xC8
 
37
#define GEOMEDIA_POLYLINE       0xC2
 
38
#define GEOMEDIA_POLYGON        0xC3
 
39
#define GEOMEDIA_BOUNDARY       0xC5
 
40
#define GEOMEDIA_COLLECTION     0xC6
 
41
#define GEOMEDIA_MULTILINE      0xCB
 
42
#define GEOMEDIA_MULTIPOLYGON   0xCC
 
43
 
 
44
/************************************************************************/
 
45
/*                       OGRCreateFromGeomedia()                        */
 
46
/************************************************************************/
 
47
 
 
48
OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
49
                              OGRGeometry **ppoGeom,
 
50
                              int nBytes )
 
51
 
 
52
{
 
53
    *ppoGeom = NULL;
 
54
 
 
55
    if( nBytes < 16 )
 
56
        return OGRERR_FAILURE;
 
57
 
 
58
    if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
 
59
        return OGRERR_FAILURE;
 
60
 
 
61
    int nGeomType = pabyGeom[0];
 
62
    pabyGeom += 16;
 
63
    nBytes -= 16;
 
64
 
 
65
    if( nGeomType == GEOMEDIA_POINT ||
 
66
        nGeomType == GEOMEDIA_ORIENTED_POINT )
 
67
    {
 
68
        if (nBytes < 3 * 8)
 
69
            return OGRERR_FAILURE;
 
70
 
 
71
        double dfX, dfY, dfZ;
 
72
        memcpy(&dfX, pabyGeom, 8);
 
73
        CPL_LSBPTR64(&dfX);
 
74
        memcpy(&dfY, pabyGeom + 8, 8);
 
75
        CPL_LSBPTR64(&dfY);
 
76
        memcpy(&dfZ, pabyGeom + 16, 8);
 
77
        CPL_LSBPTR64(&dfZ);
 
78
 
 
79
        *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
 
80
 
 
81
         return OGRERR_NONE;
 
82
    }
 
83
    else if ( nGeomType == GEOMEDIA_POLYLINE )
 
84
    {
 
85
        if (nBytes < 4)
 
86
            return OGRERR_FAILURE;
 
87
 
 
88
        int nPoints;
 
89
        memcpy(&nPoints, pabyGeom, 4);
 
90
        CPL_LSBPTR32(&nPoints);
 
91
 
 
92
        pabyGeom += 4;
 
93
        nBytes -= 4;
 
94
 
 
95
        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
 
96
            return OGRERR_FAILURE;
 
97
 
 
98
        OGRLineString* poLS = new OGRLineString();
 
99
        poLS->setNumPoints(nPoints);
 
100
        int i;
 
101
        for(i=0;i<nPoints;i++)
 
102
        {
 
103
            double dfX, dfY, dfZ;
 
104
            memcpy(&dfX, pabyGeom, 8);
 
105
            CPL_LSBPTR64(&dfX);
 
106
            memcpy(&dfY, pabyGeom + 8, 8);
 
107
            CPL_LSBPTR64(&dfY);
 
108
            memcpy(&dfZ, pabyGeom + 16, 8);
 
109
            CPL_LSBPTR64(&dfZ);
 
110
 
 
111
            poLS->setPoint(i, dfX, dfY, dfZ);
 
112
 
 
113
            pabyGeom += 24;
 
114
        }
 
115
 
 
116
        *ppoGeom = poLS;
 
117
 
 
118
        return OGRERR_NONE;
 
119
    }
 
120
    else if ( nGeomType == GEOMEDIA_POLYGON )
 
121
    {
 
122
        if (nBytes < 4)
 
123
            return OGRERR_FAILURE;
 
124
 
 
125
        int nPoints;
 
126
        memcpy(&nPoints, pabyGeom, 4);
 
127
        CPL_LSBPTR32(&nPoints);
 
128
 
 
129
        pabyGeom += 4;
 
130
        nBytes -= 4;
 
131
 
 
132
        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
 
133
            return OGRERR_FAILURE;
 
134
 
 
135
        OGRLinearRing* poRing = new OGRLinearRing();
 
136
        poRing->setNumPoints(nPoints);
 
137
        int i;
 
138
        for(i=0;i<nPoints;i++)
 
139
        {
 
140
            double dfX, dfY, dfZ;
 
141
            memcpy(&dfX, pabyGeom, 8);
 
142
            CPL_LSBPTR64(&dfX);
 
143
            memcpy(&dfY, pabyGeom + 8, 8);
 
144
            CPL_LSBPTR64(&dfY);
 
145
            memcpy(&dfZ, pabyGeom + 16, 8);
 
146
            CPL_LSBPTR64(&dfZ);
 
147
 
 
148
            poRing->setPoint(i, dfX, dfY, dfZ);
 
149
 
 
150
            pabyGeom += 24;
 
151
        }
 
152
 
 
153
        OGRPolygon* poPoly = new OGRPolygon();
 
154
        poPoly->addRingDirectly(poRing);
 
155
        *ppoGeom = poPoly;
 
156
 
 
157
        return OGRERR_NONE;
 
158
    }
 
159
    else if ( nGeomType == GEOMEDIA_BOUNDARY )
 
160
    {
 
161
        if (nBytes < 4)
 
162
            return OGRERR_FAILURE;
 
163
 
 
164
        int nExteriorSize;
 
165
        memcpy(&nExteriorSize, pabyGeom, 4);
 
166
        CPL_LSBPTR32(&nExteriorSize);
 
167
 
 
168
        pabyGeom += 4;
 
169
        nBytes -= 4;
 
170
 
 
171
        if (nBytes < nExteriorSize)
 
172
            return OGRERR_FAILURE;
 
173
 
 
174
        OGRGeometry* poExteriorGeom = NULL;
 
175
        if (OGRCreateFromGeomedia( pabyGeom, &poExteriorGeom, nExteriorSize ) != OGRERR_NONE)
 
176
            return OGRERR_FAILURE;
 
177
 
 
178
        if (poExteriorGeom->getGeometryType() != wkbPolygon)
 
179
        {
 
180
            delete poExteriorGeom;
 
181
            return OGRERR_FAILURE;
 
182
        }
 
183
 
 
184
        pabyGeom += nExteriorSize;
 
185
        nBytes -= nExteriorSize;
 
186
 
 
187
        if (nBytes < 4)
 
188
        {
 
189
            delete poExteriorGeom;
 
190
            return OGRERR_FAILURE;
 
191
        }
 
192
 
 
193
        int nInteriorSize;
 
194
        memcpy(&nInteriorSize, pabyGeom, 4);
 
195
        CPL_LSBPTR32(&nInteriorSize);
 
196
 
 
197
        pabyGeom += 4;
 
198
        nBytes -= 4;
 
199
 
 
200
        if (nBytes < nInteriorSize)
 
201
        {
 
202
            delete poExteriorGeom;
 
203
            return OGRERR_FAILURE;
 
204
        }
 
205
 
 
206
        OGRGeometry* poInteriorGeom = NULL;
 
207
        if (OGRCreateFromGeomedia( pabyGeom, &poInteriorGeom, nInteriorSize ) != OGRERR_NONE)
 
208
        {
 
209
            delete poExteriorGeom;
 
210
            return OGRERR_FAILURE;
 
211
        }
 
212
 
 
213
        if (poInteriorGeom->getGeometryType() == wkbPolygon)
 
214
        {
 
215
            ((OGRPolygon*)poExteriorGeom)->addRing(((OGRPolygon*)poInteriorGeom)->getExteriorRing());
 
216
            delete poInteriorGeom;
 
217
            *ppoGeom = poExteriorGeom;
 
218
        }
 
219
        else
 
220
        {
 
221
            delete poExteriorGeom;
 
222
            delete poInteriorGeom;
 
223
            return OGRERR_FAILURE;
 
224
        }
 
225
 
 
226
        return OGRERR_NONE;
 
227
    }
 
228
    else if ( nGeomType == GEOMEDIA_COLLECTION ||
 
229
              nGeomType == GEOMEDIA_MULTILINE ||
 
230
              nGeomType == GEOMEDIA_MULTIPOLYGON )
 
231
    {
 
232
        if (nBytes < 4)
 
233
            return OGRERR_FAILURE;
 
234
 
 
235
        int i;
 
236
        int nParts;
 
237
        memcpy(&nParts, pabyGeom, 4);
 
238
        CPL_LSBPTR32(&nParts);
 
239
 
 
240
        pabyGeom += 4;
 
241
        nBytes -= 4;
 
242
 
 
243
        if (nParts < 0 || nParts > INT_MAX / (4 + 16) || nBytes < nParts * (4 + 16))
 
244
            return OGRERR_FAILURE;
 
245
 
 
246
        /* Can this collection be considered as a multipolyline or multipolygon ? */
 
247
        if ( nGeomType == GEOMEDIA_COLLECTION )
 
248
        {
 
249
            GByte* pabyGeomBackup = pabyGeom;
 
250
            int nBytesBackup = nBytes;
 
251
 
 
252
            int bAllPolyline = TRUE;
 
253
            int bAllPolygon = TRUE;
 
254
 
 
255
            for(i=0;i<nParts;i++)
 
256
            {
 
257
                if (nBytes < 4)
 
258
                    return OGRERR_FAILURE;
 
259
                int nSubBytes;
 
260
                memcpy(&nSubBytes, pabyGeom, 4);
 
261
                CPL_LSBPTR32(&nSubBytes);
 
262
 
 
263
                if (nSubBytes < 0)
 
264
                {
 
265
                    return OGRERR_FAILURE;
 
266
                }
 
267
 
 
268
                pabyGeom += 4;
 
269
                nBytes -= 4;
 
270
 
 
271
                if (nBytes < nSubBytes)
 
272
                {
 
273
                    return OGRERR_FAILURE;
 
274
                }
 
275
 
 
276
                if( nSubBytes < 16 )
 
277
                    return OGRERR_FAILURE;
 
278
 
 
279
                if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
 
280
                    return OGRERR_FAILURE;
 
281
 
 
282
                int nSubGeomType = pabyGeom[0];
 
283
                if ( nSubGeomType != GEOMEDIA_POLYLINE )
 
284
                    bAllPolyline = FALSE;
 
285
                if ( nSubGeomType != GEOMEDIA_POLYGON )
 
286
                    bAllPolygon = FALSE;
 
287
 
 
288
                pabyGeom += nSubBytes;
 
289
                nBytes -= nSubBytes;
 
290
            }
 
291
 
 
292
            pabyGeom = pabyGeomBackup;
 
293
            nBytes = nBytesBackup;
 
294
 
 
295
            if (bAllPolyline)
 
296
                nGeomType = GEOMEDIA_MULTILINE;
 
297
            else if (bAllPolygon)
 
298
                nGeomType = GEOMEDIA_MULTIPOLYGON;
 
299
        }
 
300
 
 
301
        OGRGeometryCollection* poColl = (nGeomType == GEOMEDIA_MULTILINE) ? new OGRMultiLineString() :
 
302
                                        (nGeomType == GEOMEDIA_MULTIPOLYGON) ? new OGRMultiPolygon() :
 
303
                                                              new OGRGeometryCollection();
 
304
 
 
305
        for(i=0;i<nParts;i++)
 
306
        {
 
307
            if (nBytes < 4)
 
308
                return OGRERR_FAILURE;
 
309
            int nSubBytes;
 
310
            memcpy(&nSubBytes, pabyGeom, 4);
 
311
            CPL_LSBPTR32(&nSubBytes);
 
312
 
 
313
            if (nSubBytes < 0)
 
314
            {
 
315
                delete poColl;
 
316
                return OGRERR_FAILURE;
 
317
            }
 
318
 
 
319
            pabyGeom += 4;
 
320
            nBytes -= 4;
 
321
 
 
322
            if (nBytes < nSubBytes)
 
323
            {
 
324
                delete poColl;
 
325
                return OGRERR_FAILURE;
 
326
            }
 
327
 
 
328
            OGRGeometry* poSubGeom = NULL;
 
329
            if (OGRCreateFromGeomedia( pabyGeom, &poSubGeom, nSubBytes ) == OGRERR_NONE)
 
330
            {
 
331
                if (wkbFlatten(poColl->getGeometryType()) == wkbMultiPolygon &&
 
332
                    wkbFlatten(poSubGeom->getGeometryType()) == wkbLineString)
 
333
                {
 
334
                    OGRPolygon* poPoly = new OGRPolygon();
 
335
                    OGRLinearRing* poRing = new OGRLinearRing();
 
336
                    poRing->addSubLineString((OGRLineString*)poSubGeom);
 
337
                    poPoly->addRingDirectly(poRing);
 
338
                    delete poSubGeom;
 
339
                    poSubGeom = poPoly;
 
340
                }
 
341
 
 
342
                if (poColl->addGeometryDirectly(poSubGeom) != OGRERR_NONE)
 
343
                {
 
344
                    //printf("%d %d\n", poColl->getGeometryType() & ~wkb25DBit, poSubGeom->getGeometryType() & ~wkb25DBit);
 
345
                    delete poSubGeom;
 
346
                }
 
347
            }
 
348
 
 
349
            pabyGeom += nSubBytes;
 
350
            nBytes -= nSubBytes;
 
351
        }
 
352
 
 
353
        *ppoGeom = poColl;
 
354
 
 
355
        return OGRERR_NONE;
 
356
    }
 
357
    else
 
358
    {
 
359
        CPLDebug("GEOMEDIA", "Unhandled type %d", nGeomType);
 
360
    }
 
361
 
 
362
    return OGRERR_FAILURE;
 
363
}
 
364
 
 
365
 
 
366
/************************************************************************/
 
367
/*                         OGRGetGeomediaSRS()                          */
 
368
/************************************************************************/
 
369
 
 
370
OGRSpatialReference* OGRGetGeomediaSRS(OGRFeature* poFeature)
 
371
{
 
372
    if (poFeature == NULL)
 
373
        return NULL;
 
374
 
 
375
    int nGeodeticDatum = poFeature->GetFieldAsInteger("GeodeticDatum");
 
376
    int nEllipsoid = poFeature->GetFieldAsInteger("Ellipsoid");
 
377
    int nProjAlgorithm = poFeature->GetFieldAsInteger("ProjAlgorithm");
 
378
 
 
379
    if (nGeodeticDatum == 17 && nEllipsoid == 22)
 
380
    {
 
381
        if (nProjAlgorithm == 12)
 
382
        {
 
383
            OGRSpatialReference* poSRS = new OGRSpatialReference();
 
384
 
 
385
            const char* pszDescription = poFeature->GetFieldAsString("Description");
 
386
            if (pszDescription && pszDescription[0] != 0)
 
387
                poSRS->SetNode( "PROJCS", pszDescription );
 
388
            poSRS->SetWellKnownGeogCS("WGS84");
 
389
 
 
390
            double dfStdP1 = poFeature->GetFieldAsDouble("StandPar1");
 
391
            double dfStdP2 = poFeature->GetFieldAsDouble("StandPar2");
 
392
            double dfCenterLat = poFeature->GetFieldAsDouble("LatOfOrigin");
 
393
            double dfCenterLong = poFeature->GetFieldAsDouble("LonOfOrigin");
 
394
            double dfFalseEasting = poFeature->GetFieldAsDouble("FalseX");
 
395
            double dfFalseNorthing = poFeature->GetFieldAsDouble("FalseY");
 
396
            poSRS->SetACEA( dfStdP1, dfStdP2,
 
397
                            dfCenterLat, dfCenterLong,
 
398
                            dfFalseEasting, dfFalseNorthing );
 
399
            return poSRS;
 
400
        }
 
401
    }
 
402
 
 
403
    return NULL;
 
404
}