1
/******************************************************************************
2
* $Id: ogrgeomediageometry.cpp 21561 2011-01-23 12:22:58Z rouault $
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>
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, 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
****************************************************************************/
30
#include "ogrgeomediageometry.h"
31
#include "cpl_string.h"
33
CPL_CVSID("$Id: ogrgeomediageometry.cpp 21561 2011-01-23 12:22:58Z rouault $");
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
44
/************************************************************************/
45
/* OGRCreateFromGeomedia() */
46
/************************************************************************/
48
OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
49
OGRGeometry **ppoGeom,
56
return OGRERR_FAILURE;
58
if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
59
return OGRERR_FAILURE;
61
int nGeomType = pabyGeom[0];
65
if( nGeomType == GEOMEDIA_POINT ||
66
nGeomType == GEOMEDIA_ORIENTED_POINT )
69
return OGRERR_FAILURE;
72
memcpy(&dfX, pabyGeom, 8);
74
memcpy(&dfY, pabyGeom + 8, 8);
76
memcpy(&dfZ, pabyGeom + 16, 8);
79
*ppoGeom = new OGRPoint( dfX, dfY, dfZ );
83
else if ( nGeomType == GEOMEDIA_POLYLINE )
86
return OGRERR_FAILURE;
89
memcpy(&nPoints, pabyGeom, 4);
90
CPL_LSBPTR32(&nPoints);
95
if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
96
return OGRERR_FAILURE;
98
OGRLineString* poLS = new OGRLineString();
99
poLS->setNumPoints(nPoints);
101
for(i=0;i<nPoints;i++)
103
double dfX, dfY, dfZ;
104
memcpy(&dfX, pabyGeom, 8);
106
memcpy(&dfY, pabyGeom + 8, 8);
108
memcpy(&dfZ, pabyGeom + 16, 8);
111
poLS->setPoint(i, dfX, dfY, dfZ);
120
else if ( nGeomType == GEOMEDIA_POLYGON )
123
return OGRERR_FAILURE;
126
memcpy(&nPoints, pabyGeom, 4);
127
CPL_LSBPTR32(&nPoints);
132
if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
133
return OGRERR_FAILURE;
135
OGRLinearRing* poRing = new OGRLinearRing();
136
poRing->setNumPoints(nPoints);
138
for(i=0;i<nPoints;i++)
140
double dfX, dfY, dfZ;
141
memcpy(&dfX, pabyGeom, 8);
143
memcpy(&dfY, pabyGeom + 8, 8);
145
memcpy(&dfZ, pabyGeom + 16, 8);
148
poRing->setPoint(i, dfX, dfY, dfZ);
153
OGRPolygon* poPoly = new OGRPolygon();
154
poPoly->addRingDirectly(poRing);
159
else if ( nGeomType == GEOMEDIA_BOUNDARY )
162
return OGRERR_FAILURE;
165
memcpy(&nExteriorSize, pabyGeom, 4);
166
CPL_LSBPTR32(&nExteriorSize);
171
if (nBytes < nExteriorSize)
172
return OGRERR_FAILURE;
174
OGRGeometry* poExteriorGeom = NULL;
175
if (OGRCreateFromGeomedia( pabyGeom, &poExteriorGeom, nExteriorSize ) != OGRERR_NONE)
176
return OGRERR_FAILURE;
178
if (poExteriorGeom->getGeometryType() != wkbPolygon)
180
delete poExteriorGeom;
181
return OGRERR_FAILURE;
184
pabyGeom += nExteriorSize;
185
nBytes -= nExteriorSize;
189
delete poExteriorGeom;
190
return OGRERR_FAILURE;
194
memcpy(&nInteriorSize, pabyGeom, 4);
195
CPL_LSBPTR32(&nInteriorSize);
200
if (nBytes < nInteriorSize)
202
delete poExteriorGeom;
203
return OGRERR_FAILURE;
206
OGRGeometry* poInteriorGeom = NULL;
207
if (OGRCreateFromGeomedia( pabyGeom, &poInteriorGeom, nInteriorSize ) != OGRERR_NONE)
209
delete poExteriorGeom;
210
return OGRERR_FAILURE;
213
if (poInteriorGeom->getGeometryType() == wkbPolygon)
215
((OGRPolygon*)poExteriorGeom)->addRing(((OGRPolygon*)poInteriorGeom)->getExteriorRing());
216
delete poInteriorGeom;
217
*ppoGeom = poExteriorGeom;
221
delete poExteriorGeom;
222
delete poInteriorGeom;
223
return OGRERR_FAILURE;
228
else if ( nGeomType == GEOMEDIA_COLLECTION ||
229
nGeomType == GEOMEDIA_MULTILINE ||
230
nGeomType == GEOMEDIA_MULTIPOLYGON )
233
return OGRERR_FAILURE;
237
memcpy(&nParts, pabyGeom, 4);
238
CPL_LSBPTR32(&nParts);
243
if (nParts < 0 || nParts > INT_MAX / (4 + 16) || nBytes < nParts * (4 + 16))
244
return OGRERR_FAILURE;
246
/* Can this collection be considered as a multipolyline or multipolygon ? */
247
if ( nGeomType == GEOMEDIA_COLLECTION )
249
GByte* pabyGeomBackup = pabyGeom;
250
int nBytesBackup = nBytes;
252
int bAllPolyline = TRUE;
253
int bAllPolygon = TRUE;
255
for(i=0;i<nParts;i++)
258
return OGRERR_FAILURE;
260
memcpy(&nSubBytes, pabyGeom, 4);
261
CPL_LSBPTR32(&nSubBytes);
265
return OGRERR_FAILURE;
271
if (nBytes < nSubBytes)
273
return OGRERR_FAILURE;
277
return OGRERR_FAILURE;
279
if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
280
return OGRERR_FAILURE;
282
int nSubGeomType = pabyGeom[0];
283
if ( nSubGeomType != GEOMEDIA_POLYLINE )
284
bAllPolyline = FALSE;
285
if ( nSubGeomType != GEOMEDIA_POLYGON )
288
pabyGeom += nSubBytes;
292
pabyGeom = pabyGeomBackup;
293
nBytes = nBytesBackup;
296
nGeomType = GEOMEDIA_MULTILINE;
297
else if (bAllPolygon)
298
nGeomType = GEOMEDIA_MULTIPOLYGON;
301
OGRGeometryCollection* poColl = (nGeomType == GEOMEDIA_MULTILINE) ? new OGRMultiLineString() :
302
(nGeomType == GEOMEDIA_MULTIPOLYGON) ? new OGRMultiPolygon() :
303
new OGRGeometryCollection();
305
for(i=0;i<nParts;i++)
308
return OGRERR_FAILURE;
310
memcpy(&nSubBytes, pabyGeom, 4);
311
CPL_LSBPTR32(&nSubBytes);
316
return OGRERR_FAILURE;
322
if (nBytes < nSubBytes)
325
return OGRERR_FAILURE;
328
OGRGeometry* poSubGeom = NULL;
329
if (OGRCreateFromGeomedia( pabyGeom, &poSubGeom, nSubBytes ) == OGRERR_NONE)
331
if (wkbFlatten(poColl->getGeometryType()) == wkbMultiPolygon &&
332
wkbFlatten(poSubGeom->getGeometryType()) == wkbLineString)
334
OGRPolygon* poPoly = new OGRPolygon();
335
OGRLinearRing* poRing = new OGRLinearRing();
336
poRing->addSubLineString((OGRLineString*)poSubGeom);
337
poPoly->addRingDirectly(poRing);
342
if (poColl->addGeometryDirectly(poSubGeom) != OGRERR_NONE)
344
//printf("%d %d\n", poColl->getGeometryType() & ~wkb25DBit, poSubGeom->getGeometryType() & ~wkb25DBit);
349
pabyGeom += nSubBytes;
359
CPLDebug("GEOMEDIA", "Unhandled type %d", nGeomType);
362
return OGRERR_FAILURE;
366
/************************************************************************/
367
/* OGRGetGeomediaSRS() */
368
/************************************************************************/
370
OGRSpatialReference* OGRGetGeomediaSRS(OGRFeature* poFeature)
372
if (poFeature == NULL)
375
int nGeodeticDatum = poFeature->GetFieldAsInteger("GeodeticDatum");
376
int nEllipsoid = poFeature->GetFieldAsInteger("Ellipsoid");
377
int nProjAlgorithm = poFeature->GetFieldAsInteger("ProjAlgorithm");
379
if (nGeodeticDatum == 17 && nEllipsoid == 22)
381
if (nProjAlgorithm == 12)
383
OGRSpatialReference* poSRS = new OGRSpatialReference();
385
const char* pszDescription = poFeature->GetFieldAsString("Description");
386
if (pszDescription && pszDescription[0] != 0)
387
poSRS->SetNode( "PROJCS", pszDescription );
388
poSRS->SetWellKnownGeogCS("WGS84");
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 );