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

« back to all changes in this revision

Viewing changes to ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.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: ogrmssqlgeometryparser.cpp 20591 2010-09-12 17:27:42Z tamas $
 
3
 *
 
4
 * Project:  MSSQL Spatial driver
 
5
 * Purpose:  Implements OGRMSSQLGeometryParser class to parse native SqlGeometries.
 
6
 * Author:   Tamas Szekeres, szekerest at gmail.com
 
7
 *
 
8
 ******************************************************************************
 
9
 * Copyright (c) 2010, Tamas Szekeres
 
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 "cpl_conv.h"
 
31
#include "ogr_mssqlspatial.h"
 
32
 
 
33
CPL_CVSID("$Id: ogrmssqlgeometryparser.cpp 20591 2010-09-12 17:27:42Z tamas $");
 
34
 
 
35
/************************************************************************/
 
36
/*                         Geometry parser macros                       */
 
37
/************************************************************************/
 
38
 
 
39
#define SP_NONE 0
 
40
#define SP_HASZVALUES 1
 
41
#define SP_HASMVALUES 2
 
42
#define SP_ISVALID 4
 
43
#define SP_ISSINGLEPOINT 8
 
44
#define SP_ISSINGLELINESEGMENT 0x10
 
45
#define SP_ISWHOLEGLOBE 0x20
 
46
 
 
47
#define ST_UNKNOWN 0
 
48
#define ST_POINT 1
 
49
#define ST_LINESTRING 2
 
50
#define ST_POLYGON 3
 
51
#define ST_MULTIPOINT 4
 
52
#define ST_MULTILINESTRING 5
 
53
#define ST_MULTIPOLYGON 6
 
54
#define ST_GEOMETRYCOLLECTION 7
 
55
 
 
56
#define ReadInt32(nPos) (*((unsigned int*)(pszData + (nPos))))
 
57
 
 
58
#define ReadByte(nPos) (pszData[nPos])
 
59
 
 
60
#define ReadDouble(nPos) (*((double*)(pszData + (nPos))))
 
61
 
 
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))
 
65
 
 
66
#define NextFigureOffset(iShape) (iShape + 1 < nNumShapes? FigureOffset((iShape) +1) : nNumFigures)
 
67
 
 
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)
 
71
 
 
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))
 
75
 
 
76
/************************************************************************/
 
77
/*                   OGRMSSQLGeometryParser()                           */
 
78
/************************************************************************/
 
79
 
 
80
OGRMSSQLGeometryParser::OGRMSSQLGeometryParser()
 
81
{
 
82
}
 
83
 
 
84
/************************************************************************/
 
85
/*                         ReadPoint()                                  */
 
86
/************************************************************************/
 
87
 
 
88
OGRPoint* OGRMSSQLGeometryParser::ReadPoint(int iShape)
 
89
{
 
90
    int iFigure = FigureOffset(iShape);
 
91
    if ( iFigure < nNumFigures )
 
92
    {
 
93
        int iPoint = PointOffset(iFigure);
 
94
        if ( iPoint < nNumPoints )
 
95
        {
 
96
            if ( chProps & SP_HASZVALUES )
 
97
                return new OGRPoint( ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
 
98
            else
 
99
                return new OGRPoint( ReadX(iPoint), ReadY(iPoint) );
 
100
        }
 
101
    }
 
102
    return NULL;
 
103
}
 
104
 
 
105
/************************************************************************/
 
106
/*                         ReadMultiPoint()                             */
 
107
/************************************************************************/
 
108
 
 
109
OGRMultiPoint* OGRMSSQLGeometryParser::ReadMultiPoint(int iShape)
 
110
{
 
111
    int iFigure, iPoint, iNextPoint;
 
112
    iFigure = FigureOffset(iShape);
 
113
 
 
114
    OGRMultiPoint* poMultiPoint = new OGRMultiPoint();
 
115
    iNextPoint = NextPointOffset(iFigure);
 
116
    for (iPoint = PointOffset(iFigure); iPoint < iNextPoint; iPoint++)
 
117
    {
 
118
        OGRPoint* poPoint;
 
119
        
 
120
        if ( chProps & SP_HASZVALUES )
 
121
            poPoint = new OGRPoint( ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
 
122
        else
 
123
            poPoint = new OGRPoint( ReadX(iPoint), ReadY(iPoint) );
 
124
 
 
125
        if ( poPoint )
 
126
            poMultiPoint->addGeometryDirectly( poPoint );
 
127
    }
 
128
 
 
129
    return poMultiPoint;
 
130
}
 
131
 
 
132
/************************************************************************/
 
133
/*                         ReadLineString()                             */
 
134
/************************************************************************/
 
135
 
 
136
OGRLineString* OGRMSSQLGeometryParser::ReadLineString(int iShape)
 
137
{
 
138
    int iFigure, iPoint, iNextPoint, i;
 
139
    iFigure = FigureOffset(iShape);
 
140
 
 
141
    OGRLineString* poLineString = new OGRLineString();
 
142
    iPoint = PointOffset(iFigure);
 
143
    iNextPoint = NextPointOffset(iFigure);
 
144
    poLineString->setNumPoints(iNextPoint - iPoint);
 
145
    i = 0;
 
146
    while (iPoint < iNextPoint)
 
147
    {
 
148
        if ( chProps & SP_HASZVALUES )
 
149
            poLineString->setPoint(i, ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
 
150
        else
 
151
            poLineString->setPoint(i, ReadX(iPoint), ReadY(iPoint) );
 
152
        
 
153
        ++iPoint;
 
154
        ++i;
 
155
    }
 
156
 
 
157
    return poLineString;
 
158
}
 
159
 
 
160
/************************************************************************/
 
161
/*                         ReadMultiLineString()                        */
 
162
/************************************************************************/
 
163
 
 
164
OGRMultiLineString* OGRMSSQLGeometryParser::ReadMultiLineString(int iShape)
 
165
{
 
166
    int i;
 
167
    OGRMultiLineString* poMultiLineString = new OGRMultiLineString();
 
168
    OGRGeometry* poGeom;
 
169
 
 
170
    for (i = iShape + 1; i < nNumShapes; i++)
 
171
    {
 
172
        poGeom = NULL;
 
173
        if (ParentOffset(i) == (unsigned int)iShape)
 
174
        {
 
175
            if  ( ShapeType(i) == ST_LINESTRING )
 
176
                poGeom = ReadLineString(i);
 
177
        }
 
178
        if ( poGeom )
 
179
            poMultiLineString->addGeometryDirectly( poGeom );
 
180
    }
 
181
 
 
182
    return poMultiLineString;
 
183
}
 
184
 
 
185
/************************************************************************/
 
186
/*                         ReadPolygon()                                */
 
187
/************************************************************************/
 
188
 
 
189
OGRPolygon* OGRMSSQLGeometryParser::ReadPolygon(int iShape)
 
190
{
 
191
    int iFigure, iPoint, iNextPoint, i;
 
192
    int iNextFigure = NextFigureOffset(iShape);
 
193
    
 
194
    OGRPolygon* poPoly = new OGRPolygon();
 
195
    for (iFigure = FigureOffset(iShape); iFigure < iNextFigure; iFigure++)
 
196
    {
 
197
        OGRLinearRing* poRing = new OGRLinearRing();
 
198
        iPoint = PointOffset(iFigure);
 
199
        iNextPoint = NextPointOffset(iFigure);
 
200
        poRing->setNumPoints(iNextPoint - iPoint);
 
201
        i = 0;
 
202
        while (iPoint < iNextPoint)
 
203
        {
 
204
            if ( chProps & SP_HASZVALUES )
 
205
                poRing->setPoint(i, ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
 
206
            else
 
207
                poRing->setPoint(i, ReadX(iPoint), ReadY(iPoint) );
 
208
 
 
209
            ++iPoint;
 
210
            ++i;
 
211
        }
 
212
        poPoly->addRingDirectly( poRing );
 
213
    }
 
214
    return poPoly;
 
215
}
 
216
 
 
217
/************************************************************************/
 
218
/*                         ReadMultiPolygon()                           */
 
219
/************************************************************************/
 
220
 
 
221
OGRMultiPolygon* OGRMSSQLGeometryParser::ReadMultiPolygon(int iShape)
 
222
{
 
223
    int i;
 
224
    OGRMultiPolygon* poMultiPolygon = new OGRMultiPolygon();
 
225
    OGRGeometry* poGeom;
 
226
 
 
227
    for (i = iShape + 1; i < nNumShapes; i++)
 
228
    {
 
229
        poGeom = NULL;
 
230
        if (ParentOffset(i) == (unsigned int)iShape)
 
231
        {
 
232
            if ( ShapeType(i) == ST_POLYGON )
 
233
                poGeom = ReadPolygon(i);
 
234
        }
 
235
        if ( poGeom )
 
236
            poMultiPolygon->addGeometryDirectly( poGeom );
 
237
    }
 
238
 
 
239
    return poMultiPolygon;
 
240
}
 
241
 
 
242
/************************************************************************/
 
243
/*                         ReadGeometryCollection()                     */
 
244
/************************************************************************/
 
245
 
 
246
OGRGeometryCollection* OGRMSSQLGeometryParser::ReadGeometryCollection(int iShape)
 
247
{
 
248
    int i;
 
249
    OGRGeometryCollection* poGeomColl = new OGRGeometryCollection();
 
250
    OGRGeometry* poGeom;
 
251
 
 
252
    for (i = iShape + 1; i < nNumShapes; i++)
 
253
    {
 
254
        poGeom = NULL;
 
255
        if (ParentOffset(i) == (unsigned int)iShape)
 
256
        {
 
257
            switch (ShapeType(i))
 
258
            {
 
259
            case ST_POINT:
 
260
                poGeom = ReadPoint(i);
 
261
                break;
 
262
            case ST_LINESTRING:
 
263
                poGeom = ReadLineString(i);
 
264
                break;
 
265
            case ST_POLYGON:
 
266
                poGeom = ReadPolygon(i);
 
267
                break;
 
268
            case ST_MULTIPOINT:
 
269
                poGeom = ReadMultiPoint(i);
 
270
                break;
 
271
            case ST_MULTILINESTRING:
 
272
                poGeom = ReadMultiLineString(i);
 
273
                break;
 
274
            case ST_MULTIPOLYGON:
 
275
                poGeom = ReadMultiPolygon(i);
 
276
                break;
 
277
            case ST_GEOMETRYCOLLECTION:
 
278
                poGeom = ReadGeometryCollection(i);
 
279
                break;
 
280
            }
 
281
        }
 
282
        if ( poGeom )
 
283
            poGeomColl->addGeometryDirectly( poGeom );
 
284
    }
 
285
 
 
286
    return poGeomColl;
 
287
}
 
288
 
 
289
/************************************************************************/
 
290
/*                         ParseSqlGeometry()                           */
 
291
/************************************************************************/
 
292
 
 
293
 
 
294
OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput, 
 
295
                                int nLen, OGRGeometry **poGeom)
 
296
{
 
297
    if (nLen < 10)
 
298
        return OGRERR_NOT_ENOUGH_DATA;
 
299
 
 
300
    pszData = pszInput;
 
301
    
 
302
    /* store the SRS id for further use */
 
303
    nSRSId = ReadInt32(0);
 
304
    
 
305
    if ( ReadByte(4) != 1 )
 
306
    {
 
307
        return OGRERR_CORRUPT_DATA;
 
308
    }
 
309
 
 
310
    chProps = ReadByte(5);
 
311
 
 
312
    if ( chProps & SP_HASMVALUES )
 
313
        nPointSize = 32;
 
314
    else if ( chProps & SP_HASZVALUES )
 
315
        nPointSize = 24;
 
316
    else
 
317
        nPointSize = 16;
 
318
 
 
319
    if ( chProps & SP_ISSINGLEPOINT )
 
320
    {
 
321
        // single point geometry
 
322
        nPointPos = 6;
 
323
 
 
324
        if (nLen < 6 + nPointSize)
 
325
        {
 
326
            return OGRERR_NOT_ENOUGH_DATA;
 
327
        }
 
328
 
 
329
        if (chProps & SP_HASZVALUES)
 
330
            *poGeom = new OGRPoint(ReadX(0), ReadY(0), ReadZ(0));
 
331
        else
 
332
            *poGeom = new OGRPoint(ReadX(0), ReadY(0));
 
333
    }
 
334
    else if ( chProps & SP_ISSINGLELINESEGMENT )
 
335
    {
 
336
        // single line segment with 2 points
 
337
        nPointPos = 6;
 
338
 
 
339
        if (nLen < 6 + 2 * nPointSize)
 
340
        {
 
341
            return OGRERR_NOT_ENOUGH_DATA;
 
342
        }
 
343
 
 
344
        OGRLineString* line = new OGRLineString();
 
345
        line->setNumPoints(2);
 
346
        
 
347
        if ( chProps & SP_HASZVALUES )
 
348
        {
 
349
            line->setPoint(0, ReadX(0), ReadY(0), ReadZ(0));
 
350
            line->setPoint(1, ReadX(1), ReadY(1), ReadZ(1));
 
351
        }
 
352
        else
 
353
        {
 
354
            line->setPoint(0, ReadX(0), ReadY(0));
 
355
            line->setPoint(1, ReadX(1), ReadY(1));
 
356
        }
 
357
        
 
358
        *poGeom = line;
 
359
    }
 
360
    else
 
361
    {
 
362
        // complex geometries
 
363
        nNumPoints = ReadInt32(6);
 
364
 
 
365
        if ( nNumPoints <= 0 )
 
366
        {
 
367
            return OGRERR_NONE;
 
368
        }
 
369
 
 
370
        // position of the point array
 
371
        nPointPos = 10;
 
372
 
 
373
        // position of the figures
 
374
        nFigurePos = nPointPos + nPointSize * nNumPoints + 4;
 
375
        
 
376
        if (nLen < nFigurePos)
 
377
        {
 
378
            return OGRERR_NOT_ENOUGH_DATA;
 
379
        }
 
380
 
 
381
        nNumFigures = ReadInt32(nFigurePos - 4);
 
382
 
 
383
        if ( nNumFigures <= 0 )
 
384
        {
 
385
            return OGRERR_NONE;
 
386
        }
 
387
        
 
388
        // position of the shapes
 
389
        nShapePos = nFigurePos + 5 * nNumFigures + 4;
 
390
 
 
391
        if (nLen < nShapePos)
 
392
        {
 
393
            return OGRERR_NOT_ENOUGH_DATA;
 
394
        }
 
395
 
 
396
        nNumShapes = ReadInt32(nShapePos - 4);
 
397
 
 
398
        if (nLen < nShapePos + 9 * nNumShapes)
 
399
        {
 
400
            return OGRERR_NOT_ENOUGH_DATA;
 
401
        }
 
402
 
 
403
        if ( nNumShapes <= 0 )
 
404
        {
 
405
            return OGRERR_NONE;
 
406
        }
 
407
 
 
408
        // pick up the root shape
 
409
        if ( ParentOffset(0) != 0xFFFFFFFF)
 
410
        {
 
411
            return OGRERR_CORRUPT_DATA;
 
412
        }
 
413
 
 
414
        // determine the shape type
 
415
        switch (ShapeType(0))
 
416
        {
 
417
        case ST_POINT:
 
418
            *poGeom = ReadPoint(0);
 
419
            break;
 
420
        case ST_LINESTRING:
 
421
            *poGeom = ReadLineString(0);
 
422
            break;
 
423
        case ST_POLYGON:
 
424
            *poGeom = ReadPolygon(0);
 
425
            break;
 
426
        case ST_MULTIPOINT:
 
427
            *poGeom = ReadMultiPoint(0);
 
428
            break;
 
429
        case ST_MULTILINESTRING:
 
430
            *poGeom = ReadMultiLineString(0);
 
431
            break;
 
432
        case ST_MULTIPOLYGON:
 
433
            *poGeom = ReadMultiPolygon(0);
 
434
            break;
 
435
        case ST_GEOMETRYCOLLECTION:
 
436
            *poGeom = ReadGeometryCollection(0);
 
437
            break;
 
438
        default:
 
439
            return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
440
        }
 
441
    }
 
442
 
 
443
    return OGRERR_NONE;
 
444
}
 
445