34 |
****************************************************************************** |
****************************************************************************** |
35 |
* |
* |
36 |
* $Log$ |
* $Log$ |
37 |
* Revision 1.1 2003/08/19 21:29:25 jan |
* Revision 1.3 2004/05/17 15:47:57 bh |
38 |
* These files have been moved here from thuban/extensions/shapelib/ |
* Update to newest shapelib and get rid of Thuban specific extensions, |
39 |
* See there in the Attic for the older history. |
* i.e. use the new DBFUpdateHeader instead of our DBFCommit kludge |
40 |
* |
* |
41 |
* Revision 1.3 2002/05/07 14:09:45 bh |
* * libraries/shapelib/shpopen.c: Update to version from current |
42 |
* * extensions/shapelib/shpopen.c, extensions/shapelib/shapefil.h, |
* shapelib CVS. |
43 |
* extensions/shapelib/dbfopen.c: Really update to the versions of |
* |
44 |
* shapelib 1.2.9. For some reason it wasn't really done on |
* * libraries/shapelib/shapefil.h: Update to version from current |
45 |
* 2002-04-11. |
* shapelib CVS. |
46 |
|
* |
47 |
|
* * libraries/shapelib/dbfopen.c: Update to version from current |
48 |
|
* shapelib CVS. |
49 |
|
* (DBFCommit): Effectively removed since shapelib itself has |
50 |
|
* DBFUpdateHeader now which is better for what DBFCommit wanted to |
51 |
|
* achieve. |
52 |
|
* We're now using an unmodified version of dbfopen. |
53 |
|
* |
54 |
|
* * libraries/pyshapelib/dbflib_wrap.c, libraries/pyshapelib/dbflib.py: |
55 |
|
* Update from dbflib.i |
56 |
|
* |
57 |
|
* * libraries/pyshapelib/dbflib.i (DBFInfo_commit): New. Implementation of |
58 |
|
* the commit method. This new indirection is necessary because we use the |
59 |
|
* DBFUpdateHeader function now which is not available in shapelib <= |
60 |
|
* 1.2.10 |
61 |
|
* (DBFFile::commit): Use DBFInfo_commit as implementation |
62 |
|
* (pragma __class__): New. Kludge to remove the commit method when |
63 |
|
* the DBFUpdateHeader function isn't available |
64 |
|
* (_have_commit): New. Helper for the pragma kludge. |
65 |
|
* |
66 |
|
* * libraries/pyshapelib/setup.py (dbf_macros): New. Return the |
67 |
|
* preprocessor macros needed to compile the dbflib wrapper. Determine |
68 |
|
* whether DBFUpdateHeader is available and define the right value of |
69 |
|
* HAVE_UPDATE_HEADER |
70 |
|
* (extensions): Use dbf_macros for the dbflibc extension |
71 |
|
* |
72 |
|
* * setup.py (extensions): Add the HAVE_UPDATE_HEADER macro with |
73 |
|
* value '1' to the Lib.dbflibc extension. This simply reflects the |
74 |
|
* shapelib and pyshapelib updates |
75 |
|
* |
76 |
|
* Revision 1.44 2003/12/29 00:18:39 fwarmerdam |
77 |
|
* added error checking for failed IO and optional CPL error reporting |
78 |
|
* |
79 |
|
* Revision 1.43 2003/12/01 16:20:08 warmerda |
80 |
|
* be careful of zero vertex shapes |
81 |
|
* |
82 |
|
* Revision 1.42 2003/12/01 14:58:27 warmerda |
83 |
|
* added degenerate object check in SHPRewindObject() |
84 |
|
* |
85 |
|
* Revision 1.41 2003/07/08 15:22:43 warmerda |
86 |
|
* avoid warning |
87 |
|
* |
88 |
|
* Revision 1.40 2003/04/21 18:30:37 warmerda |
89 |
|
* added header write/update public methods |
90 |
|
* |
91 |
|
* Revision 1.39 2002/08/26 06:46:56 warmerda |
92 |
|
* avoid c++ comments |
93 |
|
* |
94 |
|
* Revision 1.38 2002/05/07 16:43:39 warmerda |
95 |
|
* Removed debugging printf. |
96 |
|
* |
97 |
|
* Revision 1.37 2002/04/10 17:35:22 warmerda |
98 |
|
* fixed bug in ring reversal code |
99 |
|
* |
100 |
|
* Revision 1.36 2002/04/10 16:59:54 warmerda |
101 |
|
* added SHPRewindObject |
102 |
|
* |
103 |
|
* Revision 1.35 2001/12/07 15:10:44 warmerda |
104 |
|
* fix if .shx fails to open |
105 |
|
* |
106 |
|
* Revision 1.34 2001/11/01 16:29:55 warmerda |
107 |
|
* move pabyRec into SHPInfo for thread safety |
108 |
* |
* |
109 |
* Revision 1.33 2001/07/03 12:18:15 warmerda |
* Revision 1.33 2001/07/03 12:18:15 warmerda |
110 |
* Improved cleanup if SHX not found, provied by Riccardo Cohen. |
* Improved cleanup if SHX not found, provied by Riccardo Cohen. |
243 |
#endif |
#endif |
244 |
|
|
245 |
static int bBigEndian; |
static int bBigEndian; |
|
static uchar *pabyRec = NULL; |
|
|
static int nBufSize = 0; |
|
246 |
|
|
247 |
|
|
248 |
/************************************************************************/ |
/************************************************************************/ |
288 |
/* contents of the index (.shx) file. */ |
/* contents of the index (.shx) file. */ |
289 |
/************************************************************************/ |
/************************************************************************/ |
290 |
|
|
291 |
static void SHPWriteHeader( SHPHandle psSHP ) |
void SHPWriteHeader( SHPHandle psSHP ) |
292 |
|
|
293 |
{ |
{ |
294 |
uchar abyHeader[100]; |
uchar abyHeader[100]; |
353 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
354 |
/* Write .shp file header. */ |
/* Write .shp file header. */ |
355 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
356 |
fseek( psSHP->fpSHP, 0, 0 ); |
if( fseek( psSHP->fpSHP, 0, 0 ) != 0 |
357 |
fwrite( abyHeader, 100, 1, psSHP->fpSHP ); |
|| fwrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 ) |
358 |
|
{ |
359 |
|
#ifdef USE_CPL |
360 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
361 |
|
"Failure writing .shp header." ); |
362 |
|
#endif |
363 |
|
return; |
364 |
|
} |
365 |
|
|
366 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
367 |
/* Prepare, and write .shx file header. */ |
/* Prepare, and write .shx file header. */ |
370 |
ByteCopy( &i32, abyHeader+24, 4 ); |
ByteCopy( &i32, abyHeader+24, 4 ); |
371 |
if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); |
if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); |
372 |
|
|
373 |
fseek( psSHP->fpSHX, 0, 0 ); |
if( fseek( psSHP->fpSHX, 0, 0 ) != 0 |
374 |
fwrite( abyHeader, 100, 1, psSHP->fpSHX ); |
|| fwrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 ) |
375 |
|
{ |
376 |
|
#ifdef USE_CPL |
377 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
378 |
|
"Failure writing .shx header." ); |
379 |
|
#endif |
380 |
|
return; |
381 |
|
} |
382 |
|
|
383 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
384 |
/* Write out the .shx contents. */ |
/* Write out the .shx contents. */ |
393 |
if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 ); |
if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 ); |
394 |
} |
} |
395 |
|
|
396 |
fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX ); |
if( fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX ) |
397 |
|
!= psSHP->nRecords ) |
398 |
|
{ |
399 |
|
#ifdef USE_CPL |
400 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
401 |
|
"Failure writing .shx contents." ); |
402 |
|
#endif |
403 |
|
} |
404 |
|
|
405 |
free( panSHX ); |
free( panSHX ); |
406 |
|
|
407 |
|
/* -------------------------------------------------------------------- */ |
408 |
|
/* Flush to disk. */ |
409 |
|
/* -------------------------------------------------------------------- */ |
410 |
|
fflush( psSHP->fpSHP ); |
411 |
|
fflush( psSHP->fpSHX ); |
412 |
} |
} |
413 |
|
|
414 |
/************************************************************************/ |
/************************************************************************/ |
415 |
/* SHPOpen() */ |
/* shpopen() */ |
416 |
/* */ |
/* */ |
417 |
/* Open the .shp and .shx files based on the basename of the */ |
/* Open the .shp and .shx files based on the basename of the */ |
418 |
/* files or either file name. */ |
/* files or either file name. */ |
423 |
|
|
424 |
{ |
{ |
425 |
char *pszFullname, *pszBasename; |
char *pszFullname, *pszBasename; |
426 |
SHPHandle psSHP; |
FILE *fpSHP, *fpSHX; |
|
|
|
|
uchar *pabyBuf; |
|
427 |
int i; |
int i; |
|
double dValue; |
|
428 |
|
|
429 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
430 |
/* Ensure the access string is one of the legal ones. We */ |
/* Ensure the access string is one of the legal ones. We */ |
447 |
bBigEndian = TRUE; |
bBigEndian = TRUE; |
448 |
|
|
449 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
|
/* Initialize the info structure. */ |
|
|
/* -------------------------------------------------------------------- */ |
|
|
psSHP = (SHPHandle) malloc(sizeof(SHPInfo)); |
|
|
|
|
|
psSHP->bUpdated = FALSE; |
|
|
|
|
|
/* -------------------------------------------------------------------- */ |
|
450 |
/* Compute the base (layer) name. If there is any extension */ |
/* Compute the base (layer) name. If there is any extension */ |
451 |
/* on the passed in filename we will strip it off. */ |
/* on the passed in filename we will strip it off. */ |
452 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
466 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
467 |
pszFullname = (char *) malloc(strlen(pszBasename) + 5); |
pszFullname = (char *) malloc(strlen(pszBasename) + 5); |
468 |
sprintf( pszFullname, "%s.shp", pszBasename ); |
sprintf( pszFullname, "%s.shp", pszBasename ); |
469 |
psSHP->fpSHP = fopen(pszFullname, pszAccess ); |
fpSHP = fopen(pszFullname, pszAccess ); |
470 |
if( psSHP->fpSHP == NULL ) |
if( fpSHP == NULL ) |
471 |
{ |
{ |
472 |
sprintf( pszFullname, "%s.SHP", pszBasename ); |
sprintf( pszFullname, "%s.SHP", pszBasename ); |
473 |
psSHP->fpSHP = fopen(pszFullname, pszAccess ); |
fpSHP = fopen(pszFullname, pszAccess ); |
474 |
} |
} |
475 |
|
|
476 |
if( psSHP->fpSHP == NULL ) |
if( fpSHP == NULL ) |
477 |
{ |
{ |
478 |
free( psSHP ); |
#ifdef USE_CPL |
479 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
480 |
|
"Unable to open %s.shp or %s.SHP.", |
481 |
|
pszBasename, pszBasename ); |
482 |
|
#endif |
483 |
free( pszBasename ); |
free( pszBasename ); |
484 |
free( pszFullname ); |
free( pszFullname ); |
485 |
return( NULL ); |
return( NULL ); |
486 |
} |
} |
487 |
|
|
488 |
sprintf( pszFullname, "%s.shx", pszBasename ); |
sprintf( pszFullname, "%s.shx", pszBasename ); |
489 |
psSHP->fpSHX = fopen(pszFullname, pszAccess ); |
fpSHX = fopen(pszFullname, pszAccess ); |
490 |
if( psSHP->fpSHX == NULL ) |
if( fpSHX == NULL ) |
491 |
{ |
{ |
492 |
sprintf( pszFullname, "%s.SHX", pszBasename ); |
sprintf( pszFullname, "%s.SHX", pszBasename ); |
493 |
psSHP->fpSHX = fopen(pszFullname, pszAccess ); |
fpSHX = fopen(pszFullname, pszAccess ); |
494 |
|
} |
495 |
|
|
496 |
|
if( fpSHX == NULL ) |
497 |
|
{ |
498 |
|
#ifdef USE_CPL |
499 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
500 |
|
"Unable to open %s.shx or %s.SHX.", |
501 |
|
pszBasename, pszBasename ); |
502 |
|
#endif |
503 |
|
fclose( fpSHP ); |
504 |
|
free( pszBasename ); |
505 |
|
free( pszFullname ); |
506 |
|
return( NULL ); |
507 |
|
} |
508 |
|
|
509 |
|
free( pszFullname ); |
510 |
|
free( pszBasename ); |
511 |
|
|
512 |
|
return SHPOpenEx( fpSHP, fpSHX ); |
513 |
|
} |
514 |
|
|
515 |
|
|
516 |
|
/************************************************************************/ |
517 |
|
/* SHPOpenW() */ |
518 |
|
/* */ |
519 |
|
/* Open the .shp and .shx files based on the basename of the */ |
520 |
|
/* files or either file name, for wide character filenames */ |
521 |
|
/************************************************************************/ |
522 |
|
|
523 |
|
#ifdef SHPAPI_HAS_WIDE |
524 |
|
|
525 |
|
SHPHandle SHPAPI_CALL |
526 |
|
SHPOpenW( const wchar_t * pszLayer, const wchar_t * pszAccess ) |
527 |
|
|
528 |
|
{ |
529 |
|
wchar_t *pszFullname, *pszBasename; |
530 |
|
FILE *fpSHP, *fpSHX; |
531 |
|
int i; |
532 |
|
|
533 |
|
/* -------------------------------------------------------------------- */ |
534 |
|
/* Ensure the access string is one of the legal ones. We */ |
535 |
|
/* ensure the result string indicates binary to avoid common */ |
536 |
|
/* problems on Windows. */ |
537 |
|
/* -------------------------------------------------------------------- */ |
538 |
|
if( wcscmp(pszAccess,L"rb+") == 0 || wcscmp(pszAccess,L"r+b") == 0 |
539 |
|
|| wcscmp(pszAccess,L"r+") == 0 ) |
540 |
|
pszAccess = L"r+b"; |
541 |
|
else |
542 |
|
pszAccess = L"rb"; |
543 |
|
|
544 |
|
/* -------------------------------------------------------------------- */ |
545 |
|
/* Compute the base (layer) name. If there is any extension */ |
546 |
|
/* on the passed in filename we will strip it off. */ |
547 |
|
/* -------------------------------------------------------------------- */ |
548 |
|
pszBasename = (wchar_t *) malloc(sizeof(wchar_t)*(wcslen(pszLayer)+5)); |
549 |
|
wcscpy( pszBasename, pszLayer ); |
550 |
|
for( i = wcslen(pszBasename)-1; |
551 |
|
i > 0 && pszBasename[i] != L'.' && pszBasename[i] != L'/' |
552 |
|
&& pszBasename[i] != L'\\'; |
553 |
|
i-- ) {} |
554 |
|
|
555 |
|
if( pszBasename[i] == L'.' ) |
556 |
|
pszBasename[i] = L'\0'; |
557 |
|
|
558 |
|
/* -------------------------------------------------------------------- */ |
559 |
|
/* Open the .shp and .shx files. Note that files pulled from */ |
560 |
|
/* a PC to Unix with upper case filenames won't work! */ |
561 |
|
/* -------------------------------------------------------------------- */ |
562 |
|
pszFullname = (wchar_t *) malloc(sizeof(wchar_t)*(wcslen(pszBasename) + 5)); |
563 |
|
swprintf( pszFullname, L"%s.shp", pszBasename ); |
564 |
|
fpSHP = _wfopen(pszFullname, pszAccess ); |
565 |
|
if( fpSHP == NULL ) |
566 |
|
{ |
567 |
|
swprintf( pszFullname, L"%s.SHP", pszBasename ); |
568 |
|
fpSHP = _wfopen(pszFullname, pszAccess ); |
569 |
} |
} |
570 |
|
|
571 |
if( psSHP->fpSHX == NULL ) |
if( fpSHP == NULL ) |
572 |
|
{ |
573 |
|
#ifdef USE_CPL |
574 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
575 |
|
"Unable to open .shp file." ); |
576 |
|
#endif |
577 |
|
free( pszBasename ); |
578 |
|
free( pszFullname ); |
579 |
|
return( NULL ); |
580 |
|
} |
581 |
|
|
582 |
|
swprintf( pszFullname, L"%s.shx", pszBasename ); |
583 |
|
fpSHX = _wfopen(pszFullname, pszAccess ); |
584 |
|
if( fpSHX == NULL ) |
585 |
|
{ |
586 |
|
swprintf( pszFullname, L"%s.SHX", pszBasename ); |
587 |
|
fpSHX = _wfopen(pszFullname, pszAccess ); |
588 |
|
} |
589 |
|
|
590 |
|
if( fpSHX == NULL ) |
591 |
{ |
{ |
592 |
fclose( psSHP->fpSHX ); |
#ifdef USE_CPL |
593 |
free( psSHP ); |
CPLError( CE_Failure, CPLE_OpenFailed, |
594 |
|
"Unable to open .shx file." ); |
595 |
|
#endif |
596 |
|
fclose( fpSHP ); |
597 |
free( pszBasename ); |
free( pszBasename ); |
598 |
free( pszFullname ); |
free( pszFullname ); |
599 |
return( NULL ); |
return( NULL ); |
602 |
free( pszFullname ); |
free( pszFullname ); |
603 |
free( pszBasename ); |
free( pszBasename ); |
604 |
|
|
605 |
|
return SHPOpenEx( fpSHP, fpSHX ); |
606 |
|
} |
607 |
|
|
608 |
|
#endif |
609 |
|
|
610 |
|
/************************************************************************/ |
611 |
|
/* shpopen() */ |
612 |
|
/* */ |
613 |
|
/* Open the .shp and .shx files based on the basename of the */ |
614 |
|
/* files or either file name. */ |
615 |
|
/************************************************************************/ |
616 |
|
|
617 |
|
SHPHandle SHPAPI_CALL |
618 |
|
SHPOpenEx( FILE * fpSHP, FILE * fpSHX ) |
619 |
|
{ |
620 |
|
SHPHandle psSHP; |
621 |
|
uchar *pabyBuf; |
622 |
|
int i; |
623 |
|
double dValue; |
624 |
|
|
625 |
|
/* -------------------------------------------------------------------- */ |
626 |
|
/* Establish the byte order on this machine. */ |
627 |
|
/* -------------------------------------------------------------------- */ |
628 |
|
i = 1; |
629 |
|
if( *((uchar *) &i) == 1 ) |
630 |
|
bBigEndian = FALSE; |
631 |
|
else |
632 |
|
bBigEndian = TRUE; |
633 |
|
|
634 |
|
/* -------------------------------------------------------------------- */ |
635 |
|
/* Initialize the info structure. */ |
636 |
|
/* -------------------------------------------------------------------- */ |
637 |
|
psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1); |
638 |
|
|
639 |
|
psSHP->fpSHP = fpSHP; |
640 |
|
psSHP->fpSHX = fpSHX; |
641 |
|
psSHP->bUpdated = FALSE; |
642 |
|
|
643 |
|
|
644 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
645 |
/* Read the file size from the SHP file. */ |
/* Read the file size from the SHP file. */ |
646 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
655 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
656 |
/* Read SHX file Header info */ |
/* Read SHX file Header info */ |
657 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
658 |
fread( pabyBuf, 100, 1, psSHP->fpSHX ); |
if( fread( pabyBuf, 100, 1, psSHP->fpSHX ) != 1 |
659 |
|
|| pabyBuf[0] != 0 |
|
if( pabyBuf[0] != 0 |
|
660 |
|| pabyBuf[1] != 0 |
|| pabyBuf[1] != 0 |
661 |
|| pabyBuf[2] != 0x27 |
|| pabyBuf[2] != 0x27 |
662 |
|| (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) ) |
|| (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) ) |
663 |
{ |
{ |
664 |
|
#ifdef USE_CPL |
665 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
666 |
|
".shx file is unreadable, or corrupt." ); |
667 |
|
#endif |
668 |
fclose( psSHP->fpSHP ); |
fclose( psSHP->fpSHP ); |
669 |
fclose( psSHP->fpSHX ); |
fclose( psSHP->fpSHX ); |
670 |
free( psSHP ); |
free( psSHP ); |
680 |
|
|
681 |
if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 ) |
if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 ) |
682 |
{ |
{ |
683 |
/* this header appears to be corrupt. Give up. */ |
#ifdef USE_CPL |
684 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
685 |
|
"Record count in .shp header is %d, which seems\n" |
686 |
|
"unreasonable. Assuming header is corrupt.", |
687 |
|
psSHP->nRecords ); |
688 |
|
#endif |
689 |
fclose( psSHP->fpSHP ); |
fclose( psSHP->fpSHP ); |
690 |
fclose( psSHP->fpSHX ); |
fclose( psSHP->fpSHX ); |
691 |
free( psSHP ); |
free( psSHP ); |
742 |
(int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) ); |
(int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) ); |
743 |
|
|
744 |
pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) ); |
pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) ); |
745 |
fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ); |
if( fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ) != psSHP->nRecords ) |
746 |
|
{ |
747 |
|
#ifdef USE_CPL |
748 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
749 |
|
"Failed to read all values for %d records in .shx file.", |
750 |
|
psSHP->nRecords ); |
751 |
|
#endif |
752 |
|
/* SHX is short or unreadable for some reason. */ |
753 |
|
fclose( psSHP->fpSHP ); |
754 |
|
fclose( psSHP->fpSHX ); |
755 |
|
free( psSHP->panRecOffset ); |
756 |
|
free( psSHP->panRecSize ); |
757 |
|
free( psSHP ); |
758 |
|
|
759 |
|
return( NULL ); |
760 |
|
} |
761 |
|
|
762 |
for( i = 0; i < psSHP->nRecords; i++ ) |
for( i = 0; i < psSHP->nRecords; i++ ) |
763 |
{ |
{ |
787 |
SHPClose(SHPHandle psSHP ) |
SHPClose(SHPHandle psSHP ) |
788 |
|
|
789 |
{ |
{ |
790 |
|
if( psSHP == NULL ) |
791 |
|
return; |
792 |
|
|
793 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
794 |
/* Update the header if we have modified anything. */ |
/* Update the header if we have modified anything. */ |
795 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
796 |
if( psSHP->bUpdated ) |
if( psSHP->bUpdated ) |
|
{ |
|
797 |
SHPWriteHeader( psSHP ); |
SHPWriteHeader( psSHP ); |
|
} |
|
798 |
|
|
799 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
800 |
/* Free all resources, and close files. */ |
/* Free all resources, and close files. */ |
805 |
fclose( psSHP->fpSHX ); |
fclose( psSHP->fpSHX ); |
806 |
fclose( psSHP->fpSHP ); |
fclose( psSHP->fpSHP ); |
807 |
|
|
808 |
free( psSHP ); |
if( psSHP->pabyRec != NULL ) |
|
|
|
|
if( pabyRec != NULL ) |
|
809 |
{ |
{ |
810 |
free( pabyRec ); |
free( psSHP->pabyRec ); |
|
pabyRec = NULL; |
|
|
nBufSize = 0; |
|
811 |
} |
} |
812 |
|
|
813 |
|
free( psSHP ); |
814 |
} |
} |
815 |
|
|
816 |
/************************************************************************/ |
/************************************************************************/ |
825 |
|
|
826 |
{ |
{ |
827 |
int i; |
int i; |
828 |
|
|
829 |
|
if( psSHP == NULL ) |
830 |
|
return; |
831 |
|
|
832 |
if( pnEntities != NULL ) |
if( pnEntities != NULL ) |
833 |
*pnEntities = psSHP->nRecords; |
*pnEntities = psSHP->nRecords; |
858 |
char *pszBasename, *pszFullname; |
char *pszBasename, *pszFullname; |
859 |
int i; |
int i; |
860 |
FILE *fpSHP, *fpSHX; |
FILE *fpSHP, *fpSHX; |
|
uchar abyHeader[100]; |
|
|
int32 i32; |
|
|
double dValue; |
|
|
|
|
|
/* -------------------------------------------------------------------- */ |
|
|
/* Establish the byte order on this system. */ |
|
|
/* -------------------------------------------------------------------- */ |
|
|
i = 1; |
|
|
if( *((uchar *) &i) == 1 ) |
|
|
bBigEndian = FALSE; |
|
|
else |
|
|
bBigEndian = TRUE; |
|
861 |
|
|
862 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
863 |
/* Compute the base (layer) name. If there is any extension */ |
/* Compute the base (layer) name. If there is any extension */ |
880 |
sprintf( pszFullname, "%s.shp", pszBasename ); |
sprintf( pszFullname, "%s.shp", pszBasename ); |
881 |
fpSHP = fopen(pszFullname, "wb" ); |
fpSHP = fopen(pszFullname, "wb" ); |
882 |
if( fpSHP == NULL ) |
if( fpSHP == NULL ) |
883 |
|
{ |
884 |
|
#ifdef USE_CPL |
885 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
886 |
|
"Failed to create file %s.", |
887 |
|
pszFullname ); |
888 |
|
#endif |
889 |
return( NULL ); |
return( NULL ); |
890 |
|
} |
891 |
|
|
892 |
sprintf( pszFullname, "%s.shx", pszBasename ); |
sprintf( pszFullname, "%s.shx", pszBasename ); |
893 |
fpSHX = fopen(pszFullname, "wb" ); |
fpSHX = fopen(pszFullname, "wb" ); |
894 |
if( fpSHX == NULL ) |
if( fpSHX == NULL ) |
895 |
|
{ |
896 |
|
#ifdef USE_CPL |
897 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
898 |
|
"Failed to create file %s.", |
899 |
|
pszFullname ); |
900 |
|
#endif |
901 |
|
return( NULL ); |
902 |
|
} |
903 |
|
|
904 |
|
free( pszFullname ); |
905 |
|
free( pszBasename ); |
906 |
|
|
907 |
|
SHPCreateEx( fpSHP, fpSHX, nShapeType ); |
908 |
|
|
909 |
|
/* -------------------------------------------------------------------- */ |
910 |
|
/* Close the files, and then open them as regular existing files. */ |
911 |
|
/* -------------------------------------------------------------------- */ |
912 |
|
fclose( fpSHP ); |
913 |
|
fclose( fpSHX ); |
914 |
|
|
915 |
|
return( SHPOpen( pszLayer, "r+b" ) ); |
916 |
|
} |
917 |
|
|
918 |
|
#ifdef SHPAPI_HAS_WIDE |
919 |
|
|
920 |
|
/************************************************************************/ |
921 |
|
/* SHPCreate() */ |
922 |
|
/* */ |
923 |
|
/* Create a new shape file and return a handle to the open */ |
924 |
|
/* shape file with read/write access. */ |
925 |
|
/************************************************************************/ |
926 |
|
|
927 |
|
SHPHandle SHPAPI_CALL |
928 |
|
SHPCreateW( const wchar_t * pszLayer, int nShapeType ) |
929 |
|
|
930 |
|
{ |
931 |
|
wchar_t *pszBasename, *pszFullname; |
932 |
|
int i; |
933 |
|
FILE *fpSHP, *fpSHX; |
934 |
|
|
935 |
|
/* -------------------------------------------------------------------- */ |
936 |
|
/* Compute the base (layer) name. If there is any extension */ |
937 |
|
/* on the passed in filename we will strip it off. */ |
938 |
|
/* -------------------------------------------------------------------- */ |
939 |
|
pszBasename = (wchar_t *) malloc(sizeof(wchar_t)*(wcslen(pszLayer)+5)); |
940 |
|
wcscpy( pszBasename, pszLayer ); |
941 |
|
for( i = wcslen(pszBasename)-1; |
942 |
|
i > 0 && pszBasename[i] != L'.' && pszBasename[i] != L'/' |
943 |
|
&& pszBasename[i] != L'\\'; |
944 |
|
i-- ) {} |
945 |
|
|
946 |
|
if( pszBasename[i] == L'.' ) |
947 |
|
pszBasename[i] = L'\0'; |
948 |
|
|
949 |
|
/* -------------------------------------------------------------------- */ |
950 |
|
/* Open the two files so we can write their headers. */ |
951 |
|
/* -------------------------------------------------------------------- */ |
952 |
|
pszFullname = (wchar_t *) malloc(sizeof(wchar_t)*(wcslen(pszBasename) + 5)); |
953 |
|
swprintf( pszFullname, L"%s.shp", pszBasename ); |
954 |
|
fpSHP = _wfopen(pszFullname, L"wb" ); |
955 |
|
if( fpSHP == NULL ) |
956 |
|
{ |
957 |
|
#ifdef USE_CPL |
958 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
959 |
|
"Failed to create file." ); |
960 |
|
#endif |
961 |
|
return( NULL ); |
962 |
|
} |
963 |
|
|
964 |
|
swprintf( pszFullname, L"%s.shx", pszBasename ); |
965 |
|
fpSHX = _wfopen(pszFullname, L"wb" ); |
966 |
|
if( fpSHX == NULL ) |
967 |
|
{ |
968 |
|
#ifdef USE_CPL |
969 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
970 |
|
"Failed to create file." ); |
971 |
|
#endif |
972 |
return( NULL ); |
return( NULL ); |
973 |
|
} |
974 |
|
|
975 |
free( pszFullname ); |
free( pszFullname ); |
976 |
free( pszBasename ); |
free( pszBasename ); |
977 |
|
|
978 |
|
SHPCreateEx( fpSHP, fpSHX, nShapeType ); |
979 |
|
|
980 |
|
/* -------------------------------------------------------------------- */ |
981 |
|
/* Close the files, and then open them as regular existing files. */ |
982 |
|
/* -------------------------------------------------------------------- */ |
983 |
|
fclose( fpSHP ); |
984 |
|
fclose( fpSHX ); |
985 |
|
|
986 |
|
return( SHPOpenW( pszLayer, L"r+b" ) ); |
987 |
|
} |
988 |
|
|
989 |
|
#endif |
990 |
|
|
991 |
|
/************************************************************************/ |
992 |
|
/* SHPCreateEx() */ |
993 |
|
/* */ |
994 |
|
/* Create a new shape file and return a handle to the open */ |
995 |
|
/* shape file with read/write access. */ |
996 |
|
/************************************************************************/ |
997 |
|
|
998 |
|
void SHPAPI_CALL |
999 |
|
SHPCreateEx( FILE * fpSHP, FILE * fpSHX, int nShapeType ) |
1000 |
|
|
1001 |
|
{ |
1002 |
|
int i; |
1003 |
|
uchar abyHeader[100]; |
1004 |
|
int32 i32; |
1005 |
|
double dValue; |
1006 |
|
|
1007 |
|
/* -------------------------------------------------------------------- */ |
1008 |
|
/* Establish the byte order on this system. */ |
1009 |
|
/* -------------------------------------------------------------------- */ |
1010 |
|
i = 1; |
1011 |
|
if( *((uchar *) &i) == 1 ) |
1012 |
|
bBigEndian = FALSE; |
1013 |
|
else |
1014 |
|
bBigEndian = TRUE; |
1015 |
|
|
1016 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1017 |
/* Prepare header block for .shp file. */ |
/* Prepare header block for .shp file. */ |
1018 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1043 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1044 |
/* Write .shp file header. */ |
/* Write .shp file header. */ |
1045 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1046 |
fwrite( abyHeader, 100, 1, fpSHP ); |
if( fwrite( abyHeader, 100, 1, fpSHP ) != 1 ) |
1047 |
|
{ |
1048 |
|
#ifdef USE_CPL |
1049 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
1050 |
|
"Failed to write .shp header." ); |
1051 |
|
#endif |
1052 |
|
return; |
1053 |
|
} |
1054 |
|
|
1055 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1056 |
/* Prepare, and write .shx file header. */ |
/* Prepare, and write .shx file header. */ |
1059 |
ByteCopy( &i32, abyHeader+24, 4 ); |
ByteCopy( &i32, abyHeader+24, 4 ); |
1060 |
if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); |
if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); |
1061 |
|
|
1062 |
fwrite( abyHeader, 100, 1, fpSHX ); |
if( fwrite( abyHeader, 100, 1, fpSHX ) != 1 ) |
1063 |
|
{ |
1064 |
/* -------------------------------------------------------------------- */ |
#ifdef USE_CPL |
1065 |
/* Close the files, and then open them as regular existing files. */ |
CPLError( CE_Failure, CPLE_AppDefined, |
1066 |
/* -------------------------------------------------------------------- */ |
"Failed to write .shx header." ); |
1067 |
fclose( fpSHP ); |
#endif |
1068 |
fclose( fpSHX ); |
return; |
1069 |
|
} |
|
return( SHPOpen( pszLayer, "r+b" ) ); |
|
1070 |
} |
} |
1071 |
|
|
1072 |
|
|
1073 |
/************************************************************************/ |
/************************************************************************/ |
1074 |
/* _SHPSetBounds() */ |
/* _SHPSetBounds() */ |
1075 |
/* */ |
/* */ |
1270 |
SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject ) |
SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject ) |
1271 |
|
|
1272 |
{ |
{ |
1273 |
int nRecordOffset, i, nRecordSize; |
int nRecordOffset, i, nRecordSize=0; |
1274 |
uchar *pabyRec; |
uchar *pabyRec; |
1275 |
int32 i32; |
int32 i32; |
1276 |
|
|
1584 |
if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 |
if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 |
1585 |
|| fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 ) |
|| fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 ) |
1586 |
{ |
{ |
1587 |
printf( "Error in fseek() or fwrite().\n" ); |
#ifdef USE_CPL |
1588 |
|
CPLError( CE_Failure, CPLE_FileIO, |
1589 |
|
"Error in fseek() or fwrite() writing object to .shp file." ); |
1590 |
|
#endif |
1591 |
free( pabyRec ); |
free( pabyRec ); |
1592 |
return -1; |
return -1; |
1593 |
} |
} |
1600 |
if( psSHP->adBoundsMin[0] == 0.0 |
if( psSHP->adBoundsMin[0] == 0.0 |
1601 |
&& psSHP->adBoundsMax[0] == 0.0 |
&& psSHP->adBoundsMax[0] == 0.0 |
1602 |
&& psSHP->adBoundsMin[1] == 0.0 |
&& psSHP->adBoundsMin[1] == 0.0 |
1603 |
&& psSHP->adBoundsMax[1] == 0.0 |
&& psSHP->adBoundsMax[1] == 0.0 ) |
|
&& psObject->nSHPType != SHPT_NULL ) |
|
1604 |
{ |
{ |
1605 |
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0]; |
if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 ) |
1606 |
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0]; |
{ |
1607 |
psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0]; |
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0; |
1608 |
psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0]; |
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0; |
1609 |
|
psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = 0.0; |
1610 |
|
psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = 0.0; |
1611 |
|
} |
1612 |
|
else |
1613 |
|
{ |
1614 |
|
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0]; |
1615 |
|
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0]; |
1616 |
|
psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0]; |
1617 |
|
psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0]; |
1618 |
|
} |
1619 |
} |
} |
1620 |
|
|
1621 |
for( i = 0; i < psObject->nVertices; i++ ) |
for( i = 0; i < psObject->nVertices; i++ ) |
1655 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1656 |
/* Ensure our record buffer is large enough. */ |
/* Ensure our record buffer is large enough. */ |
1657 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1658 |
if( psSHP->panRecSize[hEntity]+8 > nBufSize ) |
if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize ) |
1659 |
{ |
{ |
1660 |
nBufSize = psSHP->panRecSize[hEntity]+8; |
psSHP->nBufSize = psSHP->panRecSize[hEntity]+8; |
1661 |
pabyRec = (uchar *) SfRealloc(pabyRec,nBufSize); |
psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize); |
1662 |
} |
} |
1663 |
|
|
1664 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1665 |
/* Read the record. */ |
/* Read the record. */ |
1666 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1667 |
fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ); |
if( fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 |
1668 |
fread( pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP ); |
|| fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, |
1669 |
|
psSHP->fpSHP ) != 1 ) |
1670 |
|
{ |
1671 |
|
#ifdef USE_CPL |
1672 |
|
CPLError( CE_Failure, CPLE_FileIO, |
1673 |
|
"Error in fseek() or fread() reading object from .shp file." ); |
1674 |
|
#endif |
1675 |
|
return NULL; |
1676 |
|
} |
1677 |
|
|
1678 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1679 |
/* Allocate and minimally initialize the object. */ |
/* Allocate and minimally initialize the object. */ |
1681 |
psShape = (SHPObject *) calloc(1,sizeof(SHPObject)); |
psShape = (SHPObject *) calloc(1,sizeof(SHPObject)); |
1682 |
psShape->nShapeId = hEntity; |
psShape->nShapeId = hEntity; |
1683 |
|
|
1684 |
memcpy( &psShape->nSHPType, pabyRec + 8, 4 ); |
memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 ); |
1685 |
if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) ); |
if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) ); |
1686 |
|
|
1687 |
/* ==================================================================== */ |
/* ==================================================================== */ |
1700 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1701 |
/* Get the X/Y bounds. */ |
/* Get the X/Y bounds. */ |
1702 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1703 |
memcpy( &(psShape->dfXMin), pabyRec + 8 + 4, 8 ); |
memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 ); |
1704 |
memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 ); |
memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 ); |
1705 |
memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 ); |
memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 ); |
1706 |
memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 ); |
memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 ); |
1707 |
|
|
1708 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
1709 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
1714 |
/* Extract part/point count, and build vertex and part arrays */ |
/* Extract part/point count, and build vertex and part arrays */ |
1715 |
/* to proper size. */ |
/* to proper size. */ |
1716 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1717 |
memcpy( &nPoints, pabyRec + 40 + 8, 4 ); |
memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 ); |
1718 |
memcpy( &nParts, pabyRec + 36 + 8, 4 ); |
memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 ); |
1719 |
|
|
1720 |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
1721 |
if( bBigEndian ) SwapWord( 4, &nParts ); |
if( bBigEndian ) SwapWord( 4, &nParts ); |
1736 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1737 |
/* Copy out the part array from the record. */ |
/* Copy out the part array from the record. */ |
1738 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1739 |
memcpy( psShape->panPartStart, pabyRec + 44 + 8, 4 * nParts ); |
memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts ); |
1740 |
for( i = 0; i < nParts; i++ ) |
for( i = 0; i < nParts; i++ ) |
1741 |
{ |
{ |
1742 |
if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i ); |
if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i ); |
1749 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1750 |
if( psShape->nSHPType == SHPT_MULTIPATCH ) |
if( psShape->nSHPType == SHPT_MULTIPATCH ) |
1751 |
{ |
{ |
1752 |
memcpy( psShape->panPartType, pabyRec + nOffset, 4*nParts ); |
memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts ); |
1753 |
for( i = 0; i < nParts; i++ ) |
for( i = 0; i < nParts; i++ ) |
1754 |
{ |
{ |
1755 |
if( bBigEndian ) SwapWord( 4, psShape->panPartType+i ); |
if( bBigEndian ) SwapWord( 4, psShape->panPartType+i ); |
1764 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1765 |
{ |
{ |
1766 |
memcpy(psShape->padfX + i, |
memcpy(psShape->padfX + i, |
1767 |
pabyRec + nOffset + i * 16, |
psSHP->pabyRec + nOffset + i * 16, |
1768 |
8 ); |
8 ); |
1769 |
|
|
1770 |
memcpy(psShape->padfY + i, |
memcpy(psShape->padfY + i, |
1771 |
pabyRec + nOffset + i * 16 + 8, |
psSHP->pabyRec + nOffset + i * 16 + 8, |
1772 |
8 ); |
8 ); |
1773 |
|
|
1774 |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
1784 |
|| psShape->nSHPType == SHPT_ARCZ |
|| psShape->nSHPType == SHPT_ARCZ |
1785 |
|| psShape->nSHPType == SHPT_MULTIPATCH ) |
|| psShape->nSHPType == SHPT_MULTIPATCH ) |
1786 |
{ |
{ |
1787 |
memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 ); |
1788 |
memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1789 |
|
|
1790 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
1791 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
1793 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1794 |
{ |
{ |
1795 |
memcpy( psShape->padfZ + i, |
memcpy( psShape->padfZ + i, |
1796 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1797 |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
1798 |
} |
} |
1799 |
|
|
1808 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1809 |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
1810 |
{ |
{ |
1811 |
memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 ); |
1812 |
memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1813 |
|
|
1814 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
1815 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
1817 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1818 |
{ |
{ |
1819 |
memcpy( psShape->padfM + i, |
memcpy( psShape->padfM + i, |
1820 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1821 |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
1822 |
} |
} |
1823 |
} |
} |
1834 |
int32 nPoints; |
int32 nPoints; |
1835 |
int i, nOffset; |
int i, nOffset; |
1836 |
|
|
1837 |
memcpy( &nPoints, pabyRec + 44, 4 ); |
memcpy( &nPoints, psSHP->pabyRec + 44, 4 ); |
1838 |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
1839 |
|
|
1840 |
psShape->nVertices = nPoints; |
psShape->nVertices = nPoints; |
1845 |
|
|
1846 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1847 |
{ |
{ |
1848 |
memcpy(psShape->padfX+i, pabyRec + 48 + 16 * i, 8 ); |
memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 ); |
1849 |
memcpy(psShape->padfY+i, pabyRec + 48 + 16 * i + 8, 8 ); |
memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 ); |
1850 |
|
|
1851 |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
1852 |
if( bBigEndian ) SwapWord( 8, psShape->padfY + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfY + i ); |
1857 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1858 |
/* Get the X/Y bounds. */ |
/* Get the X/Y bounds. */ |
1859 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1860 |
memcpy( &(psShape->dfXMin), pabyRec + 8 + 4, 8 ); |
memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 ); |
1861 |
memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 ); |
memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 ); |
1862 |
memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 ); |
memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 ); |
1863 |
memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 ); |
memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 ); |
1864 |
|
|
1865 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
1866 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
1872 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1873 |
if( psShape->nSHPType == SHPT_MULTIPOINTZ ) |
if( psShape->nSHPType == SHPT_MULTIPOINTZ ) |
1874 |
{ |
{ |
1875 |
memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 ); |
1876 |
memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1877 |
|
|
1878 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
1879 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
1881 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1882 |
{ |
{ |
1883 |
memcpy( psShape->padfZ + i, |
memcpy( psShape->padfZ + i, |
1884 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1885 |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
1886 |
} |
} |
1887 |
|
|
1896 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1897 |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
1898 |
{ |
{ |
1899 |
memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 ); |
1900 |
memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1901 |
|
|
1902 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
1903 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
1905 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1906 |
{ |
{ |
1907 |
memcpy( psShape->padfM + i, |
memcpy( psShape->padfM + i, |
1908 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1909 |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
1910 |
} |
} |
1911 |
} |
} |
1926 |
psShape->padfZ = (double *) calloc(1,sizeof(double)); |
psShape->padfZ = (double *) calloc(1,sizeof(double)); |
1927 |
psShape->padfM = (double *) calloc(1,sizeof(double)); |
psShape->padfM = (double *) calloc(1,sizeof(double)); |
1928 |
|
|
1929 |
memcpy( psShape->padfX, pabyRec + 12, 8 ); |
memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 ); |
1930 |
memcpy( psShape->padfY, pabyRec + 20, 8 ); |
memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 ); |
1931 |
|
|
1932 |
if( bBigEndian ) SwapWord( 8, psShape->padfX ); |
if( bBigEndian ) SwapWord( 8, psShape->padfX ); |
1933 |
if( bBigEndian ) SwapWord( 8, psShape->padfY ); |
if( bBigEndian ) SwapWord( 8, psShape->padfY ); |
1939 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1940 |
if( psShape->nSHPType == SHPT_POINTZ ) |
if( psShape->nSHPType == SHPT_POINTZ ) |
1941 |
{ |
{ |
1942 |
memcpy( psShape->padfZ, pabyRec + nOffset, 8 ); |
memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 ); |
1943 |
|
|
1944 |
if( bBigEndian ) SwapWord( 8, psShape->padfZ ); |
if( bBigEndian ) SwapWord( 8, psShape->padfZ ); |
1945 |
|
|
1954 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1955 |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 ) |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 ) |
1956 |
{ |
{ |
1957 |
memcpy( psShape->padfM, pabyRec + nOffset, 8 ); |
memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 ); |
1958 |
|
|
1959 |
if( bBigEndian ) SwapWord( 8, psShape->padfM ); |
if( bBigEndian ) SwapWord( 8, psShape->padfM ); |
1960 |
} |
} |
2089 |
|
|
2090 |
free( psShape ); |
free( psShape ); |
2091 |
} |
} |
2092 |
|
|
2093 |
|
/************************************************************************/ |
2094 |
|
/* SHPRewindObject() */ |
2095 |
|
/* */ |
2096 |
|
/* Reset the winding of polygon objects to adhere to the */ |
2097 |
|
/* specification. */ |
2098 |
|
/************************************************************************/ |
2099 |
|
|
2100 |
|
int SHPAPI_CALL |
2101 |
|
SHPRewindObject( SHPHandle hSHP, SHPObject * psObject ) |
2102 |
|
|
2103 |
|
{ |
2104 |
|
int iOpRing, bAltered = 0; |
2105 |
|
|
2106 |
|
/* -------------------------------------------------------------------- */ |
2107 |
|
/* Do nothing if this is not a polygon object. */ |
2108 |
|
/* -------------------------------------------------------------------- */ |
2109 |
|
if( psObject->nSHPType != SHPT_POLYGON |
2110 |
|
&& psObject->nSHPType != SHPT_POLYGONZ |
2111 |
|
&& psObject->nSHPType != SHPT_POLYGONM ) |
2112 |
|
return 0; |
2113 |
|
|
2114 |
|
if( psObject->nVertices == 0 || psObject->nParts == 0 ) |
2115 |
|
return 0; |
2116 |
|
|
2117 |
|
/* -------------------------------------------------------------------- */ |
2118 |
|
/* Process each of the rings. */ |
2119 |
|
/* -------------------------------------------------------------------- */ |
2120 |
|
for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ ) |
2121 |
|
{ |
2122 |
|
int bInner, iVert, nVertCount, nVertStart, iCheckRing; |
2123 |
|
double dfSum, dfTestX, dfTestY; |
2124 |
|
|
2125 |
|
/* -------------------------------------------------------------------- */ |
2126 |
|
/* Determine if this ring is an inner ring or an outer ring */ |
2127 |
|
/* relative to all the other rings. For now we assume the */ |
2128 |
|
/* first ring is outer and all others are inner, but eventually */ |
2129 |
|
/* we need to fix this to handle multiple island polygons and */ |
2130 |
|
/* unordered sets of rings. */ |
2131 |
|
/* -------------------------------------------------------------------- */ |
2132 |
|
dfTestX = psObject->padfX[psObject->panPartStart[iOpRing]]; |
2133 |
|
dfTestY = psObject->padfY[psObject->panPartStart[iOpRing]]; |
2134 |
|
|
2135 |
|
bInner = FALSE; |
2136 |
|
for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ ) |
2137 |
|
{ |
2138 |
|
int iEdge; |
2139 |
|
|
2140 |
|
if( iCheckRing == iOpRing ) |
2141 |
|
continue; |
2142 |
|
|
2143 |
|
nVertStart = psObject->panPartStart[iCheckRing]; |
2144 |
|
|
2145 |
|
if( iCheckRing == psObject->nParts-1 ) |
2146 |
|
nVertCount = psObject->nVertices |
2147 |
|
- psObject->panPartStart[iCheckRing]; |
2148 |
|
else |
2149 |
|
nVertCount = psObject->panPartStart[iCheckRing+1] |
2150 |
|
- psObject->panPartStart[iCheckRing]; |
2151 |
|
|
2152 |
|
for( iEdge = 0; iEdge < nVertCount; iEdge++ ) |
2153 |
|
{ |
2154 |
|
int iNext; |
2155 |
|
|
2156 |
|
if( iEdge < nVertCount-1 ) |
2157 |
|
iNext = iEdge+1; |
2158 |
|
else |
2159 |
|
iNext = 0; |
2160 |
|
|
2161 |
|
if( (psObject->padfY[iEdge+nVertStart] < dfTestY |
2162 |
|
&& psObject->padfY[iNext+nVertStart] >= dfTestY) |
2163 |
|
|| (psObject->padfY[iNext+nVertStart] < dfTestY |
2164 |
|
&& psObject->padfY[iEdge+nVertStart] >= dfTestY) ) |
2165 |
|
{ |
2166 |
|
if( psObject->padfX[iEdge+nVertStart] |
2167 |
|
+ (dfTestY - psObject->padfY[iEdge+nVertStart]) |
2168 |
|
/ (psObject->padfY[iNext+nVertStart] |
2169 |
|
- psObject->padfY[iEdge+nVertStart]) |
2170 |
|
* (psObject->padfX[iNext+nVertStart] |
2171 |
|
- psObject->padfX[iEdge+nVertStart]) < dfTestX ) |
2172 |
|
bInner = !bInner; |
2173 |
|
} |
2174 |
|
} |
2175 |
|
} |
2176 |
|
|
2177 |
|
/* -------------------------------------------------------------------- */ |
2178 |
|
/* Determine the current order of this ring so we will know if */ |
2179 |
|
/* it has to be reversed. */ |
2180 |
|
/* -------------------------------------------------------------------- */ |
2181 |
|
nVertStart = psObject->panPartStart[iOpRing]; |
2182 |
|
|
2183 |
|
if( iOpRing == psObject->nParts-1 ) |
2184 |
|
nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing]; |
2185 |
|
else |
2186 |
|
nVertCount = psObject->panPartStart[iOpRing+1] |
2187 |
|
- psObject->panPartStart[iOpRing]; |
2188 |
|
|
2189 |
|
dfSum = 0.0; |
2190 |
|
for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ ) |
2191 |
|
{ |
2192 |
|
dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1] |
2193 |
|
- psObject->padfY[iVert] * psObject->padfX[iVert+1]; |
2194 |
|
} |
2195 |
|
|
2196 |
|
dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart] |
2197 |
|
- psObject->padfY[iVert] * psObject->padfX[nVertStart]; |
2198 |
|
|
2199 |
|
/* -------------------------------------------------------------------- */ |
2200 |
|
/* Reverse if necessary. */ |
2201 |
|
/* -------------------------------------------------------------------- */ |
2202 |
|
if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) ) |
2203 |
|
{ |
2204 |
|
int i; |
2205 |
|
|
2206 |
|
bAltered++; |
2207 |
|
for( i = 0; i < nVertCount/2; i++ ) |
2208 |
|
{ |
2209 |
|
double dfSaved; |
2210 |
|
|
2211 |
|
/* Swap X */ |
2212 |
|
dfSaved = psObject->padfX[nVertStart+i]; |
2213 |
|
psObject->padfX[nVertStart+i] = |
2214 |
|
psObject->padfX[nVertStart+nVertCount-i-1]; |
2215 |
|
psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved; |
2216 |
|
|
2217 |
|
/* Swap Y */ |
2218 |
|
dfSaved = psObject->padfY[nVertStart+i]; |
2219 |
|
psObject->padfY[nVertStart+i] = |
2220 |
|
psObject->padfY[nVertStart+nVertCount-i-1]; |
2221 |
|
psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved; |
2222 |
|
|
2223 |
|
/* Swap Z */ |
2224 |
|
if( psObject->padfZ ) |
2225 |
|
{ |
2226 |
|
dfSaved = psObject->padfZ[nVertStart+i]; |
2227 |
|
psObject->padfZ[nVertStart+i] = |
2228 |
|
psObject->padfZ[nVertStart+nVertCount-i-1]; |
2229 |
|
psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved; |
2230 |
|
} |
2231 |
|
|
2232 |
|
/* Swap M */ |
2233 |
|
if( psObject->padfM ) |
2234 |
|
{ |
2235 |
|
dfSaved = psObject->padfM[nVertStart+i]; |
2236 |
|
psObject->padfM[nVertStart+i] = |
2237 |
|
psObject->padfM[nVertStart+nVertCount-i-1]; |
2238 |
|
psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved; |
2239 |
|
} |
2240 |
|
} |
2241 |
|
} |
2242 |
|
} |
2243 |
|
|
2244 |
|
return bAltered; |
2245 |
|
} |