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. */ |
452 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
453 |
/* Initialize the info structure. */ |
/* Initialize the info structure. */ |
454 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
455 |
psSHP = (SHPHandle) malloc(sizeof(SHPInfo)); |
psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1); |
456 |
|
|
457 |
psSHP->bUpdated = FALSE; |
psSHP->bUpdated = FALSE; |
458 |
|
|
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 |
fclose( psSHP->fpSHX ); |
#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 ); |
515 |
free( psSHP ); |
free( psSHP ); |
516 |
free( pszBasename ); |
free( pszBasename ); |
517 |
free( pszFullname ); |
free( pszFullname ); |
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. */ |
685 |
fclose( psSHP->fpSHX ); |
fclose( psSHP->fpSHX ); |
686 |
fclose( psSHP->fpSHP ); |
fclose( psSHP->fpSHP ); |
687 |
|
|
688 |
free( psSHP ); |
if( psSHP->pabyRec != NULL ) |
|
|
|
|
if( pabyRec != NULL ) |
|
689 |
{ |
{ |
690 |
free( pabyRec ); |
free( psSHP->pabyRec ); |
|
pabyRec = NULL; |
|
|
nBufSize = 0; |
|
691 |
} |
} |
692 |
|
|
693 |
|
free( psSHP ); |
694 |
} |
} |
695 |
|
|
696 |
/************************************************************************/ |
/************************************************************************/ |
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++ ) |
1445 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1446 |
/* Ensure our record buffer is large enough. */ |
/* Ensure our record buffer is large enough. */ |
1447 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1448 |
if( psSHP->panRecSize[hEntity]+8 > nBufSize ) |
if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize ) |
1449 |
{ |
{ |
1450 |
nBufSize = psSHP->panRecSize[hEntity]+8; |
psSHP->nBufSize = psSHP->panRecSize[hEntity]+8; |
1451 |
pabyRec = (uchar *) SfRealloc(pabyRec,nBufSize); |
psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize); |
1452 |
} |
} |
1453 |
|
|
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( 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. */ |
1471 |
psShape = (SHPObject *) calloc(1,sizeof(SHPObject)); |
psShape = (SHPObject *) calloc(1,sizeof(SHPObject)); |
1472 |
psShape->nShapeId = hEntity; |
psShape->nShapeId = hEntity; |
1473 |
|
|
1474 |
memcpy( &psShape->nSHPType, pabyRec + 8, 4 ); |
memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 ); |
1475 |
if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) ); |
if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) ); |
1476 |
|
|
1477 |
/* ==================================================================== */ |
/* ==================================================================== */ |
1490 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1491 |
/* Get the X/Y bounds. */ |
/* Get the X/Y bounds. */ |
1492 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1493 |
memcpy( &(psShape->dfXMin), pabyRec + 8 + 4, 8 ); |
memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 ); |
1494 |
memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 ); |
memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 ); |
1495 |
memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 ); |
memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 ); |
1496 |
memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 ); |
memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 ); |
1497 |
|
|
1498 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
1499 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
1504 |
/* Extract part/point count, and build vertex and part arrays */ |
/* Extract part/point count, and build vertex and part arrays */ |
1505 |
/* to proper size. */ |
/* to proper size. */ |
1506 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1507 |
memcpy( &nPoints, pabyRec + 40 + 8, 4 ); |
memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 ); |
1508 |
memcpy( &nParts, pabyRec + 36 + 8, 4 ); |
memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 ); |
1509 |
|
|
1510 |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
1511 |
if( bBigEndian ) SwapWord( 4, &nParts ); |
if( bBigEndian ) SwapWord( 4, &nParts ); |
1526 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1527 |
/* Copy out the part array from the record. */ |
/* Copy out the part array from the record. */ |
1528 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1529 |
memcpy( psShape->panPartStart, pabyRec + 44 + 8, 4 * nParts ); |
memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts ); |
1530 |
for( i = 0; i < nParts; i++ ) |
for( i = 0; i < nParts; i++ ) |
1531 |
{ |
{ |
1532 |
if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i ); |
if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i ); |
1539 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1540 |
if( psShape->nSHPType == SHPT_MULTIPATCH ) |
if( psShape->nSHPType == SHPT_MULTIPATCH ) |
1541 |
{ |
{ |
1542 |
memcpy( psShape->panPartType, pabyRec + nOffset, 4*nParts ); |
memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts ); |
1543 |
for( i = 0; i < nParts; i++ ) |
for( i = 0; i < nParts; i++ ) |
1544 |
{ |
{ |
1545 |
if( bBigEndian ) SwapWord( 4, psShape->panPartType+i ); |
if( bBigEndian ) SwapWord( 4, psShape->panPartType+i ); |
1554 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1555 |
{ |
{ |
1556 |
memcpy(psShape->padfX + i, |
memcpy(psShape->padfX + i, |
1557 |
pabyRec + nOffset + i * 16, |
psSHP->pabyRec + nOffset + i * 16, |
1558 |
8 ); |
8 ); |
1559 |
|
|
1560 |
memcpy(psShape->padfY + i, |
memcpy(psShape->padfY + i, |
1561 |
pabyRec + nOffset + i * 16 + 8, |
psSHP->pabyRec + nOffset + i * 16 + 8, |
1562 |
8 ); |
8 ); |
1563 |
|
|
1564 |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
1574 |
|| psShape->nSHPType == SHPT_ARCZ |
|| psShape->nSHPType == SHPT_ARCZ |
1575 |
|| psShape->nSHPType == SHPT_MULTIPATCH ) |
|| psShape->nSHPType == SHPT_MULTIPATCH ) |
1576 |
{ |
{ |
1577 |
memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 ); |
1578 |
memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1579 |
|
|
1580 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
1581 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
1583 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1584 |
{ |
{ |
1585 |
memcpy( psShape->padfZ + i, |
memcpy( psShape->padfZ + i, |
1586 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1587 |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
1588 |
} |
} |
1589 |
|
|
1598 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1599 |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
1600 |
{ |
{ |
1601 |
memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 ); |
1602 |
memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1603 |
|
|
1604 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
1605 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
1607 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1608 |
{ |
{ |
1609 |
memcpy( psShape->padfM + i, |
memcpy( psShape->padfM + i, |
1610 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1611 |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
1612 |
} |
} |
1613 |
} |
} |
1624 |
int32 nPoints; |
int32 nPoints; |
1625 |
int i, nOffset; |
int i, nOffset; |
1626 |
|
|
1627 |
memcpy( &nPoints, pabyRec + 44, 4 ); |
memcpy( &nPoints, psSHP->pabyRec + 44, 4 ); |
1628 |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
if( bBigEndian ) SwapWord( 4, &nPoints ); |
1629 |
|
|
1630 |
psShape->nVertices = nPoints; |
psShape->nVertices = nPoints; |
1635 |
|
|
1636 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1637 |
{ |
{ |
1638 |
memcpy(psShape->padfX+i, pabyRec + 48 + 16 * i, 8 ); |
memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 ); |
1639 |
memcpy(psShape->padfY+i, pabyRec + 48 + 16 * i + 8, 8 ); |
memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 ); |
1640 |
|
|
1641 |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); |
1642 |
if( bBigEndian ) SwapWord( 8, psShape->padfY + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfY + i ); |
1647 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1648 |
/* Get the X/Y bounds. */ |
/* Get the X/Y bounds. */ |
1649 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1650 |
memcpy( &(psShape->dfXMin), pabyRec + 8 + 4, 8 ); |
memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 ); |
1651 |
memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 ); |
memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 ); |
1652 |
memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 ); |
memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 ); |
1653 |
memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 ); |
memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 ); |
1654 |
|
|
1655 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); |
1656 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); |
1662 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1663 |
if( psShape->nSHPType == SHPT_MULTIPOINTZ ) |
if( psShape->nSHPType == SHPT_MULTIPOINTZ ) |
1664 |
{ |
{ |
1665 |
memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 ); |
1666 |
memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1667 |
|
|
1668 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); |
1669 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); |
1671 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1672 |
{ |
{ |
1673 |
memcpy( psShape->padfZ + i, |
memcpy( psShape->padfZ + i, |
1674 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1675 |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); |
1676 |
} |
} |
1677 |
|
|
1686 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1687 |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) |
1688 |
{ |
{ |
1689 |
memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 ); |
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 ); |
1690 |
memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 ); |
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 ); |
1691 |
|
|
1692 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); |
1693 |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); |
1695 |
for( i = 0; i < nPoints; i++ ) |
for( i = 0; i < nPoints; i++ ) |
1696 |
{ |
{ |
1697 |
memcpy( psShape->padfM + i, |
memcpy( psShape->padfM + i, |
1698 |
pabyRec + nOffset + 16 + i*8, 8 ); |
psSHP->pabyRec + nOffset + 16 + i*8, 8 ); |
1699 |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); |
1700 |
} |
} |
1701 |
} |
} |
1716 |
psShape->padfZ = (double *) calloc(1,sizeof(double)); |
psShape->padfZ = (double *) calloc(1,sizeof(double)); |
1717 |
psShape->padfM = (double *) calloc(1,sizeof(double)); |
psShape->padfM = (double *) calloc(1,sizeof(double)); |
1718 |
|
|
1719 |
memcpy( psShape->padfX, pabyRec + 12, 8 ); |
memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 ); |
1720 |
memcpy( psShape->padfY, pabyRec + 20, 8 ); |
memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 ); |
1721 |
|
|
1722 |
if( bBigEndian ) SwapWord( 8, psShape->padfX ); |
if( bBigEndian ) SwapWord( 8, psShape->padfX ); |
1723 |
if( bBigEndian ) SwapWord( 8, psShape->padfY ); |
if( bBigEndian ) SwapWord( 8, psShape->padfY ); |
1729 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1730 |
if( psShape->nSHPType == SHPT_POINTZ ) |
if( psShape->nSHPType == SHPT_POINTZ ) |
1731 |
{ |
{ |
1732 |
memcpy( psShape->padfZ, pabyRec + nOffset, 8 ); |
memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 ); |
1733 |
|
|
1734 |
if( bBigEndian ) SwapWord( 8, psShape->padfZ ); |
if( bBigEndian ) SwapWord( 8, psShape->padfZ ); |
1735 |
|
|
1744 |
/* -------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------- */ |
1745 |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 ) |
if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 ) |
1746 |
{ |
{ |
1747 |
memcpy( psShape->padfM, pabyRec + nOffset, 8 ); |
memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 ); |
1748 |
|
|
1749 |
if( bBigEndian ) SwapWord( 8, psShape->padfM ); |
if( bBigEndian ) SwapWord( 8, psShape->padfM ); |
1750 |
} |
} |
1879 |
|
|
1880 |
free( psShape ); |
free( psShape ); |
1881 |
} |
} |
1882 |
|
|
1883 |
|
/************************************************************************/ |
1884 |
|
/* SHPRewindObject() */ |
1885 |
|
/* */ |
1886 |
|
/* Reset the winding of polygon objects to adhere to the */ |
1887 |
|
/* specification. */ |
1888 |
|
/************************************************************************/ |
1889 |
|
|
1890 |
|
int SHPAPI_CALL |
1891 |
|
SHPRewindObject( SHPHandle hSHP, SHPObject * psObject ) |
1892 |
|
|
1893 |
|
{ |
1894 |
|
int iOpRing, bAltered = 0; |
1895 |
|
|
1896 |
|
/* -------------------------------------------------------------------- */ |
1897 |
|
/* Do nothing if this is not a polygon object. */ |
1898 |
|
/* -------------------------------------------------------------------- */ |
1899 |
|
if( psObject->nSHPType != SHPT_POLYGON |
1900 |
|
&& psObject->nSHPType != SHPT_POLYGONZ |
1901 |
|
&& psObject->nSHPType != SHPT_POLYGONM ) |
1902 |
|
return 0; |
1903 |
|
|
1904 |
|
if( psObject->nVertices == 0 || psObject->nParts == 0 ) |
1905 |
|
return 0; |
1906 |
|
|
1907 |
|
/* -------------------------------------------------------------------- */ |
1908 |
|
/* Process each of the rings. */ |
1909 |
|
/* -------------------------------------------------------------------- */ |
1910 |
|
for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ ) |
1911 |
|
{ |
1912 |
|
int bInner, iVert, nVertCount, nVertStart, iCheckRing; |
1913 |
|
double dfSum, dfTestX, dfTestY; |
1914 |
|
|
1915 |
|
/* -------------------------------------------------------------------- */ |
1916 |
|
/* Determine if this ring is an inner ring or an outer ring */ |
1917 |
|
/* relative to all the other rings. For now we assume the */ |
1918 |
|
/* first ring is outer and all others are inner, but eventually */ |
1919 |
|
/* we need to fix this to handle multiple island polygons and */ |
1920 |
|
/* unordered sets of rings. */ |
1921 |
|
/* -------------------------------------------------------------------- */ |
1922 |
|
dfTestX = psObject->padfX[psObject->panPartStart[iOpRing]]; |
1923 |
|
dfTestY = psObject->padfY[psObject->panPartStart[iOpRing]]; |
1924 |
|
|
1925 |
|
bInner = FALSE; |
1926 |
|
for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ ) |
1927 |
|
{ |
1928 |
|
int iEdge; |
1929 |
|
|
1930 |
|
if( iCheckRing == iOpRing ) |
1931 |
|
continue; |
1932 |
|
|
1933 |
|
nVertStart = psObject->panPartStart[iCheckRing]; |
1934 |
|
|
1935 |
|
if( iCheckRing == psObject->nParts-1 ) |
1936 |
|
nVertCount = psObject->nVertices |
1937 |
|
- psObject->panPartStart[iCheckRing]; |
1938 |
|
else |
1939 |
|
nVertCount = psObject->panPartStart[iCheckRing+1] |
1940 |
|
- psObject->panPartStart[iCheckRing]; |
1941 |
|
|
1942 |
|
for( iEdge = 0; iEdge < nVertCount; iEdge++ ) |
1943 |
|
{ |
1944 |
|
int iNext; |
1945 |
|
|
1946 |
|
if( iEdge < nVertCount-1 ) |
1947 |
|
iNext = iEdge+1; |
1948 |
|
else |
1949 |
|
iNext = 0; |
1950 |
|
|
1951 |
|
if( (psObject->padfY[iEdge+nVertStart] < dfTestY |
1952 |
|
&& psObject->padfY[iNext+nVertStart] >= dfTestY) |
1953 |
|
|| (psObject->padfY[iNext+nVertStart] < dfTestY |
1954 |
|
&& psObject->padfY[iEdge+nVertStart] >= dfTestY) ) |
1955 |
|
{ |
1956 |
|
if( psObject->padfX[iEdge+nVertStart] |
1957 |
|
+ (dfTestY - psObject->padfY[iEdge+nVertStart]) |
1958 |
|
/ (psObject->padfY[iNext+nVertStart] |
1959 |
|
- psObject->padfY[iEdge+nVertStart]) |
1960 |
|
* (psObject->padfX[iNext+nVertStart] |
1961 |
|
- psObject->padfX[iEdge+nVertStart]) < dfTestX ) |
1962 |
|
bInner = !bInner; |
1963 |
|
} |
1964 |
|
} |
1965 |
|
} |
1966 |
|
|
1967 |
|
/* -------------------------------------------------------------------- */ |
1968 |
|
/* Determine the current order of this ring so we will know if */ |
1969 |
|
/* it has to be reversed. */ |
1970 |
|
/* -------------------------------------------------------------------- */ |
1971 |
|
nVertStart = psObject->panPartStart[iOpRing]; |
1972 |
|
|
1973 |
|
if( iOpRing == psObject->nParts-1 ) |
1974 |
|
nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing]; |
1975 |
|
else |
1976 |
|
nVertCount = psObject->panPartStart[iOpRing+1] |
1977 |
|
- psObject->panPartStart[iOpRing]; |
1978 |
|
|
1979 |
|
dfSum = 0.0; |
1980 |
|
for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ ) |
1981 |
|
{ |
1982 |
|
dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1] |
1983 |
|
- psObject->padfY[iVert] * psObject->padfX[iVert+1]; |
1984 |
|
} |
1985 |
|
|
1986 |
|
dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart] |
1987 |
|
- psObject->padfY[iVert] * psObject->padfX[nVertStart]; |
1988 |
|
|
1989 |
|
/* -------------------------------------------------------------------- */ |
1990 |
|
/* Reverse if necessary. */ |
1991 |
|
/* -------------------------------------------------------------------- */ |
1992 |
|
if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) ) |
1993 |
|
{ |
1994 |
|
int i; |
1995 |
|
|
1996 |
|
bAltered++; |
1997 |
|
for( i = 0; i < nVertCount/2; i++ ) |
1998 |
|
{ |
1999 |
|
double dfSaved; |
2000 |
|
|
2001 |
|
/* Swap X */ |
2002 |
|
dfSaved = psObject->padfX[nVertStart+i]; |
2003 |
|
psObject->padfX[nVertStart+i] = |
2004 |
|
psObject->padfX[nVertStart+nVertCount-i-1]; |
2005 |
|
psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved; |
2006 |
|
|
2007 |
|
/* Swap Y */ |
2008 |
|
dfSaved = psObject->padfY[nVertStart+i]; |
2009 |
|
psObject->padfY[nVertStart+i] = |
2010 |
|
psObject->padfY[nVertStart+nVertCount-i-1]; |
2011 |
|
psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved; |
2012 |
|
|
2013 |
|
/* Swap Z */ |
2014 |
|
if( psObject->padfZ ) |
2015 |
|
{ |
2016 |
|
dfSaved = psObject->padfZ[nVertStart+i]; |
2017 |
|
psObject->padfZ[nVertStart+i] = |
2018 |
|
psObject->padfZ[nVertStart+nVertCount-i-1]; |
2019 |
|
psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved; |
2020 |
|
} |
2021 |
|
|
2022 |
|
/* Swap M */ |
2023 |
|
if( psObject->padfM ) |
2024 |
|
{ |
2025 |
|
dfSaved = psObject->padfM[nVertStart+i]; |
2026 |
|
psObject->padfM[nVertStart+i] = |
2027 |
|
psObject->padfM[nVertStart+nVertCount-i-1]; |
2028 |
|
psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved; |
2029 |
|
} |
2030 |
|
} |
2031 |
|
} |
2032 |
|
} |
2033 |
|
|
2034 |
|
return bAltered; |
2035 |
|
} |