34 |
****************************************************************************** |
****************************************************************************** |
35 |
* |
* |
36 |
* $Log$ |
* $Log$ |
37 |
* Revision 1.2 2003/10/02 15:15:16 bh |
* Revision 1.3 2004/05/17 15:47:57 bh |
38 |
* Update to shapelib 1.2.10 |
* Update to newest shapelib and get rid of Thuban specific extensions, |
39 |
|
* i.e. use the new DBFUpdateHeader instead of our DBFCommit kludge |
40 |
|
* |
41 |
|
* * libraries/shapelib/shpopen.c: Update to version from current |
42 |
|
* shapelib CVS. |
43 |
|
* |
44 |
|
* * libraries/shapelib/shapefil.h: Update to version from current |
45 |
|
* 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 |
* Revision 1.39 2002/08/26 06:46:56 warmerda |
92 |
* avoid c++ comments |
* avoid c++ comments |
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. */ |
485 |
|
|
486 |
if( psSHP->fpSHP == NULL ) |
if( psSHP->fpSHP == NULL ) |
487 |
{ |
{ |
488 |
|
#ifdef USE_CPL |
489 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
490 |
|
"Unable to open %s.shp or %s.SHP.", |
491 |
|
pszBasename, pszBasename ); |
492 |
|
#endif |
493 |
free( psSHP ); |
free( psSHP ); |
494 |
free( pszBasename ); |
free( pszBasename ); |
495 |
free( pszFullname ); |
free( pszFullname ); |
506 |
|
|
507 |
if( psSHP->fpSHX == NULL ) |
if( psSHP->fpSHX == NULL ) |
508 |
{ |
{ |
509 |
|
#ifdef USE_CPL |
510 |
|
CPLError( CE_Failure, CPLE_OpenFailed, |
511 |
|
"Unable to open %s.shx or %s.SHX.", |
512 |
|
pszBasename, pszBasename ); |
513 |
|
#endif |
514 |
fclose( psSHP->fpSHP ); |
fclose( psSHP->fpSHP ); |
515 |
free( psSHP ); |
free( psSHP ); |
516 |
free( pszBasename ); |
free( pszBasename ); |
535 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
536 |
/* Read SHX file Header info */ |
/* Read SHX file Header info */ |
537 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
538 |
fread( pabyBuf, 100, 1, psSHP->fpSHX ); |
if( fread( pabyBuf, 100, 1, psSHP->fpSHX ) != 1 |
539 |
|
|| pabyBuf[0] != 0 |
|
if( pabyBuf[0] != 0 |
|
540 |
|| pabyBuf[1] != 0 |
|| pabyBuf[1] != 0 |
541 |
|| pabyBuf[2] != 0x27 |
|| pabyBuf[2] != 0x27 |
542 |
|| (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) ) |
|| (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) ) |
543 |
{ |
{ |
544 |
|
#ifdef USE_CPL |
545 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
546 |
|
".shx file is unreadable, or corrupt." ); |
547 |
|
#endif |
548 |
fclose( psSHP->fpSHP ); |
fclose( psSHP->fpSHP ); |
549 |
fclose( psSHP->fpSHX ); |
fclose( psSHP->fpSHX ); |
550 |
free( psSHP ); |
free( psSHP ); |
560 |
|
|
561 |
if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 ) |
if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 ) |
562 |
{ |
{ |
563 |
/* this header appears to be corrupt. Give up. */ |
#ifdef USE_CPL |
564 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
565 |
|
"Record count in .shp header is %d, which seems\n" |
566 |
|
"unreasonable. Assuming header is corrupt.", |
567 |
|
psSHP->nRecords ); |
568 |
|
#endif |
569 |
fclose( psSHP->fpSHP ); |
fclose( psSHP->fpSHP ); |
570 |
fclose( psSHP->fpSHX ); |
fclose( psSHP->fpSHX ); |
571 |
free( psSHP ); |
free( psSHP ); |
622 |
(int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) ); |
(int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) ); |
623 |
|
|
624 |
pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) ); |
pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) ); |
625 |
fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ); |
if( fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ) != psSHP->nRecords ) |
626 |
|
{ |
627 |
|
#ifdef USE_CPL |
628 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
629 |
|
"Failed to read all values for %d records in .shx file.", |
630 |
|
psSHP->nRecords ); |
631 |
|
#endif |
632 |
|
/* SHX is short or unreadable for some reason. */ |
633 |
|
fclose( psSHP->fpSHP ); |
634 |
|
fclose( psSHP->fpSHX ); |
635 |
|
free( psSHP->panRecOffset ); |
636 |
|
free( psSHP->panRecSize ); |
637 |
|
free( psSHP ); |
638 |
|
|
639 |
|
return( NULL ); |
640 |
|
} |
641 |
|
|
642 |
for( i = 0; i < psSHP->nRecords; i++ ) |
for( i = 0; i < psSHP->nRecords; i++ ) |
643 |
{ |
{ |
667 |
SHPClose(SHPHandle psSHP ) |
SHPClose(SHPHandle psSHP ) |
668 |
|
|
669 |
{ |
{ |
670 |
|
if( psSHP == NULL ) |
671 |
|
return; |
672 |
|
|
673 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
674 |
/* Update the header if we have modified anything. */ |
/* Update the header if we have modified anything. */ |
675 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
676 |
if( psSHP->bUpdated ) |
if( psSHP->bUpdated ) |
|
{ |
|
677 |
SHPWriteHeader( psSHP ); |
SHPWriteHeader( psSHP ); |
|
} |
|
678 |
|
|
679 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
680 |
/* Free all resources, and close files. */ |
/* Free all resources, and close files. */ |
705 |
|
|
706 |
{ |
{ |
707 |
int i; |
int i; |
708 |
|
|
709 |
|
if( psSHP == NULL ) |
710 |
|
return; |
711 |
|
|
712 |
if( pnEntities != NULL ) |
if( pnEntities != NULL ) |
713 |
*pnEntities = psSHP->nRecords; |
*pnEntities = psSHP->nRecords; |
772 |
sprintf( pszFullname, "%s.shp", pszBasename ); |
sprintf( pszFullname, "%s.shp", pszBasename ); |
773 |
fpSHP = fopen(pszFullname, "wb" ); |
fpSHP = fopen(pszFullname, "wb" ); |
774 |
if( fpSHP == NULL ) |
if( fpSHP == NULL ) |
775 |
|
{ |
776 |
|
#ifdef USE_CPL |
777 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
778 |
|
"Failed to create file %s.", |
779 |
|
pszFullname ); |
780 |
|
#endif |
781 |
return( NULL ); |
return( NULL ); |
782 |
|
} |
783 |
|
|
784 |
sprintf( pszFullname, "%s.shx", pszBasename ); |
sprintf( pszFullname, "%s.shx", pszBasename ); |
785 |
fpSHX = fopen(pszFullname, "wb" ); |
fpSHX = fopen(pszFullname, "wb" ); |
786 |
if( fpSHX == NULL ) |
if( fpSHX == NULL ) |
787 |
|
{ |
788 |
|
#ifdef USE_CPL |
789 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
790 |
|
"Failed to create file %s.", |
791 |
|
pszFullname ); |
792 |
|
#endif |
793 |
return( NULL ); |
return( NULL ); |
794 |
|
} |
795 |
|
|
796 |
free( pszFullname ); |
free( pszFullname ); |
797 |
free( pszBasename ); |
free( pszBasename ); |
826 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
827 |
/* Write .shp file header. */ |
/* Write .shp file header. */ |
828 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
829 |
fwrite( abyHeader, 100, 1, fpSHP ); |
if( fwrite( abyHeader, 100, 1, fpSHP ) != 1 ) |
830 |
|
{ |
831 |
|
#ifdef USE_CPL |
832 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
833 |
|
"Failed to write .shp header." ); |
834 |
|
#endif |
835 |
|
return NULL; |
836 |
|
} |
837 |
|
|
838 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
839 |
/* Prepare, and write .shx file header. */ |
/* Prepare, and write .shx file header. */ |
842 |
ByteCopy( &i32, abyHeader+24, 4 ); |
ByteCopy( &i32, abyHeader+24, 4 ); |
843 |
if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); |
if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); |
844 |
|
|
845 |
fwrite( abyHeader, 100, 1, fpSHX ); |
if( fwrite( abyHeader, 100, 1, fpSHX ) != 1 ) |
846 |
|
{ |
847 |
|
#ifdef USE_CPL |
848 |
|
CPLError( CE_Failure, CPLE_AppDefined, |
849 |
|
"Failed to write .shx header." ); |
850 |
|
#endif |
851 |
|
return NULL; |
852 |
|
} |
853 |
|
|
854 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
855 |
/* Close the files, and then open them as regular existing files. */ |
/* Close the files, and then open them as regular existing files. */ |
1060 |
SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject ) |
SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject ) |
1061 |
|
|
1062 |
{ |
{ |
1063 |
int nRecordOffset, i, nRecordSize; |
int nRecordOffset, i, nRecordSize=0; |
1064 |
uchar *pabyRec; |
uchar *pabyRec; |
1065 |
int32 i32; |
int32 i32; |
1066 |
|
|
1374 |
if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 |
if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 |
1375 |
|| fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 ) |
|| fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 ) |
1376 |
{ |
{ |
1377 |
printf( "Error in fseek() or fwrite().\n" ); |
#ifdef USE_CPL |
1378 |
|
CPLError( CE_Failure, CPLE_FileIO, |
1379 |
|
"Error in fseek() or fwrite() writing object to .shp file." ); |
1380 |
|
#endif |
1381 |
free( pabyRec ); |
free( pabyRec ); |
1382 |
return -1; |
return -1; |
1383 |
} |
} |
1390 |
if( psSHP->adBoundsMin[0] == 0.0 |
if( psSHP->adBoundsMin[0] == 0.0 |
1391 |
&& psSHP->adBoundsMax[0] == 0.0 |
&& psSHP->adBoundsMax[0] == 0.0 |
1392 |
&& psSHP->adBoundsMin[1] == 0.0 |
&& psSHP->adBoundsMin[1] == 0.0 |
1393 |
&& psSHP->adBoundsMax[1] == 0.0 |
&& psSHP->adBoundsMax[1] == 0.0 ) |
|
&& psObject->nSHPType != SHPT_NULL ) |
|
1394 |
{ |
{ |
1395 |
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0]; |
if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 ) |
1396 |
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0]; |
{ |
1397 |
psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0]; |
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0; |
1398 |
psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0]; |
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0; |
1399 |
|
psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = 0.0; |
1400 |
|
psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = 0.0; |
1401 |
|
} |
1402 |
|
else |
1403 |
|
{ |
1404 |
|
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0]; |
1405 |
|
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0]; |
1406 |
|
psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0]; |
1407 |
|
psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0]; |
1408 |
|
} |
1409 |
} |
} |
1410 |
|
|
1411 |
for( i = 0; i < psObject->nVertices; i++ ) |
for( i = 0; i < psObject->nVertices; i++ ) |
1454 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1455 |
/* Read the record. */ |
/* Read the record. */ |
1456 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1457 |
fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ); |
if( fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 |
1458 |
fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP ); |
|| fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, |
1459 |
|
psSHP->fpSHP ) != 1 ) |
1460 |
|
{ |
1461 |
|
#ifdef USE_CPL |
1462 |
|
CPLError( CE_Failure, CPLE_FileIO, |
1463 |
|
"Error in fseek() or fread() reading object from .shp file." ); |
1464 |
|
#endif |
1465 |
|
return NULL; |
1466 |
|
} |
1467 |
|
|
1468 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1469 |
/* Allocate and minimally initialize the object. */ |
/* Allocate and minimally initialize the object. */ |
1901 |
&& psObject->nSHPType != SHPT_POLYGONM ) |
&& psObject->nSHPType != SHPT_POLYGONM ) |
1902 |
return 0; |
return 0; |
1903 |
|
|
1904 |
|
if( psObject->nVertices == 0 || psObject->nParts == 0 ) |
1905 |
|
return 0; |
1906 |
|
|
1907 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1908 |
/* Process each of the rings. */ |
/* Process each of the rings. */ |
1909 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |