~ubuntu-branches/ubuntu/precise/spatialite/precise

« back to all changes in this revision

Viewing changes to libspatialite/src/gaiageo/gg_wkb.c

  • Committer: Package Import Robot
  • Author(s): David Paleino, Francesco Paolo Lovergine, David Paleino
  • Date: 2011-11-21 12:10:43 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20111121121043-0g14o2uf0r343a82
Tags: 3.0.0~beta20110817-3
[ Francesco Paolo Lovergine ]
* Fixed linking order for sqlite3 in debian patch 00-systemlibs.patch.
  (closes: #638929)

[ David Paleino ]
* Conditionally disable full EPSG initialization (for srs_init.c)
  on powerpc, and document what projections are available on that
  architecture (Closes: #649302)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
 gg_wkb.c -- Gaia common support for WKB encoded geometries
 
4
  
 
5
 version 3.0, 2011 July 20
 
6
 
 
7
 Author: Sandro Furieri a.furieri@lqt.it
 
8
 
 
9
 -----------------------------------------------------------------------------
 
10
 
 
11
 Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
12
 
 
13
 The contents of this file are subject to the Mozilla Public License Version
 
14
 1.1 (the "License"); you may not use this file except in compliance with
 
15
 the License. You may obtain a copy of the License at
 
16
 http://www.mozilla.org/MPL/
 
17
 
 
18
Software distributed under the License is distributed on an "AS IS" basis,
 
19
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
20
for the specific language governing rights and limitations under the
 
21
License.
 
22
 
 
23
The Original Code is the SpatiaLite library
 
24
 
 
25
The Initial Developer of the Original Code is Alessandro Furieri
 
26
 
 
27
Portions created by the Initial Developer are Copyright (C) 2008
 
28
the Initial Developer. All Rights Reserved.
 
29
 
 
30
Contributor(s):
 
31
 
 
32
Alternatively, the contents of this file may be used under the terms of
 
33
either the GNU General Public License Version 2 or later (the "GPL"), or
 
34
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
35
in which case the provisions of the GPL or the LGPL are applicable instead
 
36
of those above. If you wish to allow use of your version of this file only
 
37
under the terms of either the GPL or the LGPL, and not to allow others to
 
38
use your version of this file under the terms of the MPL, indicate your
 
39
decision by deleting the provisions above and replace them with the notice
 
40
and other provisions required by the GPL or the LGPL. If you do not delete
 
41
the provisions above, a recipient may use your version of this file under
 
42
the terms of any one of the MPL, the GPL or the LGPL.
 
43
 
 
44
*/
 
45
 
 
46
#include <sys/types.h>
 
47
#include <stdlib.h>
 
48
#include <stdio.h>
 
49
#include <float.h>
 
50
#include <string.h>
 
51
 
 
52
#ifdef SPL_AMALGAMATION         /* spatialite-amalgamation */
 
53
#include <spatialite/sqlite3ext.h>
 
54
#else
 
55
#include <sqlite3ext.h>
 
56
#endif
 
57
 
 
58
#include <spatialite/gaiageo.h>
 
59
 
 
60
static void
 
61
ParseWkbPoint (gaiaGeomCollPtr geo)
 
62
{
 
63
/* decodes a POINT from WKB */
 
64
    double x;
 
65
    double y;
 
66
    if (geo->size < geo->offset + 16)
 
67
        return;
 
68
    x = gaiaImport64 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
69
    y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
70
                      geo->endian_arch);
 
71
    geo->offset += 16;
 
72
    gaiaAddPointToGeomColl (geo, x, y);
 
73
}
 
74
 
 
75
static void
 
76
ParseWkbPointZ (gaiaGeomCollPtr geo)
 
77
{
 
78
/* decodes a POINTZ from WKB */
 
79
    double x;
 
80
    double y;
 
81
    double z;
 
82
    if (geo->size < geo->offset + 24)
 
83
        return;
 
84
    x = gaiaImport64 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
85
    y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
86
                      geo->endian_arch);
 
87
    z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
88
                      geo->endian_arch);
 
89
    geo->offset += 24;
 
90
    gaiaAddPointToGeomCollXYZ (geo, x, y, z);
 
91
}
 
92
 
 
93
static void
 
94
ParseWkbPointM (gaiaGeomCollPtr geo)
 
95
{
 
96
/* decodes a POINTM from WKB */
 
97
    double x;
 
98
    double y;
 
99
    double m;
 
100
    if (geo->size < geo->offset + 24)
 
101
        return;
 
102
    x = gaiaImport64 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
103
    y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
104
                      geo->endian_arch);
 
105
    m = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
106
                      geo->endian_arch);
 
107
    geo->offset += 24;
 
108
    gaiaAddPointToGeomCollXYM (geo, x, y, m);
 
109
}
 
110
 
 
111
static void
 
112
ParseWkbPointZM (gaiaGeomCollPtr geo)
 
113
{
 
114
/* decodes a POINTZM from WKB */
 
115
    double x;
 
116
    double y;
 
117
    double z;
 
118
    double m;
 
119
    if (geo->size < geo->offset + 32)
 
120
        return;
 
121
    x = gaiaImport64 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
122
    y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
123
                      geo->endian_arch);
 
124
    z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
125
                      geo->endian_arch);
 
126
    m = gaiaImport64 (geo->blob + (geo->offset + 24), geo->endian,
 
127
                      geo->endian_arch);
 
128
    geo->offset += 32;
 
129
    gaiaAddPointToGeomCollXYZM (geo, x, y, z, m);
 
130
}
 
131
 
 
132
static void
 
133
ParseWkbLine (gaiaGeomCollPtr geo)
 
134
{
 
135
/* decodes a LINESTRING from WKB */
 
136
    int points;
 
137
    int iv;
 
138
    double x;
 
139
    double y;
 
140
    gaiaLinestringPtr line;
 
141
    if (geo->size < geo->offset + 4)
 
142
        return;
 
143
    points =
 
144
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
145
    geo->offset += 4;
 
146
    if (geo->size < geo->offset + (16 * points))
 
147
        return;
 
148
    line = gaiaAddLinestringToGeomColl (geo, points);
 
149
    for (iv = 0; iv < points; iv++)
 
150
      {
 
151
          x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
152
                            geo->endian_arch);
 
153
          y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
154
                            geo->endian_arch);
 
155
          gaiaSetPoint (line->Coords, iv, x, y);
 
156
          geo->offset += 16;
 
157
      }
 
158
}
 
159
 
 
160
static void
 
161
ParseWkbLineZ (gaiaGeomCollPtr geo)
 
162
{
 
163
/* decodes a LINESTRINGZ from WKB */
 
164
    int points;
 
165
    int iv;
 
166
    double x;
 
167
    double y;
 
168
    double z;
 
169
    gaiaLinestringPtr line;
 
170
    if (geo->size < geo->offset + 4)
 
171
        return;
 
172
    points =
 
173
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
174
    geo->offset += 4;
 
175
    if (geo->size < geo->offset + (24 * points))
 
176
        return;
 
177
    line = gaiaAddLinestringToGeomColl (geo, points);
 
178
    for (iv = 0; iv < points; iv++)
 
179
      {
 
180
          x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
181
                            geo->endian_arch);
 
182
          y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
183
                            geo->endian_arch);
 
184
          z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
185
                            geo->endian_arch);
 
186
          gaiaSetPointXYZ (line->Coords, iv, x, y, z);
 
187
          geo->offset += 24;
 
188
      }
 
189
}
 
190
 
 
191
static void
 
192
ParseWkbLineM (gaiaGeomCollPtr geo)
 
193
{
 
194
/* decodes a LINESTRINGM from WKB */
 
195
    int points;
 
196
    int iv;
 
197
    double x;
 
198
    double y;
 
199
    double m;
 
200
    gaiaLinestringPtr line;
 
201
    if (geo->size < geo->offset + 4)
 
202
        return;
 
203
    points =
 
204
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
205
    geo->offset += 4;
 
206
    if (geo->size < geo->offset + (24 * points))
 
207
        return;
 
208
    line = gaiaAddLinestringToGeomColl (geo, points);
 
209
    for (iv = 0; iv < points; iv++)
 
210
      {
 
211
          x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
212
                            geo->endian_arch);
 
213
          y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
214
                            geo->endian_arch);
 
215
          m = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
216
                            geo->endian_arch);
 
217
          gaiaSetPointXYM (line->Coords, iv, x, y, m);
 
218
          geo->offset += 24;
 
219
      }
 
220
}
 
221
 
 
222
static void
 
223
ParseWkbLineZM (gaiaGeomCollPtr geo)
 
224
{
 
225
/* decodes a LINESTRINGZM from WKB */
 
226
    int points;
 
227
    int iv;
 
228
    double x;
 
229
    double y;
 
230
    double z;
 
231
    double m;
 
232
    gaiaLinestringPtr line;
 
233
    if (geo->size < geo->offset + 4)
 
234
        return;
 
235
    points =
 
236
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
237
    geo->offset += 4;
 
238
    if (geo->size < geo->offset + (32 * points))
 
239
        return;
 
240
    line = gaiaAddLinestringToGeomColl (geo, points);
 
241
    for (iv = 0; iv < points; iv++)
 
242
      {
 
243
          x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
244
                            geo->endian_arch);
 
245
          y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
246
                            geo->endian_arch);
 
247
          z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
248
                            geo->endian_arch);
 
249
          m = gaiaImport64 (geo->blob + (geo->offset + 24), geo->endian,
 
250
                            geo->endian_arch);
 
251
          gaiaSetPointXYZM (line->Coords, iv, x, y, z, m);
 
252
          geo->offset += 32;
 
253
      }
 
254
}
 
255
 
 
256
static void
 
257
ParseWkbPolygon (gaiaGeomCollPtr geo)
 
258
{
 
259
/* decodes a POLYGON from WKB */
 
260
    int rings;
 
261
    int nverts;
 
262
    int iv;
 
263
    int ib;
 
264
    double x;
 
265
    double y;
 
266
    gaiaPolygonPtr polyg = NULL;
 
267
    gaiaRingPtr ring;
 
268
    if (geo->size < geo->offset + 4)
 
269
        return;
 
270
    rings =
 
271
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
272
    geo->offset += 4;
 
273
    for (ib = 0; ib < rings; ib++)
 
274
      {
 
275
          if (geo->size < geo->offset + 4)
 
276
              return;
 
277
          nverts =
 
278
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
279
                            geo->endian_arch);
 
280
          geo->offset += 4;
 
281
          if (geo->size < geo->offset + (16 * nverts))
 
282
              return;
 
283
          if (ib == 0)
 
284
            {
 
285
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
286
                ring = polyg->Exterior;
 
287
            }
 
288
          else
 
289
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
290
          for (iv = 0; iv < nverts; iv++)
 
291
            {
 
292
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
293
                                  geo->endian_arch);
 
294
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
295
                                  geo->endian_arch);
 
296
                geo->offset += 16;
 
297
                gaiaSetPoint (ring->Coords, iv, x, y);
 
298
            }
 
299
      }
 
300
}
 
301
 
 
302
static void
 
303
ParseWkbPolygonZ (gaiaGeomCollPtr geo)
 
304
{
 
305
/* decodes a POLYGONZ from WKB */
 
306
    int rings;
 
307
    int nverts;
 
308
    int iv;
 
309
    int ib;
 
310
    double x;
 
311
    double y;
 
312
    double z;
 
313
    gaiaPolygonPtr polyg = NULL;
 
314
    gaiaRingPtr ring;
 
315
    if (geo->size < geo->offset + 4)
 
316
        return;
 
317
    rings =
 
318
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
319
    geo->offset += 4;
 
320
    for (ib = 0; ib < rings; ib++)
 
321
      {
 
322
          if (geo->size < geo->offset + 4)
 
323
              return;
 
324
          nverts =
 
325
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
326
                            geo->endian_arch);
 
327
          geo->offset += 4;
 
328
          if (geo->size < geo->offset + (24 * nverts))
 
329
              return;
 
330
          if (ib == 0)
 
331
            {
 
332
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
333
                ring = polyg->Exterior;
 
334
            }
 
335
          else
 
336
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
337
          for (iv = 0; iv < nverts; iv++)
 
338
            {
 
339
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
340
                                  geo->endian_arch);
 
341
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
342
                                  geo->endian_arch);
 
343
                z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
344
                                  geo->endian_arch);
 
345
                geo->offset += 24;
 
346
                gaiaSetPointXYZ (ring->Coords, iv, x, y, z);
 
347
            }
 
348
      }
 
349
}
 
350
 
 
351
static void
 
352
ParseWkbPolygonM (gaiaGeomCollPtr geo)
 
353
{
 
354
/* decodes a POLYGONM from WKB */
 
355
    int rings;
 
356
    int nverts;
 
357
    int iv;
 
358
    int ib;
 
359
    double x;
 
360
    double y;
 
361
    double m;
 
362
    gaiaPolygonPtr polyg = NULL;
 
363
    gaiaRingPtr ring;
 
364
    if (geo->size < geo->offset + 4)
 
365
        return;
 
366
    rings =
 
367
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
368
    geo->offset += 4;
 
369
    for (ib = 0; ib < rings; ib++)
 
370
      {
 
371
          if (geo->size < geo->offset + 4)
 
372
              return;
 
373
          nverts =
 
374
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
375
                            geo->endian_arch);
 
376
          geo->offset += 4;
 
377
          if (geo->size < geo->offset + (24 * nverts))
 
378
              return;
 
379
          if (ib == 0)
 
380
            {
 
381
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
382
                ring = polyg->Exterior;
 
383
            }
 
384
          else
 
385
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
386
          for (iv = 0; iv < nverts; iv++)
 
387
            {
 
388
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
389
                                  geo->endian_arch);
 
390
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
391
                                  geo->endian_arch);
 
392
                m = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
393
                                  geo->endian_arch);
 
394
                geo->offset += 24;
 
395
                gaiaSetPointXYM (ring->Coords, iv, x, y, m);
 
396
            }
 
397
      }
 
398
}
 
399
 
 
400
static void
 
401
ParseWkbPolygonZM (gaiaGeomCollPtr geo)
 
402
{
 
403
/* decodes a POLYGONZM from WKB */
 
404
    int rings;
 
405
    int nverts;
 
406
    int iv;
 
407
    int ib;
 
408
    double x;
 
409
    double y;
 
410
    double z;
 
411
    double m;
 
412
    gaiaPolygonPtr polyg = NULL;
 
413
    gaiaRingPtr ring;
 
414
    if (geo->size < geo->offset + 4)
 
415
        return;
 
416
    rings =
 
417
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
418
    geo->offset += 4;
 
419
    for (ib = 0; ib < rings; ib++)
 
420
      {
 
421
          if (geo->size < geo->offset + 4)
 
422
              return;
 
423
          nverts =
 
424
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
425
                            geo->endian_arch);
 
426
          geo->offset += 4;
 
427
          if (geo->size < geo->offset + (32 * nverts))
 
428
              return;
 
429
          if (ib == 0)
 
430
            {
 
431
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
432
                ring = polyg->Exterior;
 
433
            }
 
434
          else
 
435
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
436
          for (iv = 0; iv < nverts; iv++)
 
437
            {
 
438
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
439
                                  geo->endian_arch);
 
440
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
441
                                  geo->endian_arch);
 
442
                z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
443
                                  geo->endian_arch);
 
444
                m = gaiaImport64 (geo->blob + (geo->offset + 24), geo->endian,
 
445
                                  geo->endian_arch);
 
446
                geo->offset += 32;
 
447
                gaiaSetPointXYZM (ring->Coords, iv, x, y, z, m);
 
448
            }
 
449
      }
 
450
}
 
451
 
 
452
static void
 
453
ParseCompressedWkbLine (gaiaGeomCollPtr geo)
 
454
{
 
455
/* decodes a COMPRESSED LINESTRING from WKB */
 
456
    int points;
 
457
    int iv;
 
458
    double x;
 
459
    double y;
 
460
    double last_x = 0.0;
 
461
    double last_y = 0.0;
 
462
    float fx;
 
463
    float fy;
 
464
    gaiaLinestringPtr line;
 
465
    if (geo->size < geo->offset + 4)
 
466
        return;
 
467
    points =
 
468
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
469
    geo->offset += 4;
 
470
    if (geo->size < geo->offset + (8 * points) + 16)
 
471
        return;
 
472
    line = gaiaAddLinestringToGeomColl (geo, points);
 
473
    for (iv = 0; iv < points; iv++)
 
474
      {
 
475
          if (iv == 0 || iv == (points - 1))
 
476
            {
 
477
                /* first and last vertices are uncompressed */
 
478
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
479
                                  geo->endian_arch);
 
480
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
481
                                  geo->endian_arch);
 
482
                geo->offset += 16;
 
483
            }
 
484
          else
 
485
            {
 
486
                /* any other intermediate vertex is compressed */
 
487
                fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
488
                                    geo->endian_arch);
 
489
                fy = gaiaImportF32 (geo->blob + (geo->offset + 4), geo->endian,
 
490
                                    geo->endian_arch);
 
491
                x = last_x + fx;
 
492
                y = last_y + fy;
 
493
                geo->offset += 8;
 
494
            }
 
495
          gaiaSetPoint (line->Coords, iv, x, y);
 
496
          last_x = x;
 
497
          last_y = y;
 
498
      }
 
499
}
 
500
 
 
501
static void
 
502
ParseCompressedWkbLineZ (gaiaGeomCollPtr geo)
 
503
{
 
504
/* decodes a COMPRESSED LINESTRINGZ from WKB */
 
505
    int points;
 
506
    int iv;
 
507
    double x;
 
508
    double y;
 
509
    double z;
 
510
    double last_x = 0.0;
 
511
    double last_y = 0.0;
 
512
    double last_z = 0.0;
 
513
    float fx;
 
514
    float fy;
 
515
    float fz;
 
516
    gaiaLinestringPtr line;
 
517
    if (geo->size < geo->offset + 4)
 
518
        return;
 
519
    points =
 
520
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
521
    geo->offset += 4;
 
522
    if (geo->size < geo->offset + (12 * points) + 24)
 
523
        return;
 
524
    line = gaiaAddLinestringToGeomColl (geo, points);
 
525
    for (iv = 0; iv < points; iv++)
 
526
      {
 
527
          if (iv == 0 || iv == (points - 1))
 
528
            {
 
529
                /* first and last vertices are uncompressed */
 
530
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
531
                                  geo->endian_arch);
 
532
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
533
                                  geo->endian_arch);
 
534
                z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
535
                                  geo->endian_arch);
 
536
                geo->offset += 24;
 
537
            }
 
538
          else
 
539
            {
 
540
                /* any other intermediate vertex is compressed */
 
541
                fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
542
                                    geo->endian_arch);
 
543
                fy = gaiaImportF32 (geo->blob + (geo->offset + 4), geo->endian,
 
544
                                    geo->endian_arch);
 
545
                fz = gaiaImportF32 (geo->blob + (geo->offset + 8), geo->endian,
 
546
                                    geo->endian_arch);
 
547
                x = last_x + fx;
 
548
                y = last_y + fy;
 
549
                z = last_z + fz;
 
550
                geo->offset += 12;
 
551
            }
 
552
          gaiaSetPointXYZ (line->Coords, iv, x, y, z);
 
553
          last_x = x;
 
554
          last_y = y;
 
555
          last_z = z;
 
556
      }
 
557
}
 
558
 
 
559
static void
 
560
ParseCompressedWkbLineM (gaiaGeomCollPtr geo)
 
561
{
 
562
/* decodes a COMPRESSED LINESTRINGM from WKB */
 
563
    int points;
 
564
    int iv;
 
565
    double x;
 
566
    double y;
 
567
    double m;
 
568
    double last_x = 0.0;
 
569
    double last_y = 0.0;
 
570
    float fx;
 
571
    float fy;
 
572
    gaiaLinestringPtr line;
 
573
    if (geo->size < geo->offset + 4)
 
574
        return;
 
575
    points =
 
576
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
577
    geo->offset += 4;
 
578
    if (geo->size < geo->offset + (16 * points) + 16)
 
579
        return;
 
580
    line = gaiaAddLinestringToGeomColl (geo, points);
 
581
    for (iv = 0; iv < points; iv++)
 
582
      {
 
583
          if (iv == 0 || iv == (points - 1))
 
584
            {
 
585
                /* first and last vertices are uncompressed */
 
586
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
587
                                  geo->endian_arch);
 
588
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
589
                                  geo->endian_arch);
 
590
                m = gaiaImport64 (geo->blob + (geo->offset + 24), geo->endian,
 
591
                                  geo->endian_arch);
 
592
                geo->offset += 24;
 
593
            }
 
594
          else
 
595
            {
 
596
                /* any other intermediate vertex is compressed */
 
597
                fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
598
                                    geo->endian_arch);
 
599
                fy = gaiaImportF32 (geo->blob + (geo->offset + 4), geo->endian,
 
600
                                    geo->endian_arch);
 
601
                m = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
602
                                  geo->endian_arch);
 
603
                x = last_x + fx;
 
604
                y = last_y + fy;
 
605
                geo->offset += 16;
 
606
            }
 
607
          gaiaSetPointXYM (line->Coords, iv, x, y, m);
 
608
          last_x = x;
 
609
          last_y = y;
 
610
      }
 
611
}
 
612
 
 
613
static void
 
614
ParseCompressedWkbLineZM (gaiaGeomCollPtr geo)
 
615
{
 
616
/* decodes a COMPRESSED LINESTRINGZM from WKB */
 
617
    int points;
 
618
    int iv;
 
619
    double x;
 
620
    double y;
 
621
    double z;
 
622
    double m;
 
623
    double last_x = 0.0;
 
624
    double last_y = 0.0;
 
625
    double last_z = 0.0;
 
626
    float fx;
 
627
    float fy;
 
628
    float fz;
 
629
    gaiaLinestringPtr line;
 
630
    if (geo->size < geo->offset + 4)
 
631
        return;
 
632
    points =
 
633
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
634
    geo->offset += 4;
 
635
    if (geo->size < geo->offset + (20 * points) + 24)
 
636
        return;
 
637
    line = gaiaAddLinestringToGeomColl (geo, points);
 
638
    for (iv = 0; iv < points; iv++)
 
639
      {
 
640
          if (iv == 0 || iv == (points - 1))
 
641
            {
 
642
                /* first and last vertices are uncompressed */
 
643
                x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
644
                                  geo->endian_arch);
 
645
                y = gaiaImport64 (geo->blob + (geo->offset + 8), geo->endian,
 
646
                                  geo->endian_arch);
 
647
                z = gaiaImport64 (geo->blob + (geo->offset + 16), geo->endian,
 
648
                                  geo->endian_arch);
 
649
                m = gaiaImport64 (geo->blob + (geo->offset + 24), geo->endian,
 
650
                                  geo->endian_arch);
 
651
                geo->offset += 32;
 
652
            }
 
653
          else
 
654
            {
 
655
                /* any other intermediate vertex is compressed */
 
656
                fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
657
                                    geo->endian_arch);
 
658
                fy = gaiaImportF32 (geo->blob + (geo->offset + 4), geo->endian,
 
659
                                    geo->endian_arch);
 
660
                fz = gaiaImportF32 (geo->blob + (geo->offset + 8), geo->endian,
 
661
                                    geo->endian_arch);
 
662
                m = gaiaImport64 (geo->blob + (geo->offset + 12), geo->endian,
 
663
                                  geo->endian_arch);
 
664
                x = last_x + fx;
 
665
                y = last_y + fy;
 
666
                z = last_z + fz;
 
667
                geo->offset += 20;
 
668
            }
 
669
          gaiaSetPointXYZM (line->Coords, iv, x, y, z, m);
 
670
          last_x = x;
 
671
          last_y = y;
 
672
          last_z = z;
 
673
      }
 
674
}
 
675
 
 
676
static void
 
677
ParseCompressedWkbPolygon (gaiaGeomCollPtr geo)
 
678
{
 
679
/* decodes a COMPRESSED POLYGON from WKB */
 
680
    int rings;
 
681
    int nverts;
 
682
    int iv;
 
683
    int ib;
 
684
    double x;
 
685
    double y;
 
686
    double last_x = 0.0;
 
687
    double last_y = 0.0;
 
688
    float fx;
 
689
    float fy;
 
690
    gaiaPolygonPtr polyg = NULL;
 
691
    gaiaRingPtr ring;
 
692
    if (geo->size < geo->offset + 4)
 
693
        return;
 
694
    rings =
 
695
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
696
    geo->offset += 4;
 
697
    for (ib = 0; ib < rings; ib++)
 
698
      {
 
699
          if (geo->size < geo->offset + 4)
 
700
              return;
 
701
          nverts =
 
702
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
703
                            geo->endian_arch);
 
704
          geo->offset += 4;
 
705
          if (geo->size < geo->offset + (8 * nverts) + 16)
 
706
              return;
 
707
          if (ib == 0)
 
708
            {
 
709
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
710
                ring = polyg->Exterior;
 
711
            }
 
712
          else
 
713
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
714
          for (iv = 0; iv < nverts; iv++)
 
715
            {
 
716
                if (iv == 0 || iv == (nverts - 1))
 
717
                  {
 
718
                      /* first and last vertices are uncompressed */
 
719
                      x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
720
                                        geo->endian_arch);
 
721
                      y = gaiaImport64 (geo->blob + (geo->offset + 8),
 
722
                                        geo->endian, geo->endian_arch);
 
723
                      geo->offset += 16;
 
724
                  }
 
725
                else
 
726
                  {
 
727
                      /* any other intermediate vertex is compressed */
 
728
                      fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
729
                                          geo->endian_arch);
 
730
                      fy = gaiaImportF32 (geo->blob + (geo->offset + 4),
 
731
                                          geo->endian, geo->endian_arch);
 
732
                      x = last_x + fx;
 
733
                      y = last_y + fy;
 
734
                      geo->offset += 8;
 
735
                  }
 
736
                gaiaSetPoint (ring->Coords, iv, x, y);
 
737
                last_x = x;
 
738
                last_y = y;
 
739
            }
 
740
      }
 
741
}
 
742
 
 
743
static void
 
744
ParseCompressedWkbPolygonZ (gaiaGeomCollPtr geo)
 
745
{
 
746
/* decodes a COMPRESSED POLYGONZ from WKB */
 
747
    int rings;
 
748
    int nverts;
 
749
    int iv;
 
750
    int ib;
 
751
    double x;
 
752
    double y;
 
753
    double z;
 
754
    double last_x = 0.0;
 
755
    double last_y = 0.0;
 
756
    double last_z = 0.0;
 
757
    float fx;
 
758
    float fy;
 
759
    float fz;
 
760
    gaiaPolygonPtr polyg = NULL;
 
761
    gaiaRingPtr ring;
 
762
    if (geo->size < geo->offset + 4)
 
763
        return;
 
764
    rings =
 
765
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
766
    geo->offset += 4;
 
767
    for (ib = 0; ib < rings; ib++)
 
768
      {
 
769
          if (geo->size < geo->offset + 4)
 
770
              return;
 
771
          nverts =
 
772
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
773
                            geo->endian_arch);
 
774
          geo->offset += 4;
 
775
          if (geo->size < geo->offset + (12 * nverts) + 24)
 
776
              return;
 
777
          if (ib == 0)
 
778
            {
 
779
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
780
                ring = polyg->Exterior;
 
781
            }
 
782
          else
 
783
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
784
          for (iv = 0; iv < nverts; iv++)
 
785
            {
 
786
                if (iv == 0 || iv == (nverts - 1))
 
787
                  {
 
788
                      /* first and last vertices are uncompressed */
 
789
                      x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
790
                                        geo->endian_arch);
 
791
                      y = gaiaImport64 (geo->blob + (geo->offset + 8),
 
792
                                        geo->endian, geo->endian_arch);
 
793
                      z = gaiaImport64 (geo->blob + (geo->offset + 16),
 
794
                                        geo->endian, geo->endian_arch);
 
795
                      geo->offset += 24;
 
796
                  }
 
797
                else
 
798
                  {
 
799
                      /* any other intermediate vertex is compressed */
 
800
                      fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
801
                                          geo->endian_arch);
 
802
                      fy = gaiaImportF32 (geo->blob + (geo->offset + 4),
 
803
                                          geo->endian, geo->endian_arch);
 
804
                      fz = gaiaImportF32 (geo->blob + (geo->offset + 8),
 
805
                                          geo->endian, geo->endian_arch);
 
806
                      x = last_x + fx;
 
807
                      y = last_y + fy;
 
808
                      z = last_z + fz;
 
809
                      geo->offset += 12;
 
810
                  }
 
811
                gaiaSetPointXYZ (ring->Coords, iv, x, y, z);
 
812
                last_x = x;
 
813
                last_y = y;
 
814
                last_z = z;
 
815
            }
 
816
      }
 
817
}
 
818
 
 
819
static void
 
820
ParseCompressedWkbPolygonM (gaiaGeomCollPtr geo)
 
821
{
 
822
/* decodes a COMPRESSED POLYGONM from WKB */
 
823
    int rings;
 
824
    int nverts;
 
825
    int iv;
 
826
    int ib;
 
827
    double x;
 
828
    double y;
 
829
    double m;
 
830
    double last_x = 0.0;
 
831
    double last_y = 0.0;
 
832
    float fx;
 
833
    float fy;
 
834
    gaiaPolygonPtr polyg = NULL;
 
835
    gaiaRingPtr ring;
 
836
    if (geo->size < geo->offset + 4)
 
837
        return;
 
838
    rings =
 
839
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
840
    geo->offset += 4;
 
841
    for (ib = 0; ib < rings; ib++)
 
842
      {
 
843
          if (geo->size < geo->offset + 4)
 
844
              return;
 
845
          nverts =
 
846
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
847
                            geo->endian_arch);
 
848
          geo->offset += 4;
 
849
          if (geo->size < geo->offset + (16 * nverts) + 16)
 
850
              return;
 
851
          if (ib == 0)
 
852
            {
 
853
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
854
                ring = polyg->Exterior;
 
855
            }
 
856
          else
 
857
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
858
          for (iv = 0; iv < nverts; iv++)
 
859
            {
 
860
                if (iv == 0 || iv == (nverts - 1))
 
861
                  {
 
862
                      /* first and last vertices are uncompressed */
 
863
                      x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
864
                                        geo->endian_arch);
 
865
                      y = gaiaImport64 (geo->blob + (geo->offset + 8),
 
866
                                        geo->endian, geo->endian_arch);
 
867
                      m = gaiaImport64 (geo->blob + (geo->offset + 24),
 
868
                                        geo->endian, geo->endian_arch);
 
869
                      geo->offset += 24;
 
870
                  }
 
871
                else
 
872
                  {
 
873
                      /* any other intermediate vertex is compressed */
 
874
                      fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
875
                                          geo->endian_arch);
 
876
                      fy = gaiaImportF32 (geo->blob + (geo->offset + 4),
 
877
                                          geo->endian, geo->endian_arch);
 
878
                      m = gaiaImport64 (geo->blob + (geo->offset + 8),
 
879
                                        geo->endian, geo->endian_arch);
 
880
                      x = last_x + fx;
 
881
                      y = last_y + fy;
 
882
                      geo->offset += 16;
 
883
                  }
 
884
                gaiaSetPointXYM (ring->Coords, iv, x, y, m);
 
885
                last_x = x;
 
886
                last_y = y;
 
887
            }
 
888
      }
 
889
}
 
890
 
 
891
static void
 
892
ParseCompressedWkbPolygonZM (gaiaGeomCollPtr geo)
 
893
{
 
894
/* decodes a COMPRESSED POLYGONZM from WKB */
 
895
    int rings;
 
896
    int nverts;
 
897
    int iv;
 
898
    int ib;
 
899
    double x;
 
900
    double y;
 
901
    double z;
 
902
    double m;
 
903
    double last_x = 0.0;
 
904
    double last_y = 0.0;
 
905
    double last_z = 0.0;
 
906
    float fx;
 
907
    float fy;
 
908
    float fz;
 
909
    gaiaPolygonPtr polyg = NULL;
 
910
    gaiaRingPtr ring;
 
911
    if (geo->size < geo->offset + 4)
 
912
        return;
 
913
    rings =
 
914
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
915
    geo->offset += 4;
 
916
    for (ib = 0; ib < rings; ib++)
 
917
      {
 
918
          if (geo->size < geo->offset + 4)
 
919
              return;
 
920
          nverts =
 
921
              gaiaImport32 (geo->blob + geo->offset, geo->endian,
 
922
                            geo->endian_arch);
 
923
          geo->offset += 4;
 
924
          if (geo->size < geo->offset + (20 * nverts) + 24)
 
925
              return;
 
926
          if (ib == 0)
 
927
            {
 
928
                polyg = gaiaAddPolygonToGeomColl (geo, nverts, rings - 1);
 
929
                ring = polyg->Exterior;
 
930
            }
 
931
          else
 
932
              ring = gaiaAddInteriorRing (polyg, ib - 1, nverts);
 
933
          for (iv = 0; iv < nverts; iv++)
 
934
            {
 
935
                if (iv == 0 || iv == (nverts - 1))
 
936
                  {
 
937
                      /* first and last vertices are uncompressed */
 
938
                      x = gaiaImport64 (geo->blob + geo->offset, geo->endian,
 
939
                                        geo->endian_arch);
 
940
                      y = gaiaImport64 (geo->blob + (geo->offset + 8),
 
941
                                        geo->endian, geo->endian_arch);
 
942
                      z = gaiaImport64 (geo->blob + (geo->offset + 16),
 
943
                                        geo->endian, geo->endian_arch);
 
944
                      m = gaiaImport64 (geo->blob + (geo->offset + 24),
 
945
                                        geo->endian, geo->endian_arch);
 
946
                      geo->offset += 32;
 
947
                  }
 
948
                else
 
949
                  {
 
950
                      /* any other intermediate vertex is compressed */
 
951
                      fx = gaiaImportF32 (geo->blob + geo->offset, geo->endian,
 
952
                                          geo->endian_arch);
 
953
                      fy = gaiaImportF32 (geo->blob + (geo->offset + 4),
 
954
                                          geo->endian, geo->endian_arch);
 
955
                      fz = gaiaImportF32 (geo->blob + (geo->offset + 8),
 
956
                                          geo->endian, geo->endian_arch);
 
957
                      m = gaiaImport64 (geo->blob + (geo->offset + 12),
 
958
                                        geo->endian, geo->endian_arch);
 
959
                      x = last_x + fx;
 
960
                      y = last_y + fy;
 
961
                      z = last_z + fz;
 
962
                      geo->offset += 20;
 
963
                  }
 
964
                gaiaSetPointXYZM (ring->Coords, iv, x, y, z, m);
 
965
                last_x = x;
 
966
                last_y = y;
 
967
                last_z = z;
 
968
            }
 
969
      }
 
970
}
 
971
 
 
972
static void
 
973
ParseWkbGeometry (gaiaGeomCollPtr geo)
 
974
{
 
975
/* decodes a MULTIxx or GEOMETRYCOLLECTION from SpatiaLite BLOB */
 
976
    int entities;
 
977
    int type;
 
978
    int ie;
 
979
    if (geo->size < geo->offset + 4)
 
980
        return;
 
981
    entities =
 
982
        gaiaImport32 (geo->blob + geo->offset, geo->endian, geo->endian_arch);
 
983
    geo->offset += 4;
 
984
    for (ie = 0; ie < entities; ie++)
 
985
      {
 
986
          if (geo->size < geo->offset + 5)
 
987
              return;
 
988
          type =
 
989
              gaiaImport32 (geo->blob + geo->offset + 1, geo->endian,
 
990
                            geo->endian_arch);
 
991
          geo->offset += 5;
 
992
          switch (type)
 
993
            {
 
994
            case GAIA_POINT:
 
995
                ParseWkbPoint (geo);
 
996
                break;
 
997
            case GAIA_POINTZ:
 
998
            case GAIA_GEOSWKB_POINTZ:
 
999
                ParseWkbPointZ (geo);
 
1000
                break;
 
1001
            case GAIA_POINTM:
 
1002
                ParseWkbPointM (geo);
 
1003
                break;
 
1004
            case GAIA_POINTZM:
 
1005
                ParseWkbPointZM (geo);
 
1006
                break;
 
1007
            case GAIA_LINESTRING:
 
1008
                ParseWkbLine (geo);
 
1009
                break;
 
1010
            case GAIA_LINESTRINGZ:
 
1011
            case GAIA_GEOSWKB_LINESTRINGZ:
 
1012
                ParseWkbLineZ (geo);
 
1013
                break;
 
1014
            case GAIA_LINESTRINGM:
 
1015
                ParseWkbLineM (geo);
 
1016
                break;
 
1017
            case GAIA_LINESTRINGZM:
 
1018
                ParseWkbLineZM (geo);
 
1019
                break;
 
1020
            case GAIA_POLYGON:
 
1021
                ParseWkbPolygon (geo);
 
1022
                break;
 
1023
            case GAIA_POLYGONZ:
 
1024
            case GAIA_GEOSWKB_POLYGONZ:
 
1025
                ParseWkbPolygonZ (geo);
 
1026
                break;
 
1027
            case GAIA_POLYGONM:
 
1028
                ParseWkbPolygonM (geo);
 
1029
                break;
 
1030
            case GAIA_POLYGONZM:
 
1031
                ParseWkbPolygonZM (geo);
 
1032
                break;
 
1033
            case GAIA_COMPRESSED_LINESTRING:
 
1034
                ParseCompressedWkbLine (geo);
 
1035
                break;
 
1036
            case GAIA_COMPRESSED_LINESTRINGZ:
 
1037
                ParseCompressedWkbLineZ (geo);
 
1038
                break;
 
1039
            case GAIA_COMPRESSED_LINESTRINGM:
 
1040
                ParseCompressedWkbLineM (geo);
 
1041
                break;
 
1042
            case GAIA_COMPRESSED_LINESTRINGZM:
 
1043
                ParseCompressedWkbLineZM (geo);
 
1044
                break;
 
1045
            case GAIA_COMPRESSED_POLYGON:
 
1046
                ParseCompressedWkbPolygon (geo);
 
1047
                break;
 
1048
            case GAIA_COMPRESSED_POLYGONZ:
 
1049
                ParseCompressedWkbPolygonZ (geo);
 
1050
                break;
 
1051
            case GAIA_COMPRESSED_POLYGONM:
 
1052
                ParseCompressedWkbPolygonM (geo);
 
1053
                break;
 
1054
            case GAIA_COMPRESSED_POLYGONZM:
 
1055
                ParseCompressedWkbPolygonZM (geo);
 
1056
                break;
 
1057
            default:
 
1058
                break;
 
1059
            };
 
1060
      }
 
1061
}
 
1062
 
 
1063
GAIAGEO_DECLARE gaiaGeomCollPtr
 
1064
gaiaFromSpatiaLiteBlobWkb (const unsigned char *blob, unsigned int size)
 
1065
{
 
1066
/* decoding from SpatiaLite BLOB to GEOMETRY */
 
1067
    int type;
 
1068
    int little_endian;
 
1069
    int endian_arch = gaiaEndianArch ();
 
1070
    gaiaGeomCollPtr geo = NULL;
 
1071
    if (size < 45)
 
1072
        return NULL;            /* cannot be an internal BLOB WKB geometry */
 
1073
    if (*(blob + 0) != GAIA_MARK_START)
 
1074
        return NULL;            /* failed to recognize START signature */
 
1075
    if (*(blob + (size - 1)) != GAIA_MARK_END)
 
1076
        return NULL;            /* failed to recognize END signature */
 
1077
    if (*(blob + 38) != GAIA_MARK_MBR)
 
1078
        return NULL;            /* failed to recognize MBR signature */
 
1079
    if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
 
1080
        little_endian = 1;
 
1081
    else if (*(blob + 1) == GAIA_BIG_ENDIAN)
 
1082
        little_endian = 0;
 
1083
    else
 
1084
        return NULL;            /* unknown encoding; nor litte-endian neither big-endian */
 
1085
    type = gaiaImport32 (blob + 39, little_endian, endian_arch);
 
1086
    geo = gaiaAllocGeomColl ();
 
1087
    geo->Srid = gaiaImport32 (blob + 2, little_endian, endian_arch);
 
1088
    geo->endian_arch = (char) endian_arch;
 
1089
    geo->endian = (char) little_endian;
 
1090
    geo->blob = blob;
 
1091
    geo->size = size;
 
1092
    geo->offset = 43;
 
1093
    switch (type)
 
1094
      {
 
1095
          /* setting up DimensionModel */
 
1096
      case GAIA_POINTZ:
 
1097
      case GAIA_LINESTRINGZ:
 
1098
      case GAIA_POLYGONZ:
 
1099
      case GAIA_MULTIPOINTZ:
 
1100
      case GAIA_MULTILINESTRINGZ:
 
1101
      case GAIA_MULTIPOLYGONZ:
 
1102
      case GAIA_GEOMETRYCOLLECTIONZ:
 
1103
      case GAIA_COMPRESSED_LINESTRINGZ:
 
1104
      case GAIA_COMPRESSED_POLYGONZ:
 
1105
          geo->DimensionModel = GAIA_XY_Z;
 
1106
          break;
 
1107
      case GAIA_POINTM:
 
1108
      case GAIA_LINESTRINGM:
 
1109
      case GAIA_POLYGONM:
 
1110
      case GAIA_MULTIPOINTM:
 
1111
      case GAIA_MULTILINESTRINGM:
 
1112
      case GAIA_MULTIPOLYGONM:
 
1113
      case GAIA_GEOMETRYCOLLECTIONM:
 
1114
      case GAIA_COMPRESSED_LINESTRINGM:
 
1115
      case GAIA_COMPRESSED_POLYGONM:
 
1116
          geo->DimensionModel = GAIA_XY_M;
 
1117
          break;
 
1118
      case GAIA_POINTZM:
 
1119
      case GAIA_LINESTRINGZM:
 
1120
      case GAIA_POLYGONZM:
 
1121
      case GAIA_MULTIPOINTZM:
 
1122
      case GAIA_MULTILINESTRINGZM:
 
1123
      case GAIA_MULTIPOLYGONZM:
 
1124
      case GAIA_GEOMETRYCOLLECTIONZM:
 
1125
      case GAIA_COMPRESSED_LINESTRINGZM:
 
1126
      case GAIA_COMPRESSED_POLYGONZM:
 
1127
          geo->DimensionModel = GAIA_XY_Z_M;
 
1128
          break;
 
1129
      default:
 
1130
          geo->DimensionModel = GAIA_XY;
 
1131
          break;
 
1132
      };
 
1133
    switch (type)
 
1134
      {
 
1135
          /* parsing elementary geometries */
 
1136
      case GAIA_POINT:
 
1137
          ParseWkbPoint (geo);
 
1138
          break;
 
1139
      case GAIA_POINTZ:
 
1140
          ParseWkbPointZ (geo);
 
1141
          break;
 
1142
      case GAIA_POINTM:
 
1143
          ParseWkbPointM (geo);
 
1144
          break;
 
1145
      case GAIA_POINTZM:
 
1146
          ParseWkbPointZM (geo);
 
1147
          break;
 
1148
      case GAIA_LINESTRING:
 
1149
          ParseWkbLine (geo);
 
1150
          break;
 
1151
      case GAIA_LINESTRINGZ:
 
1152
          ParseWkbLineZ (geo);
 
1153
          break;
 
1154
      case GAIA_LINESTRINGM:
 
1155
          ParseWkbLineM (geo);
 
1156
          break;
 
1157
      case GAIA_LINESTRINGZM:
 
1158
          ParseWkbLineZM (geo);
 
1159
          break;
 
1160
      case GAIA_POLYGON:
 
1161
          ParseWkbPolygon (geo);
 
1162
          break;
 
1163
      case GAIA_POLYGONZ:
 
1164
          ParseWkbPolygonZ (geo);
 
1165
          break;
 
1166
      case GAIA_POLYGONM:
 
1167
          ParseWkbPolygonM (geo);
 
1168
          break;
 
1169
      case GAIA_POLYGONZM:
 
1170
          ParseWkbPolygonZM (geo);
 
1171
          break;
 
1172
      case GAIA_COMPRESSED_LINESTRING:
 
1173
          ParseCompressedWkbLine (geo);
 
1174
          break;
 
1175
      case GAIA_COMPRESSED_LINESTRINGZ:
 
1176
          ParseCompressedWkbLineZ (geo);
 
1177
          break;
 
1178
      case GAIA_COMPRESSED_LINESTRINGM:
 
1179
          ParseCompressedWkbLineM (geo);
 
1180
          break;
 
1181
      case GAIA_COMPRESSED_LINESTRINGZM:
 
1182
          ParseCompressedWkbLineZM (geo);
 
1183
          break;
 
1184
      case GAIA_COMPRESSED_POLYGON:
 
1185
          ParseCompressedWkbPolygon (geo);
 
1186
          break;
 
1187
      case GAIA_COMPRESSED_POLYGONZ:
 
1188
          ParseCompressedWkbPolygonZ (geo);
 
1189
          break;
 
1190
      case GAIA_COMPRESSED_POLYGONM:
 
1191
          ParseCompressedWkbPolygonM (geo);
 
1192
          break;
 
1193
      case GAIA_COMPRESSED_POLYGONZM:
 
1194
          ParseCompressedWkbPolygonZM (geo);
 
1195
          break;
 
1196
      case GAIA_MULTIPOINT:
 
1197
      case GAIA_MULTIPOINTZ:
 
1198
      case GAIA_MULTIPOINTM:
 
1199
      case GAIA_MULTIPOINTZM:
 
1200
      case GAIA_MULTILINESTRING:
 
1201
      case GAIA_MULTILINESTRINGZ:
 
1202
      case GAIA_MULTILINESTRINGM:
 
1203
      case GAIA_MULTILINESTRINGZM:
 
1204
      case GAIA_MULTIPOLYGON:
 
1205
      case GAIA_MULTIPOLYGONZ:
 
1206
      case GAIA_MULTIPOLYGONM:
 
1207
      case GAIA_MULTIPOLYGONZM:
 
1208
      case GAIA_GEOMETRYCOLLECTION:
 
1209
      case GAIA_GEOMETRYCOLLECTIONZ:
 
1210
      case GAIA_GEOMETRYCOLLECTIONM:
 
1211
      case GAIA_GEOMETRYCOLLECTIONZM:
 
1212
          ParseWkbGeometry (geo);
 
1213
          break;
 
1214
      default:
 
1215
          break;
 
1216
      };
 
1217
    geo->MinX = gaiaImport64 (blob + 6, little_endian, endian_arch);
 
1218
    geo->MinY = gaiaImport64 (blob + 14, little_endian, endian_arch);
 
1219
    geo->MaxX = gaiaImport64 (blob + 22, little_endian, endian_arch);
 
1220
    geo->MaxY = gaiaImport64 (blob + 30, little_endian, endian_arch);
 
1221
    switch (type)
 
1222
      {
 
1223
          /* setting up DeclaredType */
 
1224
      case GAIA_POINT:
 
1225
      case GAIA_POINTZ:
 
1226
      case GAIA_POINTM:
 
1227
      case GAIA_POINTZM:
 
1228
          geo->DeclaredType = GAIA_POINT;
 
1229
          break;
 
1230
      case GAIA_LINESTRING:
 
1231
      case GAIA_LINESTRINGZ:
 
1232
      case GAIA_LINESTRINGM:
 
1233
      case GAIA_LINESTRINGZM:
 
1234
      case GAIA_COMPRESSED_LINESTRING:
 
1235
      case GAIA_COMPRESSED_LINESTRINGZ:
 
1236
      case GAIA_COMPRESSED_LINESTRINGM:
 
1237
      case GAIA_COMPRESSED_LINESTRINGZM:
 
1238
          geo->DeclaredType = GAIA_LINESTRING;
 
1239
          break;
 
1240
      case GAIA_POLYGON:
 
1241
      case GAIA_POLYGONZ:
 
1242
      case GAIA_POLYGONM:
 
1243
      case GAIA_POLYGONZM:
 
1244
      case GAIA_COMPRESSED_POLYGON:
 
1245
      case GAIA_COMPRESSED_POLYGONZ:
 
1246
      case GAIA_COMPRESSED_POLYGONM:
 
1247
      case GAIA_COMPRESSED_POLYGONZM:
 
1248
          geo->DeclaredType = GAIA_POLYGON;
 
1249
          break;
 
1250
      case GAIA_MULTIPOINT:
 
1251
      case GAIA_MULTIPOINTZ:
 
1252
      case GAIA_MULTIPOINTM:
 
1253
      case GAIA_MULTIPOINTZM:
 
1254
          geo->DeclaredType = GAIA_MULTIPOINT;
 
1255
          break;
 
1256
      case GAIA_MULTILINESTRING:
 
1257
      case GAIA_MULTILINESTRINGZ:
 
1258
      case GAIA_MULTILINESTRINGM:
 
1259
      case GAIA_MULTILINESTRINGZM:
 
1260
          geo->DeclaredType = GAIA_MULTILINESTRING;
 
1261
          break;
 
1262
      case GAIA_MULTIPOLYGON:
 
1263
      case GAIA_MULTIPOLYGONZ:
 
1264
      case GAIA_MULTIPOLYGONM:
 
1265
      case GAIA_MULTIPOLYGONZM:
 
1266
          geo->DeclaredType = GAIA_MULTIPOLYGON;
 
1267
          break;
 
1268
      case GAIA_GEOMETRYCOLLECTION:
 
1269
      case GAIA_GEOMETRYCOLLECTIONZ:
 
1270
      case GAIA_GEOMETRYCOLLECTIONM:
 
1271
      case GAIA_GEOMETRYCOLLECTIONZM:
 
1272
          geo->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
1273
          break;
 
1274
      default:
 
1275
          geo->DeclaredType = GAIA_UNKNOWN;
 
1276
          break;
 
1277
      };
 
1278
    return geo;
 
1279
}
 
1280
 
 
1281
GAIAGEO_DECLARE gaiaGeomCollPtr
 
1282
gaiaFromSpatiaLiteBlobMbr (const unsigned char *blob, unsigned int size)
 
1283
{
 
1284
/* decoding from SpatiaLite BLOB to GEOMETRY [MBR only] */
 
1285
    int type;
 
1286
    int little_endian;
 
1287
    int endian_arch = gaiaEndianArch ();
 
1288
    double minx;
 
1289
    double miny;
 
1290
    double maxx;
 
1291
    double maxy;
 
1292
    gaiaGeomCollPtr geo = NULL;
 
1293
    gaiaPolygonPtr polyg;
 
1294
    gaiaRingPtr ring;
 
1295
    if (size < 45)
 
1296
        return NULL;            /* cannot be an internal BLOB WKB geometry */
 
1297
    if (*(blob + 0) != GAIA_MARK_START)
 
1298
        return NULL;            /* failed to recognize START signature */
 
1299
    if (*(blob + (size - 1)) != GAIA_MARK_END)
 
1300
        return NULL;            /* failed to recognize END signature */
 
1301
    if (*(blob + 38) != GAIA_MARK_MBR)
 
1302
        return NULL;            /* failed to recognize MBR signature */
 
1303
    if (*(blob + 1) == GAIA_LITTLE_ENDIAN)
 
1304
        little_endian = 1;
 
1305
    else if (*(blob + 1) == GAIA_BIG_ENDIAN)
 
1306
        little_endian = 0;
 
1307
    else
 
1308
        return NULL;            /* unknown encoding; nor litte-endian neither big-endian */
 
1309
    type = gaiaImport32 (blob + 39, little_endian, endian_arch);
 
1310
    geo = gaiaAllocGeomColl ();
 
1311
    polyg = gaiaAddPolygonToGeomColl (geo, 5, 0);
 
1312
    ring = polyg->Exterior;
 
1313
    minx = gaiaImport64 (blob + 6, little_endian, endian_arch);
 
1314
    miny = gaiaImport64 (blob + 14, little_endian, endian_arch);
 
1315
    maxx = gaiaImport64 (blob + 22, little_endian, endian_arch);
 
1316
    maxy = gaiaImport64 (blob + 30, little_endian, endian_arch);
 
1317
    gaiaSetPoint (ring->Coords, 0, minx, miny); /* vertex # 1 */
 
1318
    gaiaSetPoint (ring->Coords, 1, maxx, miny); /* vertex # 2 */
 
1319
    gaiaSetPoint (ring->Coords, 2, maxx, maxy); /* vertex # 3 */
 
1320
    gaiaSetPoint (ring->Coords, 3, minx, maxy); /* vertex # 4 */
 
1321
    gaiaSetPoint (ring->Coords, 4, minx, miny); /* vertex # 5 [same as vertex # 1 to close the polygon] */
 
1322
    return geo;
 
1323
}
 
1324
 
 
1325
GAIAGEO_DECLARE void
 
1326
gaiaToSpatiaLiteBlobWkb (gaiaGeomCollPtr geom, unsigned char **result,
 
1327
                         int *size)
 
1328
{
 
1329
/* builds the SpatiaLite BLOB representation for this GEOMETRY */
 
1330
    int ib;
 
1331
    int iv;
 
1332
    double x;
 
1333
    double y;
 
1334
    double z = 0.0;
 
1335
    double m = 0.0;
 
1336
    int entities = 0;
 
1337
    int n_points = 0;
 
1338
    int n_linestrings = 0;
 
1339
    int n_polygons = 0;
 
1340
    int type;
 
1341
    unsigned char *ptr;
 
1342
    gaiaPointPtr pt;
 
1343
    gaiaLinestringPtr ln;
 
1344
    gaiaPolygonPtr pg;
 
1345
    gaiaRingPtr rng;
 
1346
    gaiaPointPtr point = NULL;
 
1347
    gaiaLinestringPtr line = NULL;
 
1348
    gaiaPolygonPtr polyg = NULL;
 
1349
    int endian_arch = gaiaEndianArch ();
 
1350
    gaiaMbrGeometry (geom);
 
1351
/* how many entities, and of what kind, do we have ? */
 
1352
    pt = geom->FirstPoint;
 
1353
    while (pt)
 
1354
      {
 
1355
          point = pt;
 
1356
          entities++;
 
1357
          n_points++;
 
1358
          pt = pt->Next;
 
1359
      }
 
1360
    ln = geom->FirstLinestring;
 
1361
    while (ln)
 
1362
      {
 
1363
          line = ln;
 
1364
          entities++;
 
1365
          n_linestrings++;
 
1366
          ln = ln->Next;
 
1367
      }
 
1368
    pg = geom->FirstPolygon;
 
1369
    while (pg)
 
1370
      {
 
1371
          polyg = pg;
 
1372
          entities++;
 
1373
          n_polygons++;
 
1374
          pg = pg->Next;
 
1375
      }
 
1376
    *size = 0;
 
1377
    *result = NULL;
 
1378
    if (n_points == 0 && n_polygons == 0 && n_linestrings == 0)
 
1379
        return;
 
1380
/* ok, we can determine the geometry class */
 
1381
    if (n_points == 1 && n_linestrings == 0 && n_polygons == 0)
 
1382
      {
 
1383
          if (geom->DeclaredType == GAIA_MULTIPOINT)
 
1384
            {
 
1385
                if (geom->DimensionModel == GAIA_XY_Z)
 
1386
                    type = GAIA_MULTIPOINTZ;
 
1387
                else if (geom->DimensionModel == GAIA_XY_M)
 
1388
                    type = GAIA_MULTIPOINTM;
 
1389
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1390
                    type = GAIA_MULTIPOINTZM;
 
1391
                else
 
1392
                    type = GAIA_MULTIPOINT;
 
1393
            }
 
1394
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
1395
            {
 
1396
                if (geom->DimensionModel == GAIA_XY_Z)
 
1397
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
1398
                else if (geom->DimensionModel == GAIA_XY_M)
 
1399
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
1400
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1401
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
1402
                else
 
1403
                    type = GAIA_GEOMETRYCOLLECTION;
 
1404
            }
 
1405
          else
 
1406
            {
 
1407
                if (geom->DimensionModel == GAIA_XY_Z)
 
1408
                    type = GAIA_POINTZ;
 
1409
                else if (geom->DimensionModel == GAIA_XY_M)
 
1410
                    type = GAIA_POINTM;
 
1411
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1412
                    type = GAIA_POINTZM;
 
1413
                else
 
1414
                    type = GAIA_POINT;
 
1415
            }
 
1416
      }
 
1417
    else if (n_points > 1 && n_linestrings == 0 && n_polygons == 0)
 
1418
      {
 
1419
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
1420
            {
 
1421
                if (geom->DimensionModel == GAIA_XY_Z)
 
1422
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
1423
                else if (geom->DimensionModel == GAIA_XY_M)
 
1424
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
1425
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1426
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
1427
                else
 
1428
                    type = GAIA_GEOMETRYCOLLECTION;
 
1429
            }
 
1430
          else
 
1431
            {
 
1432
                if (geom->DimensionModel == GAIA_XY_Z)
 
1433
                    type = GAIA_MULTIPOINTZ;
 
1434
                else if (geom->DimensionModel == GAIA_XY_M)
 
1435
                    type = GAIA_MULTIPOINTM;
 
1436
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1437
                    type = GAIA_MULTIPOINTZM;
 
1438
                else
 
1439
                    type = GAIA_MULTIPOINT;
 
1440
            }
 
1441
      }
 
1442
    else if (n_points == 0 && n_linestrings == 1 && n_polygons == 0)
 
1443
      {
 
1444
          if (geom->DeclaredType == GAIA_MULTILINESTRING)
 
1445
            {
 
1446
                if (geom->DimensionModel == GAIA_XY_Z)
 
1447
                    type = GAIA_MULTILINESTRINGZ;
 
1448
                else if (geom->DimensionModel == GAIA_XY_M)
 
1449
                    type = GAIA_MULTILINESTRINGM;
 
1450
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1451
                    type = GAIA_MULTILINESTRINGZM;
 
1452
                else
 
1453
                    type = GAIA_MULTILINESTRING;
 
1454
            }
 
1455
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
1456
            {
 
1457
                if (geom->DimensionModel == GAIA_XY_Z)
 
1458
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
1459
                else if (geom->DimensionModel == GAIA_XY_M)
 
1460
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
1461
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1462
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
1463
                else
 
1464
                    type = GAIA_GEOMETRYCOLLECTION;
 
1465
            }
 
1466
          else
 
1467
            {
 
1468
                if (geom->DimensionModel == GAIA_XY_Z)
 
1469
                    type = GAIA_LINESTRINGZ;
 
1470
                else if (geom->DimensionModel == GAIA_XY_M)
 
1471
                    type = GAIA_LINESTRINGM;
 
1472
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1473
                    type = GAIA_LINESTRINGZM;
 
1474
                else
 
1475
                    type = GAIA_LINESTRING;
 
1476
            }
 
1477
      }
 
1478
    else if (n_points == 0 && n_linestrings > 1 && n_polygons == 0)
 
1479
      {
 
1480
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
1481
            {
 
1482
                if (geom->DimensionModel == GAIA_XY_Z)
 
1483
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
1484
                else if (geom->DimensionModel == GAIA_XY_M)
 
1485
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
1486
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1487
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
1488
                else
 
1489
                    type = GAIA_GEOMETRYCOLLECTION;
 
1490
            }
 
1491
          else
 
1492
            {
 
1493
                if (geom->DimensionModel == GAIA_XY_Z)
 
1494
                    type = GAIA_MULTILINESTRINGZ;
 
1495
                else if (geom->DimensionModel == GAIA_XY_M)
 
1496
                    type = GAIA_MULTILINESTRINGM;
 
1497
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1498
                    type = GAIA_MULTILINESTRINGZM;
 
1499
                else
 
1500
                    type = GAIA_MULTILINESTRING;
 
1501
            }
 
1502
      }
 
1503
    else if (n_points == 0 && n_linestrings == 0 && n_polygons == 1)
 
1504
      {
 
1505
          if (geom->DeclaredType == GAIA_MULTIPOLYGON)
 
1506
            {
 
1507
                if (geom->DimensionModel == GAIA_XY_Z)
 
1508
                    type = GAIA_MULTIPOLYGONZ;
 
1509
                else if (geom->DimensionModel == GAIA_XY_M)
 
1510
                    type = GAIA_MULTIPOLYGONM;
 
1511
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1512
                    type = GAIA_MULTIPOLYGONZM;
 
1513
                else
 
1514
                    type = GAIA_MULTIPOLYGON;
 
1515
            }
 
1516
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
1517
            {
 
1518
                if (geom->DimensionModel == GAIA_XY_Z)
 
1519
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
1520
                else if (geom->DimensionModel == GAIA_XY_M)
 
1521
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
1522
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1523
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
1524
                else
 
1525
                    type = GAIA_GEOMETRYCOLLECTION;
 
1526
            }
 
1527
          else
 
1528
            {
 
1529
                if (geom->DimensionModel == GAIA_XY_Z)
 
1530
                    type = GAIA_POLYGONZ;
 
1531
                else if (geom->DimensionModel == GAIA_XY_M)
 
1532
                    type = GAIA_POLYGONM;
 
1533
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1534
                    type = GAIA_POLYGONZM;
 
1535
                else
 
1536
                    type = GAIA_POLYGON;
 
1537
            }
 
1538
      }
 
1539
    else if (n_points == 0 && n_linestrings == 0 && n_polygons > 1)
 
1540
      {
 
1541
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
1542
            {
 
1543
                if (geom->DimensionModel == GAIA_XY_Z)
 
1544
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
1545
                else if (geom->DimensionModel == GAIA_XY_M)
 
1546
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
1547
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1548
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
1549
                else
 
1550
                    type = GAIA_GEOMETRYCOLLECTION;
 
1551
            }
 
1552
          else
 
1553
            {
 
1554
                if (geom->DimensionModel == GAIA_XY_Z)
 
1555
                    type = GAIA_MULTIPOLYGONZ;
 
1556
                else if (geom->DimensionModel == GAIA_XY_M)
 
1557
                    type = GAIA_MULTIPOLYGONM;
 
1558
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1559
                    type = GAIA_MULTIPOLYGONZM;
 
1560
                else
 
1561
                    type = GAIA_MULTIPOLYGON;
 
1562
            }
 
1563
      }
 
1564
    else
 
1565
      {
 
1566
          if (geom->DimensionModel == GAIA_XY_Z)
 
1567
              type = GAIA_GEOMETRYCOLLECTIONZ;
 
1568
          else if (geom->DimensionModel == GAIA_XY_M)
 
1569
              type = GAIA_GEOMETRYCOLLECTIONM;
 
1570
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1571
              type = GAIA_GEOMETRYCOLLECTIONZM;
 
1572
          else
 
1573
              type = GAIA_GEOMETRYCOLLECTION;
 
1574
      }
 
1575
/* and now we compute the size of BLOB */
 
1576
    *size = 44;                 /* header size */
 
1577
    switch (type)
 
1578
      {
 
1579
      case GAIA_POINT:
 
1580
          *size += (sizeof (double) * 2);       /* [x,y] coords */
 
1581
          break;
 
1582
      case GAIA_POINTZ:
 
1583
          *size += (sizeof (double) * 3);       /* [x,y,z] coords */
 
1584
          break;
 
1585
      case GAIA_POINTM:
 
1586
          *size += (sizeof (double) * 3);       /* [x,y,m] coords */
 
1587
          break;
 
1588
      case GAIA_POINTZM:
 
1589
          *size += (sizeof (double) * 4);       /* [x,y,z,m] coords */
 
1590
          break;
 
1591
      case GAIA_LINESTRING:
 
1592
          *size += (4 + ((sizeof (double) * 2) * line->Points));        /* # points + [x,y] for each vertex */
 
1593
          break;
 
1594
      case GAIA_LINESTRINGZ:
 
1595
          *size += (4 + ((sizeof (double) * 3) * line->Points));        /* # points + [x,y,z] for each vertex */
 
1596
          break;
 
1597
      case GAIA_LINESTRINGM:
 
1598
          *size += (4 + ((sizeof (double) * 3) * line->Points));        /* # points + [x,y,m] for each vertex */
 
1599
          break;
 
1600
      case GAIA_LINESTRINGZM:
 
1601
          *size += (4 + ((sizeof (double) * 4) * line->Points));        /* # points + [x,y,z,m] for each vertex */
 
1602
          break;
 
1603
      case GAIA_POLYGON:
 
1604
          rng = polyg->Exterior;
 
1605
          *size += (8 + ((sizeof (double) * 2) * rng->Points)); /* # rings + # points + [x.y] array - exterior ring */
 
1606
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1607
            {
 
1608
                rng = polyg->Interiors + ib;
 
1609
                *size += (4 + ((sizeof (double) * 2) * rng->Points));   /* # points + [x,y] array - interior ring */
 
1610
            }
 
1611
          break;
 
1612
      case GAIA_POLYGONZ:
 
1613
          rng = polyg->Exterior;
 
1614
          *size += (8 + ((sizeof (double) * 3) * rng->Points)); /* # rings + # points + [x,y,z] array - exterior ring */
 
1615
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1616
            {
 
1617
                rng = polyg->Interiors + ib;
 
1618
                *size += (4 + ((sizeof (double) * 3) * rng->Points));   /* # points + [x,y,z] array - interior ring */
 
1619
            }
 
1620
          break;
 
1621
      case GAIA_POLYGONM:
 
1622
          rng = polyg->Exterior;
 
1623
          *size += (8 + ((sizeof (double) * 3) * rng->Points)); /* # rings + # points + [x,y,m] array - exterior ring */
 
1624
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1625
            {
 
1626
                rng = polyg->Interiors + ib;
 
1627
                *size += (4 + ((sizeof (double) * 3) * rng->Points));   /* # points + [x,y,m] array - interior ring */
 
1628
            }
 
1629
          break;
 
1630
      case GAIA_POLYGONZM:
 
1631
          rng = polyg->Exterior;
 
1632
          *size += (8 + ((sizeof (double) * 4) * rng->Points)); /* # rings + # points + [x,y,z,m] array - exterior ring */
 
1633
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1634
            {
 
1635
                rng = polyg->Interiors + ib;
 
1636
                *size += (4 + ((sizeof (double) * 4) * rng->Points));   /* # points + [x,y,z,m] array - interior ring */
 
1637
            }
 
1638
          break;
 
1639
      default:
 
1640
          /* this one is not a simple geometry; should be a MULTIxxxx or a GEOMETRYCOLLECTION */
 
1641
          *size += 4;           /* # entities */
 
1642
          point = geom->FirstPoint;
 
1643
          while (point)
 
1644
            {
 
1645
                *size += 5;     /* entity header */
 
1646
                if (geom->DimensionModel == GAIA_XY_Z
 
1647
                    || geom->DimensionModel == GAIA_XY_M)
 
1648
                    *size += (sizeof (double) * 3);     /* three doubles for each POINT */
 
1649
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1650
                    *size += (sizeof (double) * 4);     /* four doubles for each POINT */
 
1651
                else
 
1652
                    *size += (sizeof (double) * 2);     /* two doubles for each POINT */
 
1653
                point = point->Next;
 
1654
            }
 
1655
          line = geom->FirstLinestring;
 
1656
          while (line)
 
1657
            {
 
1658
                *size += 5;     /* entity header */
 
1659
                if (geom->DimensionModel == GAIA_XY_Z
 
1660
                    || geom->DimensionModel == GAIA_XY_M)
 
1661
                    *size += (4 + ((sizeof (double) * 3) * line->Points));      /* # points + [x,y,z] for each vertex */
 
1662
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1663
                    *size += (4 + ((sizeof (double) * 4) * line->Points));      /* # points + [x,y,z,m] for each vertex */
 
1664
                else
 
1665
                    *size += (4 + ((sizeof (double) * 2) * line->Points));      /* # points + [x,y] for each vertex */
 
1666
                line = line->Next;
 
1667
            }
 
1668
          polyg = geom->FirstPolygon;
 
1669
          while (polyg)
 
1670
            {
 
1671
                *size += 5;     /* entity header */
 
1672
                rng = polyg->Exterior;
 
1673
                if (geom->DimensionModel == GAIA_XY_Z
 
1674
                    || geom->DimensionModel == GAIA_XY_M)
 
1675
                    *size += (8 + ((sizeof (double) * 3) * rng->Points));       /* # rings + # points + [x,y,z] array - exterior ring */
 
1676
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1677
                    *size += (8 + ((sizeof (double) * 4) * rng->Points));       /* # rings + # points + [x,y,z,m] array - exterior ring */
 
1678
                else
 
1679
                    *size += (8 + ((sizeof (double) * 2) * rng->Points));       /* # rings + # points + [x,y] array - exterior ring */
 
1680
                for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1681
                  {
 
1682
                      rng = polyg->Interiors + ib;
 
1683
                      if (geom->DimensionModel == GAIA_XY_Z
 
1684
                          || geom->DimensionModel == GAIA_XY_M)
 
1685
                          *size += (4 + ((sizeof (double) * 3) * rng->Points)); /* # points + [x,y,z] array - interior ring */
 
1686
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
1687
                          *size += (4 + ((sizeof (double) * 4) * rng->Points)); /* # points + [x,y,z,m] array - interior ring */
 
1688
                      else
 
1689
                          *size += (4 + ((sizeof (double) * 2) * rng->Points)); /* # points + [x,y] array - interior ring */
 
1690
                  }
 
1691
                polyg = polyg->Next;
 
1692
            }
 
1693
      };
 
1694
    *result = malloc (*size);
 
1695
    ptr = *result;
 
1696
/* and finally we build the BLOB */
 
1697
    switch (type)
 
1698
      {
 
1699
      case GAIA_POINT:
 
1700
          *ptr = GAIA_MARK_START;       /* START signature */
 
1701
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1702
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1703
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1704
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1705
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1706
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1707
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1708
          gaiaExport32 (ptr + 39, GAIA_POINT, 1, endian_arch);  /* class POINT */
 
1709
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
1710
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
1711
          *(ptr + 59) = GAIA_MARK_END;  /* END signature */
 
1712
          break;
 
1713
      case GAIA_POINTZ:
 
1714
          *ptr = GAIA_MARK_START;       /* START signature */
 
1715
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1716
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1717
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1718
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1719
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1720
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1721
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1722
          gaiaExport32 (ptr + 39, GAIA_POINTZ, 1, endian_arch); /* class POINT XYZ */
 
1723
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
1724
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
1725
          gaiaExport64 (ptr + 59, point->Z, 1, endian_arch);    /* Z */
 
1726
          *(ptr + 67) = GAIA_MARK_END;  /* END signature */
 
1727
          break;
 
1728
      case GAIA_POINTM:
 
1729
          *ptr = GAIA_MARK_START;       /* START signature */
 
1730
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1731
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1732
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1733
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1734
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1735
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1736
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1737
          gaiaExport32 (ptr + 39, GAIA_POINTM, 1, endian_arch); /* class POINT XYM */
 
1738
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
1739
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
1740
          gaiaExport64 (ptr + 59, point->M, 1, endian_arch);    /* M */
 
1741
          *(ptr + 67) = GAIA_MARK_END;  /* END signature */
 
1742
          break;
 
1743
      case GAIA_POINTZM:
 
1744
          *ptr = GAIA_MARK_START;       /* START signature */
 
1745
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1746
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1747
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1748
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1749
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1750
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1751
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1752
          gaiaExport32 (ptr + 39, GAIA_POINTZM, 1, endian_arch);        /* class POINT XYZM */
 
1753
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
1754
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
1755
          gaiaExport64 (ptr + 59, point->Z, 1, endian_arch);    /* M */
 
1756
          gaiaExport64 (ptr + 67, point->M, 1, endian_arch);    /* Z */
 
1757
          *(ptr + 75) = GAIA_MARK_END;  /* END signature */
 
1758
          break;
 
1759
      case GAIA_LINESTRING:
 
1760
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1761
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1762
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1763
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1764
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1765
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1766
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1767
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1768
          gaiaExport32 (ptr + 39, GAIA_LINESTRING, 1, endian_arch);     /* class LINESTRING */
 
1769
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
1770
          ptr += 47;
 
1771
          for (iv = 0; iv < line->Points; iv++)
 
1772
            {
 
1773
                gaiaGetPoint (line->Coords, iv, &x, &y);
 
1774
                gaiaExport64 (ptr, x, 1, endian_arch);
 
1775
                gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
1776
                ptr += 16;
 
1777
            }
 
1778
          *ptr = GAIA_MARK_END; /* END signature */
 
1779
          break;
 
1780
      case GAIA_LINESTRINGZ:
 
1781
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1782
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1783
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1784
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1785
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1786
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1787
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1788
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1789
          gaiaExport32 (ptr + 39, GAIA_LINESTRINGZ, 1, endian_arch);    /* class LINESTRING XYZ */
 
1790
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
1791
          ptr += 47;
 
1792
          for (iv = 0; iv < line->Points; iv++)
 
1793
            {
 
1794
                gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
 
1795
                gaiaExport64 (ptr, x, 1, endian_arch);
 
1796
                gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
1797
                gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
1798
                ptr += 24;
 
1799
            }
 
1800
          *ptr = GAIA_MARK_END; /* END signature */
 
1801
          break;
 
1802
      case GAIA_LINESTRINGM:
 
1803
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1804
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1805
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1806
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1807
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1808
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1809
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1810
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1811
          gaiaExport32 (ptr + 39, GAIA_LINESTRINGM, 1, endian_arch);    /* class LINESTRING XYM */
 
1812
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
1813
          ptr += 47;
 
1814
          for (iv = 0; iv < line->Points; iv++)
 
1815
            {
 
1816
                gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
 
1817
                gaiaExport64 (ptr, x, 1, endian_arch);
 
1818
                gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
1819
                gaiaExport64 (ptr + 16, m, 1, endian_arch);
 
1820
                ptr += 24;
 
1821
            }
 
1822
          *ptr = GAIA_MARK_END; /* END signature */
 
1823
          break;
 
1824
      case GAIA_LINESTRINGZM:
 
1825
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1826
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1827
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1828
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1829
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1830
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1831
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1832
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1833
          gaiaExport32 (ptr + 39, GAIA_LINESTRINGZM, 1, endian_arch);   /* class LINESTRING XYZM */
 
1834
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
1835
          ptr += 47;
 
1836
          for (iv = 0; iv < line->Points; iv++)
 
1837
            {
 
1838
                gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
 
1839
                gaiaExport64 (ptr, x, 1, endian_arch);
 
1840
                gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
1841
                gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
1842
                gaiaExport64 (ptr + 24, m, 1, endian_arch);
 
1843
                ptr += 32;
 
1844
            }
 
1845
          *ptr = GAIA_MARK_END; /* END signature */
 
1846
          break;
 
1847
      case GAIA_POLYGON:
 
1848
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1849
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1850
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1851
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1852
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1853
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1854
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1855
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1856
          gaiaExport32 (ptr + 39, GAIA_POLYGON, 1, endian_arch);        /* class POLYGON */
 
1857
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
1858
          rng = polyg->Exterior;
 
1859
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
1860
          ptr += 51;
 
1861
          for (iv = 0; iv < rng->Points; iv++)
 
1862
            {
 
1863
                gaiaGetPoint (rng->Coords, iv, &x, &y);
 
1864
                gaiaExport64 (ptr, x, 1, endian_arch);  /* X - exterior ring */
 
1865
                gaiaExport64 (ptr + 8, y, 1, endian_arch);      /* Y - exterior ring */
 
1866
                ptr += 16;
 
1867
            }
 
1868
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1869
            {
 
1870
                rng = polyg->Interiors + ib;
 
1871
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
1872
                ptr += 4;
 
1873
                for (iv = 0; iv < rng->Points; iv++)
 
1874
                  {
 
1875
                      gaiaGetPoint (rng->Coords, iv, &x, &y);
 
1876
                      gaiaExport64 (ptr, x, 1, endian_arch);    /* X - interior ring */
 
1877
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);        /* Y - interior ring */
 
1878
                      ptr += 16;
 
1879
                  }
 
1880
            }
 
1881
          *ptr = GAIA_MARK_END; /* END signature */
 
1882
          break;
 
1883
      case GAIA_POLYGONZ:
 
1884
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1885
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1886
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1887
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1888
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1889
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1890
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1891
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1892
          gaiaExport32 (ptr + 39, GAIA_POLYGONZ, 1, endian_arch);       /* class POLYGON XYZ */
 
1893
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
1894
          rng = polyg->Exterior;
 
1895
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
1896
          ptr += 51;
 
1897
          for (iv = 0; iv < rng->Points; iv++)
 
1898
            {
 
1899
                gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
1900
                gaiaExport64 (ptr, x, 1, endian_arch);  /* X - exterior ring */
 
1901
                gaiaExport64 (ptr + 8, y, 1, endian_arch);      /* Y - exterior ring */
 
1902
                gaiaExport64 (ptr + 16, z, 1, endian_arch);     /* Z - exterior ring */
 
1903
                ptr += 24;
 
1904
            }
 
1905
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1906
            {
 
1907
                rng = polyg->Interiors + ib;
 
1908
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
1909
                ptr += 4;
 
1910
                for (iv = 0; iv < rng->Points; iv++)
 
1911
                  {
 
1912
                      gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
1913
                      gaiaExport64 (ptr, x, 1, endian_arch);    /* X - interior ring */
 
1914
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);        /* Y - interior ring */
 
1915
                      gaiaExport64 (ptr + 16, z, 1, endian_arch);       /* Z - interior ring */
 
1916
                      ptr += 24;
 
1917
                  }
 
1918
            }
 
1919
          *ptr = GAIA_MARK_END; /* END signature */
 
1920
          break;
 
1921
      case GAIA_POLYGONM:
 
1922
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1923
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1924
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1925
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1926
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1927
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1928
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1929
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1930
          gaiaExport32 (ptr + 39, GAIA_POLYGONM, 1, endian_arch);       /* class POLYGON XYM */
 
1931
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
1932
          rng = polyg->Exterior;
 
1933
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
1934
          ptr += 51;
 
1935
          for (iv = 0; iv < rng->Points; iv++)
 
1936
            {
 
1937
                gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
1938
                gaiaExport64 (ptr, x, 1, endian_arch);  /* X - exterior ring */
 
1939
                gaiaExport64 (ptr + 8, y, 1, endian_arch);      /* Y - exterior ring */
 
1940
                gaiaExport64 (ptr + 16, m, 1, endian_arch);     /* M - exterior ring */
 
1941
                ptr += 24;
 
1942
            }
 
1943
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1944
            {
 
1945
                rng = polyg->Interiors + ib;
 
1946
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
1947
                ptr += 4;
 
1948
                for (iv = 0; iv < rng->Points; iv++)
 
1949
                  {
 
1950
                      gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
1951
                      gaiaExport64 (ptr, x, 1, endian_arch);    /* X - interior ring */
 
1952
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);        /* Y - interior ring */
 
1953
                      gaiaExport64 (ptr + 16, m, 1, endian_arch);       /* M - interior ring */
 
1954
                      ptr += 24;
 
1955
                  }
 
1956
            }
 
1957
          *ptr = GAIA_MARK_END; /* END signature */
 
1958
          break;
 
1959
      case GAIA_POLYGONZM:
 
1960
          *ptr = GAIA_MARK_START;       /* START signatue */
 
1961
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
1962
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
1963
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
1964
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
1965
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
1966
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
1967
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
1968
          gaiaExport32 (ptr + 39, GAIA_POLYGONZM, 1, endian_arch);      /* class POLYGON */
 
1969
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
1970
          rng = polyg->Exterior;
 
1971
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
1972
          ptr += 51;
 
1973
          for (iv = 0; iv < rng->Points; iv++)
 
1974
            {
 
1975
                gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
1976
                gaiaExport64 (ptr, x, 1, endian_arch);  /* X - exterior ring */
 
1977
                gaiaExport64 (ptr + 8, y, 1, endian_arch);      /* Y - exterior ring */
 
1978
                gaiaExport64 (ptr + 16, z, 1, endian_arch);     /* Z - exterior ring */
 
1979
                gaiaExport64 (ptr + 24, m, 1, endian_arch);     /* M - exterior ring */
 
1980
                ptr += 32;
 
1981
            }
 
1982
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
1983
            {
 
1984
                rng = polyg->Interiors + ib;
 
1985
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
1986
                ptr += 4;
 
1987
                for (iv = 0; iv < rng->Points; iv++)
 
1988
                  {
 
1989
                      gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
1990
                      gaiaExport64 (ptr, x, 1, endian_arch);    /* X - interior ring */
 
1991
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);        /* Y - interior ring */
 
1992
                      gaiaExport64 (ptr + 16, z, 1, endian_arch);       /* Z - exterior ring */
 
1993
                      gaiaExport64 (ptr + 24, m, 1, endian_arch);       /* M - exterior ring */
 
1994
                      ptr += 32;
 
1995
                  }
 
1996
            }
 
1997
          *ptr = GAIA_MARK_END; /* END signature */
 
1998
          break;
 
1999
      default:
 
2000
          /* this one is a MULTIxxxx or a GEOMETRYCOLLECTION - building the main header */
 
2001
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2002
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2003
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2004
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2005
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2006
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2007
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2008
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2009
          gaiaExport32 (ptr + 39, type, 1, endian_arch);        /* geometric class */
 
2010
          gaiaExport32 (ptr + 43, entities, 1, endian_arch);    /* # entities */
 
2011
          ptr += 47;
 
2012
          point = geom->FirstPoint;
 
2013
          while (point)
 
2014
            {
 
2015
                *ptr = GAIA_MARK_ENTITY;        /* ENTITY signature */
 
2016
                if (geom->DimensionModel == GAIA_XY_Z)
 
2017
                  {
 
2018
                      gaiaExport32 (ptr + 1, GAIA_POINTZ, 1, endian_arch);      /* class POINT XYZ */
 
2019
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
2020
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
2021
                      gaiaExport64 (ptr + 21, point->Z, 1, endian_arch);        /* Z */
 
2022
                      ptr += 29;
 
2023
                  }
 
2024
                else if (geom->DimensionModel == GAIA_XY_M)
 
2025
                  {
 
2026
                      gaiaExport32 (ptr + 1, GAIA_POINTM, 1, endian_arch);      /* class POINT XYM */
 
2027
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
2028
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
2029
                      gaiaExport64 (ptr + 21, point->M, 1, endian_arch);        /* M */
 
2030
                      ptr += 29;
 
2031
                  }
 
2032
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2033
                  {
 
2034
                      gaiaExport32 (ptr + 1, GAIA_POINTZM, 1, endian_arch);     /* class POINT XYZM */
 
2035
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
2036
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
2037
                      gaiaExport64 (ptr + 21, point->Z, 1, endian_arch);        /* Z */
 
2038
                      gaiaExport64 (ptr + 29, point->M, 1, endian_arch);        /* M */
 
2039
                      ptr += 37;
 
2040
                  }
 
2041
                else
 
2042
                  {
 
2043
                      gaiaExport32 (ptr + 1, GAIA_POINT, 1, endian_arch);       /* class POINT */
 
2044
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
2045
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
2046
                      ptr += 21;
 
2047
                  }
 
2048
                point = point->Next;
 
2049
            }
 
2050
          line = geom->FirstLinestring;
 
2051
          while (line)
 
2052
            {
 
2053
                *ptr = GAIA_MARK_ENTITY;        /* ENTITY signature */
 
2054
                if (geom->DimensionModel == GAIA_XY_Z)
 
2055
                    gaiaExport32 (ptr + 1, GAIA_LINESTRINGZ, 1, endian_arch);   /* class LINESTRING XYZ */
 
2056
                else if (geom->DimensionModel == GAIA_XY_M)
 
2057
                    gaiaExport32 (ptr + 1, GAIA_LINESTRINGM, 1, endian_arch);   /* class LINESTRING XYM */
 
2058
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2059
                    gaiaExport32 (ptr + 1, GAIA_LINESTRINGZM, 1, endian_arch);  /* class LINESTRING XYZM */
 
2060
                else
 
2061
                    gaiaExport32 (ptr + 1, GAIA_LINESTRING, 1, endian_arch);    /* class LINESTRING */
 
2062
                gaiaExport32 (ptr + 5, line->Points, 1, endian_arch);   /* # points */
 
2063
                ptr += 9;
 
2064
                for (iv = 0; iv < line->Points; iv++)
 
2065
                  {
 
2066
                      if (geom->DimensionModel == GAIA_XY_Z)
 
2067
                        {
 
2068
                            gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
 
2069
                        }
 
2070
                      else if (geom->DimensionModel == GAIA_XY_M)
 
2071
                        {
 
2072
                            gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
 
2073
                        }
 
2074
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2075
                        {
 
2076
                            gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
 
2077
                        }
 
2078
                      else
 
2079
                        {
 
2080
                            gaiaGetPoint (line->Coords, iv, &x, &y);
 
2081
                        }
 
2082
                      gaiaExport64 (ptr, x, 1, endian_arch);    /* X */
 
2083
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);        /* Y */
 
2084
                      ptr += 16;
 
2085
                      if (geom->DimensionModel == GAIA_XY_Z)
 
2086
                        {
 
2087
                            gaiaExport64 (ptr, z, 1, endian_arch);      /* Z */
 
2088
                            ptr += 8;
 
2089
                        }
 
2090
                      if (geom->DimensionModel == GAIA_XY_M)
 
2091
                        {
 
2092
                            gaiaExport64 (ptr, m, 1, endian_arch);      /* M */
 
2093
                            ptr += 8;
 
2094
                        }
 
2095
                      if (geom->DimensionModel == GAIA_XY_Z_M)
 
2096
                        {
 
2097
                            gaiaExport64 (ptr, z, 1, endian_arch);      /* Z */
 
2098
                            gaiaExport64 (ptr + 8, m, 1, endian_arch);  /* M */
 
2099
                            ptr += 16;
 
2100
                        }
 
2101
                  }
 
2102
                line = line->Next;
 
2103
            }
 
2104
          polyg = geom->FirstPolygon;
 
2105
          while (polyg)
 
2106
            {
 
2107
                *ptr = GAIA_MARK_ENTITY;        /* ENTITY signature */
 
2108
                if (geom->DimensionModel == GAIA_XY_Z)
 
2109
                    gaiaExport32 (ptr + 1, GAIA_POLYGONZ, 1, endian_arch);      /* class POLYGON XYZ */
 
2110
                else if (geom->DimensionModel == GAIA_XY_M)
 
2111
                    gaiaExport32 (ptr + 1, GAIA_POLYGONM, 1, endian_arch);      /* class POLYGON XYM */
 
2112
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2113
                    gaiaExport32 (ptr + 1, GAIA_POLYGONZM, 1, endian_arch);     /* class POLYGON XYZM */
 
2114
                else
 
2115
                    gaiaExport32 (ptr + 1, GAIA_POLYGON, 1, endian_arch);       /* class POLYGON */
 
2116
                gaiaExport32 (ptr + 5, polyg->NumInteriors + 1, 1, endian_arch);        /* # rings */
 
2117
                rng = polyg->Exterior;
 
2118
                gaiaExport32 (ptr + 9, rng->Points, 1, endian_arch);    /* # points - exterior ring */
 
2119
                ptr += 13;
 
2120
                for (iv = 0; iv < rng->Points; iv++)
 
2121
                  {
 
2122
                      if (geom->DimensionModel == GAIA_XY_Z)
 
2123
                        {
 
2124
                            gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
2125
                        }
 
2126
                      else if (geom->DimensionModel == GAIA_XY_M)
 
2127
                        {
 
2128
                            gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
2129
                        }
 
2130
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2131
                        {
 
2132
                            gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
2133
                        }
 
2134
                      else
 
2135
                        {
 
2136
                            gaiaGetPoint (rng->Coords, iv, &x, &y);
 
2137
                        }
 
2138
                      gaiaExport64 (ptr, x, 1, endian_arch);    /* X - exterior ring */
 
2139
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);        /* Y - exterior ring */
 
2140
                      ptr += 16;
 
2141
                      if (geom->DimensionModel == GAIA_XY_Z)
 
2142
                        {
 
2143
                            gaiaExport64 (ptr, z, 1, endian_arch);      /* Z */
 
2144
                            ptr += 8;
 
2145
                        }
 
2146
                      if (geom->DimensionModel == GAIA_XY_M)
 
2147
                        {
 
2148
                            gaiaExport64 (ptr, m, 1, endian_arch);      /* M */
 
2149
                            ptr += 8;
 
2150
                        }
 
2151
                      if (geom->DimensionModel == GAIA_XY_Z_M)
 
2152
                        {
 
2153
                            gaiaExport64 (ptr, z, 1, endian_arch);      /* Z */
 
2154
                            gaiaExport64 (ptr + 8, m, 1, endian_arch);  /* M */
 
2155
                            ptr += 16;
 
2156
                        }
 
2157
                  }
 
2158
                for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2159
                  {
 
2160
                      rng = polyg->Interiors + ib;
 
2161
                      gaiaExport32 (ptr, rng->Points, 1, endian_arch);  /* # points - interior ring */
 
2162
                      ptr += 4;
 
2163
                      for (iv = 0; iv < rng->Points; iv++)
 
2164
                        {
 
2165
                            if (geom->DimensionModel == GAIA_XY_Z)
 
2166
                              {
 
2167
                                  gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
2168
                              }
 
2169
                            else if (geom->DimensionModel == GAIA_XY_M)
 
2170
                              {
 
2171
                                  gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
2172
                              }
 
2173
                            else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2174
                              {
 
2175
                                  gaiaGetPointXYZM (rng->Coords, iv, &x, &y,
 
2176
                                                    &z, &m);
 
2177
                              }
 
2178
                            else
 
2179
                              {
 
2180
                                  gaiaGetPoint (rng->Coords, iv, &x, &y);
 
2181
                              }
 
2182
                            gaiaExport64 (ptr, x, 1, endian_arch);      /* X - interior ring */
 
2183
                            gaiaExport64 (ptr + 8, y, 1, endian_arch);  /* Y - interior ring */
 
2184
                            ptr += 16;
 
2185
                            if (geom->DimensionModel == GAIA_XY_Z)
 
2186
                              {
 
2187
                                  gaiaExport64 (ptr, z, 1, endian_arch);        /* Z */
 
2188
                                  ptr += 8;
 
2189
                              }
 
2190
                            if (geom->DimensionModel == GAIA_XY_M)
 
2191
                              {
 
2192
                                  gaiaExport64 (ptr, m, 1, endian_arch);        /* M */
 
2193
                                  ptr += 8;
 
2194
                              }
 
2195
                            if (geom->DimensionModel == GAIA_XY_Z_M)
 
2196
                              {
 
2197
                                  gaiaExport64 (ptr, z, 1, endian_arch);        /* Z */
 
2198
                                  gaiaExport64 (ptr + 8, m, 1, endian_arch);    /* M */
 
2199
                                  ptr += 16;
 
2200
                              }
 
2201
                        }
 
2202
                  }
 
2203
                polyg = polyg->Next;
 
2204
            }
 
2205
          *ptr = GAIA_MARK_END; /* END signature */
 
2206
      };
 
2207
}
 
2208
 
 
2209
GAIAGEO_DECLARE void
 
2210
gaiaToCompressedBlobWkb (gaiaGeomCollPtr geom, unsigned char **result,
 
2211
                         int *size)
 
2212
{
 
2213
/* 
 
2214
/ builds the SpatiaLite BLOB representation for this GEOMETRY 
 
2215
/ geometry-compression will be applied to LINESTRINGs and RINGs
 
2216
*/
 
2217
    int ib;
 
2218
    int iv;
 
2219
    double x;
 
2220
    double y;
 
2221
    double z;
 
2222
    double m;
 
2223
    double last_x = 0.0;
 
2224
    double last_y = 0.0;
 
2225
    double last_z = 0.0;
 
2226
    float fx;
 
2227
    float fy;
 
2228
    float fz;
 
2229
    int entities = 0;
 
2230
    int n_points = 0;
 
2231
    int n_linestrings = 0;
 
2232
    int n_polygons = 0;
 
2233
    int type;
 
2234
    unsigned char *ptr;
 
2235
    gaiaPointPtr pt;
 
2236
    gaiaLinestringPtr ln;
 
2237
    gaiaPolygonPtr pg;
 
2238
    gaiaRingPtr rng;
 
2239
    gaiaPointPtr point = NULL;
 
2240
    gaiaLinestringPtr line = NULL;
 
2241
    gaiaPolygonPtr polyg = NULL;
 
2242
    int endian_arch = gaiaEndianArch ();
 
2243
    gaiaMbrGeometry (geom);
 
2244
/* how many entities, and of what kind, do we have ? */
 
2245
    pt = geom->FirstPoint;
 
2246
    while (pt)
 
2247
      {
 
2248
          point = pt;
 
2249
          entities++;
 
2250
          n_points++;
 
2251
          pt = pt->Next;
 
2252
      }
 
2253
    ln = geom->FirstLinestring;
 
2254
    while (ln)
 
2255
      {
 
2256
          line = ln;
 
2257
          entities++;
 
2258
          n_linestrings++;
 
2259
          ln = ln->Next;
 
2260
      }
 
2261
    pg = geom->FirstPolygon;
 
2262
    while (pg)
 
2263
      {
 
2264
          polyg = pg;
 
2265
          entities++;
 
2266
          n_polygons++;
 
2267
          pg = pg->Next;
 
2268
      }
 
2269
    *size = 0;
 
2270
    *result = NULL;
 
2271
    if (n_points == 0 && n_polygons == 0 && n_linestrings == 0)
 
2272
        return;
 
2273
/* ok, we can determine the geometry class */
 
2274
    if (n_points == 1 && n_linestrings == 0 && n_polygons == 0)
 
2275
      {
 
2276
          if (geom->DeclaredType == GAIA_MULTIPOINT)
 
2277
            {
 
2278
                if (geom->DimensionModel == GAIA_XY_Z)
 
2279
                    type = GAIA_MULTIPOINTZ;
 
2280
                else if (geom->DimensionModel == GAIA_XY_M)
 
2281
                    type = GAIA_MULTIPOINTM;
 
2282
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2283
                    type = GAIA_MULTIPOINTZM;
 
2284
                else
 
2285
                    type = GAIA_MULTIPOINT;
 
2286
            }
 
2287
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2288
            {
 
2289
                if (geom->DimensionModel == GAIA_XY_Z)
 
2290
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
2291
                else if (geom->DimensionModel == GAIA_XY_M)
 
2292
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
2293
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2294
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
2295
                else
 
2296
                    type = GAIA_GEOMETRYCOLLECTION;
 
2297
            }
 
2298
          else
 
2299
            {
 
2300
                if (geom->DimensionModel == GAIA_XY_Z)
 
2301
                    type = GAIA_POINTZ;
 
2302
                else if (geom->DimensionModel == GAIA_XY_M)
 
2303
                    type = GAIA_POINTM;
 
2304
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2305
                    type = GAIA_POINTZM;
 
2306
                else
 
2307
                    type = GAIA_POINT;
 
2308
            }
 
2309
      }
 
2310
    else if (n_points > 1 && n_linestrings == 0 && n_polygons == 0)
 
2311
      {
 
2312
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2313
            {
 
2314
                if (geom->DimensionModel == GAIA_XY_Z)
 
2315
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
2316
                else if (geom->DimensionModel == GAIA_XY_M)
 
2317
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
2318
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2319
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
2320
                else
 
2321
                    type = GAIA_GEOMETRYCOLLECTION;
 
2322
            }
 
2323
          else
 
2324
            {
 
2325
                if (geom->DimensionModel == GAIA_XY_Z)
 
2326
                    type = GAIA_MULTIPOINTZ;
 
2327
                else if (geom->DimensionModel == GAIA_XY_M)
 
2328
                    type = GAIA_MULTIPOINTM;
 
2329
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2330
                    type = GAIA_MULTIPOINTZM;
 
2331
                else
 
2332
                    type = GAIA_MULTIPOINT;
 
2333
            }
 
2334
      }
 
2335
    else if (n_points == 0 && n_linestrings == 1 && n_polygons == 0)
 
2336
      {
 
2337
          if (geom->DeclaredType == GAIA_MULTILINESTRING)
 
2338
            {
 
2339
                if (geom->DimensionModel == GAIA_XY_Z)
 
2340
                    type = GAIA_MULTILINESTRINGZ;
 
2341
                else if (geom->DimensionModel == GAIA_XY_M)
 
2342
                    type = GAIA_MULTILINESTRINGM;
 
2343
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2344
                    type = GAIA_MULTILINESTRINGZM;
 
2345
                else
 
2346
                    type = GAIA_MULTILINESTRING;
 
2347
            }
 
2348
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2349
            {
 
2350
                if (geom->DimensionModel == GAIA_XY_Z)
 
2351
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
2352
                else if (geom->DimensionModel == GAIA_XY_M)
 
2353
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
2354
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2355
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
2356
                else
 
2357
                    type = GAIA_GEOMETRYCOLLECTION;
 
2358
            }
 
2359
          else
 
2360
            {
 
2361
                if (geom->DimensionModel == GAIA_XY_Z)
 
2362
                    type = GAIA_LINESTRINGZ;
 
2363
                else if (geom->DimensionModel == GAIA_XY_M)
 
2364
                    type = GAIA_LINESTRINGM;
 
2365
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2366
                    type = GAIA_LINESTRINGZM;
 
2367
                else
 
2368
                    type = GAIA_LINESTRING;
 
2369
            }
 
2370
      }
 
2371
    else if (n_points == 0 && n_linestrings > 1 && n_polygons == 0)
 
2372
      {
 
2373
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2374
            {
 
2375
                if (geom->DimensionModel == GAIA_XY_Z)
 
2376
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
2377
                else if (geom->DimensionModel == GAIA_XY_M)
 
2378
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
2379
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2380
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
2381
                else
 
2382
                    type = GAIA_GEOMETRYCOLLECTION;
 
2383
            }
 
2384
          else
 
2385
            {
 
2386
                if (geom->DimensionModel == GAIA_XY_Z)
 
2387
                    type = GAIA_MULTILINESTRINGZ;
 
2388
                else if (geom->DimensionModel == GAIA_XY_M)
 
2389
                    type = GAIA_MULTILINESTRINGM;
 
2390
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2391
                    type = GAIA_MULTILINESTRINGZM;
 
2392
                else
 
2393
                    type = GAIA_MULTILINESTRING;
 
2394
            }
 
2395
      }
 
2396
    else if (n_points == 0 && n_linestrings == 0 && n_polygons == 1)
 
2397
      {
 
2398
          if (geom->DeclaredType == GAIA_MULTIPOLYGON)
 
2399
            {
 
2400
                if (geom->DimensionModel == GAIA_XY_Z)
 
2401
                    type = GAIA_MULTIPOLYGONZ;
 
2402
                else if (geom->DimensionModel == GAIA_XY_M)
 
2403
                    type = GAIA_MULTIPOLYGONM;
 
2404
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2405
                    type = GAIA_MULTIPOLYGONZM;
 
2406
                else
 
2407
                    type = GAIA_MULTIPOLYGON;
 
2408
            }
 
2409
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2410
            {
 
2411
                if (geom->DimensionModel == GAIA_XY_Z)
 
2412
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
2413
                else if (geom->DimensionModel == GAIA_XY_M)
 
2414
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
2415
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2416
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
2417
                else
 
2418
                    type = GAIA_GEOMETRYCOLLECTION;
 
2419
            }
 
2420
          else
 
2421
            {
 
2422
                if (geom->DimensionModel == GAIA_XY_Z)
 
2423
                    type = GAIA_POLYGONZ;
 
2424
                else if (geom->DimensionModel == GAIA_XY_M)
 
2425
                    type = GAIA_POLYGONM;
 
2426
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2427
                    type = GAIA_POLYGONZM;
 
2428
                else
 
2429
                    type = GAIA_POLYGON;
 
2430
            }
 
2431
      }
 
2432
    else if (n_points == 0 && n_linestrings == 0 && n_polygons > 1)
 
2433
      {
 
2434
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2435
            {
 
2436
                if (geom->DimensionModel == GAIA_XY_Z)
 
2437
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
2438
                else if (geom->DimensionModel == GAIA_XY_M)
 
2439
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
2440
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2441
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
2442
                else
 
2443
                    type = GAIA_GEOMETRYCOLLECTION;
 
2444
            }
 
2445
          else
 
2446
            {
 
2447
                if (geom->DimensionModel == GAIA_XY_Z)
 
2448
                    type = GAIA_MULTIPOLYGONZ;
 
2449
                else if (geom->DimensionModel == GAIA_XY_M)
 
2450
                    type = GAIA_MULTIPOLYGONM;
 
2451
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2452
                    type = GAIA_MULTIPOLYGONZM;
 
2453
                else
 
2454
                    type = GAIA_MULTIPOLYGON;
 
2455
            }
 
2456
      }
 
2457
    else
 
2458
      {
 
2459
          if (geom->DimensionModel == GAIA_XY_Z)
 
2460
              type = GAIA_GEOMETRYCOLLECTIONZ;
 
2461
          else if (geom->DimensionModel == GAIA_XY_M)
 
2462
              type = GAIA_GEOMETRYCOLLECTIONM;
 
2463
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2464
              type = GAIA_GEOMETRYCOLLECTIONZM;
 
2465
          else
 
2466
              type = GAIA_GEOMETRYCOLLECTION;
 
2467
      }
 
2468
/* and now we compute the size of BLOB */
 
2469
    *size = 44;                 /* header size */
 
2470
    switch (type)
 
2471
      {
 
2472
      case GAIA_POINT:
 
2473
          *size += (sizeof (double) * 2);       /* [x,y] coords */
 
2474
          break;
 
2475
      case GAIA_POINTZ:
 
2476
          *size += (sizeof (double) * 3);       /* [x,y,z] coords */
 
2477
          break;
 
2478
      case GAIA_POINTM:
 
2479
          *size += (sizeof (double) * 3);       /* [x,y,m] coords */
 
2480
          break;
 
2481
      case GAIA_POINTZM:
 
2482
          *size += (sizeof (double) * 4);       /* [x,y,z,m] coords */
 
2483
          break;
 
2484
      case GAIA_LINESTRING:
 
2485
          *size += (4 + (8 * line->Points) + 16);       /* # points + [x,y] for each vertex */
 
2486
          break;
 
2487
      case GAIA_LINESTRINGZ:
 
2488
          *size += (4 + (12 * line->Points) + 24);      /* # points + [x,y,z] for each vertex */
 
2489
          break;
 
2490
      case GAIA_LINESTRINGM:
 
2491
          *size += (4 + (16 * line->Points) + 16);      /* # points + [x,y,m] for each vertex */
 
2492
          break;
 
2493
      case GAIA_LINESTRINGZM:
 
2494
          *size += (4 + (20 * line->Points) + 24);      /* # points + [x,y,z,m] for each vertex */
 
2495
          break;
 
2496
      case GAIA_POLYGON:
 
2497
          rng = polyg->Exterior;
 
2498
          *size += (8 + (8 * rng->Points) + 16);        /* # rings + # points + [x.y] array - exterior ring */
 
2499
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2500
            {
 
2501
                rng = polyg->Interiors + ib;
 
2502
                *size += (4 + (8 * rng->Points) + 16);  /* # points + [x,y] array - interior ring */
 
2503
            }
 
2504
          break;
 
2505
      case GAIA_POLYGONZ:
 
2506
          rng = polyg->Exterior;
 
2507
          *size += (8 + (12 * rng->Points) + 24);       /* # rings + # points + [x,y,z] array - exterior ring */
 
2508
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2509
            {
 
2510
                rng = polyg->Interiors + ib;
 
2511
                *size += (4 + (12 * rng->Points) + 24); /* # points + [x,y,z] array - interior ring */
 
2512
            }
 
2513
          break;
 
2514
      case GAIA_POLYGONM:
 
2515
          rng = polyg->Exterior;
 
2516
          *size += (8 + (16 * rng->Points) + 16);       /* # rings + # points + [x,y,m] array - exterior ring */
 
2517
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2518
            {
 
2519
                rng = polyg->Interiors + ib;
 
2520
                *size += (4 + (16 * rng->Points) + 16); /* # points + [x,y,m] array - interior ring */
 
2521
            }
 
2522
          break;
 
2523
      case GAIA_POLYGONZM:
 
2524
          rng = polyg->Exterior;
 
2525
          *size += (8 + (20 * rng->Points) + 24);       /* # rings + # points + [x,y,z,m] array - exterior ring */
 
2526
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2527
            {
 
2528
                rng = polyg->Interiors + ib;
 
2529
                *size += (4 + (20 * rng->Points) + 24); /* # points + [x,y,z,m] array - interior ring */
 
2530
            }
 
2531
          break;
 
2532
      default:
 
2533
          /* this one is not a simple geometry; should be a MULTIxxxx or a GEOMETRYCOLLECTION */
 
2534
          *size += 4;           /* # entities */
 
2535
          point = geom->FirstPoint;
 
2536
          while (point)
 
2537
            {
 
2538
                *size += 5;     /* entity header */
 
2539
                if (geom->DimensionModel == GAIA_XY_Z
 
2540
                    || geom->DimensionModel == GAIA_XY_M)
 
2541
                    *size += (sizeof (double) * 3);     /* three doubles for each POINT */
 
2542
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2543
                    *size += (sizeof (double) * 4);     /* four doubles for each POINT */
 
2544
                else
 
2545
                    *size += (sizeof (double) * 2);     /* two doubles for each POINT */
 
2546
                point = point->Next;
 
2547
            }
 
2548
          line = geom->FirstLinestring;
 
2549
          while (line)
 
2550
            {
 
2551
                *size += 5;     /* entity header */
 
2552
                if (geom->DimensionModel == GAIA_XY_Z)
 
2553
                    *size += (4 + (12 * line->Points) + 24);    /* # points + [x,y,z] for each vertex */
 
2554
                else if (geom->DimensionModel == GAIA_XY_M)
 
2555
                    *size += (4 + (16 * line->Points) + 16);    /* # points + [x,y,m] for each vertex */
 
2556
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2557
                    *size += (4 + (20 * line->Points) + 24);    /* # points + [x,y,z,m] for each vertex */
 
2558
                else
 
2559
                    *size += (4 + (8 * line->Points) + 16);     /* # points + [x,y] for each vertex */
 
2560
                line = line->Next;
 
2561
            }
 
2562
          polyg = geom->FirstPolygon;
 
2563
          while (polyg)
 
2564
            {
 
2565
                *size += 5;     /* entity header */
 
2566
                rng = polyg->Exterior;
 
2567
                if (geom->DimensionModel == GAIA_XY_Z)
 
2568
                    *size += (8 + (12 * rng->Points) + 24);     /* # rings + # points + [x,y,z] array - exterior ring */
 
2569
                else if (geom->DimensionModel == GAIA_XY_M)
 
2570
                    *size += (8 + (16 * rng->Points) + 16);     /* # rings + # points + [x,y,m] array - exterior ring */
 
2571
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2572
                    *size += (8 + (20 * rng->Points) + 24);     /* # rings + # points + [x,y,z,m] array - exterior ring */
 
2573
                else
 
2574
                    *size += (8 + (8 * rng->Points) + 16);      /* # rings + # points + [x,y] array - exterior ring */
 
2575
                for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2576
                  {
 
2577
                      rng = polyg->Interiors + ib;
 
2578
                      if (geom->DimensionModel == GAIA_XY_Z)
 
2579
                          *size += (4 + (12 * rng->Points) + 24);       /* # points + [x,y,z] array - interior ring */
 
2580
                      else if (geom->DimensionModel == GAIA_XY_M)
 
2581
                          *size += (4 + (16 * rng->Points) + 16);       /* # points + [x,y,m] array - interior ring */
 
2582
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
2583
                          *size += (4 + (20 * rng->Points) + 24);       /* # points + [x,y,z,m] array - interior ring */
 
2584
                      else
 
2585
                          *size += (4 + (8 * rng->Points) + 16);        /* # points + [x,y] array - interior ring */
 
2586
                  }
 
2587
                polyg = polyg->Next;
 
2588
            }
 
2589
      };
 
2590
    *result = malloc (*size);
 
2591
    ptr = *result;
 
2592
/* and finally we build the BLOB */
 
2593
    switch (type)
 
2594
      {
 
2595
      case GAIA_POINT:
 
2596
          *ptr = GAIA_MARK_START;       /* START signature */
 
2597
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2598
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2599
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2600
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2601
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2602
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2603
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2604
          gaiaExport32 (ptr + 39, GAIA_POINT, 1, endian_arch);  /* class POINT */
 
2605
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
2606
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
2607
          *(ptr + 59) = GAIA_MARK_END;  /* END signature */
 
2608
          break;
 
2609
      case GAIA_POINTZ:
 
2610
          *ptr = GAIA_MARK_START;       /* START signature */
 
2611
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2612
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2613
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2614
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2615
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2616
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2617
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2618
          gaiaExport32 (ptr + 39, GAIA_POINTZ, 1, endian_arch); /* class POINT XYZ */
 
2619
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
2620
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
2621
          gaiaExport64 (ptr + 59, point->Z, 1, endian_arch);    /* Z */
 
2622
          *(ptr + 67) = GAIA_MARK_END;  /* END signature */
 
2623
          break;
 
2624
      case GAIA_POINTM:
 
2625
          *ptr = GAIA_MARK_START;       /* START signature */
 
2626
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2627
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2628
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2629
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2630
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2631
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2632
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2633
          gaiaExport32 (ptr + 39, GAIA_POINTM, 1, endian_arch); /* class POINT XYM */
 
2634
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
2635
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
2636
          gaiaExport64 (ptr + 59, point->M, 1, endian_arch);    /* M */
 
2637
          *(ptr + 67) = GAIA_MARK_END;  /* END signature */
 
2638
          break;
 
2639
      case GAIA_POINTZM:
 
2640
          *ptr = GAIA_MARK_START;       /* START signature */
 
2641
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2642
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2643
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2644
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2645
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2646
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2647
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2648
          gaiaExport32 (ptr + 39, GAIA_POINTZM, 1, endian_arch);        /* class POINT XYZM */
 
2649
          gaiaExport64 (ptr + 43, point->X, 1, endian_arch);    /* X */
 
2650
          gaiaExport64 (ptr + 51, point->Y, 1, endian_arch);    /* Y */
 
2651
          gaiaExport64 (ptr + 59, point->Z, 1, endian_arch);    /* M */
 
2652
          gaiaExport64 (ptr + 67, point->M, 1, endian_arch);    /* Z */
 
2653
          *(ptr + 75) = GAIA_MARK_END;  /* END signature */
 
2654
          break;
 
2655
      case GAIA_LINESTRING:
 
2656
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2657
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2658
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2659
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2660
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2661
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2662
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2663
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2664
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_LINESTRING, 1, endian_arch);  /* class LINESTRING */
 
2665
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
2666
          ptr += 47;
 
2667
          for (iv = 0; iv < line->Points; iv++)
 
2668
            {
 
2669
                gaiaGetPoint (line->Coords, iv, &x, &y);
 
2670
                if (iv == 0 || iv == (line->Points - 1))
 
2671
                  {
 
2672
                      /* first and last vertices are uncompressed */
 
2673
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
2674
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2675
                      ptr += 16;
 
2676
                  }
 
2677
                else
 
2678
                  {
 
2679
                      /* compressing any other intermediate vertex */
 
2680
                      fx = (float) (x - last_x);
 
2681
                      fy = (float) (y - last_y);
 
2682
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2683
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2684
                      ptr += 8;
 
2685
                  }
 
2686
                last_x = x;
 
2687
                last_y = y;
 
2688
            }
 
2689
          *ptr = GAIA_MARK_END; /* END signature */
 
2690
          break;
 
2691
      case GAIA_LINESTRINGZ:
 
2692
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2693
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2694
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2695
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2696
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2697
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2698
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2699
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2700
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_LINESTRINGZ, 1, endian_arch); /* class LINESTRING XYZ */
 
2701
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
2702
          ptr += 47;
 
2703
          for (iv = 0; iv < line->Points; iv++)
 
2704
            {
 
2705
                gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
 
2706
                if (iv == 0 || iv == (line->Points - 1))
 
2707
                  {
 
2708
                      /* first and last vertices are uncompressed */
 
2709
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
2710
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2711
                      gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
2712
                      ptr += 24;
 
2713
                  }
 
2714
                else
 
2715
                  {
 
2716
                      /* compressing any other intermediate vertex */
 
2717
                      fx = (float) (x - last_x);
 
2718
                      fy = (float) (y - last_y);
 
2719
                      fz = (float) (z - last_z);
 
2720
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2721
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2722
                      gaiaExportF32 (ptr + 8, fz, 1, endian_arch);
 
2723
                      ptr += 12;
 
2724
                  }
 
2725
                last_x = x;
 
2726
                last_y = y;
 
2727
                last_z = z;
 
2728
            }
 
2729
          *ptr = GAIA_MARK_END; /* END signature */
 
2730
          break;
 
2731
      case GAIA_LINESTRINGM:
 
2732
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2733
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2734
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2735
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2736
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2737
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2738
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2739
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2740
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_LINESTRINGM, 1, endian_arch); /* class LINESTRING XYM */
 
2741
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
2742
          ptr += 47;
 
2743
          for (iv = 0; iv < line->Points; iv++)
 
2744
            {
 
2745
                gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
 
2746
                if (iv == 0 || iv == (line->Points - 1))
 
2747
                  {
 
2748
                      /* first and last vertices are uncompressed */
 
2749
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
2750
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2751
                      gaiaExport64 (ptr + 16, m, 1, endian_arch);
 
2752
                      ptr += 24;
 
2753
                  }
 
2754
                else
 
2755
                  {
 
2756
                      /* compressing any other intermediate vertex */
 
2757
                      fx = (float) (x - last_x);
 
2758
                      fy = (float) (y - last_y);
 
2759
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2760
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2761
                      gaiaExport64 (ptr + 8, m, 1, endian_arch);
 
2762
                      ptr += 16;
 
2763
                  }
 
2764
                last_x = x;
 
2765
                last_y = y;
 
2766
            }
 
2767
          *ptr = GAIA_MARK_END; /* END signature */
 
2768
          break;
 
2769
      case GAIA_LINESTRINGZM:
 
2770
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2771
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2772
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2773
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2774
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2775
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2776
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2777
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2778
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_LINESTRINGZM, 1, endian_arch);        /* class LINESTRING XYZM */
 
2779
          gaiaExport32 (ptr + 43, line->Points, 1, endian_arch);        /* # points */
 
2780
          ptr += 47;
 
2781
          for (iv = 0; iv < line->Points; iv++)
 
2782
            {
 
2783
                gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
 
2784
                if (iv == 0 || iv == (line->Points - 1))
 
2785
                  {
 
2786
                      /* first and last vertices are uncompressed */
 
2787
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
2788
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2789
                      gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
2790
                      gaiaExport64 (ptr + 24, m, 1, endian_arch);
 
2791
                      ptr += 32;
 
2792
                  }
 
2793
                else
 
2794
                  {
 
2795
                      /* compressing any other intermediate vertex */
 
2796
                      fx = (float) (x - last_x);
 
2797
                      fy = (float) (y - last_y);
 
2798
                      fz = (float) (z - last_z);
 
2799
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2800
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2801
                      gaiaExportF32 (ptr + 8, fz, 1, endian_arch);
 
2802
                      gaiaExport64 (ptr + 12, m, 1, endian_arch);
 
2803
                      ptr += 20;
 
2804
                  }
 
2805
                last_x = x;
 
2806
                last_y = y;
 
2807
                last_z = z;
 
2808
            }
 
2809
          *ptr = GAIA_MARK_END; /* END signature */
 
2810
          break;
 
2811
      case GAIA_POLYGON:
 
2812
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2813
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2814
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2815
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2816
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2817
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2818
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2819
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2820
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_POLYGON, 1, endian_arch);     /* class POLYGON */
 
2821
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
2822
          rng = polyg->Exterior;
 
2823
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
2824
          ptr += 51;
 
2825
          for (iv = 0; iv < rng->Points; iv++)
 
2826
            {
 
2827
                gaiaGetPoint (rng->Coords, iv, &x, &y);
 
2828
                if (iv == 0 || iv == (rng->Points - 1))
 
2829
                  {
 
2830
                      /* first and last vertices are uncompressed */
 
2831
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
2832
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2833
                      ptr += 16;
 
2834
                  }
 
2835
                else
 
2836
                  {
 
2837
                      /* compressing any other intermediate vertex */
 
2838
                      fx = (float) (x - last_x);
 
2839
                      fy = (float) (y - last_y);
 
2840
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2841
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2842
                      ptr += 8;
 
2843
                  }
 
2844
                last_x = x;
 
2845
                last_y = y;
 
2846
            }
 
2847
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2848
            {
 
2849
                rng = polyg->Interiors + ib;
 
2850
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
2851
                ptr += 4;
 
2852
                for (iv = 0; iv < rng->Points; iv++)
 
2853
                  {
 
2854
                      gaiaGetPoint (rng->Coords, iv, &x, &y);
 
2855
                      if (iv == 0 || iv == (rng->Points - 1))
 
2856
                        {
 
2857
                            /* first and last vertices are uncompressed */
 
2858
                            gaiaExport64 (ptr, x, 1, endian_arch);
 
2859
                            gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2860
                            ptr += 16;
 
2861
                        }
 
2862
                      else
 
2863
                        {
 
2864
                            /* compressing any other intermediate vertex */
 
2865
                            fx = (float) (x - last_x);
 
2866
                            fy = (float) (y - last_y);
 
2867
                            gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2868
                            gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2869
                            ptr += 8;
 
2870
                        }
 
2871
                      last_x = x;
 
2872
                      last_y = y;
 
2873
                  }
 
2874
            }
 
2875
          *ptr = GAIA_MARK_END; /* END signature */
 
2876
          break;
 
2877
      case GAIA_POLYGONZ:
 
2878
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2879
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2880
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2881
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2882
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2883
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2884
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2885
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2886
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_POLYGONZ, 1, endian_arch);    /* class POLYGON XYZ */
 
2887
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
2888
          rng = polyg->Exterior;
 
2889
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
2890
          ptr += 51;
 
2891
          for (iv = 0; iv < rng->Points; iv++)
 
2892
            {
 
2893
                gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
2894
                if (iv == 0 || iv == (rng->Points - 1))
 
2895
                  {
 
2896
                      /* first and last vertices are uncompressed */
 
2897
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
2898
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2899
                      gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
2900
                      ptr += 24;
 
2901
                  }
 
2902
                else
 
2903
                  {
 
2904
                      /* compressing any other intermediate vertex */
 
2905
                      fx = (float) (x - last_x);
 
2906
                      fy = (float) (y - last_y);
 
2907
                      fz = (float) (z - last_z);
 
2908
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2909
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2910
                      gaiaExportF32 (ptr + 8, fz, 1, endian_arch);
 
2911
                      ptr += 12;
 
2912
                  }
 
2913
                last_x = x;
 
2914
                last_y = y;
 
2915
                last_z = z;
 
2916
            }
 
2917
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2918
            {
 
2919
                rng = polyg->Interiors + ib;
 
2920
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
2921
                ptr += 4;
 
2922
                for (iv = 0; iv < rng->Points; iv++)
 
2923
                  {
 
2924
                      gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
2925
                      if (iv == 0 || iv == (rng->Points - 1))
 
2926
                        {
 
2927
                            /* first and last vertices are uncompressed */
 
2928
                            gaiaExport64 (ptr, x, 1, endian_arch);
 
2929
                            gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2930
                            gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
2931
                            ptr += 24;
 
2932
                        }
 
2933
                      else
 
2934
                        {
 
2935
                            /* compressing any other intermediate vertex */
 
2936
                            fx = (float) (x - last_x);
 
2937
                            fy = (float) (y - last_y);
 
2938
                            fz = (float) (z - last_z);
 
2939
                            gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2940
                            gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2941
                            gaiaExportF32 (ptr + 8, fz, 1, endian_arch);
 
2942
                            ptr += 12;
 
2943
                        }
 
2944
                      last_x = x;
 
2945
                      last_y = y;
 
2946
                      last_z = z;
 
2947
                  }
 
2948
            }
 
2949
          *ptr = GAIA_MARK_END; /* END signature */
 
2950
          break;
 
2951
      case GAIA_POLYGONM:
 
2952
          *ptr = GAIA_MARK_START;       /* START signatue */
 
2953
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
2954
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
2955
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
2956
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
2957
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
2958
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
2959
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
2960
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_POLYGONM, 1, endian_arch);    /* class POLYGON XYM */
 
2961
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
2962
          rng = polyg->Exterior;
 
2963
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
2964
          ptr += 51;
 
2965
          for (iv = 0; iv < rng->Points; iv++)
 
2966
            {
 
2967
                gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
2968
                if (iv == 0 || iv == (rng->Points - 1))
 
2969
                  {
 
2970
                      /* first and last vertices are uncompressed */
 
2971
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
2972
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
2973
                      gaiaExport64 (ptr + 16, m, 1, endian_arch);
 
2974
                      ptr += 24;
 
2975
                  }
 
2976
                else
 
2977
                  {
 
2978
                      /* compressing any other intermediate vertex */
 
2979
                      fx = (float) (x - last_x);
 
2980
                      fy = (float) (y - last_y);
 
2981
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
2982
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
2983
                      gaiaExport64 (ptr + 8, m, 1, endian_arch);
 
2984
                      ptr += 16;
 
2985
                  }
 
2986
                last_x = x;
 
2987
                last_y = y;
 
2988
            }
 
2989
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
2990
            {
 
2991
                rng = polyg->Interiors + ib;
 
2992
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
2993
                ptr += 4;
 
2994
                for (iv = 0; iv < rng->Points; iv++)
 
2995
                  {
 
2996
                      gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
2997
                      if (iv == 0 || iv == (rng->Points - 1))
 
2998
                        {
 
2999
                            /* first and last vertices are uncompressed */
 
3000
                            gaiaExport64 (ptr, x, 1, endian_arch);
 
3001
                            gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
3002
                            gaiaExport64 (ptr + 16, m, 1, endian_arch);
 
3003
                            ptr += 24;
 
3004
                        }
 
3005
                      else
 
3006
                        {
 
3007
                            /* compressing any other intermediate vertex */
 
3008
                            fx = (float) (x - last_x);
 
3009
                            fy = (float) (y - last_y);
 
3010
                            gaiaExportF32 (ptr, fx, 1, endian_arch);
 
3011
                            gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
3012
                            gaiaExport64 (ptr + 8, m, 1, endian_arch);
 
3013
                            ptr += 16;
 
3014
                        }
 
3015
                      last_x = x;
 
3016
                      last_y = y;
 
3017
                  }
 
3018
            }
 
3019
          *ptr = GAIA_MARK_END; /* END signature */
 
3020
          break;
 
3021
      case GAIA_POLYGONZM:
 
3022
          *ptr = GAIA_MARK_START;       /* START signatue */
 
3023
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
3024
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
3025
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
3026
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
3027
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
3028
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
3029
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
3030
          gaiaExport32 (ptr + 39, GAIA_COMPRESSED_POLYGONZM, 1, endian_arch);   /* class POLYGON */
 
3031
          gaiaExport32 (ptr + 43, polyg->NumInteriors + 1, 1, endian_arch);     /* # rings */
 
3032
          rng = polyg->Exterior;
 
3033
          gaiaExport32 (ptr + 47, rng->Points, 1, endian_arch); /* # points - exterior ring */
 
3034
          ptr += 51;
 
3035
          for (iv = 0; iv < rng->Points; iv++)
 
3036
            {
 
3037
                gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
3038
                if (iv == 0 || iv == (rng->Points - 1))
 
3039
                  {
 
3040
                      /* first and last vertices are uncompressed */
 
3041
                      gaiaExport64 (ptr, x, 1, endian_arch);
 
3042
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
3043
                      gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
3044
                      gaiaExport64 (ptr + 24, m, 1, endian_arch);
 
3045
                      ptr += 32;
 
3046
                  }
 
3047
                else
 
3048
                  {
 
3049
                      /* compressing any other intermediate vertex */
 
3050
                      fx = (float) (x - last_x);
 
3051
                      fy = (float) (y - last_y);
 
3052
                      fz = (float) (z - last_z);
 
3053
                      gaiaExportF32 (ptr, fx, 1, endian_arch);
 
3054
                      gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
3055
                      gaiaExportF32 (ptr + 8, fz, 1, endian_arch);
 
3056
                      gaiaExport64 (ptr + 12, m, 1, endian_arch);
 
3057
                      ptr += 20;
 
3058
                  }
 
3059
                last_x = x;
 
3060
                last_y = y;
 
3061
                last_z = z;
 
3062
            }
 
3063
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
3064
            {
 
3065
                rng = polyg->Interiors + ib;
 
3066
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
3067
                ptr += 4;
 
3068
                for (iv = 0; iv < rng->Points; iv++)
 
3069
                  {
 
3070
                      gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
3071
                      if (iv == 0 || iv == (rng->Points - 1))
 
3072
                        {
 
3073
                            /* first and last vertices are uncompressed */
 
3074
                            gaiaExport64 (ptr, x, 1, endian_arch);
 
3075
                            gaiaExport64 (ptr + 8, y, 1, endian_arch);
 
3076
                            gaiaExport64 (ptr + 16, z, 1, endian_arch);
 
3077
                            gaiaExport64 (ptr + 24, m, 1, endian_arch);
 
3078
                            ptr += 32;
 
3079
                        }
 
3080
                      else
 
3081
                        {
 
3082
                            /* compressing any other intermediate vertex */
 
3083
                            fx = (float) (x - last_x);
 
3084
                            fy = (float) (y - last_y);
 
3085
                            fz = (float) (z - last_z);
 
3086
                            gaiaExportF32 (ptr, fx, 1, endian_arch);
 
3087
                            gaiaExportF32 (ptr + 4, fy, 1, endian_arch);
 
3088
                            gaiaExportF32 (ptr + 8, fz, 1, endian_arch);
 
3089
                            gaiaExport64 (ptr + 12, m, 1, endian_arch);
 
3090
                            ptr += 20;
 
3091
                        }
 
3092
                      last_x = x;
 
3093
                      last_y = y;
 
3094
                      last_z = z;
 
3095
                  }
 
3096
            }
 
3097
          *ptr = GAIA_MARK_END; /* END signature */
 
3098
          break;
 
3099
      default:
 
3100
          /* this one is a MULTIxxxx or a GEOMETRYCOLLECTION - building the main header */
 
3101
          *ptr = GAIA_MARK_START;       /* START signatue */
 
3102
          *(ptr + 1) = GAIA_LITTLE_ENDIAN;      /* byte ordering */
 
3103
          gaiaExport32 (ptr + 2, geom->Srid, 1, endian_arch);   /* the SRID */
 
3104
          gaiaExport64 (ptr + 6, geom->MinX, 1, endian_arch);   /* MBR - minimun X */
 
3105
          gaiaExport64 (ptr + 14, geom->MinY, 1, endian_arch);  /* MBR - minimun Y */
 
3106
          gaiaExport64 (ptr + 22, geom->MaxX, 1, endian_arch);  /* MBR - maximun X */
 
3107
          gaiaExport64 (ptr + 30, geom->MaxY, 1, endian_arch);  /* MBR - maximun Y */
 
3108
          *(ptr + 38) = GAIA_MARK_MBR;  /* MBR signature */
 
3109
          gaiaExport32 (ptr + 39, type, 1, endian_arch);        /* geometric class */
 
3110
          gaiaExport32 (ptr + 43, entities, 1, endian_arch);    /* # entities */
 
3111
          ptr += 47;
 
3112
          point = geom->FirstPoint;
 
3113
          while (point)
 
3114
            {
 
3115
                *ptr = GAIA_MARK_ENTITY;        /* ENTITY signature */
 
3116
                if (geom->DimensionModel == GAIA_XY_Z)
 
3117
                  {
 
3118
                      gaiaExport32 (ptr + 1, GAIA_POINTZ, 1, endian_arch);      /* class POINT XYZ */
 
3119
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
3120
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
3121
                      gaiaExport64 (ptr + 21, point->Z, 1, endian_arch);        /* Z */
 
3122
                      ptr += 29;
 
3123
                  }
 
3124
                else if (geom->DimensionModel == GAIA_XY_M)
 
3125
                  {
 
3126
                      gaiaExport32 (ptr + 1, GAIA_POINTM, 1, endian_arch);      /* class POINT XYM */
 
3127
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
3128
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
3129
                      gaiaExport64 (ptr + 21, point->M, 1, endian_arch);        /* M */
 
3130
                      ptr += 29;
 
3131
                  }
 
3132
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3133
                  {
 
3134
                      gaiaExport32 (ptr + 1, GAIA_POINTZM, 1, endian_arch);     /* class POINT XYZM */
 
3135
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
3136
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
3137
                      gaiaExport64 (ptr + 21, point->Z, 1, endian_arch);        /* Z */
 
3138
                      gaiaExport64 (ptr + 29, point->M, 1, endian_arch);        /* M */
 
3139
                      ptr += 37;
 
3140
                  }
 
3141
                else
 
3142
                  {
 
3143
                      gaiaExport32 (ptr + 1, GAIA_POINT, 1, endian_arch);       /* class POINT */
 
3144
                      gaiaExport64 (ptr + 5, point->X, 1, endian_arch); /* X */
 
3145
                      gaiaExport64 (ptr + 13, point->Y, 1, endian_arch);        /* Y */
 
3146
                      ptr += 21;
 
3147
                  }
 
3148
                point = point->Next;
 
3149
            }
 
3150
          line = geom->FirstLinestring;
 
3151
          while (line)
 
3152
            {
 
3153
                *ptr = GAIA_MARK_ENTITY;        /* ENTITY signature */
 
3154
                if (geom->DimensionModel == GAIA_XY_Z)
 
3155
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_LINESTRINGZ, 1, endian_arch);        /* class LINESTRING XYZ */
 
3156
                else if (geom->DimensionModel == GAIA_XY_M)
 
3157
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_LINESTRINGM, 1, endian_arch);        /* class LINESTRING XYM */
 
3158
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3159
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_LINESTRINGZM, 1, endian_arch);       /* class LINESTRING XYZM */
 
3160
                else
 
3161
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_LINESTRING, 1, endian_arch); /* class LINESTRING */
 
3162
                gaiaExport32 (ptr + 5, line->Points, 1, endian_arch);   /* # points */
 
3163
                ptr += 9;
 
3164
                for (iv = 0; iv < line->Points; iv++)
 
3165
                  {
 
3166
                      z = 0.0;
 
3167
                      m = 0.0;
 
3168
                      if (geom->DimensionModel == GAIA_XY_Z)
 
3169
                        {
 
3170
                            gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
 
3171
                        }
 
3172
                      else if (geom->DimensionModel == GAIA_XY_M)
 
3173
                        {
 
3174
                            gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
 
3175
                        }
 
3176
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3177
                        {
 
3178
                            gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
 
3179
                        }
 
3180
                      else
 
3181
                        {
 
3182
                            gaiaGetPoint (line->Coords, iv, &x, &y);
 
3183
                        }
 
3184
                      if (iv == 0 || iv == (line->Points - 1))
 
3185
                        {
 
3186
                            /* first and last vertices are uncompressed */
 
3187
                            gaiaExport64 (ptr, x, 1, endian_arch);      /* X */
 
3188
                            gaiaExport64 (ptr + 8, y, 1, endian_arch);  /* Y */
 
3189
                            ptr += 16;
 
3190
                        }
 
3191
                      else
 
3192
                        {
 
3193
                            /* compressing any other intermediate vertex */
 
3194
                            fx = (float) (x - last_x);
 
3195
                            fy = (float) (y - last_y);
 
3196
                            gaiaExportF32 (ptr, fx, 1, endian_arch);    /* X */
 
3197
                            gaiaExportF32 (ptr + 4, fy, 1, endian_arch);        /* Y */
 
3198
                            ptr += 8;
 
3199
                        }
 
3200
                      if (geom->DimensionModel == GAIA_XY_Z)
 
3201
                        {
 
3202
                            if (iv == 0 || iv == (line->Points - 1))
 
3203
                              {
 
3204
                                  /* first and last vertices are uncompressed */
 
3205
                                  gaiaExport64 (ptr, z, 1, endian_arch);        /* Z */
 
3206
                                  ptr += 8;
 
3207
                              }
 
3208
                            else
 
3209
                              {
 
3210
                                  /* compressing any other intermediate vertex */
 
3211
                                  fz = (float) (z - last_z);
 
3212
                                  gaiaExportF32 (ptr, fz, 1, endian_arch);      /* Z */
 
3213
                                  ptr += 4;
 
3214
                              }
 
3215
                        }
 
3216
                      if (geom->DimensionModel == GAIA_XY_M)
 
3217
                        {
 
3218
                            gaiaExport64 (ptr, m, 1, endian_arch);      /* M */
 
3219
                            ptr += 8;
 
3220
                        }
 
3221
                      if (geom->DimensionModel == GAIA_XY_Z_M)
 
3222
                        {
 
3223
                            if (iv == 0 || iv == (line->Points - 1))
 
3224
                              {
 
3225
                                  /* first and last vertices are uncompressed */
 
3226
                                  gaiaExport64 (ptr, z, 1, endian_arch);        /* Z */
 
3227
                                  ptr += 8;
 
3228
                              }
 
3229
                            else
 
3230
                              {
 
3231
                                  /* compressing any other intermediate vertex */
 
3232
                                  fz = (float) (z - last_z);
 
3233
                                  gaiaExportF32 (ptr, fz, 1, endian_arch);      /* Z */
 
3234
                                  ptr += 4;
 
3235
                              }
 
3236
                            gaiaExport64 (ptr, m, 1, endian_arch);      /* M */
 
3237
                            ptr += 8;
 
3238
                        }
 
3239
                      last_x = x;
 
3240
                      last_y = y;
 
3241
                      last_z = z;
 
3242
                  }
 
3243
                line = line->Next;
 
3244
            }
 
3245
          polyg = geom->FirstPolygon;
 
3246
          while (polyg)
 
3247
            {
 
3248
                *ptr = GAIA_MARK_ENTITY;        /* ENTITY signature */
 
3249
                if (geom->DimensionModel == GAIA_XY_Z)
 
3250
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_POLYGONZ, 1, endian_arch);   /* class POLYGON XYZ */
 
3251
                else if (geom->DimensionModel == GAIA_XY_M)
 
3252
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_POLYGONM, 1, endian_arch);   /* class POLYGON XYM */
 
3253
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3254
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_POLYGONZM, 1, endian_arch);  /* class POLYGON XYZM */
 
3255
                else
 
3256
                    gaiaExport32 (ptr + 1, GAIA_COMPRESSED_POLYGON, 1, endian_arch);    /* class POLYGON */
 
3257
                gaiaExport32 (ptr + 5, polyg->NumInteriors + 1, 1, endian_arch);        /* # rings */
 
3258
                rng = polyg->Exterior;
 
3259
                gaiaExport32 (ptr + 9, rng->Points, 1, endian_arch);    /* # points - exterior ring */
 
3260
                ptr += 13;
 
3261
                for (iv = 0; iv < rng->Points; iv++)
 
3262
                  {
 
3263
                      z = 0.0;
 
3264
                      m = 0.0;
 
3265
                      if (geom->DimensionModel == GAIA_XY_Z)
 
3266
                        {
 
3267
                            gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
3268
                        }
 
3269
                      else if (geom->DimensionModel == GAIA_XY_M)
 
3270
                        {
 
3271
                            gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
3272
                        }
 
3273
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3274
                        {
 
3275
                            gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
3276
                        }
 
3277
                      else
 
3278
                        {
 
3279
                            gaiaGetPoint (rng->Coords, iv, &x, &y);
 
3280
                        }
 
3281
                      if (iv == 0 || iv == (rng->Points - 1))
 
3282
                        {
 
3283
                            /* first and last vertices are uncompressed */
 
3284
                            gaiaExport64 (ptr, x, 1, endian_arch);      /* X - exterior ring */
 
3285
                            gaiaExport64 (ptr + 8, y, 1, endian_arch);  /* Y - exterior ring */
 
3286
                            ptr += 16;
 
3287
                        }
 
3288
                      else
 
3289
                        {
 
3290
                            /* compressing any other intermediate vertex */
 
3291
                            fx = (float) (x - last_x);
 
3292
                            fy = (float) (y - last_y);
 
3293
                            gaiaExportF32 (ptr, fx, 1, endian_arch);    /* X */
 
3294
                            gaiaExportF32 (ptr + 4, fy, 1, endian_arch);        /* Y */
 
3295
                            ptr += 8;
 
3296
                        }
 
3297
                      if (geom->DimensionModel == GAIA_XY_Z)
 
3298
                        {
 
3299
                            if (iv == 0 || iv == (rng->Points - 1))
 
3300
                              {
 
3301
                                  /* first and last vertices are uncompressed */
 
3302
                                  gaiaExport64 (ptr, z, 1, endian_arch);        /* Z */
 
3303
                                  ptr += 8;
 
3304
                              }
 
3305
                            else
 
3306
                              {
 
3307
                                  /* compressing any other intermediate vertex */
 
3308
                                  fz = (float) (z - last_z);
 
3309
                                  gaiaExportF32 (ptr, fz, 1, endian_arch);      /* Z */
 
3310
                                  ptr += 4;
 
3311
                              }
 
3312
                        }
 
3313
                      if (geom->DimensionModel == GAIA_XY_M)
 
3314
                        {
 
3315
                            gaiaExport64 (ptr, m, 1, endian_arch);      /* M */
 
3316
                            ptr += 8;
 
3317
                        }
 
3318
                      if (geom->DimensionModel == GAIA_XY_Z_M)
 
3319
                        {
 
3320
                            if (iv == 0 || iv == (rng->Points - 1))
 
3321
                              {
 
3322
                                  /* first and last vertices are uncompressed */
 
3323
                                  gaiaExport64 (ptr, z, 1, endian_arch);        /* Z */
 
3324
                                  ptr += 8;
 
3325
                              }
 
3326
                            else
 
3327
                              {
 
3328
                                  /* compressing any other intermediate vertex */
 
3329
                                  fz = (float) (z - last_z);
 
3330
                                  gaiaExportF32 (ptr, fz, 1, endian_arch);      /* Z */
 
3331
                                  ptr += 4;
 
3332
                              }
 
3333
                            gaiaExport64 (ptr, m, 1, endian_arch);      /* M */
 
3334
                            ptr += 8;
 
3335
                        }
 
3336
                      last_x = x;
 
3337
                      last_y = y;
 
3338
                      last_z = z;
 
3339
                  }
 
3340
                for (ib = 0; ib < polyg->NumInteriors; ib++)
 
3341
                  {
 
3342
                      rng = polyg->Interiors + ib;
 
3343
                      gaiaExport32 (ptr, rng->Points, 1, endian_arch);  /* # points - interior ring */
 
3344
                      ptr += 4;
 
3345
                      for (iv = 0; iv < rng->Points; iv++)
 
3346
                        {
 
3347
                            z = 0.0;
 
3348
                            m = 0.0;
 
3349
                            if (geom->DimensionModel == GAIA_XY_Z)
 
3350
                              {
 
3351
                                  gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
3352
                              }
 
3353
                            else if (geom->DimensionModel == GAIA_XY_M)
 
3354
                              {
 
3355
                                  gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
3356
                              }
 
3357
                            else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3358
                              {
 
3359
                                  gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z,
 
3360
                                                    &m);
 
3361
                              }
 
3362
                            else
 
3363
                              {
 
3364
                                  gaiaGetPoint (rng->Coords, iv, &x, &y);
 
3365
                              }
 
3366
                            if (iv == 0 || iv == (rng->Points - 1))
 
3367
                              {
 
3368
                                  /* first and last vertices are uncompressed */
 
3369
                                  gaiaExport64 (ptr, x, 1, endian_arch);        /* X - interior ring */
 
3370
                                  gaiaExport64 (ptr + 8, y, 1, endian_arch);    /* Y - interior ring */
 
3371
                                  ptr += 16;
 
3372
                              }
 
3373
                            else
 
3374
                              {
 
3375
                                  /* compressing any other intermediate vertex */
 
3376
                                  fx = (float) (x - last_x);
 
3377
                                  fy = (float) (y - last_y);
 
3378
                                  gaiaExportF32 (ptr, fx, 1, endian_arch);      /* X */
 
3379
                                  gaiaExportF32 (ptr + 4, fy, 1, endian_arch);  /* Y */
 
3380
                                  ptr += 8;
 
3381
                              }
 
3382
                            if (geom->DimensionModel == GAIA_XY_Z)
 
3383
                              {
 
3384
                                  if (iv == 0 || iv == (rng->Points - 1))
 
3385
                                    {
 
3386
                                        /* first and last vertices are uncompressed */
 
3387
                                        gaiaExport64 (ptr, z, 1, endian_arch);  /* Z */
 
3388
                                        ptr += 8;
 
3389
                                    }
 
3390
                                  else
 
3391
                                    {
 
3392
                                        /* compressing any other intermediate vertex */
 
3393
                                        fz = (float) (z - last_z);
 
3394
                                        gaiaExportF32 (ptr, fz, 1, endian_arch);        /* Z */
 
3395
                                        ptr += 4;
 
3396
                                    }
 
3397
                              }
 
3398
                            if (geom->DimensionModel == GAIA_XY_M)
 
3399
                              {
 
3400
                                  gaiaExport64 (ptr, m, 1, endian_arch);        /* M */
 
3401
                                  ptr += 8;
 
3402
                              }
 
3403
                            if (geom->DimensionModel == GAIA_XY_Z_M)
 
3404
                              {
 
3405
                                  if (iv == 0 || iv == (rng->Points - 1))
 
3406
                                    {
 
3407
                                        /* first and last vertices are uncompressed */
 
3408
                                        gaiaExport64 (ptr, z, 1, endian_arch);  /* Z */
 
3409
                                        ptr += 8;
 
3410
                                    }
 
3411
                                  else
 
3412
                                    {
 
3413
                                        /* compressing any other intermediate vertex */
 
3414
                                        fz = (float) (z - last_z);
 
3415
                                        gaiaExportF32 (ptr, fz, 1, endian_arch);        /* Z */
 
3416
                                        ptr += 4;
 
3417
                                    }
 
3418
                                  gaiaExport64 (ptr, m, 1, endian_arch);        /* M */
 
3419
                                  ptr += 8;
 
3420
                              }
 
3421
                            last_x = x;
 
3422
                            last_y = y;
 
3423
                            last_z = z;
 
3424
                        }
 
3425
                  }
 
3426
                polyg = polyg->Next;
 
3427
            }
 
3428
          *ptr = GAIA_MARK_END; /* END signature */
 
3429
      };
 
3430
}
 
3431
 
 
3432
GAIAGEO_DECLARE gaiaGeomCollPtr
 
3433
gaiaFromWkb (const unsigned char *blob, unsigned int size)
 
3434
{
 
3435
/* decoding from WKB to GEOMETRY  */
 
3436
    int type;
 
3437
    int little_endian;
 
3438
    gaiaGeomCollPtr geo = NULL;
 
3439
    int endian_arch = gaiaEndianArch ();
 
3440
    if (size < 5)
 
3441
        return NULL;
 
3442
    if (*(blob + 0) == 0x01)
 
3443
        little_endian = GAIA_LITTLE_ENDIAN;
 
3444
    else
 
3445
        little_endian = GAIA_BIG_ENDIAN;
 
3446
    type = gaiaImport32 (blob + 1, little_endian, endian_arch);
 
3447
    if (type == GAIA_POINTZ || type == GAIA_LINESTRINGZ || type == GAIA_POLYGONZ
 
3448
        || type == GAIA_MULTIPOINTZ || type == GAIA_MULTILINESTRINGZ
 
3449
        || type == GAIA_MULTIPOLYGONZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
3450
        || type == GAIA_GEOSWKB_POINTZ || type == GAIA_GEOSWKB_LINESTRINGZ
 
3451
        || type == GAIA_GEOSWKB_POLYGONZ || type == GAIA_GEOSWKB_MULTIPOINTZ
 
3452
        || type == GAIA_GEOSWKB_MULTILINESTRINGZ
 
3453
        || type == GAIA_GEOSWKB_MULTIPOLYGONZ
 
3454
        || type == GAIA_GEOSWKB_GEOMETRYCOLLECTIONZ)
 
3455
        geo = gaiaAllocGeomCollXYZ ();
 
3456
    else if (type == GAIA_POINTM || type == GAIA_LINESTRINGM
 
3457
             || type == GAIA_POLYGONM || type == GAIA_MULTIPOINTM
 
3458
             || type == GAIA_MULTILINESTRINGM || type == GAIA_MULTIPOLYGONM
 
3459
             || type == GAIA_GEOMETRYCOLLECTIONM)
 
3460
        geo = gaiaAllocGeomCollXYM ();
 
3461
    else if (type == GAIA_POINTZM || type == GAIA_LINESTRINGZM
 
3462
             || type == GAIA_POLYGONZM || type == GAIA_MULTIPOINTZM
 
3463
             || type == GAIA_MULTILINESTRINGZM || type == GAIA_MULTIPOLYGONZM
 
3464
             || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3465
        geo = gaiaAllocGeomCollXYZM ();
 
3466
    else
 
3467
        geo = gaiaAllocGeomColl ();
 
3468
    geo->Srid = -1;
 
3469
    geo->endian_arch = (char) endian_arch;
 
3470
    geo->endian = (char) little_endian;
 
3471
    geo->blob = blob;
 
3472
    geo->size = size;
 
3473
    geo->offset = 5;
 
3474
    switch (type)
 
3475
      {
 
3476
      case GAIA_POINT:
 
3477
          ParseWkbPoint (geo);
 
3478
          break;
 
3479
      case GAIA_POINTZ:
 
3480
      case GAIA_GEOSWKB_POINTZ:
 
3481
          ParseWkbPointZ (geo);
 
3482
          break;
 
3483
      case GAIA_POINTM:
 
3484
          ParseWkbPointM (geo);
 
3485
          break;
 
3486
      case GAIA_POINTZM:
 
3487
          ParseWkbPointZM (geo);
 
3488
          break;
 
3489
      case GAIA_LINESTRING:
 
3490
          ParseWkbLine (geo);
 
3491
          break;
 
3492
      case GAIA_LINESTRINGZ:
 
3493
      case GAIA_GEOSWKB_LINESTRINGZ:
 
3494
          ParseWkbLineZ (geo);
 
3495
          break;
 
3496
      case GAIA_LINESTRINGM:
 
3497
          ParseWkbLineM (geo);
 
3498
          break;
 
3499
      case GAIA_LINESTRINGZM:
 
3500
          ParseWkbLineZM (geo);
 
3501
          break;
 
3502
      case GAIA_POLYGON:
 
3503
          ParseWkbPolygon (geo);
 
3504
          break;
 
3505
      case GAIA_POLYGONZ:
 
3506
      case GAIA_GEOSWKB_POLYGONZ:
 
3507
          ParseWkbPolygonZ (geo);
 
3508
          break;
 
3509
      case GAIA_POLYGONM:
 
3510
          ParseWkbPolygonM (geo);
 
3511
          break;
 
3512
      case GAIA_POLYGONZM:
 
3513
          ParseWkbPolygonZM (geo);
 
3514
          break;
 
3515
      case GAIA_MULTIPOINT:
 
3516
      case GAIA_MULTILINESTRING:
 
3517
      case GAIA_MULTIPOLYGON:
 
3518
      case GAIA_GEOMETRYCOLLECTION:
 
3519
      case GAIA_MULTIPOINTZ:
 
3520
      case GAIA_MULTILINESTRINGZ:
 
3521
      case GAIA_MULTIPOLYGONZ:
 
3522
      case GAIA_GEOMETRYCOLLECTIONZ:
 
3523
      case GAIA_GEOSWKB_MULTIPOINTZ:
 
3524
      case GAIA_GEOSWKB_MULTILINESTRINGZ:
 
3525
      case GAIA_GEOSWKB_MULTIPOLYGONZ:
 
3526
      case GAIA_GEOSWKB_GEOMETRYCOLLECTIONZ:
 
3527
      case GAIA_MULTIPOINTM:
 
3528
      case GAIA_MULTILINESTRINGM:
 
3529
      case GAIA_MULTIPOLYGONM:
 
3530
      case GAIA_GEOMETRYCOLLECTIONM:
 
3531
      case GAIA_MULTIPOINTZM:
 
3532
      case GAIA_MULTILINESTRINGZM:
 
3533
      case GAIA_MULTIPOLYGONZM:
 
3534
      case GAIA_GEOMETRYCOLLECTIONZM:
 
3535
          ParseWkbGeometry (geo);
 
3536
          break;
 
3537
      default:
 
3538
          break;
 
3539
      };
 
3540
    gaiaMbrGeometry (geo);
 
3541
    switch (type)
 
3542
      {
 
3543
      case GAIA_POINT:
 
3544
      case GAIA_POINTZ:
 
3545
      case GAIA_GEOSWKB_POINTZ:
 
3546
      case GAIA_POINTM:
 
3547
      case GAIA_POINTZM:
 
3548
          geo->DeclaredType = GAIA_POINT;
 
3549
          break;
 
3550
      case GAIA_LINESTRING:
 
3551
      case GAIA_LINESTRINGZ:
 
3552
      case GAIA_GEOSWKB_LINESTRINGZ:
 
3553
      case GAIA_LINESTRINGM:
 
3554
      case GAIA_LINESTRINGZM:
 
3555
          geo->DeclaredType = GAIA_LINESTRING;
 
3556
          break;
 
3557
      case GAIA_POLYGON:
 
3558
      case GAIA_POLYGONZ:
 
3559
      case GAIA_GEOSWKB_POLYGONZ:
 
3560
      case GAIA_POLYGONM:
 
3561
      case GAIA_POLYGONZM:
 
3562
          geo->DeclaredType = GAIA_POLYGON;
 
3563
          break;
 
3564
      case GAIA_MULTIPOINT:
 
3565
      case GAIA_MULTIPOINTZ:
 
3566
      case GAIA_GEOSWKB_MULTIPOINTZ:
 
3567
      case GAIA_MULTIPOINTM:
 
3568
      case GAIA_MULTIPOINTZM:
 
3569
          geo->DeclaredType = GAIA_MULTIPOINT;
 
3570
          break;
 
3571
      case GAIA_MULTILINESTRING:
 
3572
      case GAIA_MULTILINESTRINGZ:
 
3573
      case GAIA_GEOSWKB_MULTILINESTRINGZ:
 
3574
      case GAIA_MULTILINESTRINGM:
 
3575
      case GAIA_MULTILINESTRINGZM:
 
3576
          geo->DeclaredType = GAIA_MULTILINESTRING;
 
3577
          break;
 
3578
      case GAIA_MULTIPOLYGON:
 
3579
      case GAIA_MULTIPOLYGONZ:
 
3580
      case GAIA_GEOSWKB_MULTIPOLYGONZ:
 
3581
      case GAIA_MULTIPOLYGONM:
 
3582
      case GAIA_MULTIPOLYGONZM:
 
3583
          geo->DeclaredType = GAIA_MULTIPOLYGON;
 
3584
          break;
 
3585
      case GAIA_GEOMETRYCOLLECTION:
 
3586
      case GAIA_GEOMETRYCOLLECTIONZ:
 
3587
      case GAIA_GEOSWKB_GEOMETRYCOLLECTIONZ:
 
3588
      case GAIA_GEOMETRYCOLLECTIONM:
 
3589
      case GAIA_GEOMETRYCOLLECTIONZM:
 
3590
          geo->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
3591
          break;
 
3592
      }
 
3593
    return geo;
 
3594
}
 
3595
 
 
3596
GAIAGEO_DECLARE char *
 
3597
gaiaToHexWkb (gaiaGeomCollPtr geom)
 
3598
{
 
3599
/* builds the hexadecimal WKB representation for this GEOMETRY */
 
3600
    unsigned char *wkb = NULL;
 
3601
    int size = 0;
 
3602
    char *hexbuf = NULL;
 
3603
    int i;
 
3604
    char hex[16];
 
3605
    char *p;
 
3606
    gaiaToWkb (geom, &wkb, &size);
 
3607
    if (!wkb)
 
3608
        return NULL;
 
3609
    hexbuf = malloc ((size * 2) + 1);
 
3610
    p = hexbuf;
 
3611
    for (i = 0; i < size; i++)
 
3612
      {
 
3613
          sprintf (hex, "%02X", *(wkb + i));
 
3614
          *p++ = hex[0];
 
3615
          *p++ = hex[1];
 
3616
      }
 
3617
    *p = '\0';
 
3618
    return hexbuf;
 
3619
}
 
3620
 
 
3621
GAIAGEO_DECLARE void
 
3622
gaiaToWkb (gaiaGeomCollPtr geom, unsigned char **result, int *size)
 
3623
{
 
3624
/* builds the WKB representation for this GEOMETRY */
 
3625
    int ib;
 
3626
    int iv;
 
3627
    double x;
 
3628
    double y;
 
3629
    double z = 0.0;
 
3630
    double m = 0.0;
 
3631
    int entities = 0;
 
3632
    int n_points = 0;
 
3633
    int n_linestrings = 0;
 
3634
    int n_polygons = 0;
 
3635
    int type;
 
3636
    unsigned char *ptr;
 
3637
    gaiaPointPtr pt;
 
3638
    gaiaLinestringPtr ln;
 
3639
    gaiaPolygonPtr pg;
 
3640
    gaiaRingPtr rng;
 
3641
    gaiaPointPtr point = NULL;
 
3642
    gaiaLinestringPtr line = NULL;
 
3643
    gaiaPolygonPtr polyg = NULL;
 
3644
    int endian_arch = gaiaEndianArch ();
 
3645
    gaiaMbrGeometry (geom);
 
3646
/* how many entities, and of what kind, do we have ? */
 
3647
    pt = geom->FirstPoint;
 
3648
    while (pt)
 
3649
      {
 
3650
          point = pt;
 
3651
          entities++;
 
3652
          n_points++;
 
3653
          pt = pt->Next;
 
3654
      }
 
3655
    ln = geom->FirstLinestring;
 
3656
    while (ln)
 
3657
      {
 
3658
          line = ln;
 
3659
          entities++;
 
3660
          n_linestrings++;
 
3661
          ln = ln->Next;
 
3662
      }
 
3663
    pg = geom->FirstPolygon;
 
3664
    while (pg)
 
3665
      {
 
3666
          polyg = pg;
 
3667
          entities++;
 
3668
          n_polygons++;
 
3669
          pg = pg->Next;
 
3670
      }
 
3671
    *size = 0;
 
3672
    *result = NULL;
 
3673
    if (n_points == 0 && n_polygons == 0 && n_linestrings == 0)
 
3674
        return;
 
3675
/* ok, we can determine the geometry class */
 
3676
    if (n_points == 1 && n_linestrings == 0 && n_polygons == 0)
 
3677
      {
 
3678
          if (geom->DeclaredType == GAIA_MULTIPOINT)
 
3679
            {
 
3680
                if (geom->DimensionModel == GAIA_XY_Z)
 
3681
                    type = GAIA_MULTIPOINTZ;
 
3682
                else if (geom->DimensionModel == GAIA_XY_M)
 
3683
                    type = GAIA_MULTIPOINTM;
 
3684
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3685
                    type = GAIA_MULTIPOINTZM;
 
3686
                else
 
3687
                    type = GAIA_MULTIPOINT;
 
3688
            }
 
3689
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
3690
            {
 
3691
                if (geom->DimensionModel == GAIA_XY_Z)
 
3692
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
3693
                else if (geom->DimensionModel == GAIA_XY_M)
 
3694
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
3695
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3696
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
3697
                else
 
3698
                    type = GAIA_GEOMETRYCOLLECTION;
 
3699
            }
 
3700
          else
 
3701
            {
 
3702
                if (geom->DimensionModel == GAIA_XY_Z)
 
3703
                    type = GAIA_POINTZ;
 
3704
                else if (geom->DimensionModel == GAIA_XY_M)
 
3705
                    type = GAIA_POINTM;
 
3706
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3707
                    type = GAIA_POINTZM;
 
3708
                else
 
3709
                    type = GAIA_POINT;
 
3710
            }
 
3711
      }
 
3712
    else if (n_points > 1 && n_linestrings == 0 && n_polygons == 0)
 
3713
      {
 
3714
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
3715
            {
 
3716
                if (geom->DimensionModel == GAIA_XY_Z)
 
3717
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
3718
                else if (geom->DimensionModel == GAIA_XY_M)
 
3719
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
3720
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3721
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
3722
                else
 
3723
                    type = GAIA_GEOMETRYCOLLECTION;
 
3724
            }
 
3725
          else
 
3726
            {
 
3727
                if (geom->DimensionModel == GAIA_XY_Z)
 
3728
                    type = GAIA_MULTIPOINTZ;
 
3729
                else if (geom->DimensionModel == GAIA_XY_M)
 
3730
                    type = GAIA_MULTIPOINTM;
 
3731
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3732
                    type = GAIA_MULTIPOINTZM;
 
3733
                else
 
3734
                    type = GAIA_MULTIPOINT;
 
3735
            }
 
3736
      }
 
3737
    else if (n_points == 0 && n_linestrings == 1 && n_polygons == 0)
 
3738
      {
 
3739
          if (geom->DeclaredType == GAIA_MULTILINESTRING)
 
3740
            {
 
3741
                if (geom->DimensionModel == GAIA_XY_Z)
 
3742
                    type = GAIA_MULTILINESTRINGZ;
 
3743
                else if (geom->DimensionModel == GAIA_XY_M)
 
3744
                    type = GAIA_MULTILINESTRINGM;
 
3745
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3746
                    type = GAIA_MULTILINESTRINGZM;
 
3747
                else
 
3748
                    type = GAIA_MULTILINESTRING;
 
3749
            }
 
3750
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
3751
            {
 
3752
                if (geom->DimensionModel == GAIA_XY_Z)
 
3753
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
3754
                else if (geom->DimensionModel == GAIA_XY_M)
 
3755
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
3756
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3757
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
3758
                else
 
3759
                    type = GAIA_GEOMETRYCOLLECTION;
 
3760
            }
 
3761
          else
 
3762
            {
 
3763
                if (geom->DimensionModel == GAIA_XY_Z)
 
3764
                    type = GAIA_LINESTRINGZ;
 
3765
                else if (geom->DimensionModel == GAIA_XY_M)
 
3766
                    type = GAIA_LINESTRINGM;
 
3767
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3768
                    type = GAIA_LINESTRINGZM;
 
3769
                else
 
3770
                    type = GAIA_LINESTRING;
 
3771
            }
 
3772
      }
 
3773
    else if (n_points == 0 && n_linestrings > 1 && n_polygons == 0)
 
3774
      {
 
3775
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
3776
            {
 
3777
                if (geom->DimensionModel == GAIA_XY_Z)
 
3778
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
3779
                else if (geom->DimensionModel == GAIA_XY_M)
 
3780
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
3781
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3782
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
3783
                else
 
3784
                    type = GAIA_GEOMETRYCOLLECTION;
 
3785
            }
 
3786
          else
 
3787
            {
 
3788
                if (geom->DimensionModel == GAIA_XY_Z)
 
3789
                    type = GAIA_MULTILINESTRINGZ;
 
3790
                else if (geom->DimensionModel == GAIA_XY_M)
 
3791
                    type = GAIA_MULTILINESTRINGM;
 
3792
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3793
                    type = GAIA_MULTILINESTRINGZM;
 
3794
                else
 
3795
                    type = GAIA_MULTILINESTRING;
 
3796
            }
 
3797
      }
 
3798
    else if (n_points == 0 && n_linestrings == 0 && n_polygons == 1)
 
3799
      {
 
3800
          if (geom->DeclaredType == GAIA_MULTIPOLYGON)
 
3801
            {
 
3802
                if (geom->DimensionModel == GAIA_XY_Z)
 
3803
                    type = GAIA_MULTIPOLYGONZ;
 
3804
                else if (geom->DimensionModel == GAIA_XY_M)
 
3805
                    type = GAIA_MULTIPOLYGONM;
 
3806
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3807
                    type = GAIA_MULTIPOLYGONZM;
 
3808
                else
 
3809
                    type = GAIA_MULTIPOLYGON;
 
3810
            }
 
3811
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
3812
            {
 
3813
                if (geom->DimensionModel == GAIA_XY_Z)
 
3814
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
3815
                else if (geom->DimensionModel == GAIA_XY_M)
 
3816
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
3817
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3818
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
3819
                else
 
3820
                    type = GAIA_GEOMETRYCOLLECTION;
 
3821
            }
 
3822
          else
 
3823
            {
 
3824
                if (geom->DimensionModel == GAIA_XY_Z)
 
3825
                    type = GAIA_POLYGONZ;
 
3826
                else if (geom->DimensionModel == GAIA_XY_M)
 
3827
                    type = GAIA_POLYGONM;
 
3828
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3829
                    type = GAIA_POLYGONZM;
 
3830
                else
 
3831
                    type = GAIA_POLYGON;
 
3832
            }
 
3833
      }
 
3834
    else if (n_points == 0 && n_linestrings == 0 && n_polygons > 1)
 
3835
      {
 
3836
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
3837
            {
 
3838
                if (geom->DimensionModel == GAIA_XY_Z)
 
3839
                    type = GAIA_GEOMETRYCOLLECTIONZ;
 
3840
                else if (geom->DimensionModel == GAIA_XY_M)
 
3841
                    type = GAIA_GEOMETRYCOLLECTIONM;
 
3842
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3843
                    type = GAIA_GEOMETRYCOLLECTIONZM;
 
3844
                else
 
3845
                    type = GAIA_GEOMETRYCOLLECTION;
 
3846
            }
 
3847
          else
 
3848
            {
 
3849
                if (geom->DimensionModel == GAIA_XY_Z)
 
3850
                    type = GAIA_MULTIPOLYGONZ;
 
3851
                else if (geom->DimensionModel == GAIA_XY_M)
 
3852
                    type = GAIA_MULTIPOLYGONM;
 
3853
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3854
                    type = GAIA_MULTIPOLYGONZM;
 
3855
                else
 
3856
                    type = GAIA_MULTIPOLYGON;
 
3857
            }
 
3858
      }
 
3859
    else
 
3860
      {
 
3861
          if (geom->DimensionModel == GAIA_XY_Z)
 
3862
              type = GAIA_GEOMETRYCOLLECTIONZ;
 
3863
          else if (geom->DimensionModel == GAIA_XY_M)
 
3864
              type = GAIA_GEOMETRYCOLLECTIONM;
 
3865
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3866
              type = GAIA_GEOMETRYCOLLECTIONZM;
 
3867
          else
 
3868
              type = GAIA_GEOMETRYCOLLECTION;
 
3869
      }
 
3870
/* and now we compute the size of WKB */
 
3871
    *size = 5;                  /* header size */
 
3872
    if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
3873
        || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION
 
3874
        || type == GAIA_MULTIPOINTZ || type == GAIA_MULTILINESTRINGZ
 
3875
        || type == GAIA_MULTIPOLYGONZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
3876
        || type == GAIA_MULTIPOINTM || type == GAIA_MULTILINESTRINGM
 
3877
        || type == GAIA_MULTIPOLYGONM || type == GAIA_GEOMETRYCOLLECTIONM
 
3878
        || type == GAIA_MULTIPOINTZM || type == GAIA_MULTILINESTRINGZM
 
3879
        || type == GAIA_MULTIPOLYGONZM || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3880
        *size += 4;
 
3881
    point = geom->FirstPoint;
 
3882
    while (point)
 
3883
      {
 
3884
          if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
3885
              || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION
 
3886
              || type == GAIA_MULTIPOINTZ || type == GAIA_MULTILINESTRINGZ
 
3887
              || type == GAIA_MULTIPOLYGONZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
3888
              || type == GAIA_MULTIPOINTM || type == GAIA_MULTILINESTRINGM
 
3889
              || type == GAIA_MULTIPOLYGONM || type == GAIA_GEOMETRYCOLLECTIONM
 
3890
              || type == GAIA_MULTIPOINTZM || type == GAIA_MULTILINESTRINGZM
 
3891
              || type == GAIA_MULTIPOLYGONZM
 
3892
              || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3893
              *size += 5;
 
3894
          if (geom->DimensionModel == GAIA_XY_Z
 
3895
              || geom->DimensionModel == GAIA_XY_M)
 
3896
              *size += (sizeof (double) * 3);   /* three doubles for each POINT */
 
3897
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3898
              *size += (sizeof (double) * 4);   /* four doubles for each POINT */
 
3899
          else
 
3900
              *size += (sizeof (double) * 2);   /* two doubles for each POINT */
 
3901
          point = point->Next;
 
3902
      }
 
3903
    line = geom->FirstLinestring;
 
3904
    while (line)
 
3905
      {
 
3906
          if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
3907
              || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION
 
3908
              || type == GAIA_MULTIPOINTZ || type == GAIA_MULTILINESTRINGZ
 
3909
              || type == GAIA_MULTIPOLYGONZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
3910
              || type == GAIA_MULTIPOINTM || type == GAIA_MULTILINESTRINGM
 
3911
              || type == GAIA_MULTIPOLYGONM || type == GAIA_GEOMETRYCOLLECTIONM
 
3912
              || type == GAIA_MULTIPOINTZM || type == GAIA_MULTILINESTRINGZM
 
3913
              || type == GAIA_MULTIPOLYGONZM
 
3914
              || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3915
              *size += 5;
 
3916
          if (geom->DimensionModel == GAIA_XY_Z
 
3917
              || geom->DimensionModel == GAIA_XY_M)
 
3918
              *size += (4 + ((sizeof (double) * 3) * line->Points));    /* # points + [x,y,z] for each vertex */
 
3919
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3920
              *size += (4 + ((sizeof (double) * 4) * line->Points));    /* # points + [x,y,z,m] for each vertex */
 
3921
          else
 
3922
              *size += (4 + ((sizeof (double) * 2) * line->Points));    /* # points + [x,y] for each vertex */
 
3923
          line = line->Next;
 
3924
      }
 
3925
    polyg = geom->FirstPolygon;
 
3926
    while (polyg)
 
3927
      {
 
3928
          if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
3929
              || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION
 
3930
              || type == GAIA_MULTIPOINTZ || type == GAIA_MULTILINESTRINGZ
 
3931
              || type == GAIA_MULTIPOLYGONZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
3932
              || type == GAIA_MULTIPOINTM || type == GAIA_MULTILINESTRINGM
 
3933
              || type == GAIA_MULTIPOLYGONM || type == GAIA_GEOMETRYCOLLECTIONM
 
3934
              || type == GAIA_MULTIPOINTZM || type == GAIA_MULTILINESTRINGZM
 
3935
              || type == GAIA_MULTIPOLYGONZM
 
3936
              || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3937
              *size += 5;
 
3938
          rng = polyg->Exterior;
 
3939
          if (geom->DimensionModel == GAIA_XY_Z
 
3940
              || geom->DimensionModel == GAIA_XY_M)
 
3941
              *size += (8 + ((sizeof (double) * 3) * rng->Points));     /* # rings + # points + [x,y,z] array - exterior ring */
 
3942
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3943
              *size += (8 + ((sizeof (double) * 4) * rng->Points));     /* # rings + # points + [x,y,z,m] array - exterior ring */
 
3944
          else
 
3945
              *size += (8 + ((sizeof (double) * 2) * rng->Points));     /* # rings + # points + [x,y] array - exterior ring */
 
3946
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
3947
            {
 
3948
                rng = polyg->Interiors + ib;
 
3949
                if (geom->DimensionModel == GAIA_XY_Z
 
3950
                    || geom->DimensionModel == GAIA_XY_M)
 
3951
                    *size += (4 + ((sizeof (double) * 3) * rng->Points));       /* # points + [x,y,z] array - interior ring */
 
3952
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
3953
                    *size += (4 + ((sizeof (double) * 4) * rng->Points));       /* # points + [x,y,z,m] array - interior ring */
 
3954
                else
 
3955
                    *size += (4 + ((sizeof (double) * 2) * rng->Points));       /* # points + [x,y] array - interior ring */
 
3956
            }
 
3957
          polyg = polyg->Next;
 
3958
      }
 
3959
    *result = malloc (*size);
 
3960
    ptr = *result;
 
3961
/* and finally we build the WKB */
 
3962
    *ptr = 0x01;                /* little endian byte order */
 
3963
    gaiaExport32 (ptr + 1, type, 1, endian_arch);       /* the main CLASS TYPE */
 
3964
    ptr += 5;
 
3965
    if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
3966
        || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION
 
3967
        || type == GAIA_MULTIPOINTZ || type == GAIA_MULTILINESTRINGZ
 
3968
        || type == GAIA_MULTIPOLYGONZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
3969
        || type == GAIA_MULTIPOINTM || type == GAIA_MULTILINESTRINGM
 
3970
        || type == GAIA_MULTIPOLYGONM || type == GAIA_GEOMETRYCOLLECTIONM
 
3971
        || type == GAIA_MULTIPOINTZM || type == GAIA_MULTILINESTRINGZM
 
3972
        || type == GAIA_MULTIPOLYGONZM || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3973
      {
 
3974
          gaiaExport32 (ptr, entities, 1, endian_arch); /* it's a collection; # entities */
 
3975
          ptr += 4;
 
3976
      }
 
3977
    point = geom->FirstPoint;
 
3978
    while (point)
 
3979
      {
 
3980
          if (type == GAIA_MULTIPOINT || type == GAIA_GEOMETRYCOLLECTION
 
3981
              || type == GAIA_MULTIPOINTZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
3982
              || type == GAIA_MULTIPOINTM || type == GAIA_GEOMETRYCOLLECTIONM
 
3983
              || type == GAIA_MULTIPOINTZM || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3984
            {
 
3985
                *ptr = 0x01;
 
3986
                /* it's a collection: the CLASS TYPE for this element */
 
3987
                if (type == GAIA_MULTIPOINTZ
 
3988
                    || type == GAIA_GEOMETRYCOLLECTIONZ)
 
3989
                    gaiaExport32 (ptr + 1, GAIA_POINTZ, 1, endian_arch);
 
3990
                else if (type == GAIA_MULTIPOINTM
 
3991
                         || type == GAIA_GEOMETRYCOLLECTIONM)
 
3992
                    gaiaExport32 (ptr + 1, GAIA_POINTM, 1, endian_arch);
 
3993
                else if (type == GAIA_MULTIPOINTZM
 
3994
                         || type == GAIA_GEOMETRYCOLLECTIONZM)
 
3995
                    gaiaExport32 (ptr + 1, GAIA_POINTZM, 1, endian_arch);
 
3996
                else
 
3997
                    gaiaExport32 (ptr + 1, GAIA_POINT, 1, endian_arch);
 
3998
                ptr += 5;
 
3999
            }
 
4000
          gaiaExport64 (ptr, point->X, 1, endian_arch); /* X */
 
4001
          gaiaExport64 (ptr + 8, point->Y, 1, endian_arch);     /* Y */
 
4002
          ptr += 16;
 
4003
          if (type == GAIA_POINTZ || type == GAIA_MULTIPOINTZ
 
4004
              || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4005
            {
 
4006
                gaiaExport64 (ptr, point->Z, 1, endian_arch);   /* Z */
 
4007
                ptr += 8;
 
4008
            }
 
4009
          if (type == GAIA_POINTM || type == GAIA_MULTIPOINTM
 
4010
              || type == GAIA_GEOMETRYCOLLECTIONM)
 
4011
            {
 
4012
                gaiaExport64 (ptr, point->M, 1, endian_arch);   /* M */
 
4013
                ptr += 8;
 
4014
            }
 
4015
          if (type == GAIA_POINTZM || type == GAIA_MULTIPOINTZM
 
4016
              || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4017
            {
 
4018
                gaiaExport64 (ptr, point->Z, 1, endian_arch);   /* Z */
 
4019
                gaiaExport64 (ptr + 8, point->M, 1, endian_arch);       /* M */
 
4020
                ptr += 16;
 
4021
            }
 
4022
          point = point->Next;
 
4023
      }
 
4024
    line = geom->FirstLinestring;
 
4025
    while (line)
 
4026
      {
 
4027
          if (type == GAIA_MULTILINESTRING || type == GAIA_GEOMETRYCOLLECTION
 
4028
              || type == GAIA_MULTILINESTRINGZ
 
4029
              || type == GAIA_GEOMETRYCOLLECTIONZ
 
4030
              || type == GAIA_MULTILINESTRINGM
 
4031
              || type == GAIA_GEOMETRYCOLLECTIONM
 
4032
              || type == GAIA_MULTILINESTRINGZM
 
4033
              || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4034
            {
 
4035
                *ptr = 0x01;
 
4036
                /* it's a collection: the CLASS TYPE for this element */
 
4037
                if (type == GAIA_MULTILINESTRINGZ
 
4038
                    || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4039
                    gaiaExport32 (ptr + 1, GAIA_LINESTRINGZ, 1, endian_arch);
 
4040
                else if (type == GAIA_MULTILINESTRINGM
 
4041
                         || type == GAIA_GEOMETRYCOLLECTIONM)
 
4042
                    gaiaExport32 (ptr + 1, GAIA_LINESTRINGM, 1, endian_arch);
 
4043
                else if (type == GAIA_MULTILINESTRINGZM
 
4044
                         || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4045
                    gaiaExport32 (ptr + 1, GAIA_LINESTRINGZM, 1, endian_arch);
 
4046
                else
 
4047
                    gaiaExport32 (ptr + 1, GAIA_LINESTRING, 1, endian_arch);
 
4048
                ptr += 5;
 
4049
            }
 
4050
          gaiaExport32 (ptr, line->Points, 1, endian_arch);     /* # points */
 
4051
          ptr += 4;
 
4052
          for (iv = 0; iv < line->Points; iv++)
 
4053
            {
 
4054
                if (type == GAIA_LINESTRINGZ || type == GAIA_MULTILINESTRINGZ
 
4055
                    || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4056
                  {
 
4057
                      gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
 
4058
                  }
 
4059
                else if (type == GAIA_LINESTRINGM
 
4060
                         || type == GAIA_MULTILINESTRINGM
 
4061
                         || type == GAIA_GEOMETRYCOLLECTIONM)
 
4062
                  {
 
4063
                      gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
 
4064
                  }
 
4065
                else if (type == GAIA_LINESTRINGZM
 
4066
                         || type == GAIA_MULTILINESTRINGZM
 
4067
                         || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4068
                  {
 
4069
                      gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
 
4070
                  }
 
4071
                else
 
4072
                  {
 
4073
                      gaiaGetPoint (line->Coords, iv, &x, &y);
 
4074
                  }
 
4075
                gaiaExport64 (ptr, x, 1, endian_arch);  /* X */
 
4076
                gaiaExport64 (ptr + 8, y, 1, endian_arch);      /* Y */
 
4077
                ptr += 16;
 
4078
                if (type == GAIA_LINESTRINGZ || type == GAIA_MULTILINESTRINGZ
 
4079
                    || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4080
                  {
 
4081
                      gaiaExport64 (ptr, z, 1, endian_arch);    /* Z */
 
4082
                      ptr += 8;
 
4083
                  }
 
4084
                if (type == GAIA_LINESTRINGM || type == GAIA_MULTILINESTRINGM
 
4085
                    || type == GAIA_GEOMETRYCOLLECTIONM)
 
4086
                  {
 
4087
                      gaiaExport64 (ptr, m, 1, endian_arch);    /* M */
 
4088
                      ptr += 8;
 
4089
                  }
 
4090
                if (type == GAIA_LINESTRINGZM || type == GAIA_MULTILINESTRINGZM
 
4091
                    || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4092
                  {
 
4093
                      gaiaExport64 (ptr, z, 1, endian_arch);    /* Z */
 
4094
                      gaiaExport64 (ptr + 8, m, 1, endian_arch);        /* M */
 
4095
                      ptr += 16;
 
4096
                  }
 
4097
            }
 
4098
          line = line->Next;
 
4099
      }
 
4100
    polyg = geom->FirstPolygon;
 
4101
    while (polyg)
 
4102
      {
 
4103
          if (type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION
 
4104
              || type == GAIA_MULTIPOLYGONZ || type == GAIA_GEOMETRYCOLLECTIONZ
 
4105
              || type == GAIA_MULTIPOLYGONM || type == GAIA_GEOMETRYCOLLECTIONM
 
4106
              || type == GAIA_MULTIPOLYGONZM
 
4107
              || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4108
            {
 
4109
                *ptr = 0x01;
 
4110
                /* it's a collection: the CLASS TYPE for this element */
 
4111
                if (type == GAIA_MULTIPOLYGONZ
 
4112
                    || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4113
                    gaiaExport32 (ptr + 1, GAIA_POLYGONZ, 1, endian_arch);
 
4114
                else if (type == GAIA_MULTIPOLYGONM
 
4115
                         || type == GAIA_GEOMETRYCOLLECTIONM)
 
4116
                    gaiaExport32 (ptr + 1, GAIA_POLYGONM, 1, endian_arch);
 
4117
                else if (type == GAIA_MULTIPOLYGONZM
 
4118
                         || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4119
                    gaiaExport32 (ptr + 1, GAIA_POLYGONZM, 1, endian_arch);
 
4120
                else
 
4121
                    gaiaExport32 (ptr + 1, GAIA_POLYGON, 1, endian_arch);
 
4122
                ptr += 5;
 
4123
            }
 
4124
          gaiaExport32 (ptr, polyg->NumInteriors + 1, 1, endian_arch);  /* # rings */
 
4125
          rng = polyg->Exterior;
 
4126
          gaiaExport32 (ptr + 4, rng->Points, 1, endian_arch);  /* # points - exterior ring */
 
4127
          ptr += 8;
 
4128
          for (iv = 0; iv < rng->Points; iv++)
 
4129
            {
 
4130
                if (type == GAIA_POLYGONZ || type == GAIA_MULTIPOLYGONZ
 
4131
                    || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4132
                  {
 
4133
                      gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
4134
                  }
 
4135
                else if (type == GAIA_POLYGONM || type == GAIA_MULTIPOLYGONM
 
4136
                         || type == GAIA_GEOMETRYCOLLECTIONM)
 
4137
                  {
 
4138
                      gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
4139
                  }
 
4140
                else if (type == GAIA_POLYGONZM || type == GAIA_MULTIPOLYGONZM
 
4141
                         || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4142
                  {
 
4143
                      gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
4144
                  }
 
4145
                else
 
4146
                  {
 
4147
                      gaiaGetPoint (rng->Coords, iv, &x, &y);
 
4148
                  }
 
4149
                gaiaExport64 (ptr, x, 1, endian_arch);  /* X - exterior ring */
 
4150
                gaiaExport64 (ptr + 8, y, 1, endian_arch);      /* Y - exterior ring */
 
4151
                ptr += 16;
 
4152
                if (type == GAIA_POLYGONZ || type == GAIA_MULTIPOLYGONZ
 
4153
                    || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4154
                  {
 
4155
                      gaiaExport64 (ptr, z, 1, endian_arch);    /* Z - exterior ring */
 
4156
                      ptr += 8;
 
4157
                  }
 
4158
                if (type == GAIA_POLYGONM || type == GAIA_MULTIPOLYGONM
 
4159
                    || type == GAIA_GEOMETRYCOLLECTIONM)
 
4160
                  {
 
4161
                      gaiaExport64 (ptr, m, 1, endian_arch);    /* M - exterior ring */
 
4162
                      ptr += 8;
 
4163
                  }
 
4164
                if (type == GAIA_POLYGONZM || type == GAIA_MULTIPOLYGONZM
 
4165
                    || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4166
                  {
 
4167
                      gaiaExport64 (ptr, z, 1, endian_arch);    /* Z - exterior ring */
 
4168
                      gaiaExport64 (ptr + 8, m, 1, endian_arch);        /* M - exterior ring */
 
4169
                      ptr += 16;
 
4170
                  }
 
4171
            }
 
4172
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
4173
            {
 
4174
                rng = polyg->Interiors + ib;
 
4175
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
4176
                ptr += 4;
 
4177
                for (iv = 0; iv < rng->Points; iv++)
 
4178
                  {
 
4179
                      if (type == GAIA_POLYGONZ || type == GAIA_MULTIPOLYGONZ
 
4180
                          || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4181
                        {
 
4182
                            gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
4183
                        }
 
4184
                      else if (type == GAIA_POLYGONM
 
4185
                               || type == GAIA_MULTIPOLYGONM
 
4186
                               || type == GAIA_GEOMETRYCOLLECTIONM)
 
4187
                        {
 
4188
                            gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
4189
                        }
 
4190
                      else if (type == GAIA_POLYGONZM
 
4191
                               || type == GAIA_MULTIPOLYGONZM
 
4192
                               || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4193
                        {
 
4194
                            gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
4195
                        }
 
4196
                      else
 
4197
                        {
 
4198
                            gaiaGetPoint (rng->Coords, iv, &x, &y);
 
4199
                        }
 
4200
                      gaiaExport64 (ptr, x, 1, endian_arch);    /* X - interior ring */
 
4201
                      gaiaExport64 (ptr + 8, y, 1, endian_arch);        /* Y - interior ring */
 
4202
                      ptr += 16;
 
4203
                      if (type == GAIA_POLYGONZ || type == GAIA_MULTIPOLYGONZ
 
4204
                          || type == GAIA_GEOMETRYCOLLECTIONZ)
 
4205
                        {
 
4206
                            gaiaExport64 (ptr, z, 1, endian_arch);      /* Z - exterior ring */
 
4207
                            ptr += 8;
 
4208
                        }
 
4209
                      if (type == GAIA_POLYGONM || type == GAIA_MULTIPOLYGONM
 
4210
                          || type == GAIA_GEOMETRYCOLLECTIONM)
 
4211
                        {
 
4212
                            gaiaExport64 (ptr, m, 1, endian_arch);      /* M - exterior ring */
 
4213
                            ptr += 8;
 
4214
                        }
 
4215
                      if (type == GAIA_POLYGONZM || type == GAIA_MULTIPOLYGONZM
 
4216
                          || type == GAIA_GEOMETRYCOLLECTIONZM)
 
4217
                        {
 
4218
                            gaiaExport64 (ptr, z, 1, endian_arch);      /* Z - exterior ring */
 
4219
                            gaiaExport64 (ptr + 8, m, 1, endian_arch);  /* M - exterior ring */
 
4220
                            ptr += 16;
 
4221
                        }
 
4222
                  }
 
4223
            }
 
4224
          polyg = polyg->Next;
 
4225
      }
 
4226
}
 
4227
 
 
4228
static int
 
4229
ewkbGetPoint (gaiaGeomCollPtr geom, unsigned char *blob,
 
4230
              int offset, int blob_size, int endian, int endian_arch, int dims)
 
4231
{
 
4232
/* decodes a POINT from PostGIS EWKB binary GEOMETRY */
 
4233
    double x;
 
4234
    double y;
 
4235
    double z;
 
4236
    double m;
 
4237
    switch (dims)
 
4238
      {
 
4239
      case GAIA_XY_Z_M:
 
4240
          if (blob_size < offset + 32)
 
4241
              return -1;
 
4242
          break;
 
4243
      case GAIA_XY_Z:
 
4244
      case GAIA_XY_M:
 
4245
          if (blob_size < offset + 24)
 
4246
              return -1;
 
4247
          break;
 
4248
      default:
 
4249
          if (blob_size < offset + 16)
 
4250
              return -1;
 
4251
          break;
 
4252
      }
 
4253
    x = gaiaImport64 (blob + offset, endian, endian_arch);
 
4254
    offset += 8;
 
4255
    y = gaiaImport64 (blob + offset, endian, endian_arch);
 
4256
    offset += 8;
 
4257
    if (dims == GAIA_XY_Z_M)
 
4258
      {
 
4259
          z = gaiaImport64 (blob + offset, endian, endian_arch);
 
4260
          offset += 8;
 
4261
          m = gaiaImport64 (blob + offset, endian, endian_arch);
 
4262
          offset += 8;
 
4263
          gaiaAddPointToGeomCollXYZM (geom, x, y, z, m);
 
4264
      }
 
4265
    else if (dims == GAIA_XY_Z)
 
4266
      {
 
4267
          z = gaiaImport64 (blob + offset, endian, endian_arch);
 
4268
          offset += 8;
 
4269
          gaiaAddPointToGeomCollXYZ (geom, x, y, z);
 
4270
      }
 
4271
    else if (dims == GAIA_XY_M)
 
4272
      {
 
4273
          m = gaiaImport64 (blob + offset, endian, endian_arch);
 
4274
          offset += 8;
 
4275
          gaiaAddPointToGeomCollXYM (geom, x, y, m);
 
4276
      }
 
4277
    else
 
4278
        gaiaAddPointToGeomColl (geom, x, y);
 
4279
    return offset;
 
4280
}
 
4281
 
 
4282
static int
 
4283
ewkbGetLinestring (gaiaGeomCollPtr geom, unsigned char *blob,
 
4284
                   int offset, int blob_size, int endian,
 
4285
                   int endian_arch, int dims)
 
4286
{
 
4287
/* decodes a LINESTRING from PostGIS binary GEOMETRY */
 
4288
    int npoints;
 
4289
    int iv;
 
4290
    double x;
 
4291
    double y;
 
4292
    double z;
 
4293
    double m;
 
4294
    gaiaLinestringPtr ln;
 
4295
    if (blob_size < offset + 4)
 
4296
        return -1;
 
4297
    npoints = gaiaImport32 (blob + offset, endian, endian_arch);
 
4298
    offset += 4;
 
4299
    switch (dims)
 
4300
      {
 
4301
      case GAIA_XY_Z_M:
 
4302
          if (blob_size < offset + (32 * npoints))
 
4303
              return -1;
 
4304
          break;
 
4305
      case GAIA_XY_Z:
 
4306
      case GAIA_XY_M:
 
4307
          if (blob_size < offset + (24 * npoints))
 
4308
              return -1;
 
4309
          break;
 
4310
      default:
 
4311
          if (blob_size < offset + (16 * npoints))
 
4312
              return -1;
 
4313
          break;
 
4314
      }
 
4315
    ln = gaiaAddLinestringToGeomColl (geom, npoints);
 
4316
    for (iv = 0; iv < npoints; iv++)
 
4317
      {
 
4318
          x = gaiaImport64 (blob + offset, endian, endian_arch);
 
4319
          offset += 8;
 
4320
          y = gaiaImport64 (blob + offset, endian, endian_arch);
 
4321
          offset += 8;
 
4322
          if (dims == GAIA_XY_Z_M)
 
4323
            {
 
4324
                z = gaiaImport64 (blob + offset, endian, endian_arch);
 
4325
                offset += 8;
 
4326
                m = gaiaImport64 (blob + offset, endian, endian_arch);
 
4327
                offset += 8;
 
4328
                gaiaSetPointXYZM (ln->Coords, iv, x, y, z, m);
 
4329
            }
 
4330
          else if (dims == GAIA_XY_Z)
 
4331
            {
 
4332
                z = gaiaImport64 (blob + offset, endian, endian_arch);
 
4333
                offset += 8;
 
4334
                gaiaSetPointXYZ (ln->Coords, iv, x, y, z);
 
4335
            }
 
4336
          else if (dims == GAIA_XY_M)
 
4337
            {
 
4338
                m = gaiaImport64 (blob + offset, endian, endian_arch);
 
4339
                offset += 8;
 
4340
                gaiaSetPointXYM (ln->Coords, iv, x, y, m);
 
4341
            }
 
4342
          else
 
4343
              gaiaSetPoint (ln->Coords, iv, x, y);
 
4344
      }
 
4345
    return offset;
 
4346
}
 
4347
 
 
4348
static int
 
4349
ewkbGetPolygon (gaiaGeomCollPtr geom, unsigned char *blob,
 
4350
                int offset, int blob_size, int endian,
 
4351
                int endian_arch, int dims)
 
4352
{
 
4353
/* decodes a POLYGON from PostGIS binary GEOMETRY */
 
4354
    int rings;
 
4355
    int npoints;
 
4356
    int iv;
 
4357
    int ib;
 
4358
    double x;
 
4359
    double y;
 
4360
    double z;
 
4361
    double m;
 
4362
    gaiaPolygonPtr polyg = NULL;
 
4363
    gaiaRingPtr rng;
 
4364
    if (blob_size < offset + 4)
 
4365
        return -1;
 
4366
    rings = gaiaImport32 (blob + offset, endian, endian_arch);
 
4367
    offset += 4;
 
4368
    for (ib = 0; ib < rings; ib++)
 
4369
      {
 
4370
          if (blob_size < offset + 4)
 
4371
              return -1;
 
4372
          npoints = gaiaImport32 (blob + offset, endian, endian_arch);
 
4373
          offset += 4;
 
4374
          switch (dims)
 
4375
            {
 
4376
            case GAIA_XY_Z_M:
 
4377
                if (blob_size < offset + (32 * npoints))
 
4378
                    return -1;
 
4379
                break;
 
4380
            case GAIA_XY_Z:
 
4381
            case GAIA_XY_M:
 
4382
                if (blob_size < offset + (24 * npoints))
 
4383
                    return -1;
 
4384
                break;
 
4385
            default:
 
4386
                if (blob_size < offset + (16 * npoints))
 
4387
                    return -1;
 
4388
                break;
 
4389
            }
 
4390
          if (ib == 0)
 
4391
            {
 
4392
                polyg = gaiaAddPolygonToGeomColl (geom, npoints, rings - 1);
 
4393
                rng = polyg->Exterior;
 
4394
            }
 
4395
          else
 
4396
              rng = gaiaAddInteriorRing (polyg, ib - 1, npoints);
 
4397
          for (iv = 0; iv < npoints; iv++)
 
4398
            {
 
4399
                x = gaiaImport64 (blob + offset, endian, endian_arch);
 
4400
                offset += 8;
 
4401
                y = gaiaImport64 (blob + offset, endian, endian_arch);
 
4402
                offset += 8;
 
4403
                if (dims == GAIA_XY_Z_M)
 
4404
                  {
 
4405
                      z = gaiaImport64 (blob + offset, endian, endian_arch);
 
4406
                      offset += 8;
 
4407
                      m = gaiaImport64 (blob + offset, endian, endian_arch);
 
4408
                      offset += 8;
 
4409
                      gaiaSetPointXYZM (rng->Coords, iv, x, y, z, m);
 
4410
                  }
 
4411
                else if (dims == GAIA_XY_Z)
 
4412
                  {
 
4413
                      z = gaiaImport64 (blob + offset, endian, endian_arch);
 
4414
                      offset += 8;
 
4415
                      gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
 
4416
                  }
 
4417
                else if (dims == GAIA_XY_M)
 
4418
                  {
 
4419
                      m = gaiaImport64 (blob + offset, endian, endian_arch);
 
4420
                      offset += 8;
 
4421
                      gaiaSetPointXYM (rng->Coords, iv, x, y, m);
 
4422
                  }
 
4423
                else
 
4424
                    gaiaSetPoint (rng->Coords, iv, x, y);
 
4425
            }
 
4426
      }
 
4427
    return offset;
 
4428
}
 
4429
 
 
4430
static int
 
4431
ewkbGetMultiGeometry (gaiaGeomCollPtr geom, unsigned char *blob,
 
4432
                      int offset, int blob_size, int endian,
 
4433
                      int endian_arch, int dims)
 
4434
{
 
4435
/* decodes a MultiGeometry from PostGIS EWKB binary GEOMETRY */
 
4436
    int entities;
 
4437
    int type;
 
4438
    unsigned char xtype[4];
 
4439
    int ie;
 
4440
    int off;
 
4441
    if (blob_size < offset + 4)
 
4442
        return -1;
 
4443
    entities = gaiaImport32 (blob + offset, endian, endian_arch);
 
4444
    offset += 4;
 
4445
    for (ie = 0; ie < entities; ie++)
 
4446
      {
 
4447
          if (blob_size < offset + 5)
 
4448
              return -1;
 
4449
          memcpy (xtype, blob + offset + 1, 4);
 
4450
          if (endian)
 
4451
              xtype[3] = 0x00;
 
4452
          else
 
4453
              xtype[0] = 0x00;
 
4454
          type = gaiaImport32 (xtype, endian, endian_arch);
 
4455
          offset += 5;
 
4456
          switch (type)
 
4457
            {
 
4458
            case GAIA_POINT:
 
4459
                off =
 
4460
                    ewkbGetPoint (geom, blob, offset, blob_size, endian,
 
4461
                                  endian_arch, dims);
 
4462
                if (off < 0)
 
4463
                    return -1;
 
4464
                offset += off;
 
4465
                break;
 
4466
            case GAIA_LINESTRING:
 
4467
                off =
 
4468
                    ewkbGetLinestring (geom, blob, offset, blob_size, endian,
 
4469
                                       endian_arch, dims);
 
4470
                if (off < 0)
 
4471
                    return -1;
 
4472
                offset += off;
 
4473
                break;
 
4474
            case GAIA_POLYGON:
 
4475
                off =
 
4476
                    ewkbGetPolygon (geom, blob, offset, blob_size, endian,
 
4477
                                    endian_arch, dims);
 
4478
                if (off < 0)
 
4479
                    return -1;
 
4480
                offset += off;
 
4481
            };
 
4482
      }
 
4483
    return offset;
 
4484
}
 
4485
 
 
4486
static int
 
4487
parseHexEwkbByte (const unsigned char high, const unsigned char low,
 
4488
                  unsigned char *byte)
 
4489
{
 
4490
/* parsing an Hexadecimal byte */
 
4491
    unsigned char hex;
 
4492
    switch (high)
 
4493
      {
 
4494
      case '0':
 
4495
          hex = 16 * 0;
 
4496
          break;
 
4497
      case '1':
 
4498
          hex = 16 * 1;
 
4499
          break;
 
4500
      case '2':
 
4501
          hex = 16 * 2;
 
4502
          break;
 
4503
      case '3':
 
4504
          hex = 16 * 3;
 
4505
          break;
 
4506
      case '4':
 
4507
          hex = 16 * 4;
 
4508
          break;
 
4509
      case '5':
 
4510
          hex = 16 * 5;
 
4511
          break;
 
4512
      case '6':
 
4513
          hex = 16 * 6;
 
4514
          break;
 
4515
      case '7':
 
4516
          hex = 16 * 7;
 
4517
          break;
 
4518
      case '8':
 
4519
          hex = 16 * 8;
 
4520
          break;
 
4521
      case '9':
 
4522
          hex = 16 * 9;
 
4523
          break;
 
4524
      case 'A':
 
4525
      case 'a':
 
4526
          hex = 16 * 10;
 
4527
          break;
 
4528
      case 'B':
 
4529
      case 'b':
 
4530
          hex = 16 * 11;
 
4531
          break;
 
4532
      case 'C':
 
4533
      case 'c':
 
4534
          hex = 16 * 12;
 
4535
          break;
 
4536
      case 'D':
 
4537
      case 'd':
 
4538
          hex = 16 * 13;
 
4539
          break;
 
4540
      case 'E':
 
4541
      case 'e':
 
4542
          hex = 16 * 14;
 
4543
          break;
 
4544
      case 'F':
 
4545
      case 'f':
 
4546
          hex = 16 * 15;
 
4547
          break;
 
4548
      default:
 
4549
          return 0;
 
4550
      };
 
4551
    switch (low)
 
4552
      {
 
4553
      case '0':
 
4554
          hex += 0;
 
4555
          break;
 
4556
      case '1':
 
4557
          hex += 1;
 
4558
          break;
 
4559
      case '2':
 
4560
          hex += 2;
 
4561
          break;
 
4562
      case '3':
 
4563
          hex += 3;
 
4564
          break;
 
4565
      case '4':
 
4566
          hex += 4;
 
4567
          break;
 
4568
      case '5':
 
4569
          hex += 5;
 
4570
          break;
 
4571
      case '6':
 
4572
          hex += 6;
 
4573
          break;
 
4574
      case '7':
 
4575
          hex += 7;
 
4576
          break;
 
4577
      case '8':
 
4578
          hex += 8;
 
4579
          break;
 
4580
      case '9':
 
4581
          hex += 9;
 
4582
          break;
 
4583
      case 'A':
 
4584
      case 'a':
 
4585
          hex += 10;
 
4586
          break;
 
4587
      case 'B':
 
4588
      case 'b':
 
4589
          hex += 11;
 
4590
          break;
 
4591
      case 'C':
 
4592
      case 'c':
 
4593
          hex += 12;
 
4594
          break;
 
4595
      case 'D':
 
4596
      case 'd':
 
4597
          hex += 13;
 
4598
          break;
 
4599
      case 'E':
 
4600
      case 'e':
 
4601
          hex += 14;
 
4602
          break;
 
4603
      case 'F':
 
4604
      case 'f':
 
4605
          hex += 15;
 
4606
          break;
 
4607
      default:
 
4608
          return 0;
 
4609
      };
 
4610
    *byte = hex;
 
4611
    return 1;
 
4612
}
 
4613
 
 
4614
static unsigned char *
 
4615
parseHexEWKB (const unsigned char *blob_hex, int *blob_size)
 
4616
{
 
4617
/* parsing an Hexadecimal EWKB Geometry */
 
4618
    unsigned char *blob;
 
4619
    unsigned char *p_out;
 
4620
    const unsigned char *p_in;
 
4621
    char high;
 
4622
    char low;
 
4623
    unsigned char hex;
 
4624
    int size;
 
4625
    int len = strlen ((const char *) blob_hex);
 
4626
    size = len / 2;
 
4627
    if (size * 2 != len)
 
4628
        return NULL;
 
4629
    blob = malloc (size);
 
4630
    if (!blob)
 
4631
        return NULL;
 
4632
    *blob_size = size;
 
4633
    p_in = blob_hex;
 
4634
    p_out = blob;
 
4635
    while (*p_in != '\0')
 
4636
      {
 
4637
          high = *p_in++;
 
4638
          low = *p_in++;
 
4639
          if (!parseHexEwkbByte (high, low, &hex))
 
4640
            {
 
4641
                free (blob);
 
4642
                return NULL;
 
4643
            }
 
4644
          *p_out++ = hex;
 
4645
      }
 
4646
    *blob_size = size;
 
4647
    return blob;
 
4648
}
 
4649
 
 
4650
gaiaGeomCollPtr
 
4651
gaiaFromEWKB (const unsigned char *in_buffer)
 
4652
{
 
4653
/* creates a Gaia own Geometry from GEOS/PostGIS EWKB */
 
4654
    unsigned char *blob;
 
4655
    int blob_size;
 
4656
    unsigned char xtype[4];
 
4657
    unsigned char xdims;
 
4658
    int type;
 
4659
    int has_z = 0;
 
4660
    int has_m = 0;
 
4661
    int dims = GAIA_XY;
 
4662
    int srid;
 
4663
    int endian;
 
4664
    int endian_arch = gaiaEndianArch ();
 
4665
    gaiaGeomCollPtr geom = NULL;
 
4666
    blob = parseHexEWKB (in_buffer, &blob_size);
 
4667
    if (!blob)
 
4668
        return NULL;
 
4669
    if (blob_size < 9)
 
4670
        return NULL;
 
4671
    if (*(blob + 0) == 0x01)
 
4672
        endian = 1;
 
4673
    else
 
4674
        endian = 0;
 
4675
    memcpy (xtype, blob + 1, 4);
 
4676
    if (endian)
 
4677
      {
 
4678
          xdims = xtype[3];
 
4679
          xtype[3] = 0x00;
 
4680
      }
 
4681
    else
 
4682
      {
 
4683
          xdims = xtype[0];
 
4684
          xtype[0] = 0x00;
 
4685
      }
 
4686
    type = gaiaImport32 (xtype, endian, endian_arch);
 
4687
    if (xdims & 0x40)
 
4688
        has_m = 1;
 
4689
    if (xdims & 0x80)
 
4690
        has_z = 1;
 
4691
    if (has_m && has_z)
 
4692
      {
 
4693
          dims = GAIA_XY_Z_M;
 
4694
          geom = gaiaAllocGeomCollXYZM ();
 
4695
      }
 
4696
    else if (has_m)
 
4697
      {
 
4698
          dims = GAIA_XY_M;
 
4699
          geom = gaiaAllocGeomCollXYM ();
 
4700
      }
 
4701
    else if (has_z)
 
4702
      {
 
4703
          dims = GAIA_XY_Z;
 
4704
          geom = gaiaAllocGeomCollXYZ ();
 
4705
      }
 
4706
    else
 
4707
      {
 
4708
          dims = GAIA_XY;
 
4709
          geom = gaiaAllocGeomColl ();
 
4710
      }
 
4711
    srid = gaiaImport32 (blob + 5, endian, endian_arch);
 
4712
    geom->Srid = srid;
 
4713
    if (geom->Srid <= 0)
 
4714
        geom->Srid = -1;
 
4715
    switch (type)
 
4716
      {
 
4717
      case GAIA_POINT:
 
4718
          ewkbGetPoint (geom, blob, 9, blob_size, endian, endian_arch, dims);
 
4719
          break;
 
4720
      case GAIA_LINESTRING:
 
4721
          ewkbGetLinestring (geom, blob, 9, blob_size, endian, endian_arch,
 
4722
                             dims);
 
4723
          break;
 
4724
      case GAIA_POLYGON:
 
4725
          ewkbGetPolygon (geom, blob, 9, blob_size, endian, endian_arch, dims);
 
4726
          break;
 
4727
      default:
 
4728
          ewkbGetMultiGeometry (geom, blob, 9, blob_size, endian, endian_arch,
 
4729
                                dims);
 
4730
          break;
 
4731
      };
 
4732
 
 
4733
    return geom;
 
4734
}
 
4735
 
 
4736
GAIAGEO_DECLARE void
 
4737
gaiaToEWKB (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom)
 
4738
{
 
4739
/* prints the GEOS/PostGIS EWKB text representation of current geometry */
 
4740
    char buf[2048];
 
4741
    unsigned char endian_buf[16];
 
4742
    char byte[2];
 
4743
    char *ptr;
 
4744
    int size;
 
4745
    int type;
 
4746
    int entities = 0;
 
4747
    int n_points = 0;
 
4748
    int n_linestrings = 0;
 
4749
    int n_polygons = 0;
 
4750
    int i;
 
4751
    int iv;
 
4752
    int ib;
 
4753
    double x;
 
4754
    double y;
 
4755
    double z;
 
4756
    double m;
 
4757
    int endian_arch = gaiaEndianArch ();
 
4758
    gaiaPointPtr pt;
 
4759
    gaiaLinestringPtr ln;
 
4760
    gaiaPolygonPtr pg;
 
4761
    gaiaRingPtr rng;
 
4762
    gaiaPointPtr point = NULL;
 
4763
    gaiaLinestringPtr line = NULL;
 
4764
    gaiaPolygonPtr polyg = NULL;
 
4765
 
 
4766
/* precomputing the required size */
 
4767
    sprintf (buf, "SRID=%d;", geom->Srid);
 
4768
    size = strlen (buf);        /* the header size */
 
4769
    size++;                     /* terminating '\0' */
 
4770
    pt = geom->FirstPoint;
 
4771
    while (pt)
 
4772
      {
 
4773
          point = pt;
 
4774
          entities++;
 
4775
          n_points++;
 
4776
          pt = pt->Next;
 
4777
      }
 
4778
    ln = geom->FirstLinestring;
 
4779
    while (ln)
 
4780
      {
 
4781
          line = ln;
 
4782
          entities++;
 
4783
          n_linestrings++;
 
4784
          ln = ln->Next;
 
4785
      }
 
4786
    pg = geom->FirstPolygon;
 
4787
    while (pg)
 
4788
      {
 
4789
          polyg = pg;
 
4790
          entities++;
 
4791
          n_polygons++;
 
4792
          pg = pg->Next;
 
4793
      }
 
4794
    if (n_points == 0 && n_polygons == 0 && n_linestrings == 0)
 
4795
        return;
 
4796
/* ok, we can determine the geometry class */
 
4797
    if (n_points == 1 && n_linestrings == 0 && n_polygons == 0)
 
4798
      {
 
4799
          if (geom->DeclaredType == GAIA_MULTIPOINT)
 
4800
              type = GAIA_MULTIPOINT;
 
4801
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
4802
              type = GAIA_GEOMETRYCOLLECTION;
 
4803
          else
 
4804
              type = GAIA_POINT;
 
4805
      }
 
4806
    else if (n_points > 1 && n_linestrings == 0 && n_polygons == 0)
 
4807
      {
 
4808
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
4809
              type = GAIA_GEOMETRYCOLLECTION;
 
4810
          else
 
4811
              type = GAIA_MULTIPOINT;
 
4812
      }
 
4813
    else if (n_points == 0 && n_linestrings == 1 && n_polygons == 0)
 
4814
      {
 
4815
          if (geom->DeclaredType == GAIA_MULTILINESTRING)
 
4816
              type = GAIA_MULTILINESTRING;
 
4817
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
4818
              type = GAIA_GEOMETRYCOLLECTION;
 
4819
          else
 
4820
              type = GAIA_LINESTRING;
 
4821
      }
 
4822
    else if (n_points == 0 && n_linestrings > 1 && n_polygons == 0)
 
4823
      {
 
4824
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
4825
              type = GAIA_GEOMETRYCOLLECTION;
 
4826
          else
 
4827
              type = GAIA_MULTILINESTRING;
 
4828
      }
 
4829
    else if (n_points == 0 && n_linestrings == 0 && n_polygons == 1)
 
4830
      {
 
4831
          if (geom->DeclaredType == GAIA_MULTIPOLYGON)
 
4832
              type = GAIA_MULTIPOLYGON;
 
4833
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
4834
              type = GAIA_GEOMETRYCOLLECTION;
 
4835
          else
 
4836
              type = GAIA_POLYGON;
 
4837
      }
 
4838
    else if (n_points == 0 && n_linestrings == 0 && n_polygons > 1)
 
4839
      {
 
4840
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
4841
              type = GAIA_GEOMETRYCOLLECTION;
 
4842
          else
 
4843
              type = GAIA_MULTIPOLYGON;
 
4844
      }
 
4845
    else
 
4846
        type = GAIA_GEOMETRYCOLLECTION;
 
4847
/* and now we compute the size of EWKB */
 
4848
    size += 10;                 /* header size */
 
4849
    if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
4850
        || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
4851
        size += 8;
 
4852
    point = geom->FirstPoint;
 
4853
    while (point)
 
4854
      {
 
4855
          if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
4856
              || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
4857
              size += 10;
 
4858
          if (geom->DimensionModel == GAIA_XY_Z
 
4859
              || geom->DimensionModel == GAIA_XY_M)
 
4860
              size += 48;       /* three doubles for each POINT */
 
4861
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
4862
              size += 64;       /* four doubles for each POINT */
 
4863
          else
 
4864
              size += 32;       /* two doubles for each POINT */
 
4865
          point = point->Next;
 
4866
      }
 
4867
    line = geom->FirstLinestring;
 
4868
    while (line)
 
4869
      {
 
4870
          if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
4871
              || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
4872
              size += 10;
 
4873
          if (geom->DimensionModel == GAIA_XY_Z
 
4874
              || geom->DimensionModel == GAIA_XY_M)
 
4875
              size += 8 + (line->Points * 48);  /* three doubles for each VERTEX */
 
4876
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
4877
              size += 8 + (line->Points * 64);  /* four doubles for each VERTEX */
 
4878
          else
 
4879
              size += 8 + (line->Points * 32);  /* two doubles for each VERTEX */
 
4880
          line = line->Next;
 
4881
      }
 
4882
    polyg = geom->FirstPolygon;
 
4883
    while (polyg)
 
4884
      {
 
4885
          if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
4886
              || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
4887
              size += 10;
 
4888
          rng = polyg->Exterior;
 
4889
          if (geom->DimensionModel == GAIA_XY_Z
 
4890
              || geom->DimensionModel == GAIA_XY_M)
 
4891
              size += 16 + (rng->Points * 48);  /* three doubles for each VERTEX */
 
4892
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
4893
              size += 16 + (rng->Points * 64);  /* four doubles for each VERTEX */
 
4894
          else
 
4895
              size += 16 + (rng->Points * 32);  /* two doubles for each VERTEX */
 
4896
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
4897
            {
 
4898
                rng = polyg->Interiors + ib;
 
4899
                if (geom->DimensionModel == GAIA_XY_Z
 
4900
                    || geom->DimensionModel == GAIA_XY_M)
 
4901
                    size += 8 + (rng->Points * 48);     /* three doubles for each VERTEX */
 
4902
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
4903
                    size += 8 + (rng->Points * 64);     /* four doubles for each VERTEX */
 
4904
                else
 
4905
                    size += 8 + (rng->Points * 32);     /* two doubles for each VERTEX */
 
4906
            }
 
4907
          polyg = polyg->Next;
 
4908
      }
 
4909
/* and finally we build the EWKB expression */
 
4910
    sprintf (buf, "SRID=%d;", geom->Srid);
 
4911
    gaiaAppendToOutBuffer (out_buf, buf);
 
4912
    ptr = buf;
 
4913
 
 
4914
    *ptr++ = '0';               /* little endian byte order */
 
4915
    *ptr++ = '1';
 
4916
    gaiaExport32 (endian_buf, type, 1, endian_arch);    /* the main CLASS TYPE */
 
4917
    for (i = 0; i < 3; i++)
 
4918
      {
 
4919
          /* CAVEAT: the 4th byte in PostGIS encodes M/Z presence !!!! */
 
4920
          sprintf (byte, "%02X", endian_buf[i]);
 
4921
          *ptr++ = byte[0];
 
4922
          *ptr++ = byte[1];
 
4923
      }
 
4924
/* marking M/Z presence */
 
4925
    if (geom->DimensionModel == GAIA_XY_Z)
 
4926
        *ptr++ = '8';
 
4927
    else if (geom->DimensionModel == GAIA_XY_M)
 
4928
        *ptr++ = '4';
 
4929
    else if (geom->DimensionModel == GAIA_XY_Z_M)
 
4930
        *ptr++ = 'C';
 
4931
    else
 
4932
        *ptr++ = '0';
 
4933
    *ptr++ = '0';
 
4934
    *ptr++ = '\0';
 
4935
    gaiaAppendToOutBuffer (out_buf, buf);
 
4936
    ptr = buf;
 
4937
    if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
4938
        || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
4939
      {
 
4940
          gaiaExport32 (endian_buf, entities, 1, endian_arch);  /* it's a collection; # entities */
 
4941
          for (i = 0; i < 4; i++)
 
4942
            {
 
4943
                sprintf (byte, "%02X", endian_buf[i]);
 
4944
                *ptr++ = byte[0];
 
4945
                *ptr++ = byte[1];
 
4946
            }
 
4947
      }
 
4948
    point = geom->FirstPoint;
 
4949
    while (point)
 
4950
      {
 
4951
          if ((ptr - buf) > 1024)
 
4952
            {
 
4953
                /* flushing the internal buffer */
 
4954
                *ptr++ = '\0';
 
4955
                gaiaAppendToOutBuffer (out_buf, buf);
 
4956
                ptr = buf;
 
4957
            }
 
4958
          if (type == GAIA_MULTIPOINT || type == GAIA_GEOMETRYCOLLECTION)
 
4959
            {
 
4960
                *ptr++ = '0';
 
4961
                *ptr++ = '1';
 
4962
                /* it's a collection: the CLASS TYPE for this element */
 
4963
                gaiaExport32 (endian_buf, GAIA_POINT, 1, endian_arch);
 
4964
                for (i = 0; i < 3; i++)
 
4965
                  {
 
4966
                      /* CAVEAT: the 4th byte in PostGIS encodes M/Z presence !!!! */
 
4967
                      sprintf (byte, "%02X", endian_buf[i]);
 
4968
                      *ptr++ = byte[0];
 
4969
                      *ptr++ = byte[1];
 
4970
                  }
 
4971
                /* marking M/Z presence */
 
4972
                if (geom->DimensionModel == GAIA_XY_Z)
 
4973
                    *ptr++ = '8';
 
4974
                else if (geom->DimensionModel == GAIA_XY_M)
 
4975
                    *ptr++ = '4';
 
4976
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
4977
                    *ptr++ = 'C';
 
4978
                else
 
4979
                    *ptr++ = '0';
 
4980
                *ptr++ = '0';
 
4981
            }
 
4982
          gaiaExport64 (endian_buf, point->X, 1, endian_arch);  /* X */
 
4983
          for (i = 0; i < 8; i++)
 
4984
            {
 
4985
                sprintf (byte, "%02X", endian_buf[i]);
 
4986
                *ptr++ = byte[0];
 
4987
                *ptr++ = byte[1];
 
4988
            }
 
4989
          gaiaExport64 (endian_buf, point->Y, 1, endian_arch);  /* Y */
 
4990
          for (i = 0; i < 8; i++)
 
4991
            {
 
4992
                sprintf (byte, "%02X", endian_buf[i]);
 
4993
                *ptr++ = byte[0];
 
4994
                *ptr++ = byte[1];
 
4995
            }
 
4996
          if (geom->DimensionModel == GAIA_XY_Z)
 
4997
            {
 
4998
                gaiaExport64 (endian_buf, point->Z, 1, endian_arch);    /* Z */
 
4999
                for (i = 0; i < 8; i++)
 
5000
                  {
 
5001
                      sprintf (byte, "%02X", endian_buf[i]);
 
5002
                      *ptr++ = byte[0];
 
5003
                      *ptr++ = byte[1];
 
5004
                  }
 
5005
            }
 
5006
          else if (geom->DimensionModel == GAIA_XY_M)
 
5007
            {
 
5008
                gaiaExport64 (endian_buf, point->M, 1, endian_arch);    /* M */
 
5009
                for (i = 0; i < 8; i++)
 
5010
                  {
 
5011
                      sprintf (byte, "%02X", endian_buf[i]);
 
5012
                      *ptr++ = byte[0];
 
5013
                      *ptr++ = byte[1];
 
5014
                  }
 
5015
            }
 
5016
          else if (geom->DimensionModel == GAIA_XY_Z_M)
 
5017
            {
 
5018
                gaiaExport64 (endian_buf, point->Z, 1, endian_arch);    /* Z */
 
5019
                for (i = 0; i < 8; i++)
 
5020
                  {
 
5021
                      sprintf (byte, "%02X", endian_buf[i]);
 
5022
                      *ptr++ = byte[0];
 
5023
                      *ptr++ = byte[1];
 
5024
                  }
 
5025
                gaiaExport64 (endian_buf, point->M, 1, endian_arch);    /* M */
 
5026
                for (i = 0; i < 8; i++)
 
5027
                  {
 
5028
                      sprintf (byte, "%02X", endian_buf[i]);
 
5029
                      *ptr++ = byte[0];
 
5030
                      *ptr++ = byte[1];
 
5031
                  }
 
5032
            }
 
5033
          point = point->Next;
 
5034
      }
 
5035
    line = geom->FirstLinestring;
 
5036
    while (line)
 
5037
      {
 
5038
          if ((ptr - buf) > 1024)
 
5039
            {
 
5040
                /* flushing the internal buffer */
 
5041
                *ptr++ = '\0';
 
5042
                gaiaAppendToOutBuffer (out_buf, buf);
 
5043
                ptr = buf;
 
5044
            }
 
5045
          if (type == GAIA_MULTILINESTRING || type == GAIA_GEOMETRYCOLLECTION)
 
5046
            {
 
5047
                *ptr++ = '0';
 
5048
                *ptr++ = '1';
 
5049
                /* it's a collection: the CLASS TYPE for this element */
 
5050
                gaiaExport32 (endian_buf, GAIA_LINESTRING, 1, endian_arch);
 
5051
                for (i = 0; i < 3; i++)
 
5052
                  {
 
5053
                      /* CAVEAT: the 4th byte in PostGIS encodes M/Z presence !!!! */
 
5054
                      sprintf (byte, "%02X", endian_buf[i]);
 
5055
                      *ptr++ = byte[0];
 
5056
                      *ptr++ = byte[1];
 
5057
                  }
 
5058
                /* marking M/Z presence */
 
5059
                if (geom->DimensionModel == GAIA_XY_Z)
 
5060
                    *ptr++ = '8';
 
5061
                else if (geom->DimensionModel == GAIA_XY_M)
 
5062
                    *ptr++ = '4';
 
5063
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
5064
                    *ptr++ = 'C';
 
5065
                else
 
5066
                    *ptr++ = '0';
 
5067
                *ptr++ = '0';
 
5068
            }
 
5069
          gaiaExport32 (endian_buf, line->Points, 1, endian_arch);      /* # points */
 
5070
          for (i = 0; i < 4; i++)
 
5071
            {
 
5072
                sprintf (byte, "%02X", endian_buf[i]);
 
5073
                *ptr++ = byte[0];
 
5074
                *ptr++ = byte[1];
 
5075
            }
 
5076
          for (iv = 0; iv < line->Points; iv++)
 
5077
            {
 
5078
                if ((ptr - buf) > 1024)
 
5079
                  {
 
5080
                      /* flushing the internal buffer */
 
5081
                      *ptr++ = '\0';
 
5082
                      gaiaAppendToOutBuffer (out_buf, buf);
 
5083
                      ptr = buf;
 
5084
                  }
 
5085
                gaiaLineGetPoint (line, iv, &x, &y, &z, &m);
 
5086
                gaiaExport64 (endian_buf, x, 1, endian_arch);   /* X */
 
5087
                for (i = 0; i < 8; i++)
 
5088
                  {
 
5089
                      sprintf (byte, "%02X", endian_buf[i]);
 
5090
                      *ptr++ = byte[0];
 
5091
                      *ptr++ = byte[1];
 
5092
                  }
 
5093
                gaiaExport64 (endian_buf, y, 1, endian_arch);   /* Y */
 
5094
                for (i = 0; i < 8; i++)
 
5095
                  {
 
5096
                      sprintf (byte, "%02X", endian_buf[i]);
 
5097
                      *ptr++ = byte[0];
 
5098
                      *ptr++ = byte[1];
 
5099
                  }
 
5100
                if (geom->DimensionModel == GAIA_XY_Z)
 
5101
                  {
 
5102
                      gaiaExport64 (endian_buf, z, 1, endian_arch);     /* Z */
 
5103
                      for (i = 0; i < 8; i++)
 
5104
                        {
 
5105
                            sprintf (byte, "%02X", endian_buf[i]);
 
5106
                            *ptr++ = byte[0];
 
5107
                            *ptr++ = byte[1];
 
5108
                        }
 
5109
                  }
 
5110
                else if (geom->DimensionModel == GAIA_XY_M)
 
5111
                  {
 
5112
                      gaiaExport64 (endian_buf, m, 1, endian_arch);     /* M */
 
5113
                      for (i = 0; i < 8; i++)
 
5114
                        {
 
5115
                            sprintf (byte, "%02X", endian_buf[i]);
 
5116
                            *ptr++ = byte[0];
 
5117
                            *ptr++ = byte[1];
 
5118
                        }
 
5119
                  }
 
5120
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
5121
                  {
 
5122
                      gaiaExport64 (endian_buf, z, 1, endian_arch);     /* Z */
 
5123
                      for (i = 0; i < 8; i++)
 
5124
                        {
 
5125
                            sprintf (byte, "%02X", endian_buf[i]);
 
5126
                            *ptr++ = byte[0];
 
5127
                            *ptr++ = byte[1];
 
5128
                        }
 
5129
                      gaiaExport64 (endian_buf, m, 1, endian_arch);     /* M */
 
5130
                      for (i = 0; i < 8; i++)
 
5131
                        {
 
5132
                            sprintf (byte, "%02X", endian_buf[i]);
 
5133
                            *ptr++ = byte[0];
 
5134
                            *ptr++ = byte[1];
 
5135
                        }
 
5136
                  }
 
5137
            }
 
5138
          line = line->Next;
 
5139
      }
 
5140
    polyg = geom->FirstPolygon;
 
5141
    while (polyg)
 
5142
      {
 
5143
          if ((ptr - buf) > 1024)
 
5144
            {
 
5145
                /* flushing the internal buffer */
 
5146
                *ptr++ = '\0';
 
5147
                gaiaAppendToOutBuffer (out_buf, buf);
 
5148
                ptr = buf;
 
5149
            }
 
5150
          if (type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
5151
            {
 
5152
                *ptr++ = '0';
 
5153
                *ptr++ = '1';
 
5154
                /* it's a collection: the CLASS TYPE for this element */
 
5155
                gaiaExport32 (endian_buf, GAIA_POLYGON, 1, endian_arch);
 
5156
                for (i = 0; i < 3; i++)
 
5157
                  {
 
5158
                      /* CAVEAT: the 4th byte in PostGIS encodes M/Z presence !!!! */
 
5159
                      sprintf (byte, "%02X", endian_buf[i]);
 
5160
                      *ptr++ = byte[0];
 
5161
                      *ptr++ = byte[1];
 
5162
                  }
 
5163
                /* marking M/Z presence */
 
5164
                if (geom->DimensionModel == GAIA_XY_Z)
 
5165
                    *ptr++ = '8';
 
5166
                else if (geom->DimensionModel == GAIA_XY_M)
 
5167
                    *ptr++ = '4';
 
5168
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
5169
                    *ptr++ = 'C';
 
5170
                else
 
5171
                    *ptr++ = '0';
 
5172
                *ptr++ = '0';
 
5173
            }
 
5174
          gaiaExport32 (endian_buf, polyg->NumInteriors + 1, 1, endian_arch);   /* # rings */
 
5175
          for (i = 0; i < 4; i++)
 
5176
            {
 
5177
                sprintf (byte, "%02X", endian_buf[i]);
 
5178
                *ptr++ = byte[0];
 
5179
                *ptr++ = byte[1];
 
5180
            }
 
5181
          rng = polyg->Exterior;
 
5182
          gaiaExport32 (endian_buf, rng->Points, 1, endian_arch);       /* # points - exterior ring */
 
5183
          for (i = 0; i < 4; i++)
 
5184
            {
 
5185
                sprintf (byte, "%02X", endian_buf[i]);
 
5186
                *ptr++ = byte[0];
 
5187
                *ptr++ = byte[1];
 
5188
            }
 
5189
          for (iv = 0; iv < rng->Points; iv++)
 
5190
            {
 
5191
                if ((ptr - buf) > 1024)
 
5192
                  {
 
5193
                      /* flushing the internal buffer */
 
5194
                      *ptr++ = '\0';
 
5195
                      gaiaAppendToOutBuffer (out_buf, buf);
 
5196
                      ptr = buf;
 
5197
                  }
 
5198
                gaiaRingGetPoint (rng, iv, &x, &y, &z, &m);
 
5199
                gaiaExport64 (endian_buf, x, 1, endian_arch);   /* X - exterior ring */
 
5200
                for (i = 0; i < 8; i++)
 
5201
                  {
 
5202
                      sprintf (byte, "%02X", endian_buf[i]);
 
5203
                      *ptr++ = byte[0];
 
5204
                      *ptr++ = byte[1];
 
5205
                  }
 
5206
                gaiaExport64 (endian_buf, y, 1, endian_arch);   /* Y - exterior ring */
 
5207
                for (i = 0; i < 8; i++)
 
5208
                  {
 
5209
                      sprintf (byte, "%02X", endian_buf[i]);
 
5210
                      *ptr++ = byte[0];
 
5211
                      *ptr++ = byte[1];
 
5212
                  }
 
5213
                if (geom->DimensionModel == GAIA_XY_Z)
 
5214
                  {
 
5215
                      gaiaExport64 (endian_buf, z, 1, endian_arch);     /* Z */
 
5216
                      for (i = 0; i < 8; i++)
 
5217
                        {
 
5218
                            sprintf (byte, "%02X", endian_buf[i]);
 
5219
                            *ptr++ = byte[0];
 
5220
                            *ptr++ = byte[1];
 
5221
                        }
 
5222
                  }
 
5223
                else if (geom->DimensionModel == GAIA_XY_M)
 
5224
                  {
 
5225
                      gaiaExport64 (endian_buf, m, 1, endian_arch);     /* M */
 
5226
                      for (i = 0; i < 8; i++)
 
5227
                        {
 
5228
                            sprintf (byte, "%02X", endian_buf[i]);
 
5229
                            *ptr++ = byte[0];
 
5230
                            *ptr++ = byte[1];
 
5231
                        }
 
5232
                  }
 
5233
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
5234
                  {
 
5235
                      gaiaExport64 (endian_buf, z, 1, endian_arch);     /* Z */
 
5236
                      for (i = 0; i < 8; i++)
 
5237
                        {
 
5238
                            sprintf (byte, "%02X", endian_buf[i]);
 
5239
                            *ptr++ = byte[0];
 
5240
                            *ptr++ = byte[1];
 
5241
                        }
 
5242
                      gaiaExport64 (endian_buf, m, 1, endian_arch);     /* M */
 
5243
                      for (i = 0; i < 8; i++)
 
5244
                        {
 
5245
                            sprintf (byte, "%02X", endian_buf[i]);
 
5246
                            *ptr++ = byte[0];
 
5247
                            *ptr++ = byte[1];
 
5248
                        }
 
5249
                  }
 
5250
            }
 
5251
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
5252
            {
 
5253
                rng = polyg->Interiors + ib;
 
5254
                gaiaExport32 (endian_buf, rng->Points, 1, endian_arch); /* # points - interior ring */
 
5255
                for (i = 0; i < 4; i++)
 
5256
                  {
 
5257
                      sprintf (byte, "%02X", endian_buf[i]);
 
5258
                      *ptr++ = byte[0];
 
5259
                      *ptr++ = byte[1];
 
5260
                  }
 
5261
                for (iv = 0; iv < rng->Points; iv++)
 
5262
                  {
 
5263
                      if ((ptr - buf) > 1024)
 
5264
                        {
 
5265
                            /* flushing the internal buffer */
 
5266
                            *ptr++ = '\0';
 
5267
                            gaiaAppendToOutBuffer (out_buf, buf);
 
5268
                            ptr = buf;
 
5269
                        }
 
5270
                      gaiaRingGetPoint (rng, iv, &x, &y, &z, &m);
 
5271
                      gaiaExport64 (endian_buf, x, 1, endian_arch);     /* X - interior ring */
 
5272
                      for (i = 0; i < 8; i++)
 
5273
                        {
 
5274
                            sprintf (byte, "%02X", endian_buf[i]);
 
5275
                            *ptr++ = byte[0];
 
5276
                            *ptr++ = byte[1];
 
5277
                        }
 
5278
                      gaiaExport64 (endian_buf, y, 1, endian_arch);     /* Y - interior ring */
 
5279
                      for (i = 0; i < 8; i++)
 
5280
                        {
 
5281
                            sprintf (byte, "%02X", endian_buf[i]);
 
5282
                            *ptr++ = byte[0];
 
5283
                            *ptr++ = byte[1];
 
5284
                        }
 
5285
                      if (geom->DimensionModel == GAIA_XY_Z)
 
5286
                        {
 
5287
                            gaiaExport64 (endian_buf, z, 1, endian_arch);       /* Z */
 
5288
                            for (i = 0; i < 8; i++)
 
5289
                              {
 
5290
                                  sprintf (byte, "%02X", endian_buf[i]);
 
5291
                                  *ptr++ = byte[0];
 
5292
                                  *ptr++ = byte[1];
 
5293
                              }
 
5294
                        }
 
5295
                      else if (geom->DimensionModel == GAIA_XY_M)
 
5296
                        {
 
5297
                            gaiaExport64 (endian_buf, m, 1, endian_arch);       /* M */
 
5298
                            for (i = 0; i < 8; i++)
 
5299
                              {
 
5300
                                  sprintf (byte, "%02X", endian_buf[i]);
 
5301
                                  *ptr++ = byte[0];
 
5302
                                  *ptr++ = byte[1];
 
5303
                              }
 
5304
                        }
 
5305
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
5306
                        {
 
5307
                            gaiaExport64 (endian_buf, z, 1, endian_arch);       /* Z */
 
5308
                            for (i = 0; i < 8; i++)
 
5309
                              {
 
5310
                                  sprintf (byte, "%02X", endian_buf[i]);
 
5311
                                  *ptr++ = byte[0];
 
5312
                                  *ptr++ = byte[1];
 
5313
                              }
 
5314
                            gaiaExport64 (endian_buf, m, 1, endian_arch);       /* M */
 
5315
                            for (i = 0; i < 8; i++)
 
5316
                              {
 
5317
                                  sprintf (byte, "%02X", endian_buf[i]);
 
5318
                                  *ptr++ = byte[0];
 
5319
                                  *ptr++ = byte[1];
 
5320
                              }
 
5321
                        }
 
5322
                  }
 
5323
            }
 
5324
          polyg = polyg->Next;
 
5325
      }
 
5326
 
 
5327
/* terminating the EWKB string */
 
5328
    *ptr = '\0';
 
5329
    gaiaAppendToOutBuffer (out_buf, buf);
 
5330
}
 
5331
 
 
5332
static int
 
5333
coordDimsFromFgf (int endian_arch, const unsigned char *blob, unsigned int size,
 
5334
                  int *type)
 
5335
{
 
5336
/* decoding the coordinate Dimensions for an FGF Geometry */
 
5337
    int coord_dims;
 
5338
    if (size < 4)
 
5339
        return 0;
 
5340
    coord_dims = gaiaImport32 (blob, GAIA_LITTLE_ENDIAN, endian_arch);
 
5341
    *type = coord_dims;
 
5342
    switch (coord_dims)
 
5343
      {
 
5344
      case GAIA_XY:
 
5345
          return 2;
 
5346
      case GAIA_XY_M:
 
5347
      case GAIA_XY_Z:
 
5348
          return 3;
 
5349
      case GAIA_XY_Z_M:
 
5350
          return 4;
 
5351
      default:
 
5352
          return 0;
 
5353
      }
 
5354
}
 
5355
 
 
5356
static int
 
5357
pointFromFgf (gaiaGeomCollPtr geom, int endian_arch, const unsigned char *blob,
 
5358
              unsigned int size, unsigned int *consumed)
 
5359
{
 
5360
/* decoding a POINT Geometry from FGF  */
 
5361
    double x;
 
5362
    double y;
 
5363
    double z;
 
5364
    double m;
 
5365
    unsigned int sz = size;
 
5366
    const unsigned char *ptr = blob;
 
5367
    int coord_dims;
 
5368
    int type;
 
5369
/* checking Geometry Type */
 
5370
    if (sz < 4)
 
5371
        return 0;
 
5372
    if (gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch) != GAIA_POINT)
 
5373
        return 0;
 
5374
    ptr += 4;
 
5375
    sz -= 4;
 
5376
/* checking size */
 
5377
    if (sz < 4)
 
5378
        return 0;
 
5379
    coord_dims = coordDimsFromFgf (endian_arch, ptr, size, &type);
 
5380
    if (!coord_dims)
 
5381
        return 0;
 
5382
    ptr += 4;
 
5383
    sz -= 4;
 
5384
    if (sz < (coord_dims * sizeof (double)))
 
5385
        return 0;
 
5386
    if (consumed)
 
5387
        *consumed = coord_dims * sizeof (double);
 
5388
    if (type == GAIA_XY_Z)
 
5389
      {
 
5390
          /* building the POINTZ */
 
5391
          x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5392
          y = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5393
          z = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5394
          gaiaAddPointToGeomCollXYZ (geom, x, y, z);
 
5395
      }
 
5396
    else if (type == GAIA_XY_M)
 
5397
      {
 
5398
          /* building the POINTM */
 
5399
          x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5400
          y = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5401
          m = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5402
          gaiaAddPointToGeomCollXYM (geom, x, y, m);
 
5403
      }
 
5404
    else if (type == GAIA_XY_Z_M)
 
5405
      {
 
5406
          /* building the POINTZM */
 
5407
          x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5408
          y = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5409
          z = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5410
          m = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5411
          gaiaAddPointToGeomCollXYZM (geom, x, y, z, m);
 
5412
      }
 
5413
    else
 
5414
      {
 
5415
          /* building the POINT */
 
5416
          x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5417
          y = gaiaImport64 (ptr + 8, GAIA_LITTLE_ENDIAN, endian_arch);
 
5418
          gaiaAddPointToGeomColl (geom, x, y);
 
5419
      }
 
5420
    return 1;
 
5421
}
 
5422
 
 
5423
static int
 
5424
linestringFromFgf (gaiaGeomCollPtr geom, int endian_arch,
 
5425
                   const unsigned char *blob, unsigned int size,
 
5426
                   unsigned int *consumed)
 
5427
{
 
5428
/* decoding a LINESTRING Geometry from FGF  */
 
5429
    gaiaLinestringPtr ln;
 
5430
    int pts;
 
5431
    int iv;
 
5432
    double x;
 
5433
    double y;
 
5434
    double z;
 
5435
    double m;
 
5436
    unsigned int ln_sz;
 
5437
    unsigned int sz = size;
 
5438
    const unsigned char *ptr = blob;
 
5439
    int coord_dims;
 
5440
    int type;
 
5441
/* checking Geometry Type */
 
5442
    if (sz < 4)
 
5443
        return 0;
 
5444
    if (gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch) != GAIA_LINESTRING)
 
5445
        return 0;
 
5446
    ptr += 4;
 
5447
    sz -= 4;
 
5448
/* checking size */
 
5449
    coord_dims = coordDimsFromFgf (endian_arch, ptr, size, &type);
 
5450
    if (!coord_dims)
 
5451
        return 0;
 
5452
    ptr += 4;
 
5453
    sz -= 4;
 
5454
/* how many points are there ? */
 
5455
    if (sz < 4)
 
5456
        return 0;
 
5457
    pts = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5458
    ptr += 4;
 
5459
    sz -= 4;
 
5460
    if (pts < 2)
 
5461
        return 0;
 
5462
    ln_sz = pts * coord_dims * sizeof (double);
 
5463
    if (sz < ln_sz)
 
5464
        return 0;
 
5465
    if (consumed)
 
5466
        *consumed = (12 + ln_sz);
 
5467
    if (type == GAIA_XY_Z)
 
5468
      {
 
5469
          /* building the LINESTRINGZ */
 
5470
          geom->DimensionModel = GAIA_XY_Z;
 
5471
          ln = gaiaAddLinestringToGeomColl (geom, pts);
 
5472
          for (iv = 0; iv < pts; iv++)
 
5473
            {
 
5474
                /* inserting vertices into the linestring */
 
5475
                x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5476
                y = gaiaImport64 (ptr + sizeof (double), GAIA_LITTLE_ENDIAN,
 
5477
                                  endian_arch);
 
5478
                ptr += (coord_dims * sizeof (double));
 
5479
                gaiaSetPoint (ln->Coords, iv, x, y);
 
5480
            }
 
5481
      }
 
5482
    else if (type == GAIA_XY_M)
 
5483
      {
 
5484
          /* building the LINESTRINGM */
 
5485
          geom->DimensionModel = GAIA_XY_M;
 
5486
          ln = gaiaAddLinestringToGeomColl (geom, pts);
 
5487
          for (iv = 0; iv < pts; iv++)
 
5488
            {
 
5489
                /* inserting vertices into the linestring */
 
5490
                x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5491
                y = gaiaImport64 (ptr + sizeof (double), GAIA_LITTLE_ENDIAN,
 
5492
                                  endian_arch);
 
5493
                z = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5494
                                  GAIA_LITTLE_ENDIAN, endian_arch);
 
5495
                ptr += (coord_dims * sizeof (double));
 
5496
                gaiaSetPoint (ln->Coords, iv, x, y);
 
5497
            }
 
5498
      }
 
5499
    else if (type == GAIA_XY_Z_M)
 
5500
      {
 
5501
          /* building the LINESTRINGZM */
 
5502
          geom->DimensionModel = GAIA_XY_Z_M;
 
5503
          ln = gaiaAddLinestringToGeomColl (geom, pts);
 
5504
          for (iv = 0; iv < pts; iv++)
 
5505
            {
 
5506
                /* inserting vertices into the linestring */
 
5507
                x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5508
                y = gaiaImport64 (ptr + sizeof (double), GAIA_LITTLE_ENDIAN,
 
5509
                                  endian_arch);
 
5510
                m = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5511
                                  GAIA_LITTLE_ENDIAN, endian_arch);
 
5512
                ptr += (coord_dims * sizeof (double));
 
5513
                gaiaSetPoint (ln->Coords, iv, x, y);
 
5514
            }
 
5515
      }
 
5516
    else
 
5517
      {
 
5518
          /* building the LINESTRING */
 
5519
          geom->DimensionModel = GAIA_XY;
 
5520
          ln = gaiaAddLinestringToGeomColl (geom, pts);
 
5521
          for (iv = 0; iv < pts; iv++)
 
5522
            {
 
5523
                /* inserting vertices into the linestring */
 
5524
                x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5525
                y = gaiaImport64 (ptr + sizeof (double), GAIA_LITTLE_ENDIAN,
 
5526
                                  endian_arch);
 
5527
                z = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5528
                                  GAIA_LITTLE_ENDIAN, endian_arch);
 
5529
                m = gaiaImport64 (ptr + (sizeof (double) * 3),
 
5530
                                  GAIA_LITTLE_ENDIAN, endian_arch);
 
5531
                ptr += (coord_dims * sizeof (double));
 
5532
                gaiaSetPoint (ln->Coords, iv, x, y);
 
5533
            }
 
5534
      }
 
5535
    return 1;
 
5536
}
 
5537
 
 
5538
static int
 
5539
polygonFromFgf (gaiaGeomCollPtr geom, int endian_arch,
 
5540
                const unsigned char *blob, unsigned int size,
 
5541
                unsigned int *consumed)
 
5542
{
 
5543
/* decoding a POLYGON Geometry from FGF  */
 
5544
    gaiaPolygonPtr pg = NULL;
 
5545
    gaiaRingPtr rng;
 
5546
    int rings;
 
5547
    int ir;
 
5548
    int pts;
 
5549
    int iv;
 
5550
    double x;
 
5551
    double y;
 
5552
    double z;
 
5553
    double m;
 
5554
    unsigned int rng_sz;
 
5555
    unsigned int sz = size;
 
5556
    const unsigned char *ptr = blob;
 
5557
    int coord_dims;
 
5558
    int type;
 
5559
    unsigned int bytes = 0;
 
5560
/* checking Geometry Type */
 
5561
    if (sz < 4)
 
5562
        return 0;
 
5563
    if (gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch) != GAIA_POLYGON)
 
5564
        return 0;
 
5565
    ptr += 4;
 
5566
    sz -= 4;
 
5567
    bytes += 4;
 
5568
/* checking size */
 
5569
    coord_dims = coordDimsFromFgf (endian_arch, ptr, size, &type);
 
5570
    if (!coord_dims)
 
5571
        return 0;
 
5572
    ptr += 4;
 
5573
    sz -= 4;
 
5574
    bytes += 4;
 
5575
/* how many rings are there ? */
 
5576
    if (sz < 4)
 
5577
        return 0;
 
5578
    rings = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5579
    ptr += 4;
 
5580
    sz -= 4;
 
5581
    bytes += 4;
 
5582
    if (rings < 1)
 
5583
        return 0;
 
5584
    for (ir = 0; ir < rings; ir++)
 
5585
      {
 
5586
          /* fetching Polygon's rings */
 
5587
          if (sz < 4)
 
5588
              return 0;
 
5589
          pts = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5590
          ptr += 4;
 
5591
          sz -= 4;
 
5592
          bytes += 4;
 
5593
          if (pts < 4)
 
5594
              return 0;
 
5595
          rng_sz = pts * coord_dims * sizeof (double);
 
5596
          if (sz < rng_sz)
 
5597
              return 0;
 
5598
          bytes += rng_sz;
 
5599
          if (type == GAIA_XY_Z)
 
5600
            {
 
5601
                /* POLYGONZ */
 
5602
                geom->DimensionModel = GAIA_XY_Z;
 
5603
                if (ir == 0)
 
5604
                  {
 
5605
                      /* building the EXTERIOR RING */
 
5606
                      pg = gaiaAddPolygonToGeomColl (geom, pts, rings - 1);
 
5607
                      rng = pg->Exterior;
 
5608
                      for (iv = 0; iv < pts; iv++)
 
5609
                        {
 
5610
                            /* inserting vertices into the EXTERIOR Ring */
 
5611
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5612
                                              endian_arch);
 
5613
                            y = gaiaImport64 (ptr + sizeof (double),
 
5614
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5615
                            z = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5616
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5617
                            ptr += (coord_dims * sizeof (double));
 
5618
                            gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
 
5619
                        }
 
5620
                  }
 
5621
                else
 
5622
                  {
 
5623
                      /* building an INTERIOR RING */
 
5624
                      rng = gaiaAddInteriorRing (pg, ir - 1, pts);
 
5625
                      for (iv = 0; iv < pts; iv++)
 
5626
                        {
 
5627
                            /* inserting vertices into some INTERIOR Ring */
 
5628
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5629
                                              endian_arch);
 
5630
                            y = gaiaImport64 (ptr + sizeof (double),
 
5631
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5632
                            z = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5633
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5634
                            ptr += (coord_dims * sizeof (double));
 
5635
                            gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
 
5636
                        }
 
5637
                  }
 
5638
            }
 
5639
          if (type == GAIA_XY_M)
 
5640
            {
 
5641
                /* POLYGONM */
 
5642
                geom->DimensionModel = GAIA_XY_M;
 
5643
                if (ir == 0)
 
5644
                  {
 
5645
                      /* building the EXTERIOR RING */
 
5646
                      pg = gaiaAddPolygonToGeomColl (geom, pts, rings - 1);
 
5647
                      rng = pg->Exterior;
 
5648
                      for (iv = 0; iv < pts; iv++)
 
5649
                        {
 
5650
                            /* inserting vertices into the EXTERIOR Ring */
 
5651
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5652
                                              endian_arch);
 
5653
                            y = gaiaImport64 (ptr + sizeof (double),
 
5654
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5655
                            m = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5656
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5657
                            ptr += (coord_dims * sizeof (double));
 
5658
                            gaiaSetPointXYM (rng->Coords, iv, x, y, m);
 
5659
                        }
 
5660
                  }
 
5661
                else
 
5662
                  {
 
5663
                      /* building an INTERIOR RING */
 
5664
                      rng = gaiaAddInteriorRing (pg, ir - 1, pts);
 
5665
                      for (iv = 0; iv < pts; iv++)
 
5666
                        {
 
5667
                            /* inserting vertices into some INTERIOR Ring */
 
5668
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5669
                                              endian_arch);
 
5670
                            y = gaiaImport64 (ptr + sizeof (double),
 
5671
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5672
                            m = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5673
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5674
                            ptr += (coord_dims * sizeof (double));
 
5675
                            gaiaSetPointXYM (rng->Coords, iv, x, y, m);
 
5676
                        }
 
5677
                  }
 
5678
            }
 
5679
          else if (type == GAIA_XY_Z_M)
 
5680
            {
 
5681
                /* POLYGONZM */
 
5682
                geom->DimensionModel = GAIA_XY_Z_M;
 
5683
                if (ir == 0)
 
5684
                  {
 
5685
                      /* building the EXTERIOR RING */
 
5686
                      pg = gaiaAddPolygonToGeomColl (geom, pts, rings - 1);
 
5687
                      rng = pg->Exterior;
 
5688
                      for (iv = 0; iv < pts; iv++)
 
5689
                        {
 
5690
                            /* inserting vertices into the EXTERIOR Ring */
 
5691
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5692
                                              endian_arch);
 
5693
                            y = gaiaImport64 (ptr + sizeof (double),
 
5694
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5695
                            z = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5696
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5697
                            m = gaiaImport64 (ptr + (sizeof (double) * 3),
 
5698
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5699
                            ptr += (coord_dims * sizeof (double));
 
5700
                            gaiaSetPointXYZM (rng->Coords, iv, x, y, z, m);
 
5701
                        }
 
5702
                  }
 
5703
                else
 
5704
                  {
 
5705
                      /* building an INTERIOR RING */
 
5706
                      rng = gaiaAddInteriorRing (pg, ir - 1, pts);
 
5707
                      for (iv = 0; iv < pts; iv++)
 
5708
                        {
 
5709
                            /* inserting vertices into some INTERIOR Ring */
 
5710
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5711
                                              endian_arch);
 
5712
                            y = gaiaImport64 (ptr + sizeof (double),
 
5713
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5714
                            z = gaiaImport64 (ptr + (sizeof (double) * 2),
 
5715
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5716
                            m = gaiaImport64 (ptr + (sizeof (double) * 3),
 
5717
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5718
                            ptr += (coord_dims * sizeof (double));
 
5719
                            gaiaSetPointXYZM (rng->Coords, iv, x, y, z, m);
 
5720
                        }
 
5721
                  }
 
5722
            }
 
5723
          else
 
5724
            {
 
5725
                /* POLYGON */
 
5726
                geom->DimensionModel = GAIA_XY;
 
5727
                if (ir == 0)
 
5728
                  {
 
5729
                      /* building the EXTERIOR RING */
 
5730
                      pg = gaiaAddPolygonToGeomColl (geom, pts, rings - 1);
 
5731
                      rng = pg->Exterior;
 
5732
                      for (iv = 0; iv < pts; iv++)
 
5733
                        {
 
5734
                            /* inserting vertices into the EXTERIOR Ring */
 
5735
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5736
                                              endian_arch);
 
5737
                            y = gaiaImport64 (ptr + sizeof (double),
 
5738
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5739
                            ptr += (coord_dims * sizeof (double));
 
5740
                            gaiaSetPoint (rng->Coords, iv, x, y);
 
5741
                        }
 
5742
                  }
 
5743
                else
 
5744
                  {
 
5745
                      /* building an INTERIOR RING */
 
5746
                      rng = gaiaAddInteriorRing (pg, ir - 1, pts);
 
5747
                      for (iv = 0; iv < pts; iv++)
 
5748
                        {
 
5749
                            /* inserting vertices into some INTERIOR Ring */
 
5750
                            x = gaiaImport64 (ptr, GAIA_LITTLE_ENDIAN,
 
5751
                                              endian_arch);
 
5752
                            y = gaiaImport64 (ptr + sizeof (double),
 
5753
                                              GAIA_LITTLE_ENDIAN, endian_arch);
 
5754
                            ptr += (coord_dims * sizeof (double));
 
5755
                            gaiaSetPoint (rng->Coords, iv, x, y);
 
5756
                        }
 
5757
                  }
 
5758
            }
 
5759
          sz -= rng_sz;
 
5760
      }
 
5761
    if (consumed)
 
5762
        *consumed = bytes;
 
5763
    return 1;
 
5764
}
 
5765
 
 
5766
static int
 
5767
multiPointFromFgf (gaiaGeomCollPtr geom, int endian_arch,
 
5768
                   const unsigned char *blob, unsigned int size)
 
5769
{
 
5770
/* decoding a MULTIPOINT Geometry from FGF  */
 
5771
    int pts;
 
5772
    int ipt;
 
5773
    unsigned int sz = size;
 
5774
    const unsigned char *ptr = blob;
 
5775
    unsigned int consumed;
 
5776
/* checking Geometry Type */
 
5777
    if (sz < 4)
 
5778
        return 0;
 
5779
    if (gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch) != GAIA_MULTIPOINT)
 
5780
        return 0;
 
5781
    ptr += 4;
 
5782
    sz -= 4;
 
5783
/* how many points are there ? */
 
5784
    if (sz < 4)
 
5785
        return 0;
 
5786
    pts = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5787
    ptr += 4;
 
5788
    sz -= 4;
 
5789
    if (pts < 1)
 
5790
        return 0;
 
5791
    for (ipt = 0; ipt < pts; ipt++)
 
5792
      {
 
5793
          /* fetching individual Points from FGF */
 
5794
          if (!pointFromFgf (geom, endian_arch, ptr, sz, &consumed))
 
5795
              return 0;
 
5796
          ptr += consumed;
 
5797
          sz -= consumed;
 
5798
      }
 
5799
    return 1;
 
5800
}
 
5801
 
 
5802
static int
 
5803
multiLinestringFromFgf (gaiaGeomCollPtr geom, int endian_arch,
 
5804
                        const unsigned char *blob, unsigned int size)
 
5805
{
 
5806
/* decoding a MULTILINESTRING Geometry from FGF  */
 
5807
    int lns;
 
5808
    int iln;
 
5809
    unsigned int sz = size;
 
5810
    const unsigned char *ptr = blob;
 
5811
    unsigned int consumed;
 
5812
/* checking Geometry Type */
 
5813
    if (sz < 4)
 
5814
        return 0;
 
5815
    if (gaiaImport32
 
5816
        (ptr, GAIA_LITTLE_ENDIAN, endian_arch) != GAIA_MULTILINESTRING)
 
5817
        return 0;
 
5818
    ptr += 4;
 
5819
    sz -= 4;
 
5820
/* how many linestrings are there ? */
 
5821
    if (sz < 4)
 
5822
        return 0;
 
5823
    lns = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5824
    ptr += 4;
 
5825
    sz -= 4;
 
5826
    if (lns < 1)
 
5827
        return 0;
 
5828
    for (iln = 0; iln < lns; iln++)
 
5829
      {
 
5830
          /* fetching individual Linestrings from FGF */
 
5831
          if (!linestringFromFgf (geom, endian_arch, ptr, sz, &consumed))
 
5832
              return 0;
 
5833
          ptr += consumed;
 
5834
          sz -= consumed;
 
5835
      }
 
5836
    return 1;
 
5837
}
 
5838
 
 
5839
static int
 
5840
multiPolygonFromFgf (gaiaGeomCollPtr geom, int endian_arch,
 
5841
                     const unsigned char *blob, unsigned int size)
 
5842
{
 
5843
/* decoding a MULTIPOLYGON Geometry from FGF  */
 
5844
    int pgs;
 
5845
    int ipg;
 
5846
    unsigned int sz = size;
 
5847
    const unsigned char *ptr = blob;
 
5848
    unsigned int consumed;
 
5849
/* checking Geometry Type */
 
5850
    if (sz < 4)
 
5851
        return 0;
 
5852
    if (gaiaImport32
 
5853
        (ptr, GAIA_LITTLE_ENDIAN, endian_arch) != GAIA_MULTIPOLYGON)
 
5854
        return 0;
 
5855
    ptr += 4;
 
5856
    sz -= 4;
 
5857
/* how many polygons are there ? */
 
5858
    if (sz < 4)
 
5859
        return 0;
 
5860
    pgs = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5861
    ptr += 4;
 
5862
    sz -= 4;
 
5863
    if (pgs < 1)
 
5864
        return 0;
 
5865
    for (ipg = 0; ipg < pgs; ipg++)
 
5866
      {
 
5867
          /* fetching individual Polygons from FGF */
 
5868
          if (!polygonFromFgf (geom, endian_arch, ptr, sz, &consumed))
 
5869
              return 0;
 
5870
          ptr += consumed;
 
5871
          sz -= consumed;
 
5872
      }
 
5873
    return 1;
 
5874
}
 
5875
 
 
5876
static int
 
5877
geomCollectionFromFgf (gaiaGeomCollPtr geom, int endian_arch,
 
5878
                       const unsigned char *blob, unsigned int size)
 
5879
{
 
5880
/* decoding a  GEOMETRYCOLLECTION Geometry from FGF  */
 
5881
    int geoms;
 
5882
    int ig;
 
5883
    int geom_type;
 
5884
    unsigned int sz = size;
 
5885
    const unsigned char *ptr = blob;
 
5886
    unsigned int consumed;
 
5887
/* checking Geometry Type */
 
5888
    if (sz < 4)
 
5889
        return 0;
 
5890
    if (gaiaImport32
 
5891
        (ptr, GAIA_LITTLE_ENDIAN, endian_arch) != GAIA_GEOMETRYCOLLECTION)
 
5892
        return 0;
 
5893
    ptr += 4;
 
5894
    sz -= 4;
 
5895
/* how many individual Geometries are there ? */
 
5896
    if (sz < 4)
 
5897
        return 0;
 
5898
    geoms = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5899
    ptr += 4;
 
5900
    sz -= 4;
 
5901
    if (geoms < 1)
 
5902
        return 0;
 
5903
    for (ig = 0; ig < geoms; ig++)
 
5904
      {
 
5905
          /* fetching individual Geometries from FGF */
 
5906
          if (sz < 4)
 
5907
              return 0;
 
5908
          geom_type = gaiaImport32 (ptr, GAIA_LITTLE_ENDIAN, endian_arch);
 
5909
          switch (geom_type)
 
5910
            {
 
5911
            case GAIA_POINT:
 
5912
                if (!pointFromFgf (geom, endian_arch, ptr, sz, &consumed))
 
5913
                    return 0;
 
5914
                break;
 
5915
            case GAIA_LINESTRING:
 
5916
                if (!linestringFromFgf (geom, endian_arch, ptr, sz, &consumed))
 
5917
                    return 0;
 
5918
                break;
 
5919
            case GAIA_POLYGON:
 
5920
                if (!polygonFromFgf (geom, endian_arch, ptr, sz, &consumed))
 
5921
                    return 0;
 
5922
                break;
 
5923
            default:            /* unsupported geometry type */
 
5924
                return 0;
 
5925
                break;
 
5926
            };
 
5927
          ptr += consumed;
 
5928
          sz -= consumed;
 
5929
      }
 
5930
    return 1;
 
5931
}
 
5932
 
 
5933
GAIAGEO_DECLARE gaiaGeomCollPtr
 
5934
gaiaFromFgf (const unsigned char *blob, unsigned int size)
 
5935
{
 
5936
/* decoding from FGF to GEOMETRY  */
 
5937
    gaiaGeomCollPtr geom = NULL;
 
5938
    int geom_type;
 
5939
    int endian_arch = gaiaEndianArch ();
 
5940
    if (size < 4)
 
5941
        return NULL;
 
5942
/* checking FGF type */
 
5943
    geom_type = gaiaImport32 (blob, GAIA_LITTLE_ENDIAN, endian_arch);
 
5944
    geom = gaiaAllocGeomColl ();
 
5945
    geom->DeclaredType = geom_type;
 
5946
    switch (geom_type)
 
5947
      {
 
5948
      case GAIA_POINT:
 
5949
          if (pointFromFgf (geom, endian_arch, blob, size, NULL))
 
5950
              return geom;
 
5951
          break;
 
5952
      case GAIA_LINESTRING:
 
5953
          if (linestringFromFgf (geom, endian_arch, blob, size, NULL))
 
5954
              return geom;
 
5955
          break;
 
5956
      case GAIA_POLYGON:
 
5957
          if (polygonFromFgf (geom, endian_arch, blob, size, NULL))
 
5958
              return geom;
 
5959
          break;
 
5960
      case GAIA_MULTIPOINT:
 
5961
          if (multiPointFromFgf (geom, endian_arch, blob, size))
 
5962
              return geom;
 
5963
          break;
 
5964
      case GAIA_MULTILINESTRING:
 
5965
          if (multiLinestringFromFgf (geom, endian_arch, blob, size))
 
5966
              return geom;
 
5967
          break;
 
5968
      case GAIA_MULTIPOLYGON:
 
5969
          if (multiPolygonFromFgf (geom, endian_arch, blob, size))
 
5970
              return geom;
 
5971
          break;
 
5972
      case GAIA_GEOMETRYCOLLECTION:
 
5973
          if (geomCollectionFromFgf (geom, endian_arch, blob, size))
 
5974
              return geom;
 
5975
          break;
 
5976
      default:                  /* unsupported geometry type */
 
5977
          break;
 
5978
      };
 
5979
    gaiaFreeGeomColl (geom);
 
5980
    return NULL;
 
5981
}
 
5982
 
 
5983
GAIAGEO_DECLARE void
 
5984
gaiaToFgf (gaiaGeomCollPtr geom, unsigned char **result, int *size,
 
5985
           int coord_dims)
 
5986
{
 
5987
/* builds the FGF representation for this GEOMETRY */
 
5988
    int ib;
 
5989
    int iv;
 
5990
    double x;
 
5991
    double y;
 
5992
    double z;
 
5993
    double m;
 
5994
    int entities = 0;
 
5995
    int n_points = 0;
 
5996
    int n_linestrings = 0;
 
5997
    int n_polygons = 0;
 
5998
    int type;
 
5999
    int n_coords;
 
6000
    unsigned char *ptr;
 
6001
    int sz = 0;
 
6002
    gaiaPointPtr pt;
 
6003
    gaiaLinestringPtr ln;
 
6004
    gaiaPolygonPtr pg;
 
6005
    gaiaRingPtr rng;
 
6006
    gaiaPointPtr point = NULL;
 
6007
    gaiaLinestringPtr line = NULL;
 
6008
    gaiaPolygonPtr polyg = NULL;
 
6009
    int endian_arch = gaiaEndianArch ();
 
6010
    gaiaMbrGeometry (geom);
 
6011
    switch (coord_dims)
 
6012
      {
 
6013
      case GAIA_XY:
 
6014
          n_coords = 2;
 
6015
          break;
 
6016
      case GAIA_XY_M:
 
6017
      case GAIA_XY_Z:
 
6018
          n_coords = 3;
 
6019
          break;
 
6020
      case GAIA_XY_Z_M:
 
6021
          n_coords = 4;
 
6022
          break;
 
6023
      default:
 
6024
          n_coords = 0;
 
6025
          break;
 
6026
      }
 
6027
/* how many entities, and of what kind, do we have ? */
 
6028
    pt = geom->FirstPoint;
 
6029
    while (pt)
 
6030
      {
 
6031
          point = pt;
 
6032
          entities++;
 
6033
          n_points++;
 
6034
          pt = pt->Next;
 
6035
      }
 
6036
    ln = geom->FirstLinestring;
 
6037
    while (ln)
 
6038
      {
 
6039
          line = ln;
 
6040
          entities++;
 
6041
          n_linestrings++;
 
6042
          ln = ln->Next;
 
6043
      }
 
6044
    pg = geom->FirstPolygon;
 
6045
    while (pg)
 
6046
      {
 
6047
          polyg = pg;
 
6048
          entities++;
 
6049
          n_polygons++;
 
6050
          pg = pg->Next;
 
6051
      }
 
6052
    *size = 0;
 
6053
    sz = 0;
 
6054
    *result = NULL;
 
6055
    if (n_points == 0 && n_polygons == 0 && n_linestrings == 0)
 
6056
        return;
 
6057
/* ok, we can determine the geometry class */
 
6058
    if (n_points == 1 && n_linestrings == 0 && n_polygons == 0)
 
6059
      {
 
6060
          if (geom->DeclaredType == GAIA_MULTIPOINT)
 
6061
              type = GAIA_MULTIPOINT;
 
6062
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
6063
              type = GAIA_GEOMETRYCOLLECTION;
 
6064
          else
 
6065
              type = GAIA_POINT;
 
6066
      }
 
6067
    else if (n_points > 1 && n_linestrings == 0 && n_polygons == 0)
 
6068
      {
 
6069
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
6070
              type = GAIA_GEOMETRYCOLLECTION;
 
6071
          else
 
6072
              type = GAIA_MULTIPOINT;
 
6073
      }
 
6074
    else if (n_points == 0 && n_linestrings == 1 && n_polygons == 0)
 
6075
      {
 
6076
          if (geom->DeclaredType == GAIA_MULTILINESTRING)
 
6077
              type = GAIA_MULTILINESTRING;
 
6078
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
6079
              type = GAIA_GEOMETRYCOLLECTION;
 
6080
          else
 
6081
              type = GAIA_LINESTRING;
 
6082
      }
 
6083
    else if (n_points == 0 && n_linestrings > 1 && n_polygons == 0)
 
6084
      {
 
6085
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
6086
              type = GAIA_GEOMETRYCOLLECTION;
 
6087
          else
 
6088
              type = GAIA_MULTILINESTRING;
 
6089
      }
 
6090
    else if (n_points == 0 && n_linestrings == 0 && n_polygons == 1)
 
6091
      {
 
6092
          if (geom->DeclaredType == GAIA_MULTIPOLYGON)
 
6093
              type = GAIA_MULTIPOLYGON;
 
6094
          else if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
6095
              type = GAIA_GEOMETRYCOLLECTION;
 
6096
          else
 
6097
              type = GAIA_POLYGON;
 
6098
      }
 
6099
    else if (n_points == 0 && n_linestrings == 0 && n_polygons > 1)
 
6100
      {
 
6101
          if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
6102
              type = GAIA_GEOMETRYCOLLECTION;
 
6103
          else
 
6104
              type = GAIA_MULTIPOLYGON;
 
6105
      }
 
6106
    else
 
6107
        type = GAIA_GEOMETRYCOLLECTION;
 
6108
/* and now we compute the size of FGF */
 
6109
    if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
6110
        || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
6111
        sz += 8;
 
6112
    point = geom->FirstPoint;
 
6113
    while (point)
 
6114
      {
 
6115
          sz += (8 + (n_coords * sizeof (double)));     /* the size of each POINT */
 
6116
          point = point->Next;
 
6117
      }
 
6118
    line = geom->FirstLinestring;
 
6119
    while (line)
 
6120
      {
 
6121
          sz += (12 + ((n_coords * sizeof (double)) * line->Points));   /* # points + [x,y] for each vertex */
 
6122
          line = line->Next;
 
6123
      }
 
6124
    polyg = geom->FirstPolygon;
 
6125
    while (polyg)
 
6126
      {
 
6127
          rng = polyg->Exterior;
 
6128
          sz += (16 + ((n_coords * sizeof (double)) * rng->Points));    /* # rings + # points + [x.y] array - exterior ring */
 
6129
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
6130
            {
 
6131
                rng = polyg->Interiors + ib;
 
6132
                sz += (4 + ((n_coords * sizeof (double)) * rng->Points));       /* # points + [x,y] array - interior ring */
 
6133
            }
 
6134
          polyg = polyg->Next;
 
6135
      }
 
6136
    *size = sz;
 
6137
    ptr = malloc (sz);
 
6138
    *result = ptr;
 
6139
/* and finally we build the FGF */
 
6140
    if (type == GAIA_MULTIPOINT || type == GAIA_MULTILINESTRING
 
6141
        || type == GAIA_MULTIPOLYGON || type == GAIA_GEOMETRYCOLLECTION)
 
6142
      {
 
6143
          gaiaExport32 (ptr, type, GAIA_LITTLE_ENDIAN, endian_arch);    /* Geometry Type */
 
6144
          ptr += 4;
 
6145
          gaiaExport32 (ptr, entities, GAIA_LITTLE_ENDIAN, endian_arch);        /* it's a collection; # entities */
 
6146
          ptr += 4;
 
6147
      }
 
6148
    point = geom->FirstPoint;
 
6149
    while (point)
 
6150
      {
 
6151
          gaiaExport32 (ptr, GAIA_POINT, GAIA_LITTLE_ENDIAN, endian_arch);      /* the CLASS TYPE for this element */
 
6152
          ptr += 4;
 
6153
          gaiaExport32 (ptr, coord_dims, GAIA_LITTLE_ENDIAN, endian_arch);      /* the CoordDimension */
 
6154
          ptr += 4;
 
6155
          gaiaExport64 (ptr, point->X, GAIA_LITTLE_ENDIAN, endian_arch);        /* X */
 
6156
          ptr += 8;
 
6157
          gaiaExport64 (ptr, point->Y, GAIA_LITTLE_ENDIAN, endian_arch);        /* Y */
 
6158
          ptr += 8;
 
6159
          if (n_coords > 2)
 
6160
            {
 
6161
                /* the third coordinate [Z or M] */
 
6162
                if (coord_dims == GAIA_XY_Z || coord_dims == GAIA_XY_Z_M)
 
6163
                    gaiaExport64 (ptr, point->Z, GAIA_LITTLE_ENDIAN,
 
6164
                                  endian_arch);
 
6165
                else
 
6166
                    gaiaExport64 (ptr, point->M, GAIA_LITTLE_ENDIAN,
 
6167
                                  endian_arch);
 
6168
                ptr += 8;
 
6169
            }
 
6170
          if (n_coords > 3)
 
6171
            {
 
6172
                /* the fourth coordinate [M] */
 
6173
                gaiaExport64 (ptr, point->M, GAIA_LITTLE_ENDIAN, endian_arch);
 
6174
                ptr += 8;
 
6175
            }
 
6176
          point = point->Next;
 
6177
      }
 
6178
    line = geom->FirstLinestring;
 
6179
    while (line)
 
6180
      {
 
6181
          gaiaExport32 (ptr, GAIA_LINESTRING, GAIA_LITTLE_ENDIAN, endian_arch); /* the CLASS TYPE for this element */
 
6182
          ptr += 4;
 
6183
          gaiaExport32 (ptr, coord_dims, GAIA_LITTLE_ENDIAN, endian_arch);      /* the CoordDimension */
 
6184
          ptr += 4;
 
6185
          gaiaExport32 (ptr, line->Points, GAIA_LITTLE_ENDIAN, endian_arch);    /* # points */
 
6186
          ptr += 4;
 
6187
          for (iv = 0; iv < line->Points; iv++)
 
6188
            {
 
6189
                z = 0.0;
 
6190
                m = 0.0;
 
6191
                if (geom->DimensionModel == GAIA_XY_Z)
 
6192
                  {
 
6193
                      gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
 
6194
                  }
 
6195
                else if (geom->DimensionModel == GAIA_XY_M)
 
6196
                  {
 
6197
                      gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
 
6198
                  }
 
6199
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
6200
                  {
 
6201
                      gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
 
6202
                  }
 
6203
                else
 
6204
                  {
 
6205
                      gaiaGetPoint (line->Coords, iv, &x, &y);
 
6206
                  }
 
6207
                gaiaExport64 (ptr, x, GAIA_LITTLE_ENDIAN, endian_arch); /* X */
 
6208
                ptr += 8;
 
6209
                gaiaExport64 (ptr, y, GAIA_LITTLE_ENDIAN, endian_arch); /* Y */
 
6210
                ptr += 8;
 
6211
                if (n_coords > 2)
 
6212
                  {
 
6213
                      /* the third coordinate [Z or M] */
 
6214
                      if (coord_dims == GAIA_XY_Z || coord_dims == GAIA_XY_Z_M)
 
6215
                          gaiaExport64 (ptr, z, GAIA_LITTLE_ENDIAN,
 
6216
                                        endian_arch);
 
6217
                      else
 
6218
                          gaiaExport64 (ptr, m, GAIA_LITTLE_ENDIAN,
 
6219
                                        endian_arch);
 
6220
                      ptr += 8;
 
6221
                  }
 
6222
                if (n_coords > 3)
 
6223
                  {
 
6224
                      /* the fourth coordinate [M]; */
 
6225
                      gaiaExport64 (ptr, m, GAIA_LITTLE_ENDIAN, endian_arch);
 
6226
                      ptr += 8;
 
6227
                  }
 
6228
            }
 
6229
          line = line->Next;
 
6230
      }
 
6231
    polyg = geom->FirstPolygon;
 
6232
    while (polyg)
 
6233
      {
 
6234
          gaiaExport32 (ptr, GAIA_POLYGON, GAIA_LITTLE_ENDIAN, endian_arch);    /* the CLASS TYPE for this element */
 
6235
          ptr += 4;
 
6236
          gaiaExport32 (ptr, coord_dims, GAIA_LITTLE_ENDIAN, endian_arch);      /* the CoordDimension */
 
6237
          ptr += 4;
 
6238
          gaiaExport32 (ptr, polyg->NumInteriors + 1, GAIA_LITTLE_ENDIAN, endian_arch); /* # rings */
 
6239
          ptr += 4;
 
6240
          rng = polyg->Exterior;
 
6241
          gaiaExport32 (ptr, rng->Points, GAIA_LITTLE_ENDIAN, endian_arch);     /* # points - exterior ring */
 
6242
          ptr += 4;
 
6243
          for (iv = 0; iv < rng->Points; iv++)
 
6244
            {
 
6245
                z = 0.0;
 
6246
                m = 0.0;
 
6247
                if (geom->DimensionModel == GAIA_XY_Z)
 
6248
                  {
 
6249
                      gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
6250
                  }
 
6251
                else if (geom->DimensionModel == GAIA_XY_M)
 
6252
                  {
 
6253
                      gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
6254
                  }
 
6255
                else if (geom->DimensionModel == GAIA_XY_Z_M)
 
6256
                  {
 
6257
                      gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
6258
                  }
 
6259
                else
 
6260
                  {
 
6261
                      gaiaGetPoint (rng->Coords, iv, &x, &y);
 
6262
                  }
 
6263
                gaiaExport64 (ptr, x, GAIA_LITTLE_ENDIAN, endian_arch); /* X - exterior ring */
 
6264
                ptr += 8;
 
6265
                gaiaExport64 (ptr, y, GAIA_LITTLE_ENDIAN, endian_arch); /* Y - exterior ring */
 
6266
                ptr += 8;
 
6267
                if (n_coords > 2)
 
6268
                  {
 
6269
                      /* the third coordinate [Z or M] */
 
6270
                      if (coord_dims == GAIA_XY_Z || coord_dims == GAIA_XY_Z_M)
 
6271
                          gaiaExport64 (ptr, z, GAIA_LITTLE_ENDIAN,
 
6272
                                        endian_arch);
 
6273
                      else
 
6274
                          gaiaExport64 (ptr, m, GAIA_LITTLE_ENDIAN,
 
6275
                                        endian_arch);
 
6276
                      ptr += 8;
 
6277
                  }
 
6278
                if (n_coords > 3)
 
6279
                  {
 
6280
                      /* the fourth coordinate [M] */
 
6281
                      gaiaExport64 (ptr, m, GAIA_LITTLE_ENDIAN, endian_arch);
 
6282
                      ptr += 8;
 
6283
                  }
 
6284
            }
 
6285
          for (ib = 0; ib < polyg->NumInteriors; ib++)
 
6286
            {
 
6287
                rng = polyg->Interiors + ib;
 
6288
                gaiaExport32 (ptr, rng->Points, 1, endian_arch);        /* # points - interior ring */
 
6289
                ptr += 4;
 
6290
                for (iv = 0; iv < rng->Points; iv++)
 
6291
                  {
 
6292
                      z = 0.0;
 
6293
                      m = 0.0;
 
6294
                      if (geom->DimensionModel == GAIA_XY_Z)
 
6295
                        {
 
6296
                            gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
 
6297
                        }
 
6298
                      else if (geom->DimensionModel == GAIA_XY_M)
 
6299
                        {
 
6300
                            gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
 
6301
                        }
 
6302
                      else if (geom->DimensionModel == GAIA_XY_Z_M)
 
6303
                        {
 
6304
                            gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
 
6305
                        }
 
6306
                      else
 
6307
                        {
 
6308
                            gaiaGetPoint (rng->Coords, iv, &x, &y);
 
6309
                        }
 
6310
                      gaiaExport64 (ptr, x, GAIA_LITTLE_ENDIAN, endian_arch);   /* X - interior ring */
 
6311
                      ptr += 8;
 
6312
                      gaiaExport64 (ptr, y, GAIA_LITTLE_ENDIAN, endian_arch);   /* Y - interior ring */
 
6313
                      ptr += 8;
 
6314
                      if (n_coords > 2)
 
6315
                        {
 
6316
                            /* the third coordinate [Z or M]; defaulting to ZERO */
 
6317
                            if (coord_dims == GAIA_XY_Z
 
6318
                                || coord_dims == GAIA_XY_Z_M)
 
6319
                                gaiaExport64 (ptr, z, GAIA_LITTLE_ENDIAN,
 
6320
                                              endian_arch);
 
6321
                            else
 
6322
                                gaiaExport64 (ptr, m, GAIA_LITTLE_ENDIAN,
 
6323
                                              endian_arch);
 
6324
                            ptr += 8;
 
6325
                        }
 
6326
                      if (n_coords > 3)
 
6327
                        {
 
6328
                            /* the fourth coordinate [M] */
 
6329
                            gaiaExport64 (ptr, m, GAIA_LITTLE_ENDIAN,
 
6330
                                          endian_arch);
 
6331
                            ptr += 8;
 
6332
                        }
 
6333
                  }
 
6334
            }
 
6335
          polyg = polyg->Next;
 
6336
      }
 
6337
}