00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 static char rcsid[] =
00162 "$Id: shpopen.c,v 1.39 2002/08/26 06:46:56 warmerda Exp $";
00163
00164 #include "shapefil.h"
00165
00166 #include <math.h>
00167 #include <limits.h>
00168 #include <assert.h>
00169 #include <stdlib.h>
00170 #include <string.h>
00171
00172 typedef unsigned char uchar;
00173
00174 #if UINT_MAX == 65535
00175 typedef long int32;
00176 #else
00177 typedef int int32;
00178 #endif
00179
00180 #ifndef FALSE
00181 # define FALSE 0
00182 # define TRUE 1
00183 #endif
00184
00185 #define ByteCopy( a, b, c ) memcpy( b, a, c )
00186 #ifndef MAX
00187 # define MIN(a,b) ((a<b) ? a : b)
00188 # define MAX(a,b) ((a>b) ? a : b)
00189 #endif
00190
00191 static int bBigEndian;
00192
00193
00194
00195
00196
00197
00198
00199
00200 static void SwapWord( int length, void * wordP )
00201
00202 {
00203 int i;
00204 uchar temp;
00205
00206 for( i=0; i < length/2; i++ )
00207 {
00208 temp = ((uchar *) wordP)[i];
00209 ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
00210 ((uchar *) wordP)[length-i-1] = temp;
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221 static void * SfRealloc( void * pMem, int nNewSize )
00222
00223 {
00224 if( pMem == NULL )
00225 return( (void *) malloc(nNewSize) );
00226 else
00227 return( (void *) realloc(pMem,nNewSize) );
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237 static void SHPWriteHeader( SHPHandle psSHP )
00238
00239 {
00240 uchar abyHeader[100];
00241 int i;
00242 int32 i32;
00243 double dValue;
00244 int32 *panSHX;
00245
00246
00247
00248
00249 for( i = 0; i < 100; i++ )
00250 abyHeader[i] = 0;
00251
00252 abyHeader[2] = 0x27;
00253 abyHeader[3] = 0x0a;
00254
00255 i32 = psSHP->nFileSize/2;
00256 ByteCopy( &i32, abyHeader+24, 4 );
00257 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
00258
00259 i32 = 1000;
00260 ByteCopy( &i32, abyHeader+28, 4 );
00261 if( bBigEndian ) SwapWord( 4, abyHeader+28 );
00262
00263 i32 = psSHP->nShapeType;
00264 ByteCopy( &i32, abyHeader+32, 4 );
00265 if( bBigEndian ) SwapWord( 4, abyHeader+32 );
00266
00267 dValue = psSHP->adBoundsMin[0];
00268 ByteCopy( &dValue, abyHeader+36, 8 );
00269 if( bBigEndian ) SwapWord( 8, abyHeader+36 );
00270
00271 dValue = psSHP->adBoundsMin[1];
00272 ByteCopy( &dValue, abyHeader+44, 8 );
00273 if( bBigEndian ) SwapWord( 8, abyHeader+44 );
00274
00275 dValue = psSHP->adBoundsMax[0];
00276 ByteCopy( &dValue, abyHeader+52, 8 );
00277 if( bBigEndian ) SwapWord( 8, abyHeader+52 );
00278
00279 dValue = psSHP->adBoundsMax[1];
00280 ByteCopy( &dValue, abyHeader+60, 8 );
00281 if( bBigEndian ) SwapWord( 8, abyHeader+60 );
00282
00283 dValue = psSHP->adBoundsMin[2];
00284 ByteCopy( &dValue, abyHeader+68, 8 );
00285 if( bBigEndian ) SwapWord( 8, abyHeader+68 );
00286
00287 dValue = psSHP->adBoundsMax[2];
00288 ByteCopy( &dValue, abyHeader+76, 8 );
00289 if( bBigEndian ) SwapWord( 8, abyHeader+76 );
00290
00291 dValue = psSHP->adBoundsMin[3];
00292 ByteCopy( &dValue, abyHeader+84, 8 );
00293 if( bBigEndian ) SwapWord( 8, abyHeader+84 );
00294
00295 dValue = psSHP->adBoundsMax[3];
00296 ByteCopy( &dValue, abyHeader+92, 8 );
00297 if( bBigEndian ) SwapWord( 8, abyHeader+92 );
00298
00299
00300
00301
00302 fseek( psSHP->fpSHP, 0, 0 );
00303 fwrite( abyHeader, 100, 1, psSHP->fpSHP );
00304
00305
00306
00307
00308 i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2;
00309 ByteCopy( &i32, abyHeader+24, 4 );
00310 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
00311
00312 fseek( psSHP->fpSHX, 0, 0 );
00313 fwrite( abyHeader, 100, 1, psSHP->fpSHX );
00314
00315
00316
00317
00318 panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
00319
00320 for( i = 0; i < psSHP->nRecords; i++ )
00321 {
00322 panSHX[i*2 ] = psSHP->panRecOffset[i]/2;
00323 panSHX[i*2+1] = psSHP->panRecSize[i]/2;
00324 if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
00325 if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
00326 }
00327
00328 fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX );
00329
00330 free( panSHX );
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340 SHPHandle SHPAPI_CALL
00341 SHPOpen( const char * pszLayer, const char * pszAccess )
00342
00343 {
00344 char *pszFullname, *pszBasename;
00345 SHPHandle psSHP;
00346
00347 uchar *pabyBuf;
00348 int i;
00349 double dValue;
00350
00351
00352
00353
00354
00355
00356 if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
00357 || strcmp(pszAccess,"r+") == 0 )
00358 pszAccess = "r+b";
00359 else
00360 pszAccess = "rb";
00361
00362
00363
00364
00365 i = 1;
00366 if( *((uchar *) &i) == 1 )
00367 bBigEndian = FALSE;
00368 else
00369 bBigEndian = TRUE;
00370
00371
00372
00373
00374 psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
00375
00376 psSHP->bUpdated = FALSE;
00377
00378
00379
00380
00381
00382 pszBasename = (char *) malloc(strlen(pszLayer)+5);
00383 strcpy( pszBasename, pszLayer );
00384 for( i = strlen(pszBasename)-1;
00385 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
00386 && pszBasename[i] != '\\';
00387 i-- ) {}
00388
00389 if( pszBasename[i] == '.' )
00390 pszBasename[i] = '\0';
00391
00392
00393
00394
00395
00396 pszFullname = (char *) malloc(strlen(pszBasename) + 5);
00397 sprintf( pszFullname, "%s.shp", pszBasename );
00398 psSHP->fpSHP = fopen(pszFullname, pszAccess );
00399 if( psSHP->fpSHP == NULL )
00400 {
00401 sprintf( pszFullname, "%s.SHP", pszBasename );
00402 psSHP->fpSHP = fopen(pszFullname, pszAccess );
00403 }
00404
00405 if( psSHP->fpSHP == NULL )
00406 {
00407 free( psSHP );
00408 free( pszBasename );
00409 free( pszFullname );
00410 return( NULL );
00411 }
00412
00413 sprintf( pszFullname, "%s.shx", pszBasename );
00414 psSHP->fpSHX = fopen(pszFullname, pszAccess );
00415 if( psSHP->fpSHX == NULL )
00416 {
00417 sprintf( pszFullname, "%s.SHX", pszBasename );
00418 psSHP->fpSHX = fopen(pszFullname, pszAccess );
00419 }
00420
00421 if( psSHP->fpSHX == NULL )
00422 {
00423 fclose( psSHP->fpSHP );
00424 free( psSHP );
00425 free( pszBasename );
00426 free( pszFullname );
00427 return( NULL );
00428 }
00429
00430 free( pszFullname );
00431 free( pszBasename );
00432
00433
00434
00435
00436 pabyBuf = (uchar *) malloc(100);
00437 fread( pabyBuf, 100, 1, psSHP->fpSHP );
00438
00439 psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
00440 + pabyBuf[25] * 256 * 256
00441 + pabyBuf[26] * 256
00442 + pabyBuf[27]) * 2;
00443
00444
00445
00446
00447 fread( pabyBuf, 100, 1, psSHP->fpSHX );
00448
00449 if( pabyBuf[0] != 0
00450 || pabyBuf[1] != 0
00451 || pabyBuf[2] != 0x27
00452 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
00453 {
00454 fclose( psSHP->fpSHP );
00455 fclose( psSHP->fpSHX );
00456 free( psSHP );
00457
00458 return( NULL );
00459 }
00460
00461 psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
00462 + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
00463 psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
00464
00465 psSHP->nShapeType = pabyBuf[32];
00466
00467 if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
00468 {
00469
00470 fclose( psSHP->fpSHP );
00471 fclose( psSHP->fpSHX );
00472 free( psSHP );
00473
00474 return( NULL );
00475 }
00476
00477
00478
00479
00480 if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
00481 memcpy( &dValue, pabyBuf+36, 8 );
00482 psSHP->adBoundsMin[0] = dValue;
00483
00484 if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
00485 memcpy( &dValue, pabyBuf+44, 8 );
00486 psSHP->adBoundsMin[1] = dValue;
00487
00488 if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
00489 memcpy( &dValue, pabyBuf+52, 8 );
00490 psSHP->adBoundsMax[0] = dValue;
00491
00492 if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
00493 memcpy( &dValue, pabyBuf+60, 8 );
00494 psSHP->adBoundsMax[1] = dValue;
00495
00496 if( bBigEndian ) SwapWord( 8, pabyBuf+68 );
00497 memcpy( &dValue, pabyBuf+68, 8 );
00498 psSHP->adBoundsMin[2] = dValue;
00499
00500 if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
00501 memcpy( &dValue, pabyBuf+76, 8 );
00502 psSHP->adBoundsMax[2] = dValue;
00503
00504 if( bBigEndian ) SwapWord( 8, pabyBuf+84 );
00505 memcpy( &dValue, pabyBuf+84, 8 );
00506 psSHP->adBoundsMin[3] = dValue;
00507
00508 if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
00509 memcpy( &dValue, pabyBuf+92, 8 );
00510 psSHP->adBoundsMax[3] = dValue;
00511
00512 free( pabyBuf );
00513
00514
00515
00516
00517
00518 psSHP->nMaxRecords = psSHP->nRecords;
00519
00520 psSHP->panRecOffset =
00521 (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
00522 psSHP->panRecSize =
00523 (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
00524
00525 pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
00526 fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX );
00527
00528 for( i = 0; i < psSHP->nRecords; i++ )
00529 {
00530 int32 nOffset, nLength;
00531
00532 memcpy( &nOffset, pabyBuf + i * 8, 4 );
00533 if( !bBigEndian ) SwapWord( 4, &nOffset );
00534
00535 memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
00536 if( !bBigEndian ) SwapWord( 4, &nLength );
00537
00538 psSHP->panRecOffset[i] = nOffset*2;
00539 psSHP->panRecSize[i] = nLength*2;
00540 }
00541 free( pabyBuf );
00542
00543 return( psSHP );
00544 }
00545
00546
00547
00548
00549
00550
00551
00552 void SHPAPI_CALL
00553 SHPClose(SHPHandle psSHP )
00554
00555 {
00556
00557
00558
00559 if( psSHP->bUpdated )
00560 {
00561 SHPWriteHeader( psSHP );
00562 }
00563
00564
00565
00566
00567 free( psSHP->panRecOffset );
00568 free( psSHP->panRecSize );
00569
00570 fclose( psSHP->fpSHX );
00571 fclose( psSHP->fpSHP );
00572
00573 if( psSHP->pabyRec != NULL )
00574 {
00575 free( psSHP->pabyRec );
00576 }
00577
00578 free( psSHP );
00579 }
00580
00581
00582
00583
00584
00585
00586
00587 void SHPAPI_CALL
00588 SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
00589 double * padfMinBound, double * padfMaxBound )
00590
00591 {
00592 int i;
00593
00594 if( pnEntities != NULL )
00595 *pnEntities = psSHP->nRecords;
00596
00597 if( pnShapeType != NULL )
00598 *pnShapeType = psSHP->nShapeType;
00599
00600 for( i = 0; i < 4; i++ )
00601 {
00602 if( padfMinBound != NULL )
00603 padfMinBound[i] = psSHP->adBoundsMin[i];
00604 if( padfMaxBound != NULL )
00605 padfMaxBound[i] = psSHP->adBoundsMax[i];
00606 }
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616 SHPHandle SHPAPI_CALL
00617 SHPCreate( const char * pszLayer, int nShapeType )
00618
00619 {
00620 char *pszBasename, *pszFullname;
00621 int i;
00622 FILE *fpSHP, *fpSHX;
00623 uchar abyHeader[100];
00624 int32 i32;
00625 double dValue;
00626
00627
00628
00629
00630 i = 1;
00631 if( *((uchar *) &i) == 1 )
00632 bBigEndian = FALSE;
00633 else
00634 bBigEndian = TRUE;
00635
00636
00637
00638
00639
00640 pszBasename = (char *) malloc(strlen(pszLayer)+5);
00641 strcpy( pszBasename, pszLayer );
00642 for( i = strlen(pszBasename)-1;
00643 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
00644 && pszBasename[i] != '\\';
00645 i-- ) {}
00646
00647 if( pszBasename[i] == '.' )
00648 pszBasename[i] = '\0';
00649
00650
00651
00652
00653 pszFullname = (char *) malloc(strlen(pszBasename) + 5);
00654 sprintf( pszFullname, "%s.shp", pszBasename );
00655 fpSHP = fopen(pszFullname, "wb" );
00656 if( fpSHP == NULL )
00657 return( NULL );
00658
00659 sprintf( pszFullname, "%s.shx", pszBasename );
00660 fpSHX = fopen(pszFullname, "wb" );
00661 if( fpSHX == NULL )
00662 return( NULL );
00663
00664 free( pszFullname );
00665 free( pszBasename );
00666
00667
00668
00669
00670 for( i = 0; i < 100; i++ )
00671 abyHeader[i] = 0;
00672
00673 abyHeader[2] = 0x27;
00674 abyHeader[3] = 0x0a;
00675
00676 i32 = 50;
00677 ByteCopy( &i32, abyHeader+24, 4 );
00678 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
00679
00680 i32 = 1000;
00681 ByteCopy( &i32, abyHeader+28, 4 );
00682 if( bBigEndian ) SwapWord( 4, abyHeader+28 );
00683
00684 i32 = nShapeType;
00685 ByteCopy( &i32, abyHeader+32, 4 );
00686 if( bBigEndian ) SwapWord( 4, abyHeader+32 );
00687
00688 dValue = 0.0;
00689 ByteCopy( &dValue, abyHeader+36, 8 );
00690 ByteCopy( &dValue, abyHeader+44, 8 );
00691 ByteCopy( &dValue, abyHeader+52, 8 );
00692 ByteCopy( &dValue, abyHeader+60, 8 );
00693
00694
00695
00696
00697 fwrite( abyHeader, 100, 1, fpSHP );
00698
00699
00700
00701
00702 i32 = 50;
00703 ByteCopy( &i32, abyHeader+24, 4 );
00704 if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
00705
00706 fwrite( abyHeader, 100, 1, fpSHX );
00707
00708
00709
00710
00711 fclose( fpSHP );
00712 fclose( fpSHX );
00713
00714 return( SHPOpen( pszLayer, "r+b" ) );
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724 static void _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
00725
00726 {
00727 ByteCopy( &(psShape->dfXMin), pabyRec + 0, 8 );
00728 ByteCopy( &(psShape->dfYMin), pabyRec + 8, 8 );
00729 ByteCopy( &(psShape->dfXMax), pabyRec + 16, 8 );
00730 ByteCopy( &(psShape->dfYMax), pabyRec + 24, 8 );
00731
00732 if( bBigEndian )
00733 {
00734 SwapWord( 8, pabyRec + 0 );
00735 SwapWord( 8, pabyRec + 8 );
00736 SwapWord( 8, pabyRec + 16 );
00737 SwapWord( 8, pabyRec + 24 );
00738 }
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748 void SHPAPI_CALL
00749 SHPComputeExtents( SHPObject * psObject )
00750
00751 {
00752 int i;
00753
00754
00755
00756
00757 if( psObject->nVertices > 0 )
00758 {
00759 psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
00760 psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
00761 psObject->dfZMin = psObject->dfZMax = psObject->padfZ[0];
00762 psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
00763 }
00764
00765 for( i = 0; i < psObject->nVertices; i++ )
00766 {
00767 psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
00768 psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
00769 psObject->dfZMin = MIN(psObject->dfZMin, psObject->padfZ[i]);
00770 psObject->dfMMin = MIN(psObject->dfMMin, psObject->padfM[i]);
00771
00772 psObject->dfXMax = MAX(psObject->dfXMax, psObject->padfX[i]);
00773 psObject->dfYMax = MAX(psObject->dfYMax, psObject->padfY[i]);
00774 psObject->dfZMax = MAX(psObject->dfZMax, psObject->padfZ[i]);
00775 psObject->dfMMax = MAX(psObject->dfMMax, psObject->padfM[i]);
00776 }
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786 SHPObject SHPAPI_CALL1(*)
00787 SHPCreateObject( int nSHPType, int nShapeId, int nParts,
00788 int * panPartStart, int * panPartType,
00789 int nVertices, double * padfX, double * padfY,
00790 double * padfZ, double * padfM )
00791
00792 {
00793 SHPObject *psObject;
00794 int i, bHasM, bHasZ;
00795
00796 psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
00797 psObject->nSHPType = nSHPType;
00798 psObject->nShapeId = nShapeId;
00799
00800
00801
00802
00803 if( nSHPType == SHPT_ARCM
00804 || nSHPType == SHPT_POINTM
00805 || nSHPType == SHPT_POLYGONM
00806 || nSHPType == SHPT_MULTIPOINTM )
00807 {
00808 bHasM = TRUE;
00809 bHasZ = FALSE;
00810 }
00811 else if( nSHPType == SHPT_ARCZ
00812 || nSHPType == SHPT_POINTZ
00813 || nSHPType == SHPT_POLYGONZ
00814 || nSHPType == SHPT_MULTIPOINTZ
00815 || nSHPType == SHPT_MULTIPATCH )
00816 {
00817 bHasM = TRUE;
00818 bHasZ = TRUE;
00819 }
00820 else
00821 {
00822 bHasM = FALSE;
00823 bHasZ = FALSE;
00824 }
00825
00826
00827
00828
00829
00830 if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
00831 || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
00832 || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
00833 || nSHPType == SHPT_MULTIPATCH )
00834 {
00835 psObject->nParts = MAX(1,nParts);
00836
00837 psObject->panPartStart = (int *)
00838 malloc(sizeof(int) * psObject->nParts);
00839 psObject->panPartType = (int *)
00840 malloc(sizeof(int) * psObject->nParts);
00841
00842 psObject->panPartStart[0] = 0;
00843 psObject->panPartType[0] = SHPP_RING;
00844
00845 for( i = 0; i < nParts; i++ )
00846 {
00847 psObject->panPartStart[i] = panPartStart[i];
00848 if( panPartType != NULL )
00849 psObject->panPartType[i] = panPartType[i];
00850 else
00851 psObject->panPartType[i] = SHPP_RING;
00852 }
00853 }
00854
00855
00856
00857
00858
00859 if( nVertices > 0 )
00860 {
00861 psObject->padfX = (double *) calloc(sizeof(double),nVertices);
00862 psObject->padfY = (double *) calloc(sizeof(double),nVertices);
00863 psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
00864 psObject->padfM = (double *) calloc(sizeof(double),nVertices);
00865
00866 assert( padfX != NULL );
00867 assert( padfY != NULL );
00868
00869 for( i = 0; i < nVertices; i++ )
00870 {
00871 psObject->padfX[i] = padfX[i];
00872 psObject->padfY[i] = padfY[i];
00873 if( padfZ != NULL && bHasZ )
00874 psObject->padfZ[i] = padfZ[i];
00875 if( padfM != NULL && bHasM )
00876 psObject->padfM[i] = padfM[i];
00877 }
00878 }
00879
00880
00881
00882
00883 psObject->nVertices = nVertices;
00884 SHPComputeExtents( psObject );
00885
00886 return( psObject );
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896 SHPObject SHPAPI_CALL1(*)
00897 SHPCreateSimpleObject( int nSHPType, int nVertices,
00898 double * padfX, double * padfY,
00899 double * padfZ )
00900
00901 {
00902 return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
00903 nVertices, padfX, padfY, padfZ, NULL ) );
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913 int SHPAPI_CALL
00914 SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
00915
00916 {
00917 int nRecordOffset, i, nRecordSize;
00918 uchar *pabyRec;
00919 int32 i32;
00920
00921 psSHP->bUpdated = TRUE;
00922
00923
00924
00925
00926
00927 assert( psObject->nSHPType == psSHP->nShapeType
00928 || psObject->nSHPType == SHPT_NULL );
00929
00930
00931
00932
00933
00934
00935 assert( nShapeId == -1
00936 || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
00937
00938 if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
00939 nShapeId = -1;
00940
00941
00942
00943
00944 if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
00945 {
00946 psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
00947
00948 psSHP->panRecOffset = (int *)
00949 SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
00950 psSHP->panRecSize = (int *)
00951 SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
00952 }
00953
00954
00955
00956
00957 pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
00958 + psObject->nParts * 8 + 128);
00959
00960
00961
00962
00963 if( psObject->nSHPType == SHPT_POLYGON
00964 || psObject->nSHPType == SHPT_POLYGONZ
00965 || psObject->nSHPType == SHPT_POLYGONM
00966 || psObject->nSHPType == SHPT_ARC
00967 || psObject->nSHPType == SHPT_ARCZ
00968 || psObject->nSHPType == SHPT_ARCM
00969 || psObject->nSHPType == SHPT_MULTIPATCH )
00970 {
00971 int32 nPoints, nParts;
00972 int i;
00973
00974 nPoints = psObject->nVertices;
00975 nParts = psObject->nParts;
00976
00977 _SHPSetBounds( pabyRec + 12, psObject );
00978
00979 if( bBigEndian ) SwapWord( 4, &nPoints );
00980 if( bBigEndian ) SwapWord( 4, &nParts );
00981
00982 ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
00983 ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
00984
00985 nRecordSize = 52;
00986
00987
00988
00989
00990 ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
00991 4 * psObject->nParts );
00992 for( i = 0; i < psObject->nParts; i++ )
00993 {
00994 if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
00995 nRecordSize += 4;
00996 }
00997
00998
00999
01000
01001 if( psObject->nSHPType == SHPT_MULTIPATCH )
01002 {
01003 memcpy( pabyRec + nRecordSize, psObject->panPartType,
01004 4*psObject->nParts );
01005 for( i = 0; i < psObject->nParts; i++ )
01006 {
01007 if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
01008 nRecordSize += 4;
01009 }
01010 }
01011
01012
01013
01014
01015 for( i = 0; i < psObject->nVertices; i++ )
01016 {
01017 ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
01018 ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
01019
01020 if( bBigEndian )
01021 SwapWord( 8, pabyRec + nRecordSize );
01022
01023 if( bBigEndian )
01024 SwapWord( 8, pabyRec + nRecordSize + 8 );
01025
01026 nRecordSize += 2 * 8;
01027 }
01028
01029
01030
01031
01032 if( psObject->nSHPType == SHPT_POLYGONZ
01033 || psObject->nSHPType == SHPT_ARCZ
01034 || psObject->nSHPType == SHPT_MULTIPATCH )
01035 {
01036 ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
01037 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01038 nRecordSize += 8;
01039
01040 ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
01041 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01042 nRecordSize += 8;
01043
01044 for( i = 0; i < psObject->nVertices; i++ )
01045 {
01046 ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
01047 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01048 nRecordSize += 8;
01049 }
01050 }
01051
01052
01053
01054
01055 if( psObject->nSHPType == SHPT_POLYGONM
01056 || psObject->nSHPType == SHPT_ARCM
01057 #ifndef DISABLE_MULTIPATCH_MEASURE
01058 || psObject->nSHPType == SHPT_MULTIPATCH
01059 #endif
01060 || psObject->nSHPType == SHPT_POLYGONZ
01061 || psObject->nSHPType == SHPT_ARCZ )
01062 {
01063 ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
01064 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01065 nRecordSize += 8;
01066
01067 ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
01068 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01069 nRecordSize += 8;
01070
01071 for( i = 0; i < psObject->nVertices; i++ )
01072 {
01073 ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
01074 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01075 nRecordSize += 8;
01076 }
01077 }
01078 }
01079
01080
01081
01082
01083 else if( psObject->nSHPType == SHPT_MULTIPOINT
01084 || psObject->nSHPType == SHPT_MULTIPOINTZ
01085 || psObject->nSHPType == SHPT_MULTIPOINTM )
01086 {
01087 int32 nPoints;
01088 int i;
01089
01090 nPoints = psObject->nVertices;
01091
01092 _SHPSetBounds( pabyRec + 12, psObject );
01093
01094 if( bBigEndian ) SwapWord( 4, &nPoints );
01095 ByteCopy( &nPoints, pabyRec + 44, 4 );
01096
01097 for( i = 0; i < psObject->nVertices; i++ )
01098 {
01099 ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
01100 ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
01101
01102 if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
01103 if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
01104 }
01105
01106 nRecordSize = 48 + 16 * psObject->nVertices;
01107
01108 if( psObject->nSHPType == SHPT_MULTIPOINTZ )
01109 {
01110 ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
01111 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01112 nRecordSize += 8;
01113
01114 ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
01115 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01116 nRecordSize += 8;
01117
01118 for( i = 0; i < psObject->nVertices; i++ )
01119 {
01120 ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
01121 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01122 nRecordSize += 8;
01123 }
01124 }
01125
01126 if( psObject->nSHPType == SHPT_MULTIPOINTZ
01127 || psObject->nSHPType == SHPT_MULTIPOINTM )
01128 {
01129 ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
01130 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01131 nRecordSize += 8;
01132
01133 ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
01134 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01135 nRecordSize += 8;
01136
01137 for( i = 0; i < psObject->nVertices; i++ )
01138 {
01139 ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
01140 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01141 nRecordSize += 8;
01142 }
01143 }
01144 }
01145
01146
01147
01148
01149 else if( psObject->nSHPType == SHPT_POINT
01150 || psObject->nSHPType == SHPT_POINTZ
01151 || psObject->nSHPType == SHPT_POINTM )
01152 {
01153 ByteCopy( psObject->padfX, pabyRec + 12, 8 );
01154 ByteCopy( psObject->padfY, pabyRec + 20, 8 );
01155
01156 if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
01157 if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
01158
01159 nRecordSize = 28;
01160
01161 if( psObject->nSHPType == SHPT_POINTZ )
01162 {
01163 ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
01164 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01165 nRecordSize += 8;
01166 }
01167
01168 if( psObject->nSHPType == SHPT_POINTZ
01169 || psObject->nSHPType == SHPT_POINTM )
01170 {
01171 ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
01172 if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
01173 nRecordSize += 8;
01174 }
01175 }
01176
01177
01178
01179
01180 else if( psObject->nSHPType == SHPT_NULL )
01181 {
01182 nRecordSize = 12;
01183 }
01184
01185 else
01186 {
01187
01188 assert( FALSE );
01189 }
01190
01191
01192
01193
01194
01195
01196 if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
01197 {
01198 if( nShapeId == -1 )
01199 nShapeId = psSHP->nRecords++;
01200
01201 psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
01202 psSHP->panRecSize[nShapeId] = nRecordSize-8;
01203 psSHP->nFileSize += nRecordSize;
01204 }
01205 else
01206 {
01207 nRecordOffset = psSHP->panRecOffset[nShapeId];
01208 }
01209
01210
01211
01212
01213 i32 = nShapeId+1;
01214 if( !bBigEndian ) SwapWord( 4, &i32 );
01215 ByteCopy( &i32, pabyRec, 4 );
01216
01217 i32 = (nRecordSize-8)/2;
01218 if( !bBigEndian ) SwapWord( 4, &i32 );
01219 ByteCopy( &i32, pabyRec + 4, 4 );
01220
01221 i32 = psObject->nSHPType;
01222 if( bBigEndian ) SwapWord( 4, &i32 );
01223 ByteCopy( &i32, pabyRec + 8, 4 );
01224
01225
01226
01227
01228 if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
01229 || fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
01230 {
01231 printf( "Error in fseek() or fwrite().\n" );
01232 free( pabyRec );
01233 return -1;
01234 }
01235
01236 free( pabyRec );
01237
01238
01239
01240
01241 if( psSHP->adBoundsMin[0] == 0.0
01242 && psSHP->adBoundsMax[0] == 0.0
01243 && psSHP->adBoundsMin[1] == 0.0
01244 && psSHP->adBoundsMax[1] == 0.0
01245 && psObject->nSHPType != SHPT_NULL )
01246 {
01247 psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
01248 psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
01249 psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
01250 psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
01251 }
01252
01253 for( i = 0; i < psObject->nVertices; i++ )
01254 {
01255 psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
01256 psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
01257 psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
01258 psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
01259 psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
01260 psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
01261 psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
01262 psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
01263 }
01264
01265 return( nShapeId );
01266 }
01267
01268
01269
01270
01271
01272
01273
01274
01275 SHPObject SHPAPI_CALL1(*)
01276 SHPReadObject( SHPHandle psSHP, int hEntity )
01277
01278 {
01279 SHPObject *psShape;
01280
01281
01282
01283
01284 if( hEntity < 0 || hEntity >= psSHP->nRecords )
01285 return( NULL );
01286
01287
01288
01289
01290 if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
01291 {
01292 psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
01293 psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
01294 }
01295
01296
01297
01298
01299 fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 );
01300 fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP );
01301
01302
01303
01304
01305 psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
01306 psShape->nShapeId = hEntity;
01307
01308 memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
01309 if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
01310
01311
01312
01313
01314 if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
01315 || psShape->nSHPType == SHPT_POLYGONZ
01316 || psShape->nSHPType == SHPT_POLYGONM
01317 || psShape->nSHPType == SHPT_ARCZ
01318 || psShape->nSHPType == SHPT_ARCM
01319 || psShape->nSHPType == SHPT_MULTIPATCH )
01320 {
01321 int32 nPoints, nParts;
01322 int i, nOffset;
01323
01324
01325
01326
01327 memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
01328 memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
01329 memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
01330 memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
01331
01332 if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
01333 if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
01334 if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
01335 if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
01336
01337
01338
01339
01340
01341 memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
01342 memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
01343
01344 if( bBigEndian ) SwapWord( 4, &nPoints );
01345 if( bBigEndian ) SwapWord( 4, &nParts );
01346
01347 psShape->nVertices = nPoints;
01348 psShape->padfX = (double *) calloc(nPoints,sizeof(double));
01349 psShape->padfY = (double *) calloc(nPoints,sizeof(double));
01350 psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
01351 psShape->padfM = (double *) calloc(nPoints,sizeof(double));
01352
01353 psShape->nParts = nParts;
01354 psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
01355 psShape->panPartType = (int *) calloc(nParts,sizeof(int));
01356
01357 for( i = 0; i < nParts; i++ )
01358 psShape->panPartType[i] = SHPP_RING;
01359
01360
01361
01362
01363 memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
01364 for( i = 0; i < nParts; i++ )
01365 {
01366 if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
01367 }
01368
01369 nOffset = 44 + 8 + 4*nParts;
01370
01371
01372
01373
01374 if( psShape->nSHPType == SHPT_MULTIPATCH )
01375 {
01376 memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
01377 for( i = 0; i < nParts; i++ )
01378 {
01379 if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
01380 }
01381
01382 nOffset += 4*nParts;
01383 }
01384
01385
01386
01387
01388 for( i = 0; i < nPoints; i++ )
01389 {
01390 memcpy(psShape->padfX + i,
01391 psSHP->pabyRec + nOffset + i * 16,
01392 8 );
01393
01394 memcpy(psShape->padfY + i,
01395 psSHP->pabyRec + nOffset + i * 16 + 8,
01396 8 );
01397
01398 if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
01399 if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
01400 }
01401
01402 nOffset += 16*nPoints;
01403
01404
01405
01406
01407 if( psShape->nSHPType == SHPT_POLYGONZ
01408 || psShape->nSHPType == SHPT_ARCZ
01409 || psShape->nSHPType == SHPT_MULTIPATCH )
01410 {
01411 memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
01412 memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
01413
01414 if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
01415 if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
01416
01417 for( i = 0; i < nPoints; i++ )
01418 {
01419 memcpy( psShape->padfZ + i,
01420 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
01421 if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
01422 }
01423
01424 nOffset += 16 + 8*nPoints;
01425 }
01426
01427
01428
01429
01430
01431
01432
01433 if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
01434 {
01435 memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
01436 memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
01437
01438 if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
01439 if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
01440
01441 for( i = 0; i < nPoints; i++ )
01442 {
01443 memcpy( psShape->padfM + i,
01444 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
01445 if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
01446 }
01447 }
01448
01449 }
01450
01451
01452
01453
01454 else if( psShape->nSHPType == SHPT_MULTIPOINT
01455 || psShape->nSHPType == SHPT_MULTIPOINTM
01456 || psShape->nSHPType == SHPT_MULTIPOINTZ )
01457 {
01458 int32 nPoints;
01459 int i, nOffset;
01460
01461 memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
01462 if( bBigEndian ) SwapWord( 4, &nPoints );
01463
01464 psShape->nVertices = nPoints;
01465 psShape->padfX = (double *) calloc(nPoints,sizeof(double));
01466 psShape->padfY = (double *) calloc(nPoints,sizeof(double));
01467 psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
01468 psShape->padfM = (double *) calloc(nPoints,sizeof(double));
01469
01470 for( i = 0; i < nPoints; i++ )
01471 {
01472 memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
01473 memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
01474
01475 if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
01476 if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
01477 }
01478
01479 nOffset = 48 + 16*nPoints;
01480
01481
01482
01483
01484 memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
01485 memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
01486 memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
01487 memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
01488
01489 if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
01490 if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
01491 if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
01492 if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
01493
01494
01495
01496
01497 if( psShape->nSHPType == SHPT_MULTIPOINTZ )
01498 {
01499 memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
01500 memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
01501
01502 if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
01503 if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
01504
01505 for( i = 0; i < nPoints; i++ )
01506 {
01507 memcpy( psShape->padfZ + i,
01508 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
01509 if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
01510 }
01511
01512 nOffset += 16 + 8*nPoints;
01513 }
01514
01515
01516
01517
01518
01519
01520
01521 if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
01522 {
01523 memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
01524 memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
01525
01526 if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
01527 if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
01528
01529 for( i = 0; i < nPoints; i++ )
01530 {
01531 memcpy( psShape->padfM + i,
01532 psSHP->pabyRec + nOffset + 16 + i*8, 8 );
01533 if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
01534 }
01535 }
01536 }
01537
01538
01539
01540
01541 else if( psShape->nSHPType == SHPT_POINT
01542 || psShape->nSHPType == SHPT_POINTM
01543 || psShape->nSHPType == SHPT_POINTZ )
01544 {
01545 int nOffset;
01546
01547 psShape->nVertices = 1;
01548 psShape->padfX = (double *) calloc(1,sizeof(double));
01549 psShape->padfY = (double *) calloc(1,sizeof(double));
01550 psShape->padfZ = (double *) calloc(1,sizeof(double));
01551 psShape->padfM = (double *) calloc(1,sizeof(double));
01552
01553 memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
01554 memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
01555
01556 if( bBigEndian ) SwapWord( 8, psShape->padfX );
01557 if( bBigEndian ) SwapWord( 8, psShape->padfY );
01558
01559 nOffset = 20 + 8;
01560
01561
01562
01563
01564 if( psShape->nSHPType == SHPT_POINTZ )
01565 {
01566 memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
01567
01568 if( bBigEndian ) SwapWord( 8, psShape->padfZ );
01569
01570 nOffset += 8;
01571 }
01572
01573
01574
01575
01576
01577
01578
01579 if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
01580 {
01581 memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
01582
01583 if( bBigEndian ) SwapWord( 8, psShape->padfM );
01584 }
01585
01586
01587
01588
01589
01590 psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
01591 psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
01592 psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
01593 psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
01594 }
01595
01596 return( psShape );
01597 }
01598
01599
01600
01601
01602
01603 const char SHPAPI_CALL1(*)
01604 SHPTypeName( int nSHPType )
01605
01606 {
01607 switch( nSHPType )
01608 {
01609 case SHPT_NULL:
01610 return "NullShape";
01611
01612 case SHPT_POINT:
01613 return "Point";
01614
01615 case SHPT_ARC:
01616 return "Arc";
01617
01618 case SHPT_POLYGON:
01619 return "Polygon";
01620
01621 case SHPT_MULTIPOINT:
01622 return "MultiPoint";
01623
01624 case SHPT_POINTZ:
01625 return "PointZ";
01626
01627 case SHPT_ARCZ:
01628 return "ArcZ";
01629
01630 case SHPT_POLYGONZ:
01631 return "PolygonZ";
01632
01633 case SHPT_MULTIPOINTZ:
01634 return "MultiPointZ";
01635
01636 case SHPT_POINTM:
01637 return "PointM";
01638
01639 case SHPT_ARCM:
01640 return "ArcM";
01641
01642 case SHPT_POLYGONM:
01643 return "PolygonM";
01644
01645 case SHPT_MULTIPOINTM:
01646 return "MultiPointM";
01647
01648 case SHPT_MULTIPATCH:
01649 return "MultiPatch";
01650
01651 default:
01652 return "UnknownShapeType";
01653 }
01654 }
01655
01656
01657
01658
01659
01660 const char SHPAPI_CALL1(*)
01661 SHPPartTypeName( int nPartType )
01662
01663 {
01664 switch( nPartType )
01665 {
01666 case SHPP_TRISTRIP:
01667 return "TriangleStrip";
01668
01669 case SHPP_TRIFAN:
01670 return "TriangleFan";
01671
01672 case SHPP_OUTERRING:
01673 return "OuterRing";
01674
01675 case SHPP_INNERRING:
01676 return "InnerRing";
01677
01678 case SHPP_FIRSTRING:
01679 return "FirstRing";
01680
01681 case SHPP_RING:
01682 return "Ring";
01683
01684 default:
01685 return "UnknownPartType";
01686 }
01687 }
01688
01689
01690
01691
01692
01693 void SHPAPI_CALL
01694 SHPDestroyObject( SHPObject * psShape )
01695
01696 {
01697 if( psShape == NULL )
01698 return;
01699
01700 if( psShape->padfX != NULL )
01701 free( psShape->padfX );
01702 if( psShape->padfY != NULL )
01703 free( psShape->padfY );
01704 if( psShape->padfZ != NULL )
01705 free( psShape->padfZ );
01706 if( psShape->padfM != NULL )
01707 free( psShape->padfM );
01708
01709 if( psShape->panPartStart != NULL )
01710 free( psShape->panPartStart );
01711 if( psShape->panPartType != NULL )
01712 free( psShape->panPartType );
01713
01714 free( psShape );
01715 }
01716
01717
01718
01719
01720
01721
01722
01723
01724 int SHPAPI_CALL
01725 SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
01726
01727 {
01728 int iOpRing, bAltered = 0;
01729
01730
01731
01732
01733 if( psObject->nSHPType != SHPT_POLYGON
01734 && psObject->nSHPType != SHPT_POLYGONZ
01735 && psObject->nSHPType != SHPT_POLYGONM )
01736 return 0;
01737
01738
01739
01740
01741 for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
01742 {
01743 int bInner, iVert, nVertCount, nVertStart, iCheckRing;
01744 double dfSum, dfTestX, dfTestY;
01745
01746
01747
01748
01749
01750
01751
01752
01753 dfTestX = psObject->padfX[psObject->panPartStart[iOpRing]];
01754 dfTestY = psObject->padfY[psObject->panPartStart[iOpRing]];
01755
01756 bInner = FALSE;
01757 for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
01758 {
01759 int iEdge;
01760
01761 if( iCheckRing == iOpRing )
01762 continue;
01763
01764 nVertStart = psObject->panPartStart[iCheckRing];
01765
01766 if( iCheckRing == psObject->nParts-1 )
01767 nVertCount = psObject->nVertices
01768 - psObject->panPartStart[iCheckRing];
01769 else
01770 nVertCount = psObject->panPartStart[iCheckRing+1]
01771 - psObject->panPartStart[iCheckRing];
01772
01773 for( iEdge = 0; iEdge < nVertCount; iEdge++ )
01774 {
01775 int iNext;
01776
01777 if( iEdge < nVertCount-1 )
01778 iNext = iEdge+1;
01779 else
01780 iNext = 0;
01781
01782 if( (psObject->padfY[iEdge+nVertStart] < dfTestY
01783 && psObject->padfY[iNext+nVertStart] >= dfTestY)
01784 || (psObject->padfY[iNext+nVertStart] < dfTestY
01785 && psObject->padfY[iEdge+nVertStart] >= dfTestY) )
01786 {
01787 if( psObject->padfX[iEdge+nVertStart]
01788 + (dfTestY - psObject->padfY[iEdge+nVertStart])
01789 / (psObject->padfY[iNext+nVertStart]
01790 - psObject->padfY[iEdge+nVertStart])
01791 * (psObject->padfX[iNext+nVertStart]
01792 - psObject->padfX[iEdge+nVertStart]) < dfTestX )
01793 bInner = !bInner;
01794 }
01795 }
01796 }
01797
01798
01799
01800
01801
01802 nVertStart = psObject->panPartStart[iOpRing];
01803
01804 if( iOpRing == psObject->nParts-1 )
01805 nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
01806 else
01807 nVertCount = psObject->panPartStart[iOpRing+1]
01808 - psObject->panPartStart[iOpRing];
01809
01810 dfSum = 0.0;
01811 for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ )
01812 {
01813 dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1]
01814 - psObject->padfY[iVert] * psObject->padfX[iVert+1];
01815 }
01816
01817 dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart]
01818 - psObject->padfY[iVert] * psObject->padfX[nVertStart];
01819
01820
01821
01822
01823 if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
01824 {
01825 int i;
01826
01827 bAltered++;
01828 for( i = 0; i < nVertCount/2; i++ )
01829 {
01830 double dfSaved;
01831
01832
01833 dfSaved = psObject->padfX[nVertStart+i];
01834 psObject->padfX[nVertStart+i] =
01835 psObject->padfX[nVertStart+nVertCount-i-1];
01836 psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
01837
01838
01839 dfSaved = psObject->padfY[nVertStart+i];
01840 psObject->padfY[nVertStart+i] =
01841 psObject->padfY[nVertStart+nVertCount-i-1];
01842 psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
01843
01844
01845 if( psObject->padfZ )
01846 {
01847 dfSaved = psObject->padfZ[nVertStart+i];
01848 psObject->padfZ[nVertStart+i] =
01849 psObject->padfZ[nVertStart+nVertCount-i-1];
01850 psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
01851 }
01852
01853
01854 if( psObject->padfM )
01855 {
01856 dfSaved = psObject->padfM[nVertStart+i];
01857 psObject->padfM[nVertStart+i] =
01858 psObject->padfM[nVertStart+nVertCount-i-1];
01859 psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
01860 }
01861 }
01862 }
01863 }
01864
01865 return bAltered;
01866 }