/[thuban]/branches/WIP-pyshapelib-bramz/libraries/shapelib/shpopen.c
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/libraries/shapelib/shpopen.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/thuban/libraries/shapelib/shpopen.c revision 1612 by jan, Tue Aug 19 21:29:25 2003 UTC branches/WIP-pyshapelib-bramz/libraries/shapelib/shpopen.c revision 2751 by bramz, Wed Mar 28 23:30:15 2007 UTC
# Line 34  Line 34 
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.
# Line 181  typedef int          int32; Line 243  typedef int          int32;
243  #endif  #endif
244    
245  static int      bBigEndian;  static int      bBigEndian;
 static uchar    *pabyRec = NULL;  
 static int      nBufSize = 0;  
246    
247    
248  /************************************************************************/  /************************************************************************/
# Line 228  static void * SfRealloc( void * pMem, in Line 288  static void * SfRealloc( void * pMem, in
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];
# Line 293  static void SHPWriteHeader( SHPHandle ps Line 353  static void SHPWriteHeader( SHPHandle ps
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.                            */
# Line 303  static void SHPWriteHeader( SHPHandle ps Line 370  static void SHPWriteHeader( SHPHandle ps
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.                                    */
# Line 319  static void SHPWriteHeader( SHPHandle ps Line 393  static void SHPWriteHeader( SHPHandle ps
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.                                      */
# Line 336  SHPOpen( const char * pszLayer, const ch Line 423  SHPOpen( const char * pszLayer, const ch
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          */
# Line 363  SHPOpen( const char * pszLayer, const ch Line 447  SHPOpen( const char * pszLayer, const ch
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  /* -------------------------------------------------------------------- */  /* -------------------------------------------------------------------- */
# Line 389  SHPOpen( const char * pszLayer, const ch Line 466  SHPOpen( const char * pszLayer, const ch
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 );
# Line 424  SHPOpen( const char * pszLayer, const ch Line 602  SHPOpen( const char * pszLayer, const ch
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  /* -------------------------------------------------------------------- */  /* -------------------------------------------------------------------- */
# Line 438  SHPOpen( const char * pszLayer, const ch Line 655  SHPOpen( const char * pszLayer, const ch
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 );
# Line 460  SHPOpen( const char * pszLayer, const ch Line 680  SHPOpen( const char * pszLayer, const ch
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 );
# Line 517  SHPOpen( const char * pszLayer, const ch Line 742  SHPOpen( const char * pszLayer, const ch
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      {      {
# Line 547  void SHPAPI_CALL Line 787  void SHPAPI_CALL
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.                            */
# Line 564  SHPClose(SHPHandle psSHP ) Line 805  SHPClose(SHPHandle psSHP )
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  /************************************************************************/  /************************************************************************/
# Line 586  SHPGetInfo(SHPHandle psSHP, int * pnEnti Line 825  SHPGetInfo(SHPHandle psSHP, int * pnEnti
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;
# Line 616  SHPCreate( const char * pszLayer, int nS Line 858  SHPCreate( const char * pszLayer, int nS
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       */
# Line 650  SHPCreate( const char * pszLayer, int nS Line 880  SHPCreate( const char * pszLayer, int nS
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  /* -------------------------------------------------------------------- */  /* -------------------------------------------------------------------- */
# Line 690  SHPCreate( const char * pszLayer, int nS Line 1043  SHPCreate( const char * pszLayer, int nS
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.                            */
# Line 699  SHPCreate( const char * pszLayer, int nS Line 1059  SHPCreate( const char * pszLayer, int nS
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  /*                                                                      */  /*                                                                      */
# Line 910  int SHPAPI_CALL Line 1270  int SHPAPI_CALL
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    
# Line 1224  SHPWriteObject(SHPHandle psSHP, int nSha Line 1584  SHPWriteObject(SHPHandle psSHP, int nSha
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      }      }
# Line 1237  SHPWriteObject(SHPHandle psSHP, int nSha Line 1600  SHPWriteObject(SHPHandle psSHP, int nSha
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++ )
# Line 1283  SHPReadObject( SHPHandle psSHP, int hEnt Line 1655  SHPReadObject( SHPHandle psSHP, int hEnt
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.                   */
# Line 1301  SHPReadObject( SHPHandle psSHP, int hEnt Line 1681  SHPReadObject( SHPHandle psSHP, int hEnt
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  /* ==================================================================== */  /* ==================================================================== */
# Line 1320  SHPReadObject( SHPHandle psSHP, int hEnt Line 1700  SHPReadObject( SHPHandle psSHP, int hEnt
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) );
# Line 1334  SHPReadObject( SHPHandle psSHP, int hEnt Line 1714  SHPReadObject( SHPHandle psSHP, int hEnt
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 );
# Line 1356  SHPReadObject( SHPHandle psSHP, int hEnt Line 1736  SHPReadObject( SHPHandle psSHP, int hEnt
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 );
# Line 1369  SHPReadObject( SHPHandle psSHP, int hEnt Line 1749  SHPReadObject( SHPHandle psSHP, int hEnt
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 );
# Line 1384  SHPReadObject( SHPHandle psSHP, int hEnt Line 1764  SHPReadObject( SHPHandle psSHP, int hEnt
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 );
# Line 1404  SHPReadObject( SHPHandle psSHP, int hEnt Line 1784  SHPReadObject( SHPHandle psSHP, int hEnt
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) );
# Line 1413  SHPReadObject( SHPHandle psSHP, int hEnt Line 1793  SHPReadObject( SHPHandle psSHP, int hEnt
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    
# Line 1428  SHPReadObject( SHPHandle psSHP, int hEnt Line 1808  SHPReadObject( SHPHandle psSHP, int hEnt
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) );
# Line 1437  SHPReadObject( SHPHandle psSHP, int hEnt Line 1817  SHPReadObject( SHPHandle psSHP, int hEnt
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          }          }
# Line 1454  SHPReadObject( SHPHandle psSHP, int hEnt Line 1834  SHPReadObject( SHPHandle psSHP, int hEnt
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;
# Line 1465  SHPReadObject( SHPHandle psSHP, int hEnt Line 1845  SHPReadObject( SHPHandle psSHP, int hEnt
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 );
# Line 1477  SHPReadObject( SHPHandle psSHP, int hEnt Line 1857  SHPReadObject( SHPHandle psSHP, int hEnt
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) );
# Line 1492  SHPReadObject( SHPHandle psSHP, int hEnt Line 1872  SHPReadObject( SHPHandle psSHP, int hEnt
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) );
# Line 1501  SHPReadObject( SHPHandle psSHP, int hEnt Line 1881  SHPReadObject( SHPHandle psSHP, int hEnt
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    
# Line 1516  SHPReadObject( SHPHandle psSHP, int hEnt Line 1896  SHPReadObject( SHPHandle psSHP, int hEnt
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) );
# Line 1525  SHPReadObject( SHPHandle psSHP, int hEnt Line 1905  SHPReadObject( SHPHandle psSHP, int hEnt
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          }          }
# Line 1546  SHPReadObject( SHPHandle psSHP, int hEnt Line 1926  SHPReadObject( SHPHandle psSHP, int hEnt
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 );
# Line 1559  SHPReadObject( SHPHandle psSHP, int hEnt Line 1939  SHPReadObject( SHPHandle psSHP, int hEnt
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                            
# Line 1574  SHPReadObject( SHPHandle psSHP, int hEnt Line 1954  SHPReadObject( SHPHandle psSHP, int hEnt
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          }          }
# Line 1709  SHPDestroyObject( SHPObject * psShape ) Line 2089  SHPDestroyObject( SHPObject * psShape )
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    }

Legend:
Removed from v.1612  
changed lines
  Added in v.2751

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26