1
/******************************************************************************
2
* $Id: ogrmssqlgeometryparser.cpp 20591 2010-09-12 17:27:42Z tamas $
4
* Project: MSSQL Spatial driver
5
* Purpose: Implements OGRMSSQLGeometryParser class to parse native SqlGeometries.
6
* Author: Tamas Szekeres, szekerest at gmail.com
8
******************************************************************************
9
* Copyright (c) 2010, Tamas Szekeres
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
****************************************************************************/
31
#include "ogr_mssqlspatial.h"
33
CPL_CVSID("$Id: ogrmssqlgeometryparser.cpp 20591 2010-09-12 17:27:42Z tamas $");
35
/************************************************************************/
36
/* Geometry parser macros */
37
/************************************************************************/
40
#define SP_HASZVALUES 1
41
#define SP_HASMVALUES 2
43
#define SP_ISSINGLEPOINT 8
44
#define SP_ISSINGLELINESEGMENT 0x10
45
#define SP_ISWHOLEGLOBE 0x20
49
#define ST_LINESTRING 2
51
#define ST_MULTIPOINT 4
52
#define ST_MULTILINESTRING 5
53
#define ST_MULTIPOLYGON 6
54
#define ST_GEOMETRYCOLLECTION 7
56
#define ReadInt32(nPos) (*((unsigned int*)(pszData + (nPos))))
58
#define ReadByte(nPos) (pszData[nPos])
60
#define ReadDouble(nPos) (*((double*)(pszData + (nPos))))
62
#define ParentOffset(iShape) (ReadInt32(nShapePos + (iShape) * 9 ))
63
#define FigureOffset(iShape) (ReadInt32(nShapePos + (iShape) * 9 + 4))
64
#define ShapeType(iShape) (ReadByte(nShapePos + (iShape) * 9 + 8))
66
#define NextFigureOffset(iShape) (iShape + 1 < nNumShapes? FigureOffset((iShape) +1) : nNumFigures)
68
#define FigureAttribute(iFigure) (ReadByte(nFigurePos + (iFigure) * 5))
69
#define PointOffset(iFigure) (ReadInt32(nFigurePos + (iFigure) * 5 + 1))
70
#define NextPointOffset(iFigure) (iFigure + 1 < nNumFigures? PointOffset((iFigure) +1) : nNumPoints)
72
#define ReadX(iPoint) (ReadDouble(nPointPos + nPointSize * (iPoint)))
73
#define ReadY(iPoint) (ReadDouble(nPointPos + nPointSize * (iPoint) + 8))
74
#define ReadZ(iPoint) (ReadDouble(nPointPos + nPointSize * (iPoint) + 16))
76
/************************************************************************/
77
/* OGRMSSQLGeometryParser() */
78
/************************************************************************/
80
OGRMSSQLGeometryParser::OGRMSSQLGeometryParser()
84
/************************************************************************/
86
/************************************************************************/
88
OGRPoint* OGRMSSQLGeometryParser::ReadPoint(int iShape)
90
int iFigure = FigureOffset(iShape);
91
if ( iFigure < nNumFigures )
93
int iPoint = PointOffset(iFigure);
94
if ( iPoint < nNumPoints )
96
if ( chProps & SP_HASZVALUES )
97
return new OGRPoint( ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
99
return new OGRPoint( ReadX(iPoint), ReadY(iPoint) );
105
/************************************************************************/
106
/* ReadMultiPoint() */
107
/************************************************************************/
109
OGRMultiPoint* OGRMSSQLGeometryParser::ReadMultiPoint(int iShape)
111
int iFigure, iPoint, iNextPoint;
112
iFigure = FigureOffset(iShape);
114
OGRMultiPoint* poMultiPoint = new OGRMultiPoint();
115
iNextPoint = NextPointOffset(iFigure);
116
for (iPoint = PointOffset(iFigure); iPoint < iNextPoint; iPoint++)
120
if ( chProps & SP_HASZVALUES )
121
poPoint = new OGRPoint( ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
123
poPoint = new OGRPoint( ReadX(iPoint), ReadY(iPoint) );
126
poMultiPoint->addGeometryDirectly( poPoint );
132
/************************************************************************/
133
/* ReadLineString() */
134
/************************************************************************/
136
OGRLineString* OGRMSSQLGeometryParser::ReadLineString(int iShape)
138
int iFigure, iPoint, iNextPoint, i;
139
iFigure = FigureOffset(iShape);
141
OGRLineString* poLineString = new OGRLineString();
142
iPoint = PointOffset(iFigure);
143
iNextPoint = NextPointOffset(iFigure);
144
poLineString->setNumPoints(iNextPoint - iPoint);
146
while (iPoint < iNextPoint)
148
if ( chProps & SP_HASZVALUES )
149
poLineString->setPoint(i, ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
151
poLineString->setPoint(i, ReadX(iPoint), ReadY(iPoint) );
160
/************************************************************************/
161
/* ReadMultiLineString() */
162
/************************************************************************/
164
OGRMultiLineString* OGRMSSQLGeometryParser::ReadMultiLineString(int iShape)
167
OGRMultiLineString* poMultiLineString = new OGRMultiLineString();
170
for (i = iShape + 1; i < nNumShapes; i++)
173
if (ParentOffset(i) == (unsigned int)iShape)
175
if ( ShapeType(i) == ST_LINESTRING )
176
poGeom = ReadLineString(i);
179
poMultiLineString->addGeometryDirectly( poGeom );
182
return poMultiLineString;
185
/************************************************************************/
187
/************************************************************************/
189
OGRPolygon* OGRMSSQLGeometryParser::ReadPolygon(int iShape)
191
int iFigure, iPoint, iNextPoint, i;
192
int iNextFigure = NextFigureOffset(iShape);
194
OGRPolygon* poPoly = new OGRPolygon();
195
for (iFigure = FigureOffset(iShape); iFigure < iNextFigure; iFigure++)
197
OGRLinearRing* poRing = new OGRLinearRing();
198
iPoint = PointOffset(iFigure);
199
iNextPoint = NextPointOffset(iFigure);
200
poRing->setNumPoints(iNextPoint - iPoint);
202
while (iPoint < iNextPoint)
204
if ( chProps & SP_HASZVALUES )
205
poRing->setPoint(i, ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
207
poRing->setPoint(i, ReadX(iPoint), ReadY(iPoint) );
212
poPoly->addRingDirectly( poRing );
217
/************************************************************************/
218
/* ReadMultiPolygon() */
219
/************************************************************************/
221
OGRMultiPolygon* OGRMSSQLGeometryParser::ReadMultiPolygon(int iShape)
224
OGRMultiPolygon* poMultiPolygon = new OGRMultiPolygon();
227
for (i = iShape + 1; i < nNumShapes; i++)
230
if (ParentOffset(i) == (unsigned int)iShape)
232
if ( ShapeType(i) == ST_POLYGON )
233
poGeom = ReadPolygon(i);
236
poMultiPolygon->addGeometryDirectly( poGeom );
239
return poMultiPolygon;
242
/************************************************************************/
243
/* ReadGeometryCollection() */
244
/************************************************************************/
246
OGRGeometryCollection* OGRMSSQLGeometryParser::ReadGeometryCollection(int iShape)
249
OGRGeometryCollection* poGeomColl = new OGRGeometryCollection();
252
for (i = iShape + 1; i < nNumShapes; i++)
255
if (ParentOffset(i) == (unsigned int)iShape)
257
switch (ShapeType(i))
260
poGeom = ReadPoint(i);
263
poGeom = ReadLineString(i);
266
poGeom = ReadPolygon(i);
269
poGeom = ReadMultiPoint(i);
271
case ST_MULTILINESTRING:
272
poGeom = ReadMultiLineString(i);
274
case ST_MULTIPOLYGON:
275
poGeom = ReadMultiPolygon(i);
277
case ST_GEOMETRYCOLLECTION:
278
poGeom = ReadGeometryCollection(i);
283
poGeomColl->addGeometryDirectly( poGeom );
289
/************************************************************************/
290
/* ParseSqlGeometry() */
291
/************************************************************************/
294
OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
295
int nLen, OGRGeometry **poGeom)
298
return OGRERR_NOT_ENOUGH_DATA;
302
/* store the SRS id for further use */
303
nSRSId = ReadInt32(0);
305
if ( ReadByte(4) != 1 )
307
return OGRERR_CORRUPT_DATA;
310
chProps = ReadByte(5);
312
if ( chProps & SP_HASMVALUES )
314
else if ( chProps & SP_HASZVALUES )
319
if ( chProps & SP_ISSINGLEPOINT )
321
// single point geometry
324
if (nLen < 6 + nPointSize)
326
return OGRERR_NOT_ENOUGH_DATA;
329
if (chProps & SP_HASZVALUES)
330
*poGeom = new OGRPoint(ReadX(0), ReadY(0), ReadZ(0));
332
*poGeom = new OGRPoint(ReadX(0), ReadY(0));
334
else if ( chProps & SP_ISSINGLELINESEGMENT )
336
// single line segment with 2 points
339
if (nLen < 6 + 2 * nPointSize)
341
return OGRERR_NOT_ENOUGH_DATA;
344
OGRLineString* line = new OGRLineString();
345
line->setNumPoints(2);
347
if ( chProps & SP_HASZVALUES )
349
line->setPoint(0, ReadX(0), ReadY(0), ReadZ(0));
350
line->setPoint(1, ReadX(1), ReadY(1), ReadZ(1));
354
line->setPoint(0, ReadX(0), ReadY(0));
355
line->setPoint(1, ReadX(1), ReadY(1));
362
// complex geometries
363
nNumPoints = ReadInt32(6);
365
if ( nNumPoints <= 0 )
370
// position of the point array
373
// position of the figures
374
nFigurePos = nPointPos + nPointSize * nNumPoints + 4;
376
if (nLen < nFigurePos)
378
return OGRERR_NOT_ENOUGH_DATA;
381
nNumFigures = ReadInt32(nFigurePos - 4);
383
if ( nNumFigures <= 0 )
388
// position of the shapes
389
nShapePos = nFigurePos + 5 * nNumFigures + 4;
391
if (nLen < nShapePos)
393
return OGRERR_NOT_ENOUGH_DATA;
396
nNumShapes = ReadInt32(nShapePos - 4);
398
if (nLen < nShapePos + 9 * nNumShapes)
400
return OGRERR_NOT_ENOUGH_DATA;
403
if ( nNumShapes <= 0 )
408
// pick up the root shape
409
if ( ParentOffset(0) != 0xFFFFFFFF)
411
return OGRERR_CORRUPT_DATA;
414
// determine the shape type
415
switch (ShapeType(0))
418
*poGeom = ReadPoint(0);
421
*poGeom = ReadLineString(0);
424
*poGeom = ReadPolygon(0);
427
*poGeom = ReadMultiPoint(0);
429
case ST_MULTILINESTRING:
430
*poGeom = ReadMultiLineString(0);
432
case ST_MULTIPOLYGON:
433
*poGeom = ReadMultiPolygon(0);
435
case ST_GEOMETRYCOLLECTION:
436
*poGeom = ReadGeometryCollection(0);
439
return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;