~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/plugins/grid_maker/shpopen.c

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/******************************************************************************
2
 
 * $Id: shpopen.c 1155 2004-04-05 15:39:45Z timlinux $
3
 
 *
4
 
 * Project:  Shapelib
5
 
 * Purpose:  Implementation of core Shapefile read/write functions.
6
 
 * Author:   Frank Warmerdam, warmerda@home.com
7
 
 *
8
 
 ******************************************************************************
9
 
 * Copyright (c) 1999, Frank Warmerdam
10
 
 *
11
 
 * This software is available under the following "MIT Style" license,
12
 
 * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
13
 
 * option is discussed in more detail in shapelib.html.
14
 
 *
15
 
 * --
16
 
 * 
17
 
 * Permission is hereby granted, free of charge, to any person obtaining a
18
 
 * copy of this software and associated documentation files (the "Software"),
19
 
 * to deal in the Software without restriction, including without limitation
20
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21
 
 * and/or sell copies of the Software, and to permit persons to whom the
22
 
 * Software is furnished to do so, subject to the following conditions:
23
 
 *
24
 
 * The above copyright notice and this permission notice shall be included
25
 
 * in all copies or substantial portions of the Software.
26
 
 *
27
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33
 
 * DEALINGS IN THE SOFTWARE.
34
 
 ******************************************************************************
35
 
 *
36
 
 * $Log$
37
 
 * Revision 1.1  2004/04/05 15:39:45  timlinux
38
 
 * Initial commit of new plugin to build graticules - not working yet! And thus not added to higher level makefiles yet.
39
 
 *
40
 
 * Revision 1.2  2004/03/31 20:36:46  timlinux
41
 
 * Fix for knock on effects of change of filename from shapefil.h to shapefile.h
42
 
 *
43
 
 * Revision 1.1  2004/03/22 23:38:26  timlinux
44
 
 * This is a c++ first draft of a port of a perl script by Schuyler to import Garmin gps dump files as a shapefile. The resulting imported file will be displayed in the map view. At the moment it only generates a point layer of the waypoints but a future version will generate polylines and perhaps polygons too using similar logic to that used by Shuylers perl stuff. Note this plugin is still under construction and I am commiting it mainly so that other developers can assist me when I get stuck. Also note that the plugins Makefile builds a standalone app based on the plugin gui that can be run separately from qgis.
45
 
 *
46
 
 * Revision 1.26  2000/02/16 16:03:51  warmerda
47
 
 * added null shape support
48
 
 *
49
 
 * Revision 1.25  1999/12/15 13:47:07  warmerda
50
 
 * Fixed record size settings in .shp file (was 4 words too long)
51
 
 * Added stdlib.h.
52
 
 *
53
 
 * Revision 1.24  1999/11/05 14:12:04  warmerda
54
 
 * updated license terms
55
 
 *
56
 
 * Revision 1.23  1999/07/27 00:53:46  warmerda
57
 
 * added support for rewriting shapes
58
 
 *
59
 
 * Revision 1.22  1999/06/11 19:19:11  warmerda
60
 
 * Cleanup pabyRec static buffer on SHPClose().
61
 
 *
62
 
 * Revision 1.21  1999/06/02 14:57:56  kshih
63
 
 * Remove unused variables
64
 
 *
65
 
 * Revision 1.20  1999/04/19 21:04:17  warmerda
66
 
 * Fixed syntax error.
67
 
 *
68
 
 * Revision 1.19  1999/04/19 21:01:57  warmerda
69
 
 * Force access string to binary in SHPOpen().
70
 
 *
71
 
 * Revision 1.18  1999/04/01 18:48:07  warmerda
72
 
 * Try upper case extensions if lower case doesn't work.
73
 
 *
74
 
 * Revision 1.17  1998/12/31 15:29:39  warmerda
75
 
 * Disable writing measure values to multipatch objects if
76
 
 * DISABLE_MULTIPATCH_MEASURE is defined.
77
 
 *
78
 
 * Revision 1.16  1998/12/16 05:14:33  warmerda
79
 
 * Added support to write MULTIPATCH.  Fixed reading Z coordinate of
80
 
 * MULTIPATCH. Fixed record size written for all feature types.
81
 
 *
82
 
 * Revision 1.15  1998/12/03 16:35:29  warmerda
83
 
 * r+b is proper binary access string, not rb+.
84
 
 *
85
 
 * Revision 1.14  1998/12/03 15:47:56  warmerda
86
 
 * Fixed setting of nVertices in SHPCreateObject().
87
 
 *
88
 
 * Revision 1.13  1998/12/03 15:33:54  warmerda
89
 
 * Made SHPCalculateExtents() separately callable.
90
 
 *
91
 
 * Revision 1.12  1998/11/11 20:01:50  warmerda
92
 
 * Fixed bug writing ArcM/Z, and PolygonM/Z for big endian machines.
93
 
 *
94
 
 * Revision 1.11  1998/11/09 20:56:44  warmerda
95
 
 * Fixed up handling of file wide bounds.
96
 
 *
97
 
 * Revision 1.10  1998/11/09 20:18:51  warmerda
98
 
 * Converted to support 3D shapefiles, and use of SHPObject.
99
 
 *
100
 
 * Revision 1.9  1998/02/24 15:09:05  warmerda
101
 
 * Fixed memory leak.
102
 
 *
103
 
 * Revision 1.8  1997/12/04 15:40:29  warmerda
104
 
 * Fixed byte swapping of record number, and record length fields in the
105
 
 * .shp file.
106
 
 *
107
 
 * Revision 1.7  1995/10/21 03:15:58  warmerda
108
 
 * Added support for binary file access, the magic cookie 9997
109
 
 * and tried to improve the int32 selection logic for 16bit systems.
110
 
 *
111
 
 * Revision 1.6  1995/09/04  04:19:41  warmerda
112
 
 * Added fix for file bounds.
113
 
 *
114
 
 * Revision 1.5  1995/08/25  15:16:44  warmerda
115
 
 * Fixed a couple of problems with big endian systems ... one with bounds
116
 
 * and the other with multipart polygons.
117
 
 *
118
 
 * Revision 1.4  1995/08/24  18:10:17  warmerda
119
 
 * Switch to use SfRealloc() to avoid problems with pre-ANSI realloc()
120
 
 * functions (such as on the Sun).
121
 
 *
122
 
 * Revision 1.3  1995/08/23  02:23:15  warmerda
123
 
 * Added support for reading bounds, and fixed up problems in setting the
124
 
 * file wide bounds.
125
 
 *
126
 
 * Revision 1.2  1995/08/04  03:16:57  warmerda
127
 
 * Added header.
128
 
 *
129
 
 */
130
 
 
131
 
static char rcsid[] = 
132
 
  "$Id: shpopen.c 1155 2004-04-05 15:39:45Z timlinux $";
133
 
 
134
 
#include "shapefile.h"
135
 
 
136
 
#include <math.h>
137
 
#include <limits.h>
138
 
#include <assert.h>
139
 
#include <stdlib.h>
140
 
 
141
 
typedef unsigned char uchar;
142
 
 
143
 
#if UINT_MAX == 65535
144
 
typedef long          int32;
145
 
#else
146
 
typedef int           int32;
147
 
#endif
148
 
 
149
 
#ifndef FALSE
150
 
#  define FALSE         0
151
 
#  define TRUE          1
152
 
#endif
153
 
 
154
 
#define ByteCopy( a, b, c )     memcpy( b, a, c )
155
 
#ifndef MAX
156
 
#  define MIN(a,b)      ((a<b) ? a : b)
157
 
#  define MAX(a,b)      ((a>b) ? a : b)
158
 
#endif
159
 
 
160
 
static int      bBigEndian;
161
 
static uchar    *pabyRec = NULL;
162
 
static int      nBufSize = 0;
163
 
 
164
 
 
165
 
/************************************************************************/
166
 
/*                              SwapWord()                              */
167
 
/*                                                                      */
168
 
/*      Swap a 2, 4 or 8 byte word.                                     */
169
 
/************************************************************************/
170
 
 
171
 
static void     SwapWord( int length, void * wordP )
172
 
 
173
 
{
174
 
    int         i;
175
 
    uchar       temp;
176
 
 
177
 
    for( i=0; i < length/2; i++ )
178
 
    {
179
 
        temp = ((uchar *) wordP)[i];
180
 
        ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
181
 
        ((uchar *) wordP)[length-i-1] = temp;
182
 
    }
183
 
}
184
 
 
185
 
/************************************************************************/
186
 
/*                             SfRealloc()                              */
187
 
/*                                                                      */
188
 
/*      A realloc cover function that will access a NULL pointer as     */
189
 
/*      a valid input.                                                  */
190
 
/************************************************************************/
191
 
 
192
 
static void * SfRealloc( void * pMem, int nNewSize )
193
 
 
194
 
{
195
 
    if( pMem == NULL )
196
 
        return( (void *) malloc(nNewSize) );
197
 
    else
198
 
        return( (void *) realloc(pMem,nNewSize) );
199
 
}
200
 
 
201
 
/************************************************************************/
202
 
/*                          SHPWriteHeader()                            */
203
 
/*                                                                      */
204
 
/*      Write out a header for the .shp and .shx files as well as the   */
205
 
/*      contents of the index (.shx) file.                              */
206
 
/************************************************************************/
207
 
 
208
 
static void SHPWriteHeader( SHPHandle psSHP )
209
 
 
210
 
{
211
 
    uchar       abyHeader[100];
212
 
    int         i;
213
 
    int32       i32;
214
 
    double      dValue;
215
 
    int32       *panSHX;
216
 
 
217
 
/* -------------------------------------------------------------------- */
218
 
/*      Prepare header block for .shp file.                             */
219
 
/* -------------------------------------------------------------------- */
220
 
    for( i = 0; i < 100; i++ )
221
 
      abyHeader[i] = 0;
222
 
 
223
 
    abyHeader[2] = 0x27;                                /* magic cookie */
224
 
    abyHeader[3] = 0x0a;
225
 
 
226
 
    i32 = psSHP->nFileSize/2;                           /* file size */
227
 
    ByteCopy( &i32, abyHeader+24, 4 );
228
 
    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
229
 
    
230
 
    i32 = 1000;                                         /* version */
231
 
    ByteCopy( &i32, abyHeader+28, 4 );
232
 
    if( bBigEndian ) SwapWord( 4, abyHeader+28 );
233
 
    
234
 
    i32 = psSHP->nShapeType;                            /* shape type */
235
 
    ByteCopy( &i32, abyHeader+32, 4 );
236
 
    if( bBigEndian ) SwapWord( 4, abyHeader+32 );
237
 
 
238
 
    dValue = psSHP->adBoundsMin[0];                     /* set bounds */
239
 
    ByteCopy( &dValue, abyHeader+36, 8 );
240
 
    if( bBigEndian ) SwapWord( 8, abyHeader+36 );
241
 
 
242
 
    dValue = psSHP->adBoundsMin[1];
243
 
    ByteCopy( &dValue, abyHeader+44, 8 );
244
 
    if( bBigEndian ) SwapWord( 8, abyHeader+44 );
245
 
 
246
 
    dValue = psSHP->adBoundsMax[0];
247
 
    ByteCopy( &dValue, abyHeader+52, 8 );
248
 
    if( bBigEndian ) SwapWord( 8, abyHeader+52 );
249
 
 
250
 
    dValue = psSHP->adBoundsMax[1];
251
 
    ByteCopy( &dValue, abyHeader+60, 8 );
252
 
    if( bBigEndian ) SwapWord( 8, abyHeader+60 );
253
 
 
254
 
    dValue = psSHP->adBoundsMin[2];                     /* z */
255
 
    ByteCopy( &dValue, abyHeader+68, 8 );
256
 
    if( bBigEndian ) SwapWord( 8, abyHeader+68 );
257
 
 
258
 
    dValue = psSHP->adBoundsMax[2];
259
 
    ByteCopy( &dValue, abyHeader+76, 8 );
260
 
    if( bBigEndian ) SwapWord( 8, abyHeader+76 );
261
 
 
262
 
    dValue = psSHP->adBoundsMin[3];                     /* m */
263
 
    ByteCopy( &dValue, abyHeader+84, 8 );
264
 
    if( bBigEndian ) SwapWord( 8, abyHeader+84 );
265
 
 
266
 
    dValue = psSHP->adBoundsMax[3];
267
 
    ByteCopy( &dValue, abyHeader+92, 8 );
268
 
    if( bBigEndian ) SwapWord( 8, abyHeader+92 );
269
 
 
270
 
/* -------------------------------------------------------------------- */
271
 
/*      Write .shp file header.                                         */
272
 
/* -------------------------------------------------------------------- */
273
 
    fseek( psSHP->fpSHP, 0, 0 );
274
 
    fwrite( abyHeader, 100, 1, psSHP->fpSHP );
275
 
 
276
 
/* -------------------------------------------------------------------- */
277
 
/*      Prepare, and write .shx file header.                            */
278
 
/* -------------------------------------------------------------------- */
279
 
    i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2;   /* file size */
280
 
    ByteCopy( &i32, abyHeader+24, 4 );
281
 
    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
282
 
    
283
 
    fseek( psSHP->fpSHX, 0, 0 );
284
 
    fwrite( abyHeader, 100, 1, psSHP->fpSHX );
285
 
 
286
 
/* -------------------------------------------------------------------- */
287
 
/*      Write out the .shx contents.                                    */
288
 
/* -------------------------------------------------------------------- */
289
 
    panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
290
 
 
291
 
    for( i = 0; i < psSHP->nRecords; i++ )
292
 
    {
293
 
        panSHX[i*2  ] = psSHP->panRecOffset[i]/2;
294
 
        panSHX[i*2+1] = psSHP->panRecSize[i]/2;
295
 
        if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
296
 
        if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
297
 
    }
298
 
 
299
 
    fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX );
300
 
 
301
 
    free( panSHX );
302
 
}
303
 
 
304
 
/************************************************************************/
305
 
/*                              SHPOpen()                               */
306
 
/*                                                                      */
307
 
/*      Open the .shp and .shx files based on the basename of the       */
308
 
/*      files or either file name.                                      */
309
 
/************************************************************************/
310
 
   
311
 
SHPHandle SHPOpen( const char * pszLayer, const char * pszAccess )
312
 
 
313
 
{
314
 
    char                *pszFullname, *pszBasename;
315
 
    SHPHandle           psSHP;
316
 
    
317
 
    uchar               *pabyBuf;
318
 
    int                 i;
319
 
    double              dValue;
320
 
    
321
 
/* -------------------------------------------------------------------- */
322
 
/*      Ensure the access string is one of the legal ones.  We          */
323
 
/*      ensure the result string indicates binary to avoid common       */
324
 
/*      problems on Windows.                                            */
325
 
/* -------------------------------------------------------------------- */
326
 
    if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
327
 
        || strcmp(pszAccess,"r+") == 0 )
328
 
        pszAccess = "r+b";
329
 
    else
330
 
        pszAccess = "rb";
331
 
    
332
 
/* -------------------------------------------------------------------- */
333
 
/*      Establish the byte order on this machine.                       */
334
 
/* -------------------------------------------------------------------- */
335
 
    i = 1;
336
 
    if( *((uchar *) &i) == 1 )
337
 
        bBigEndian = FALSE;
338
 
    else
339
 
        bBigEndian = TRUE;
340
 
 
341
 
/* -------------------------------------------------------------------- */
342
 
/*      Initialize the info structure.                                  */
343
 
/* -------------------------------------------------------------------- */
344
 
    psSHP = (SHPHandle) malloc(sizeof(SHPInfo));
345
 
 
346
 
    psSHP->bUpdated = FALSE;
347
 
 
348
 
/* -------------------------------------------------------------------- */
349
 
/*      Compute the base (layer) name.  If there is any extension       */
350
 
/*      on the passed in filename we will strip it off.                 */
351
 
/* -------------------------------------------------------------------- */
352
 
    pszBasename = (char *) malloc(strlen(pszLayer)+5);
353
 
    strcpy( pszBasename, pszLayer );
354
 
    for( i = strlen(pszBasename)-1; 
355
 
         i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
356
 
               && pszBasename[i] != '\\';
357
 
         i-- ) {}
358
 
 
359
 
    if( pszBasename[i] == '.' )
360
 
        pszBasename[i] = '\0';
361
 
 
362
 
/* -------------------------------------------------------------------- */
363
 
/*      Open the .shp and .shx files.  Note that files pulled from      */
364
 
/*      a PC to Unix with upper case filenames won't work!              */
365
 
/* -------------------------------------------------------------------- */
366
 
    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
367
 
    sprintf( pszFullname, "%s.shp", pszBasename );
368
 
    psSHP->fpSHP = fopen(pszFullname, pszAccess );
369
 
    if( psSHP->fpSHP == NULL )
370
 
    {
371
 
        sprintf( pszFullname, "%s.SHP", pszBasename );
372
 
        psSHP->fpSHP = fopen(pszFullname, pszAccess );
373
 
    }
374
 
    
375
 
    if( psSHP->fpSHP == NULL )
376
 
        return( NULL );
377
 
 
378
 
    sprintf( pszFullname, "%s.shx", pszBasename );
379
 
    psSHP->fpSHX = fopen(pszFullname, pszAccess );
380
 
    if( psSHP->fpSHX == NULL )
381
 
    {
382
 
        sprintf( pszFullname, "%s.SHX", pszBasename );
383
 
        psSHP->fpSHX = fopen(pszFullname, pszAccess );
384
 
    }
385
 
    
386
 
    if( psSHP->fpSHX == NULL )
387
 
        return( NULL );
388
 
 
389
 
    free( pszFullname );
390
 
    free( pszBasename );
391
 
 
392
 
/* -------------------------------------------------------------------- */
393
 
/*  Read the file size from the SHP file.                               */
394
 
/* -------------------------------------------------------------------- */
395
 
    pabyBuf = (uchar *) malloc(100);
396
 
    fread( pabyBuf, 100, 1, psSHP->fpSHP );
397
 
 
398
 
    psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
399
 
                        + pabyBuf[25] * 256 * 256
400
 
                        + pabyBuf[26] * 256
401
 
                        + pabyBuf[27]) * 2;
402
 
 
403
 
/* -------------------------------------------------------------------- */
404
 
/*  Read SHX file Header info                                           */
405
 
/* -------------------------------------------------------------------- */
406
 
    fread( pabyBuf, 100, 1, psSHP->fpSHX );
407
 
 
408
 
    if( pabyBuf[0] != 0 
409
 
        || pabyBuf[1] != 0 
410
 
        || pabyBuf[2] != 0x27 
411
 
        || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
412
 
    {
413
 
        fclose( psSHP->fpSHP );
414
 
        fclose( psSHP->fpSHX );
415
 
        free( psSHP );
416
 
 
417
 
        return( NULL );
418
 
    }
419
 
 
420
 
    psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
421
 
      + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
422
 
    psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
423
 
 
424
 
    psSHP->nShapeType = pabyBuf[32];
425
 
 
426
 
/* -------------------------------------------------------------------- */
427
 
/*      Read the bounds.                                                */
428
 
/* -------------------------------------------------------------------- */
429
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
430
 
    memcpy( &dValue, pabyBuf+36, 8 );
431
 
    psSHP->adBoundsMin[0] = dValue;
432
 
 
433
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
434
 
    memcpy( &dValue, pabyBuf+44, 8 );
435
 
    psSHP->adBoundsMin[1] = dValue;
436
 
 
437
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
438
 
    memcpy( &dValue, pabyBuf+52, 8 );
439
 
    psSHP->adBoundsMax[0] = dValue;
440
 
 
441
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
442
 
    memcpy( &dValue, pabyBuf+60, 8 );
443
 
    psSHP->adBoundsMax[1] = dValue;
444
 
 
445
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+68 );         /* z */
446
 
    memcpy( &dValue, pabyBuf+68, 8 );
447
 
    psSHP->adBoundsMin[2] = dValue;
448
 
    
449
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
450
 
    memcpy( &dValue, pabyBuf+76, 8 );
451
 
    psSHP->adBoundsMax[2] = dValue;
452
 
    
453
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+84 );         /* z */
454
 
    memcpy( &dValue, pabyBuf+84, 8 );
455
 
    psSHP->adBoundsMin[3] = dValue;
456
 
 
457
 
    if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
458
 
    memcpy( &dValue, pabyBuf+92, 8 );
459
 
    psSHP->adBoundsMax[3] = dValue;
460
 
 
461
 
    free( pabyBuf );
462
 
 
463
 
/* -------------------------------------------------------------------- */
464
 
/*      Read the .shx file to get the offsets to each record in         */
465
 
/*      the .shp file.                                                  */
466
 
/* -------------------------------------------------------------------- */
467
 
    psSHP->nMaxRecords = psSHP->nRecords;
468
 
 
469
 
    psSHP->panRecOffset =
470
 
        (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
471
 
    psSHP->panRecSize =
472
 
        (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
473
 
 
474
 
    pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
475
 
    fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX );
476
 
 
477
 
    for( i = 0; i < psSHP->nRecords; i++ )
478
 
    {
479
 
        int32           nOffset, nLength;
480
 
 
481
 
        memcpy( &nOffset, pabyBuf + i * 8, 4 );
482
 
        if( !bBigEndian ) SwapWord( 4, &nOffset );
483
 
 
484
 
        memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
485
 
        if( !bBigEndian ) SwapWord( 4, &nLength );
486
 
 
487
 
        psSHP->panRecOffset[i] = nOffset*2;
488
 
        psSHP->panRecSize[i] = nLength*2;
489
 
    }
490
 
    free( pabyBuf );
491
 
 
492
 
    return( psSHP );
493
 
}
494
 
 
495
 
/************************************************************************/
496
 
/*                              SHPClose()                              */
497
 
/*                                                                      */
498
 
/*      Close the .shp and .shx files.                                  */
499
 
/************************************************************************/
500
 
 
501
 
void    SHPClose(SHPHandle psSHP )
502
 
 
503
 
{
504
 
/* -------------------------------------------------------------------- */
505
 
/*      Update the header if we have modified anything.                 */
506
 
/* -------------------------------------------------------------------- */
507
 
    if( psSHP->bUpdated )
508
 
    {
509
 
        SHPWriteHeader( psSHP );
510
 
    }
511
 
 
512
 
/* -------------------------------------------------------------------- */
513
 
/*      Free all resources, and close files.                            */
514
 
/* -------------------------------------------------------------------- */
515
 
    free( psSHP->panRecOffset );
516
 
    free( psSHP->panRecSize );
517
 
 
518
 
    fclose( psSHP->fpSHX );
519
 
    fclose( psSHP->fpSHP );
520
 
 
521
 
    free( psSHP );
522
 
 
523
 
    if( pabyRec != NULL )
524
 
    {
525
 
        free( pabyRec );
526
 
        pabyRec = NULL;
527
 
        nBufSize = 0;
528
 
    }
529
 
}
530
 
 
531
 
/************************************************************************/
532
 
/*                             SHPGetInfo()                             */
533
 
/*                                                                      */
534
 
/*      Fetch general information about the shape file.                 */
535
 
/************************************************************************/
536
 
 
537
 
void SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
538
 
                double * padfMinBound, double * padfMaxBound )
539
 
 
540
 
{
541
 
    int         i;
542
 
    
543
 
    if( pnEntities != NULL )
544
 
        *pnEntities = psSHP->nRecords;
545
 
 
546
 
    if( pnShapeType != NULL )
547
 
        *pnShapeType = psSHP->nShapeType;
548
 
 
549
 
    for( i = 0; i < 4; i++ )
550
 
    {
551
 
        if( padfMinBound != NULL )
552
 
            padfMinBound[i] = psSHP->adBoundsMin[i];
553
 
        if( padfMaxBound != NULL )
554
 
            padfMaxBound[i] = psSHP->adBoundsMax[i];
555
 
    }
556
 
}
557
 
 
558
 
/************************************************************************/
559
 
/*                             SHPCreate()                              */
560
 
/*                                                                      */
561
 
/*      Create a new shape file and return a handle to the open         */
562
 
/*      shape file with read/write access.                              */
563
 
/************************************************************************/
564
 
 
565
 
SHPHandle SHPCreate( const char * pszLayer, int nShapeType )
566
 
 
567
 
{
568
 
    char        *pszBasename, *pszFullname;
569
 
    int         i;
570
 
    FILE        *fpSHP, *fpSHX;
571
 
    uchar       abyHeader[100];
572
 
    int32       i32;
573
 
    double      dValue;
574
 
    
575
 
/* -------------------------------------------------------------------- */
576
 
/*      Establish the byte order on this system.                        */
577
 
/* -------------------------------------------------------------------- */
578
 
    i = 1;
579
 
    if( *((uchar *) &i) == 1 )
580
 
        bBigEndian = FALSE;
581
 
    else
582
 
        bBigEndian = TRUE;
583
 
 
584
 
/* -------------------------------------------------------------------- */
585
 
/*      Compute the base (layer) name.  If there is any extension       */
586
 
/*      on the passed in filename we will strip it off.                 */
587
 
/* -------------------------------------------------------------------- */
588
 
    pszBasename = (char *) malloc(strlen(pszLayer)+5);
589
 
    strcpy( pszBasename, pszLayer );
590
 
    for( i = strlen(pszBasename)-1; 
591
 
         i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
592
 
               && pszBasename[i] != '\\';
593
 
         i-- ) {}
594
 
 
595
 
    if( pszBasename[i] == '.' )
596
 
        pszBasename[i] = '\0';
597
 
 
598
 
/* -------------------------------------------------------------------- */
599
 
/*      Open the two files so we can write their headers.               */
600
 
/* -------------------------------------------------------------------- */
601
 
    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
602
 
    sprintf( pszFullname, "%s.shp", pszBasename );
603
 
    fpSHP = fopen(pszFullname, "wb" );
604
 
    if( fpSHP == NULL )
605
 
        return( NULL );
606
 
 
607
 
    sprintf( pszFullname, "%s.shx", pszBasename );
608
 
    fpSHX = fopen(pszFullname, "wb" );
609
 
    if( fpSHX == NULL )
610
 
        return( NULL );
611
 
 
612
 
    free( pszFullname );
613
 
    free( pszBasename );
614
 
 
615
 
/* -------------------------------------------------------------------- */
616
 
/*      Prepare header block for .shp file.                             */
617
 
/* -------------------------------------------------------------------- */
618
 
    for( i = 0; i < 100; i++ )
619
 
      abyHeader[i] = 0;
620
 
 
621
 
    abyHeader[2] = 0x27;                                /* magic cookie */
622
 
    abyHeader[3] = 0x0a;
623
 
 
624
 
    i32 = 50;                                           /* file size */
625
 
    ByteCopy( &i32, abyHeader+24, 4 );
626
 
    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
627
 
    
628
 
    i32 = 1000;                                         /* version */
629
 
    ByteCopy( &i32, abyHeader+28, 4 );
630
 
    if( bBigEndian ) SwapWord( 4, abyHeader+28 );
631
 
    
632
 
    i32 = nShapeType;                                   /* shape type */
633
 
    ByteCopy( &i32, abyHeader+32, 4 );
634
 
    if( bBigEndian ) SwapWord( 4, abyHeader+32 );
635
 
 
636
 
    dValue = 0.0;                                       /* set bounds */
637
 
    ByteCopy( &dValue, abyHeader+36, 8 );
638
 
    ByteCopy( &dValue, abyHeader+44, 8 );
639
 
    ByteCopy( &dValue, abyHeader+52, 8 );
640
 
    ByteCopy( &dValue, abyHeader+60, 8 );
641
 
 
642
 
/* -------------------------------------------------------------------- */
643
 
/*      Write .shp file header.                                         */
644
 
/* -------------------------------------------------------------------- */
645
 
    fwrite( abyHeader, 100, 1, fpSHP );
646
 
 
647
 
/* -------------------------------------------------------------------- */
648
 
/*      Prepare, and write .shx file header.                            */
649
 
/* -------------------------------------------------------------------- */
650
 
    i32 = 50;                                           /* file size */
651
 
    ByteCopy( &i32, abyHeader+24, 4 );
652
 
    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
653
 
    
654
 
    fwrite( abyHeader, 100, 1, fpSHX );
655
 
 
656
 
/* -------------------------------------------------------------------- */
657
 
/*      Close the files, and then open them as regular existing files.  */
658
 
/* -------------------------------------------------------------------- */
659
 
    fclose( fpSHP );
660
 
    fclose( fpSHX );
661
 
 
662
 
    return( SHPOpen( pszLayer, "r+b" ) );
663
 
}
664
 
 
665
 
/************************************************************************/
666
 
/*                           _SHPSetBounds()                            */
667
 
/*                                                                      */
668
 
/*      Compute a bounds rectangle for a shape, and set it into the     */
669
 
/*      indicated location in the record.                               */
670
 
/************************************************************************/
671
 
 
672
 
static void     _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
673
 
 
674
 
{
675
 
    ByteCopy( &(psShape->dfXMin), pabyRec +  0, 8 );
676
 
    ByteCopy( &(psShape->dfYMin), pabyRec +  8, 8 );
677
 
    ByteCopy( &(psShape->dfXMax), pabyRec + 16, 8 );
678
 
    ByteCopy( &(psShape->dfYMax), pabyRec + 24, 8 );
679
 
 
680
 
    if( bBigEndian )
681
 
    {
682
 
        SwapWord( 8, pabyRec + 0 );
683
 
        SwapWord( 8, pabyRec + 8 );
684
 
        SwapWord( 8, pabyRec + 16 );
685
 
        SwapWord( 8, pabyRec + 24 );
686
 
    }
687
 
}
688
 
 
689
 
/************************************************************************/
690
 
/*                         SHPComputeExtents()                          */
691
 
/*                                                                      */
692
 
/*      Recompute the extents of a shape.  Automatically done by        */
693
 
/*      SHPCreateObject().                                              */
694
 
/************************************************************************/
695
 
 
696
 
void SHPComputeExtents( SHPObject * psObject )
697
 
 
698
 
{
699
 
    int         i;
700
 
    
701
 
/* -------------------------------------------------------------------- */
702
 
/*      Build extents for this object.                                  */
703
 
/* -------------------------------------------------------------------- */
704
 
    if( psObject->nVertices > 0 )
705
 
    {
706
 
        psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
707
 
        psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
708
 
        psObject->dfZMin = psObject->dfZMax = psObject->padfZ[0];
709
 
        psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
710
 
    }
711
 
    
712
 
    for( i = 0; i < psObject->nVertices; i++ )
713
 
    {
714
 
        psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
715
 
        psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
716
 
        psObject->dfZMin = MIN(psObject->dfZMin, psObject->padfZ[i]);
717
 
        psObject->dfMMin = MIN(psObject->dfMMin, psObject->padfM[i]);
718
 
 
719
 
        psObject->dfXMax = MAX(psObject->dfXMax, psObject->padfX[i]);
720
 
        psObject->dfYMax = MAX(psObject->dfYMax, psObject->padfY[i]);
721
 
        psObject->dfZMax = MAX(psObject->dfZMax, psObject->padfZ[i]);
722
 
        psObject->dfMMax = MAX(psObject->dfMMax, psObject->padfM[i]);
723
 
    }
724
 
}
725
 
 
726
 
/************************************************************************/
727
 
/*                          SHPCreateObject()                           */
728
 
/*                                                                      */
729
 
/*      Create a shape object.  It should be freed with                 */
730
 
/*      SHPDestroyObject().                                             */
731
 
/************************************************************************/
732
 
 
733
 
SHPObject *SHPCreateObject( int nSHPType, int nShapeId, int nParts,
734
 
                            int * panPartStart, int * panPartType,
735
 
                            int nVertices, double * padfX, double * padfY,
736
 
                            double * padfZ, double * padfM )
737
 
 
738
 
{
739
 
    SHPObject   *psObject;
740
 
    int         i, bHasM, bHasZ;
741
 
 
742
 
    psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
743
 
    psObject->nSHPType = nSHPType;
744
 
    psObject->nShapeId = nShapeId;
745
 
 
746
 
/* -------------------------------------------------------------------- */
747
 
/*      Establish whether this shape type has M, and Z values.          */
748
 
/* -------------------------------------------------------------------- */
749
 
    if( nSHPType == SHPT_ARCM
750
 
        || nSHPType == SHPT_POINTM
751
 
        || nSHPType == SHPT_POLYGONM
752
 
        || nSHPType == SHPT_MULTIPOINTM )
753
 
    {
754
 
        bHasM = TRUE;
755
 
        bHasZ = FALSE;
756
 
    }
757
 
    else if( nSHPType == SHPT_ARCZ
758
 
             || nSHPType == SHPT_POINTZ
759
 
             || nSHPType == SHPT_POLYGONZ
760
 
             || nSHPType == SHPT_MULTIPOINTZ
761
 
             || nSHPType == SHPT_MULTIPATCH )
762
 
    {
763
 
        bHasM = TRUE;
764
 
        bHasZ = TRUE;
765
 
    }
766
 
    else
767
 
    {
768
 
        bHasM = FALSE;
769
 
        bHasZ = FALSE;
770
 
    }
771
 
 
772
 
/* -------------------------------------------------------------------- */
773
 
/*      Capture parts.  Note that part type is optional, and            */
774
 
/*      defaults to ring.                                               */
775
 
/* -------------------------------------------------------------------- */
776
 
    if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
777
 
        || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
778
 
        || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
779
 
        || nSHPType == SHPT_MULTIPATCH )
780
 
    {
781
 
        psObject->nParts = MAX(1,nParts);
782
 
 
783
 
        psObject->panPartStart = (int *)
784
 
            malloc(sizeof(int) * psObject->nParts);
785
 
        psObject->panPartType = (int *)
786
 
            malloc(sizeof(int) * psObject->nParts);
787
 
 
788
 
        psObject->panPartStart[0] = 0;
789
 
        psObject->panPartType[0] = SHPP_RING;
790
 
        
791
 
        for( i = 0; i < nParts; i++ )
792
 
        {
793
 
            psObject->panPartStart[i] = panPartStart[i];
794
 
            if( panPartType != NULL )
795
 
                psObject->panPartType[i] = panPartType[i];
796
 
            else
797
 
                psObject->panPartType[i] = SHPP_RING;
798
 
        }
799
 
    }
800
 
 
801
 
/* -------------------------------------------------------------------- */
802
 
/*      Capture vertices.  Note that Z and M are optional, but X and    */
803
 
/*      Y are not.                                                      */
804
 
/* -------------------------------------------------------------------- */
805
 
    psObject->padfX = (double *) calloc(sizeof(double),nVertices);
806
 
    psObject->padfY = (double *) calloc(sizeof(double),nVertices);
807
 
    psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
808
 
    psObject->padfM = (double *) calloc(sizeof(double),nVertices);
809
 
 
810
 
    assert( padfX != NULL );
811
 
    assert( padfY != NULL );
812
 
    
813
 
    for( i = 0; i < nVertices; i++ )
814
 
    {
815
 
        psObject->padfX[i] = padfX[i];
816
 
        psObject->padfY[i] = padfY[i];
817
 
        if( padfZ != NULL && bHasZ )
818
 
            psObject->padfZ[i] = padfZ[i];
819
 
        if( padfM != NULL && bHasM )
820
 
            psObject->padfM[i] = padfM[i];
821
 
    }
822
 
 
823
 
/* -------------------------------------------------------------------- */
824
 
/*      Compute the extents.                                            */
825
 
/* -------------------------------------------------------------------- */
826
 
    psObject->nVertices = nVertices;
827
 
    
828
 
    SHPComputeExtents( psObject );
829
 
 
830
 
    return( psObject );
831
 
}
832
 
 
833
 
/************************************************************************/
834
 
/*                       SHPCreateSimpleObject()                        */
835
 
/*                                                                      */
836
 
/*      Create a simple (common) shape object.  Destroy with            */
837
 
/*      SHPDestroyObject().                                             */
838
 
/************************************************************************/
839
 
 
840
 
SHPObject *SHPCreateSimpleObject( int nSHPType, int nVertices,
841
 
                                  double * padfX, double * padfY,
842
 
                                  double * padfZ )
843
 
 
844
 
{
845
 
    return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
846
 
                             nVertices, padfX, padfY, padfZ, NULL ) );
847
 
}
848
 
                                  
849
 
/************************************************************************/
850
 
/*                           SHPWriteObject()                           */
851
 
/*                                                                      */
852
 
/*      Write out the vertices of a new structure.  Note that it is     */
853
 
/*      only possible to write vertices at the end of the file.         */
854
 
/************************************************************************/
855
 
 
856
 
int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
857
 
                      
858
 
{
859
 
    int         nRecordOffset, i, nRecordSize;
860
 
    uchar       *pabyRec;
861
 
    int32       i32;
862
 
 
863
 
    psSHP->bUpdated = TRUE;
864
 
 
865
 
/* -------------------------------------------------------------------- */
866
 
/*      Ensure that shape object matches the type of the file it is     */
867
 
/*      being written to.                                               */
868
 
/* -------------------------------------------------------------------- */
869
 
    assert( psObject->nSHPType == psSHP->nShapeType );
870
 
 
871
 
/* -------------------------------------------------------------------- */
872
 
/*      Add the new entity to the in memory index.                      */
873
 
/* -------------------------------------------------------------------- */
874
 
    if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
875
 
    {
876
 
        psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
877
 
 
878
 
        psSHP->panRecOffset = (int *) 
879
 
          SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
880
 
        psSHP->panRecSize = (int *) 
881
 
          SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
882
 
    }
883
 
 
884
 
/* -------------------------------------------------------------------- */
885
 
/*      Initialize record.                                              */
886
 
/* -------------------------------------------------------------------- */
887
 
    pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double) 
888
 
                               + psObject->nParts * 8 + 128);
889
 
    
890
 
/* -------------------------------------------------------------------- */
891
 
/*  Extract vertices for a Polygon or Arc.                              */
892
 
/* -------------------------------------------------------------------- */
893
 
    if( psSHP->nShapeType == SHPT_POLYGON
894
 
        || psSHP->nShapeType == SHPT_POLYGONZ
895
 
        || psSHP->nShapeType == SHPT_POLYGONM
896
 
        || psSHP->nShapeType == SHPT_ARC 
897
 
        || psSHP->nShapeType == SHPT_ARCZ
898
 
        || psSHP->nShapeType == SHPT_ARCM
899
 
        || psSHP->nShapeType == SHPT_MULTIPATCH )
900
 
    {
901
 
        int32           nPoints, nParts;
902
 
        int             i;
903
 
 
904
 
        nPoints = psObject->nVertices;
905
 
        nParts = psObject->nParts;
906
 
 
907
 
        _SHPSetBounds( pabyRec + 12, psObject );
908
 
 
909
 
        if( bBigEndian ) SwapWord( 4, &nPoints );
910
 
        if( bBigEndian ) SwapWord( 4, &nParts );
911
 
 
912
 
        ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
913
 
        ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
914
 
 
915
 
        nRecordSize = 52;
916
 
 
917
 
        /*
918
 
         * Write part start positions.
919
 
         */
920
 
        ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
921
 
                  4 * psObject->nParts );
922
 
        for( i = 0; i < psObject->nParts; i++ )
923
 
        {
924
 
            if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
925
 
            nRecordSize += 4;
926
 
        }
927
 
 
928
 
        /*
929
 
         * Write multipatch part types if needed.
930
 
         */
931
 
        if( psSHP->nShapeType == SHPT_MULTIPATCH )
932
 
        {
933
 
            memcpy( pabyRec + nRecordSize, psObject->panPartType,
934
 
                    4*psObject->nParts );
935
 
            for( i = 0; i < psObject->nParts; i++ )
936
 
            {
937
 
                if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
938
 
                nRecordSize += 4;
939
 
            }
940
 
        }
941
 
 
942
 
        /*
943
 
         * Write the (x,y) vertex values.
944
 
         */
945
 
        for( i = 0; i < psObject->nVertices; i++ )
946
 
        {
947
 
            ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
948
 
            ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
949
 
 
950
 
            if( bBigEndian )
951
 
                SwapWord( 8, pabyRec + nRecordSize );
952
 
            
953
 
            if( bBigEndian )
954
 
                SwapWord( 8, pabyRec + nRecordSize + 8 );
955
 
 
956
 
            nRecordSize += 2 * 8;
957
 
        }
958
 
 
959
 
        /*
960
 
         * Write the Z coordinates (if any).
961
 
         */
962
 
        if( psSHP->nShapeType == SHPT_POLYGONZ
963
 
            || psSHP->nShapeType == SHPT_ARCZ
964
 
            || psSHP->nShapeType == SHPT_MULTIPATCH )
965
 
        {
966
 
            ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
967
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
968
 
            nRecordSize += 8;
969
 
            
970
 
            ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
971
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
972
 
            nRecordSize += 8;
973
 
 
974
 
            for( i = 0; i < psObject->nVertices; i++ )
975
 
            {
976
 
                ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
977
 
                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
978
 
                nRecordSize += 8;
979
 
            }
980
 
        }
981
 
 
982
 
        /*
983
 
         * Write the M values, if any.
984
 
         */
985
 
        if( psSHP->nShapeType == SHPT_POLYGONM
986
 
            || psSHP->nShapeType == SHPT_ARCM
987
 
#ifndef DISABLE_MULTIPATCH_MEASURE            
988
 
            || psSHP->nShapeType == SHPT_MULTIPATCH
989
 
#endif            
990
 
            || psSHP->nShapeType == SHPT_POLYGONZ
991
 
            || psSHP->nShapeType == SHPT_ARCZ )
992
 
        {
993
 
            ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
994
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
995
 
            nRecordSize += 8;
996
 
            
997
 
            ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
998
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
999
 
            nRecordSize += 8;
1000
 
 
1001
 
            for( i = 0; i < psObject->nVertices; i++ )
1002
 
            {
1003
 
                ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
1004
 
                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1005
 
                nRecordSize += 8;
1006
 
            }
1007
 
        }
1008
 
    }
1009
 
 
1010
 
/* -------------------------------------------------------------------- */
1011
 
/*  Extract vertices for a MultiPoint.                                  */
1012
 
/* -------------------------------------------------------------------- */
1013
 
    else if( psSHP->nShapeType == SHPT_MULTIPOINT
1014
 
             || psSHP->nShapeType == SHPT_MULTIPOINTZ
1015
 
             || psSHP->nShapeType == SHPT_MULTIPOINTM )
1016
 
    {
1017
 
        int32           nPoints;
1018
 
        int             i;
1019
 
 
1020
 
        nPoints = psObject->nVertices;
1021
 
 
1022
 
        _SHPSetBounds( pabyRec + 12, psObject );
1023
 
 
1024
 
        if( bBigEndian ) SwapWord( 4, &nPoints );
1025
 
        ByteCopy( &nPoints, pabyRec + 44, 4 );
1026
 
        
1027
 
        for( i = 0; i < psObject->nVertices; i++ )
1028
 
        {
1029
 
            ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
1030
 
            ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
1031
 
 
1032
 
            if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
1033
 
            if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
1034
 
        }
1035
 
 
1036
 
        nRecordSize = 48 + 16 * psObject->nVertices;
1037
 
 
1038
 
        if( psSHP->nShapeType == SHPT_MULTIPOINTZ )
1039
 
        {
1040
 
            ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
1041
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1042
 
            nRecordSize += 8;
1043
 
 
1044
 
            ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
1045
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1046
 
            nRecordSize += 8;
1047
 
            
1048
 
            for( i = 0; i < psObject->nVertices; i++ )
1049
 
            {
1050
 
                ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
1051
 
                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1052
 
                nRecordSize += 8;
1053
 
            }
1054
 
        }
1055
 
 
1056
 
        if( psSHP->nShapeType == SHPT_MULTIPOINTZ
1057
 
            || psSHP->nShapeType == SHPT_MULTIPOINTM )
1058
 
        {
1059
 
            ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
1060
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1061
 
            nRecordSize += 8;
1062
 
 
1063
 
            ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
1064
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1065
 
            nRecordSize += 8;
1066
 
            
1067
 
            for( i = 0; i < psObject->nVertices; i++ )
1068
 
            {
1069
 
                ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
1070
 
                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1071
 
                nRecordSize += 8;
1072
 
            }
1073
 
        }
1074
 
    }
1075
 
 
1076
 
/* -------------------------------------------------------------------- */
1077
 
/*      Extract vertices for a point.                                   */
1078
 
/* -------------------------------------------------------------------- */
1079
 
    else if( psSHP->nShapeType == SHPT_POINT
1080
 
             || psSHP->nShapeType == SHPT_POINTZ
1081
 
             || psSHP->nShapeType == SHPT_POINTM )
1082
 
    {
1083
 
        ByteCopy( psObject->padfX, pabyRec + 12, 8 );
1084
 
        ByteCopy( psObject->padfY, pabyRec + 20, 8 );
1085
 
 
1086
 
        if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
1087
 
        if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
1088
 
 
1089
 
        nRecordSize = 28;
1090
 
        
1091
 
        if( psSHP->nShapeType == SHPT_POINTZ )
1092
 
        {
1093
 
            ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
1094
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1095
 
            nRecordSize += 8;
1096
 
        }
1097
 
        
1098
 
        if( psSHP->nShapeType == SHPT_POINTZ
1099
 
            || psSHP->nShapeType == SHPT_POINTM )
1100
 
        {
1101
 
            ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
1102
 
            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1103
 
            nRecordSize += 8;
1104
 
        }
1105
 
    }
1106
 
 
1107
 
    else
1108
 
    {
1109
 
        /* unknown type */
1110
 
        assert( FALSE );
1111
 
    }
1112
 
 
1113
 
/* -------------------------------------------------------------------- */
1114
 
/*      Establish where we are going to put this record. If we are      */
1115
 
/*      rewriting and existing record, and it will fit, then put it     */
1116
 
/*      back where the original came from.  Otherwise write at the end. */
1117
 
/* -------------------------------------------------------------------- */
1118
 
    if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
1119
 
    {
1120
 
        if( nShapeId == -1 )
1121
 
            nShapeId = psSHP->nRecords++;
1122
 
 
1123
 
        psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
1124
 
        psSHP->panRecSize[nShapeId] = nRecordSize-8;
1125
 
        psSHP->nFileSize += nRecordSize;
1126
 
    }
1127
 
    else
1128
 
    {
1129
 
        nRecordOffset = psSHP->panRecOffset[nShapeId];
1130
 
    }
1131
 
    
1132
 
/* -------------------------------------------------------------------- */
1133
 
/*      Set the shape type, record number, and record size.             */
1134
 
/* -------------------------------------------------------------------- */
1135
 
    i32 = nShapeId+1;                                   /* record # */
1136
 
    if( !bBigEndian ) SwapWord( 4, &i32 );
1137
 
    ByteCopy( &i32, pabyRec, 4 );
1138
 
 
1139
 
    i32 = (nRecordSize-8)/2;                            /* record size */
1140
 
    if( !bBigEndian ) SwapWord( 4, &i32 );
1141
 
    ByteCopy( &i32, pabyRec + 4, 4 );
1142
 
 
1143
 
    i32 = psSHP->nShapeType;                            /* shape type */
1144
 
    if( bBigEndian ) SwapWord( 4, &i32 );
1145
 
    ByteCopy( &i32, pabyRec + 8, 4 );
1146
 
 
1147
 
/* -------------------------------------------------------------------- */
1148
 
/*      Write out record.                                               */
1149
 
/* -------------------------------------------------------------------- */
1150
 
    if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
1151
 
        || fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
1152
 
    {
1153
 
        printf( "Error in fseek() or fwrite().\n" );
1154
 
        free( pabyRec );
1155
 
        return -1;
1156
 
    }
1157
 
    
1158
 
    free( pabyRec );
1159
 
 
1160
 
/* -------------------------------------------------------------------- */
1161
 
/*      Expand file wide bounds based on this shape.                    */
1162
 
/* -------------------------------------------------------------------- */
1163
 
    if( psSHP->nRecords == 1 )
1164
 
    {
1165
 
        psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
1166
 
        psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
1167
 
        psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
1168
 
        psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
1169
 
    }
1170
 
 
1171
 
    for( i = 0; i < psObject->nVertices; i++ )
1172
 
    {
1173
 
        psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
1174
 
        psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
1175
 
        psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
1176
 
        psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
1177
 
        psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
1178
 
        psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
1179
 
        psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
1180
 
        psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
1181
 
    }
1182
 
 
1183
 
    return( nShapeId  );
1184
 
}
1185
 
 
1186
 
/************************************************************************/
1187
 
/*                          SHPReadObject()                             */
1188
 
/*                                                                      */
1189
 
/*      Read the vertices, parts, and other non-attribute information   */
1190
 
/*      for one shape.                                                  */
1191
 
/************************************************************************/
1192
 
 
1193
 
SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
1194
 
 
1195
 
{
1196
 
    SHPObject           *psShape;
1197
 
 
1198
 
/* -------------------------------------------------------------------- */
1199
 
/*      Validate the record/entity number.                              */
1200
 
/* -------------------------------------------------------------------- */
1201
 
    if( hEntity < 0 || hEntity >= psSHP->nRecords )
1202
 
        return( NULL );
1203
 
 
1204
 
/* -------------------------------------------------------------------- */
1205
 
/*      Ensure our record buffer is large enough.                       */
1206
 
/* -------------------------------------------------------------------- */
1207
 
    if( psSHP->panRecSize[hEntity]+8 > nBufSize )
1208
 
    {
1209
 
        nBufSize = psSHP->panRecSize[hEntity]+8;
1210
 
        pabyRec = (uchar *) SfRealloc(pabyRec,nBufSize);
1211
 
    }
1212
 
 
1213
 
/* -------------------------------------------------------------------- */
1214
 
/*      Read the record.                                                */
1215
 
/* -------------------------------------------------------------------- */
1216
 
    fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 );
1217
 
    fread( pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP );
1218
 
 
1219
 
/* -------------------------------------------------------------------- */
1220
 
/*      Allocate and minimally initialize the object.                   */
1221
 
/* -------------------------------------------------------------------- */
1222
 
    psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
1223
 
    psShape->nShapeId = hEntity;
1224
 
 
1225
 
    memcpy( &psShape->nSHPType, pabyRec + 8, 4 );
1226
 
    if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
1227
 
 
1228
 
/* ==================================================================== */
1229
 
/*  Extract vertices for a Polygon or Arc.                              */
1230
 
/* ==================================================================== */
1231
 
    if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
1232
 
        || psShape->nSHPType == SHPT_POLYGONZ
1233
 
        || psShape->nSHPType == SHPT_POLYGONM
1234
 
        || psShape->nSHPType == SHPT_ARCZ
1235
 
        || psShape->nSHPType == SHPT_ARCM
1236
 
        || psShape->nSHPType == SHPT_MULTIPATCH )
1237
 
    {
1238
 
        int32           nPoints, nParts;
1239
 
        int             i, nOffset;
1240
 
 
1241
 
/* -------------------------------------------------------------------- */
1242
 
/*      Get the X/Y bounds.                                             */
1243
 
/* -------------------------------------------------------------------- */
1244
 
        memcpy( &(psShape->dfXMin), pabyRec + 8 +  4, 8 );
1245
 
        memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 );
1246
 
        memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 );
1247
 
        memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 );
1248
 
 
1249
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
1250
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
1251
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
1252
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
1253
 
 
1254
 
/* -------------------------------------------------------------------- */
1255
 
/*      Extract part/point count, and build vertex and part arrays      */
1256
 
/*      to proper size.                                                 */
1257
 
/* -------------------------------------------------------------------- */
1258
 
        memcpy( &nPoints, pabyRec + 40 + 8, 4 );
1259
 
        memcpy( &nParts, pabyRec + 36 + 8, 4 );
1260
 
 
1261
 
        if( bBigEndian ) SwapWord( 4, &nPoints );
1262
 
        if( bBigEndian ) SwapWord( 4, &nParts );
1263
 
 
1264
 
        psShape->nVertices = nPoints;
1265
 
        psShape->padfX = (double *) calloc(nPoints,sizeof(double));
1266
 
        psShape->padfY = (double *) calloc(nPoints,sizeof(double));
1267
 
        psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
1268
 
        psShape->padfM = (double *) calloc(nPoints,sizeof(double));
1269
 
 
1270
 
        psShape->nParts = nParts;
1271
 
        psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
1272
 
        psShape->panPartType = (int *) calloc(nParts,sizeof(int));
1273
 
 
1274
 
        for( i = 0; i < nParts; i++ )
1275
 
            psShape->panPartType[i] = SHPP_RING;
1276
 
 
1277
 
/* -------------------------------------------------------------------- */
1278
 
/*      Copy out the part array from the record.                        */
1279
 
/* -------------------------------------------------------------------- */
1280
 
        memcpy( psShape->panPartStart, pabyRec + 44 + 8, 4 * nParts );
1281
 
        for( i = 0; i < nParts; i++ )
1282
 
        {
1283
 
            if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
1284
 
        }
1285
 
 
1286
 
        nOffset = 44 + 8 + 4*nParts;
1287
 
 
1288
 
/* -------------------------------------------------------------------- */
1289
 
/*      If this is a multipatch, we will also have parts types.         */
1290
 
/* -------------------------------------------------------------------- */
1291
 
        if( psShape->nSHPType == SHPT_MULTIPATCH )
1292
 
        {
1293
 
            memcpy( psShape->panPartType, pabyRec + nOffset, 4*nParts );
1294
 
            for( i = 0; i < nParts; i++ )
1295
 
            {
1296
 
                if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
1297
 
            }
1298
 
 
1299
 
            nOffset += 4*nParts;
1300
 
        }
1301
 
        
1302
 
/* -------------------------------------------------------------------- */
1303
 
/*      Copy out the vertices from the record.                          */
1304
 
/* -------------------------------------------------------------------- */
1305
 
        for( i = 0; i < nPoints; i++ )
1306
 
        {
1307
 
            memcpy(psShape->padfX + i,
1308
 
                   pabyRec + nOffset + i * 16,
1309
 
                   8 );
1310
 
 
1311
 
            memcpy(psShape->padfY + i,
1312
 
                   pabyRec + nOffset + i * 16 + 8,
1313
 
                   8 );
1314
 
 
1315
 
            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
1316
 
            if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
1317
 
        }
1318
 
 
1319
 
        nOffset += 16*nPoints;
1320
 
        
1321
 
/* -------------------------------------------------------------------- */
1322
 
/*      If we have a Z coordinate, collect that now.                    */
1323
 
/* -------------------------------------------------------------------- */
1324
 
        if( psShape->nSHPType == SHPT_POLYGONZ
1325
 
            || psShape->nSHPType == SHPT_ARCZ
1326
 
            || psShape->nSHPType == SHPT_MULTIPATCH )
1327
 
        {
1328
 
            memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 );
1329
 
            memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 );
1330
 
            
1331
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
1332
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
1333
 
            
1334
 
            for( i = 0; i < nPoints; i++ )
1335
 
            {
1336
 
                memcpy( psShape->padfZ + i,
1337
 
                        pabyRec + nOffset + 16 + i*8, 8 );
1338
 
                if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
1339
 
            }
1340
 
 
1341
 
            nOffset += 16 + 8*nPoints;
1342
 
        }
1343
 
 
1344
 
/* -------------------------------------------------------------------- */
1345
 
/*      If we have a M measure value, then read it now.  We assume      */
1346
 
/*      that the measure can be present for any shape if the size is    */
1347
 
/*      big enough, but really it will only occur for the Z shapes      */
1348
 
/*      (options), and the M shapes.                                    */
1349
 
/* -------------------------------------------------------------------- */
1350
 
        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
1351
 
        {
1352
 
            memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 );
1353
 
            memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 );
1354
 
            
1355
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
1356
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
1357
 
            
1358
 
            for( i = 0; i < nPoints; i++ )
1359
 
            {
1360
 
                memcpy( psShape->padfM + i,
1361
 
                        pabyRec + nOffset + 16 + i*8, 8 );
1362
 
                if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
1363
 
            }
1364
 
        }
1365
 
        
1366
 
    }
1367
 
 
1368
 
/* ==================================================================== */
1369
 
/*  Extract vertices for a MultiPoint.                                  */
1370
 
/* ==================================================================== */
1371
 
    else if( psShape->nSHPType == SHPT_MULTIPOINT
1372
 
             || psShape->nSHPType == SHPT_MULTIPOINTM
1373
 
             || psShape->nSHPType == SHPT_MULTIPOINTZ )
1374
 
    {
1375
 
        int32           nPoints;
1376
 
        int             i, nOffset;
1377
 
 
1378
 
        memcpy( &nPoints, pabyRec + 44, 4 );
1379
 
        if( bBigEndian ) SwapWord( 4, &nPoints );
1380
 
 
1381
 
        psShape->nVertices = nPoints;
1382
 
        psShape->padfX = (double *) calloc(nPoints,sizeof(double));
1383
 
        psShape->padfY = (double *) calloc(nPoints,sizeof(double));
1384
 
        psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
1385
 
        psShape->padfM = (double *) calloc(nPoints,sizeof(double));
1386
 
 
1387
 
        for( i = 0; i < nPoints; i++ )
1388
 
        {
1389
 
            memcpy(psShape->padfX+i, pabyRec + 48 + 16 * i, 8 );
1390
 
            memcpy(psShape->padfY+i, pabyRec + 48 + 16 * i + 8, 8 );
1391
 
 
1392
 
            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
1393
 
            if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
1394
 
        }
1395
 
 
1396
 
        nOffset = 48 + 16*nPoints;
1397
 
        
1398
 
/* -------------------------------------------------------------------- */
1399
 
/*      Get the X/Y bounds.                                             */
1400
 
/* -------------------------------------------------------------------- */
1401
 
        memcpy( &(psShape->dfXMin), pabyRec + 8 +  4, 8 );
1402
 
        memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 );
1403
 
        memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 );
1404
 
        memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 );
1405
 
 
1406
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
1407
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
1408
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
1409
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
1410
 
 
1411
 
/* -------------------------------------------------------------------- */
1412
 
/*      If we have a Z coordinate, collect that now.                    */
1413
 
/* -------------------------------------------------------------------- */
1414
 
        if( psShape->nSHPType == SHPT_MULTIPOINTZ )
1415
 
        {
1416
 
            memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 );
1417
 
            memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 );
1418
 
            
1419
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
1420
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
1421
 
            
1422
 
            for( i = 0; i < nPoints; i++ )
1423
 
            {
1424
 
                memcpy( psShape->padfZ + i,
1425
 
                        pabyRec + nOffset + 16 + i*8, 8 );
1426
 
                if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
1427
 
            }
1428
 
 
1429
 
            nOffset += 16 + 8*nPoints;
1430
 
        }
1431
 
 
1432
 
/* -------------------------------------------------------------------- */
1433
 
/*      If we have a M measure value, then read it now.  We assume      */
1434
 
/*      that the measure can be present for any shape if the size is    */
1435
 
/*      big enough, but really it will only occur for the Z shapes      */
1436
 
/*      (options), and the M shapes.                                    */
1437
 
/* -------------------------------------------------------------------- */
1438
 
        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
1439
 
        {
1440
 
            memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 );
1441
 
            memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 );
1442
 
            
1443
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
1444
 
            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
1445
 
            
1446
 
            for( i = 0; i < nPoints; i++ )
1447
 
            {
1448
 
                memcpy( psShape->padfM + i,
1449
 
                        pabyRec + nOffset + 16 + i*8, 8 );
1450
 
                if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
1451
 
            }
1452
 
        }
1453
 
    }
1454
 
 
1455
 
/* ==================================================================== */
1456
 
/*      Extract vertices for a point.                                   */
1457
 
/* ==================================================================== */
1458
 
    else if( psShape->nSHPType == SHPT_POINT
1459
 
             || psShape->nSHPType == SHPT_POINTM
1460
 
             || psShape->nSHPType == SHPT_POINTZ )
1461
 
    {
1462
 
        int     nOffset;
1463
 
        
1464
 
        psShape->nVertices = 1;
1465
 
        psShape->padfX = (double *) calloc(1,sizeof(double));
1466
 
        psShape->padfY = (double *) calloc(1,sizeof(double));
1467
 
        psShape->padfZ = (double *) calloc(1,sizeof(double));
1468
 
        psShape->padfM = (double *) calloc(1,sizeof(double));
1469
 
 
1470
 
        memcpy( psShape->padfX, pabyRec + 12, 8 );
1471
 
        memcpy( psShape->padfY, pabyRec + 20, 8 );
1472
 
 
1473
 
        if( bBigEndian ) SwapWord( 8, psShape->padfX );
1474
 
        if( bBigEndian ) SwapWord( 8, psShape->padfY );
1475
 
 
1476
 
        nOffset = 20 + 8;
1477
 
        
1478
 
/* -------------------------------------------------------------------- */
1479
 
/*      If we have a Z coordinate, collect that now.                    */
1480
 
/* -------------------------------------------------------------------- */
1481
 
        if( psShape->nSHPType == SHPT_POINTZ )
1482
 
        {
1483
 
            memcpy( psShape->padfZ, pabyRec + nOffset, 8 );
1484
 
        
1485
 
            if( bBigEndian ) SwapWord( 8, psShape->padfZ );
1486
 
            
1487
 
            nOffset += 8;
1488
 
        }
1489
 
 
1490
 
/* -------------------------------------------------------------------- */
1491
 
/*      If we have a M measure value, then read it now.  We assume      */
1492
 
/*      that the measure can be present for any shape if the size is    */
1493
 
/*      big enough, but really it will only occur for the Z shapes      */
1494
 
/*      (options), and the M shapes.                                    */
1495
 
/* -------------------------------------------------------------------- */
1496
 
        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
1497
 
        {
1498
 
            memcpy( psShape->padfM, pabyRec + nOffset, 8 );
1499
 
        
1500
 
            if( bBigEndian ) SwapWord( 8, psShape->padfM );
1501
 
        }
1502
 
 
1503
 
/* -------------------------------------------------------------------- */
1504
 
/*      Since no extents are supplied in the record, we will apply      */
1505
 
/*      them from the single vertex.                                    */
1506
 
/* -------------------------------------------------------------------- */
1507
 
        psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
1508
 
        psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
1509
 
        psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
1510
 
        psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
1511
 
    }
1512
 
 
1513
 
    return( psShape );
1514
 
}
1515
 
 
1516
 
/************************************************************************/
1517
 
/*                            SHPTypeName()                             */
1518
 
/************************************************************************/
1519
 
 
1520
 
const char *SHPTypeName( int nSHPType )
1521
 
 
1522
 
{
1523
 
    switch( nSHPType )
1524
 
    {
1525
 
      case 0:
1526
 
        return "NullShape";
1527
 
 
1528
 
      case SHPT_POINT:
1529
 
        return "Point";
1530
 
 
1531
 
      case SHPT_ARC:
1532
 
        return "Arc";
1533
 
 
1534
 
      case SHPT_POLYGON:
1535
 
        return "Polygon";
1536
 
 
1537
 
      case SHPT_MULTIPOINT:
1538
 
        return "MultiPoint";
1539
 
        
1540
 
      case SHPT_POINTZ:
1541
 
        return "PointZ";
1542
 
 
1543
 
      case SHPT_ARCZ:
1544
 
        return "ArcZ";
1545
 
 
1546
 
      case SHPT_POLYGONZ:
1547
 
        return "PolygonZ";
1548
 
 
1549
 
      case SHPT_MULTIPOINTZ:
1550
 
        return "MultiPointZ";
1551
 
        
1552
 
      case SHPT_POINTM:
1553
 
        return "PointM";
1554
 
 
1555
 
      case SHPT_ARCM:
1556
 
        return "ArcM";
1557
 
 
1558
 
      case SHPT_POLYGONM:
1559
 
        return "PolygonM";
1560
 
 
1561
 
      case SHPT_MULTIPOINTM:
1562
 
        return "MultiPointM";
1563
 
 
1564
 
      case SHPT_MULTIPATCH:
1565
 
        return "MultiPatch";
1566
 
 
1567
 
      default:
1568
 
        return "UnknownShapeType";
1569
 
    }
1570
 
}
1571
 
 
1572
 
/************************************************************************/
1573
 
/*                          SHPPartTypeName()                           */
1574
 
/************************************************************************/
1575
 
 
1576
 
const char *SHPPartTypeName( int nPartType )
1577
 
 
1578
 
{
1579
 
    switch( nPartType )
1580
 
    {
1581
 
      case SHPP_TRISTRIP:
1582
 
        return "TriangleStrip";
1583
 
        
1584
 
      case SHPP_TRIFAN:
1585
 
        return "TriangleFan";
1586
 
 
1587
 
      case SHPP_OUTERRING:
1588
 
        return "OuterRing";
1589
 
 
1590
 
      case SHPP_INNERRING:
1591
 
        return "InnerRing";
1592
 
 
1593
 
      case SHPP_FIRSTRING:
1594
 
        return "FirstRing";
1595
 
 
1596
 
      case SHPP_RING:
1597
 
        return "Ring";
1598
 
 
1599
 
      default:
1600
 
        return "UnknownPartType";
1601
 
    }
1602
 
}
1603
 
 
1604
 
/************************************************************************/
1605
 
/*                          SHPDestroyObject()                          */
1606
 
/************************************************************************/
1607
 
 
1608
 
void SHPDestroyObject( SHPObject * psShape )
1609
 
 
1610
 
{
1611
 
    if( psShape == NULL )
1612
 
        return;
1613
 
    
1614
 
    if( psShape->padfX != NULL )
1615
 
        free( psShape->padfX );
1616
 
    if( psShape->padfY != NULL )
1617
 
        free( psShape->padfY );
1618
 
    if( psShape->padfZ != NULL )
1619
 
        free( psShape->padfZ );
1620
 
    if( psShape->padfM != NULL )
1621
 
        free( psShape->padfM );
1622
 
 
1623
 
    if( psShape->panPartStart != NULL )
1624
 
        free( psShape->panPartStart );
1625
 
    if( psShape->panPartType != NULL )
1626
 
        free( psShape->panPartType );
1627
 
 
1628
 
    free( psShape );
1629
 
}