1
0
Fork 0

Upgrade shapelib to 1.2.10

This commit is contained in:
Frederic Bouvier 2009-03-14 12:03:36 +01:00 committed by Ralf Gerlich
parent ba5a9b363e
commit d5da7c56f6
23 changed files with 3996 additions and 895 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,3 +1,201 @@
2003-04-07 Frank Warmerdam <warmerdam@pobox.com>
* Issue 1.2.10 Release.
2003-03-10 Frank Warmerdam <warmerdam@pobox.com>
* dbfopen.c: modified DBFWriteAttribute call so that it returns FALSE
if it has to truncate the input value.
2003-01-28 Frank Warmerdam <warmerdam@pobox.com>
* shptree.c: avoid build warnings.
2002-05-07 Frank Warmerdam <warmerdam@pobox.com>
* dbfopen.c: Added DBFWriteAttributeDirectly() from the AVCE00
distribution to simplify AVC integration in GDAL.
* shptree.c: added use of qsort() in place of bubble sort as
submitted by Bernhard Herzog.
2002-04-10 Frank Warmerdam <warmerdam@pobox.com>
* shpopen.c: Added SHPRewindObject() to correct ring winding.
* shprewind.c: New utility program.
2002-03-12 Frank Warmerdam <warmerdam@pobox.com>
* shapelib.def: added DBFWriteNULLAttribute.
2002-01-17 Frank Warmerdam <warmerdam@pobox.com>
* contrib/ShapeFileII.pas: Contributed Delphi Pascal interface
to Shapelib.
2002-01-15 Frank Warmerdam <warmerdam@pobox.com>
* shapelib.h: Added support for SHAPELIB_DLLEXPORT macro, and write
up material attempting to explain the use of SHPAPI_CALL macros.
* dbfopen.c: Compute nHeaderLength in DBFCloneEmpty() instead of
copying it from the source file so we don't have quirks when copying
from files with extra bytes of spacers in the header that don't
themselves get copied properly.
2001-12-07 Frank Warmerdam <warmerdam@pobox.com>
* shpopen.c: Fix fclose() of SHX file if SHX file fails to open.
Should be closing SHP file. Reported by Ben Discoe.
2001-11-28 Frank Warmerdam <warmerdam@pobox.com>
* dbfopen.c: two fixes for compiler warnings as suggested by
Richard Hash.
2001-11-01 Frank Warmerdam <warmerdam@pobox.com>
* shpopen.c/shapefil.h: Move record buffer into SHPInfo so that
different threads can safely access separate files. Other threading
issues may remain.
2001-08-28 Frank Warmerdam <warmerdam@pobox.com>
* Issue Shapelib 1.2.9
* shputils.c: DBFAddField() call should check for -1 return value
for failure.
2001-07-03 Frank Warmerdam <warmerdam@pobox.com>
* shpopen.c: cleanup better if SHX missing, provided by
Riccardo Cohen.
2001-06-21 Frank Warmerdam <warmerdam@pobox.com>
* dbfopen.c: Fixed NULL support with patches from Jim Matthews.
* shpopen.c: Be more careful of establishing initial file bounds in
face of possible NULL shapes.
2001-06-01 Frank Warmerdam <warmerdam@pobox.com>
* dbfopen.c: ensure binary mode open.
2001-05-31 Frank Warmerdam <warmerdam@pobox.com>
* shpopen.c: Add support for writing null shapes.
* dbfopen.c: added DBFGetFieldIndex(), contributed by Jim Matthews.
* dbfopen.c/shapefil.h/dbf_api.h: added support for NULL fields
in .dbf files.
2001-05-28 Frank Warmerdam <warmerdam@pobox.com>
* shpopen.c: add some checking on the record count to ensure it
is reasonable.
2001-05-23 Frank Warmerdam <warmerdam@pobox.com>
* shapefile.h, shpopen.c, dbfopen.c, shptree.c: added the SHPAPI_CALL
macro to allow compilation with _stdcall conventions.
2001-02-06 Frank Warmerdam <warmerdam@pobox.com>
* Fixed a few memory leaks when SHPOpen() fails.
2000-12-05 Frank Warmerdam <warmerdam@pobox.com>
* Fix from Craig Bruce (Cubewerx) for DBFReadAttribute() for
the white space trimming code to avoid reading outside allocated
memory.
2000-11-02 Frank Warmerdam <warmerda@cs46980-c>
* Checked in upgraded shputils.c from Bill Miller.
2000-10-05 Frank Warmerdam <warmerda@cs46980-c>
* Fixed DBFWriteAttribute() to ensure we can't overwrite the
end of the szSField buffer even if the width is set large.
Bug report by Kirk Benell <kirk@rsinc.com>.
2000-09-25 Frank Warmerdam <warmerda@cs46980-c>
* Added DBFGetNativeFieldType() (contributed by Daniel) to dbfopen.c.
2000-07-18 Frank Warmerdam <warmerda@cs46980-c>
* added better enforcement of -1 for append in SHPWriteObject().
2000-07-07 Frank Warmerdam <warmerda@cs46980-c>
* Added stdlib.h and string.h where needed, and removed lots of
unused variables, mainly from example mainlines at the suggestion
of Bill Hughes.
2000-05-24 Frank Warmerdam <warmerda@cs46980-c>
* Added logic to shpadd to grow vertex lists at the suggestion of
Santiago Nullo <sn@softhome.net>.
2000-05-23 Frank Warmerdam <warmerda@cs46980-c>
* Added checks in dbfopen.c on return result of fseek() and fread().
* Avoid crashing in DBReadIntegerAttribute() or DBFReadDoubleAttribte()
if the field or record are out of range.
2000-03-28 Frank Warmerdam <warmerda@cs46980-c>
* Release as 1.2.8.
* Incorporated a -version-info fix and added mkinstalldirs from Jan.
2000-03-17 Frank Warmerdam <warmerda@cs46980-c>
* Added shared library hack to Makefile.
* Fixed up test scripts to look in ./ for executables.
Wed Feb 16 11:20:29 2000 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Release 1.2.7.
* Modified SHPReadObject() so that will return NULL (type 0) shapes
in a sort of sensible way.
Wed Dec 15 08:49:53 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Fixed record size written at beginning of records in .shp
file. It was 4 bytes to long (thanks to Mikko Syrja of 3D-system Oy)
* Use atof() instead of sscanf() in dbfopen.c, and add stdlib.h.
Mon Dec 13 12:29:01 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Added support for uppercase .DBF extention c/o
Dennis Christopher <dennis@avenza.com>
Fri Nov 5 09:12:31 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Updated license headers to include the option of use of the code
under the LGPL.
1999-09-15 <warmerda@CS46980-B>
* Added shapelib.dll target to makefile.vc.
Mon May 10 23:19:42 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Added candrsn's improvements to extension handling in dbfopen.c
* Added ``raw tuple'' api to dbfopen.c, still not in dbf_api.html.
From candrsn.
Tue May 4 11:04:31 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Prepare 1.2.5 release.

View file

@ -80,6 +80,22 @@ int DBFGetRecordCount( DBFHandle hDBF );
<!-------------------------------------------------------------------------->
<h2>DBFGetFieldIndex()</h2>
<pre>
int DBFGetFieldIndex( DBFHandle hDBF, const char *pszFieldName );
hDBF: The access handle for the file to be queried, as returned by
DBFOpen(), or DBFCreate().
pszFieldName: Name of the field to search for.
</pre>
Returns the index of the field matching this name, or -1 on failure. The
comparison is case insensitive. However, lengths must match exactly.<p>
<!-------------------------------------------------------------------------->
<h2>DBFGetFieldInfo()</h2>
<pre>
@ -119,6 +135,7 @@ DBFFieldType DBFGetFieldInfo( DBFHandle hDBF, int iField, char * pszFieldName,
FTString, /* fixed length string field */
FTInteger, /* numeric field with no decimals */
FTDouble, /* numeric field with decimals */
FTLogical, /* logical field. */
FTInvalid /* not a recognised field type */
} DBFFieldType;
</pre>
@ -145,7 +162,8 @@ int DBFAddField( DBFHandle hDBF, const char * pszFieldName,
nWidth: The width of the field to be created. For FTString fields this
establishes the maximum length of string that can be stored.
For FTInteger this establishes the largest number that can
For FTInteger this establishes the number of digits of the
largest number that can
be represented. For FTDouble fields this in combination
with the nDecimals value establish the size, and precision
of the created field.
@ -232,6 +250,28 @@ const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
<!-------------------------------------------------------------------------->
<h2>DBFIsAttributeNULL()</h2>
<pre>
int DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
hDBF: The access handle for the file to be queried, as returned by
DBFOpen(), or DBFCreate().
iShape: The record number (shape number) from which the field value
should be read.
iField: The field within the selected record that should be read.
</pre>
This function will return TRUE if the indicated field is NULL valued
otherwise FALSE. Note that NULL fields are represented in the .dbf file
as having all spaces in the field. Reading NULL fields will result in
a value of 0.0 or an empty string with the other DBFRead*Attribute()
functions.<p>
<!-------------------------------------------------------------------------->
<h2>DBFWriteIntegerAttribute</h2>
<pre>
@ -251,8 +291,8 @@ int DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
The DBFWriteIntegerAttribute() function is used to write a value to a numeric
field (FTInteger, or FTDouble). If the write succeeds the value TRUE will
be returned, otherwise FALSE will be returned. The value may be truncated
without warning if written to a field to narrow to represent the value.<p>
be returned, otherwise FALSE will be returned. If the value is too large to
fit in the field, it will be truncated and FALSE returned.<p>
<!-------------------------------------------------------------------------->
@ -275,8 +315,8 @@ int DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
The DBFWriteDoubleAttribute() function is used to write a value to a numeric
field (FTInteger, or FTDouble). If the write succeeds the value TRUE will
be returned, otherwise FALSE will be returned. The value may be truncated
without warning if written to a field to narrow to represent the value.<p>
be returned, otherwise FALSE will be returned. If the value is too large to
fit in the field, it will be truncated and FALSE returned.<p>
<!-------------------------------------------------------------------------->
@ -299,8 +339,29 @@ int DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
The DBFWriteStringAttribute() function is used to write a value to a string
field (FString). If the write succeeds the value TRUE willbe returned,
otherwise FALSE will be returned. The value may be truncated
without warning if written to a field to narrow to hold the string.<p>
otherwise FALSE will be returned. If the value is too large to
fit in the field, it will be truncated and FALSE returned.<p>
<!-------------------------------------------------------------------------->
<h2>DBFWriteNULLAttribute()</h2>
<pre>
int DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
hDBF: The access handle for the file to be written, as returned by
DBFOpen(), or DBFCreate().
iShape: The record number (shape number) to which the field value
should be written.
iField: The field within the selected record that should be written.
</pre>
The DBFWriteNULLAttribute() function is used to clear the indicated field
to a NULL value. In the .dbf file this is represented by setting the entire
field to spaces. If the write succeeds the value TRUE willbe returned,
otherwise FALSE will be returned.<p>
<!-------------------------------------------------------------------------->
@ -318,5 +379,30 @@ void DBFClose( DBFHandle hDBF );
The file handle (hDBF) should not be used again with the DBF API after
calling DBFClose().<p>
<!-------------------------------------------------------------------------->
<h2>DBFGetNativeFieldType()</h2>
<pre>
char DBFGetNativeFieldType( DBFHandle hDBF, int iField );
hDBF: The access handle for the file.
iField: The field index to query.
</pre>
This function returns the DBF type code of the indicated field. It will
be one of:<p>
<ul>
<li> 'C' (String)
<li> 'D' (Date)
<li> 'F' (Float)
<li> 'N' (Numeric, with or without decimal)
<li> 'L' (Logical)
<li> 'M' (Memo: 10 digits .DBT block ptr)
<li> ' ' (field out of range)
</ul>
</body>
</html>

View file

@ -1,14 +1,47 @@
/*
* Copyright (c) 1995 Frank Warmerdam
/******************************************************************************
* $Id: dbfadd.c,v 1.7 2002/01/15 14:36:07 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Sample application for adding a record to an existing .dbf file.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: dbfadd.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.7 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.1 1999/08/24 21:13:00 curt
* Initial revision.
* Revision 1.6 2001/05/31 18:15:40 warmerda
* Added support for NULL fields in DBF files
*
* Revision 1.5 1999/11/05 14:12:04 warmerda
* updated license terms
*
* Revision 1.4 1998/12/03 16:36:06 warmerda
* Added stdlib.h and math.h to get atof() prototype.
@ -22,7 +55,7 @@
*/
static char rcsid[] =
"$Id: dbfadd.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: dbfadd.c,v 1.7 2002/01/15 14:36:07 warmerda Exp $";
#include "shapefil.h"
#include <math.h>
@ -71,7 +104,9 @@ int main( int argc, char ** argv )
/* -------------------------------------------------------------------- */
for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
{
if( DBFGetFieldInfo( hDBF, i, NULL, NULL, NULL ) == FTString )
if( strcmp( argv[i+2], "" ) == 0 )
DBFWriteNULLAttribute(hDBF, iRecord, i );
else if( DBFGetFieldInfo( hDBF, i, NULL, NULL, NULL ) == FTString )
DBFWriteStringAttribute(hDBF, iRecord, i, argv[i+2] );
else
DBFWriteDoubleAttribute(hDBF, iRecord, i, atof(argv[i+2]) );

View file

@ -1,14 +1,47 @@
/*
* Copyright (c) 1995 Frank Warmerdam
/******************************************************************************
* $Id: dbfcreate.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Sample application for creating a new .dbf file.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: dbfcreate.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.6 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.1 1999/08/24 21:13:00 curt
* Initial revision.
* Revision 1.5 2000/07/07 13:39:45 warmerda
* removed unused variables, and added system include files
*
* Revision 1.4 1999/11/05 14:12:04 warmerda
* updated license terms
*
* Revision 1.3 1999/04/01 18:47:44 warmerda
* Fixed DBFAddField() call convention.
@ -19,17 +52,17 @@
*/
static char rcsid[] =
"$Id: dbfcreate.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: dbfcreate.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $";
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
int main( int argc, char ** argv )
{
DBFHandle hDBF;
int *panWidth, i, iRecord;
char szFormat[32], szField[1024];
int nWidth, nDecimals;
int i;
/* -------------------------------------------------------------------- */
/* Display a usage message. */

View file

@ -1,14 +1,53 @@
/*
* Copyright (c) 1995 Frank Warmerdam
/******************************************************************************
* $Id: dbfdump.c,v 1.9 2002/01/15 14:36:07 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Sample application for dumping .dbf files to the terminal.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: dbfdump.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.9 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.1 1999/08/24 21:13:00 curt
* Initial revision.
* Revision 1.8 2001/05/31 18:15:40 warmerda
* Added support for NULL fields in DBF files
*
* Revision 1.7 2000/09/20 13:13:55 warmerda
* added break after default:
*
* Revision 1.6 2000/07/07 13:39:45 warmerda
* removed unused variables, and added system include files
*
* Revision 1.5 1999/11/05 14:12:04 warmerda
* updated license terms
*
* Revision 1.4 1998/12/31 15:30:13 warmerda
* Added -m, -r, and -h commandline options.
@ -22,8 +61,10 @@
*/
static char rcsid[] =
"$Id: dbfdump.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: dbfdump.c,v 1.9 2002/01/15 14:36:07 warmerda Exp $";
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
int main( int argc, char ** argv )
@ -31,7 +72,7 @@ int main( int argc, char ** argv )
{
DBFHandle hDBF;
int *panWidth, i, iRecord;
char szFormat[32], szField[1024], *pszFilename = NULL;
char szFormat[32], *pszFilename = NULL;
int nWidth, nDecimals;
int bHeader = 0;
int bRaw = 0;
@ -159,25 +200,40 @@ int main( int argc, char ** argv )
/* -------------------------------------------------------------------- */
if( !bRaw )
{
switch( eType )
if( DBFIsAttributeNULL( hDBF, iRecord, i ) )
{
case FTString:
sprintf( szFormat, "%%-%ds", nWidth );
printf( szFormat,
DBFReadStringAttribute( hDBF, iRecord, i ) );
break;
case FTInteger:
sprintf( szFormat, "%%%dd", nWidth );
printf( szFormat,
DBFReadIntegerAttribute( hDBF, iRecord, i ) );
break;
if( eType == FTString )
sprintf( szFormat, "%%-%ds", nWidth );
else
sprintf( szFormat, "%%%ds", nWidth );
case FTDouble:
sprintf( szFormat, "%%%d.%dlf", nWidth, nDecimals );
printf( szFormat,
DBFReadDoubleAttribute( hDBF, iRecord, i ) );
break;
printf( szFormat, "(NULL)" );
}
else
{
switch( eType )
{
case FTString:
sprintf( szFormat, "%%-%ds", nWidth );
printf( szFormat,
DBFReadStringAttribute( hDBF, iRecord, i ) );
break;
case FTInteger:
sprintf( szFormat, "%%%dd", nWidth );
printf( szFormat,
DBFReadIntegerAttribute( hDBF, iRecord, i ) );
break;
case FTDouble:
sprintf( szFormat, "%%%d.%dlf", nWidth, nDecimals );
printf( szFormat,
DBFReadDoubleAttribute( hDBF, iRecord, i ) );
break;
default:
break;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -14,5 +14,8 @@ dbfadd test.dbf "Square with triangle missing" 1.5 2.5
shpadd test 150 150 160 150 180 170 150 150
dbfadd test.dbf "Smaller triangle" 100 1000.25
shpadd test 150 150 160 150 180 170 150 150
dbfadd test.dbf "" "" ""
shpdump test.shp
dbfdump test.dbf

View file

@ -1,17 +1,95 @@
#ifndef _SHAPEFILE_H_INCLUDED
#define _SHAPEFILE_H_INCLUDED
/*
* Copyright (c) 1995 Frank Warmerdam
/******************************************************************************
* $Id: shapefil.h,v 1.26 2002/09/29 00:00:08 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Primary include file for Shapelib.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shapefil.h,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.26 2002/09/29 00:00:08 warmerda
* added FTLogical and logical attribute read/write calls
*
* Revision 1.1 1999/08/24 21:13:01 curt
* Initial revision.
* Revision 1.25 2002/05/07 13:46:30 warmerda
* added DBFWriteAttributeDirectly().
*
* Revision 1.24 2002/04/10 16:59:54 warmerda
* added SHPRewindObject
*
* Revision 1.23 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.22 2002/01/15 14:32:00 warmerda
* try to improve SHPAPI_CALL docs
*
* Revision 1.21 2001/11/01 16:29:55 warmerda
* move pabyRec into SHPInfo for thread safety
*
* Revision 1.20 2001/07/20 13:06:02 warmerda
* fixed SHPAPI attribute for SHPTreeFindLikelyShapes
*
* Revision 1.19 2001/05/31 19:20:13 warmerda
* added DBFGetFieldIndex()
*
* Revision 1.18 2001/05/31 18:15:40 warmerda
* Added support for NULL fields in DBF files
*
* Revision 1.17 2001/05/23 13:36:52 warmerda
* added use of SHPAPI_CALL
*
* Revision 1.16 2000/09/25 14:15:59 warmerda
* added DBFGetNativeFieldType()
*
* Revision 1.15 2000/02/16 16:03:51 warmerda
* added null shape support
*
* Revision 1.14 1999/11/05 14:12:05 warmerda
* updated license terms
*
* Revision 1.13 1999/06/02 18:24:21 warmerda
* added trimming code
*
* Revision 1.12 1999/06/02 17:56:12 warmerda
* added quad'' subnode support for trees
*
* Revision 1.11 1999/05/18 19:11:11 warmerda
* Added example searching capability
*
* Revision 1.10 1999/05/18 17:49:38 warmerda
* added initial quadtree support
*
* Revision 1.9 1999/05/11 03:19:28 warmerda
* added new Tuple api, and improved extension handling - add from candrsn
*
* Revision 1.8 1999/03/23 17:22:27 warmerda
* Added extern "C" protection for C++ users of shapefil.h.
@ -45,7 +123,7 @@
#ifdef __cplusplus
extern "C" {
#endif
/************************************************************************/
/* Configuration options. */
/************************************************************************/
@ -63,6 +141,48 @@ extern "C" {
/* -------------------------------------------------------------------- */
#define DISABLE_MULTIPATCH_MEASURE
/* -------------------------------------------------------------------- */
/* SHPAPI_CALL */
/* */
/* The following two macros are present to allow forcing */
/* various calling conventions on the Shapelib API. */
/* */
/* To force __stdcall conventions (needed to call Shapelib */
/* from Visual Basic and/or Dephi I believe) the makefile could */
/* be modified to define: */
/* */
/* /DSHPAPI_CALL=__stdcall */
/* */
/* If it is desired to force export of the Shapelib API without */
/* using the shapelib.def file, use the following definition. */
/* */
/* /DSHAPELIB_DLLEXPORT */
/* */
/* To get both at once it will be necessary to hack this */
/* include file to define: */
/* */
/* #define SHPAPI_CALL __declspec(dllexport) __stdcall */
/* #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall */
/* */
/* The complexity of the situtation is partly caused by the */
/* peculiar requirement of Visual C++ that __stdcall appear */
/* after any "*"'s in the return value of a function while the */
/* __declspec(dllexport) must appear before them. */
/* -------------------------------------------------------------------- */
#ifdef SHAPELIB_DLLEXPORT
# define SHPAPI_CALL __declspec(dllexport)
# define SHPAPI_CALL1(x) __declspec(dllexport) x
#endif
#ifndef SHPAPI_CALL
# define SHPAPI_CALL
#endif
#ifndef SHPAPI_CALL1
# define SHPAPI_CALL1(x) x SHPAPI_CALL
#endif
/************************************************************************/
/* SHP Support. */
/************************************************************************/
@ -84,6 +204,9 @@ typedef struct
double adBoundsMax[4];
int bUpdated;
unsigned char *pabyRec;
int nBufSize;
} SHPInfo;
typedef SHPInfo * SHPHandle;
@ -91,6 +214,7 @@ typedef SHPInfo * SHPHandle;
/* -------------------------------------------------------------------- */
/* Shape types (nSHPType) */
/* -------------------------------------------------------------------- */
#define SHPT_NULL 0
#define SHPT_POINT 1
#define SHPT_ARC 3
#define SHPT_POLYGON 5
@ -152,27 +276,105 @@ typedef struct
/* -------------------------------------------------------------------- */
/* SHP API Prototypes */
/* -------------------------------------------------------------------- */
SHPHandle SHPOpen( const char * pszShapeFile, const char * pszAccess );
SHPHandle SHPCreate( const char * pszShapeFile, int nShapeType );
void SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
double * padfMinBound, double * padfMaxBound );
SHPHandle SHPAPI_CALL
SHPOpen( const char * pszShapeFile, const char * pszAccess );
SHPHandle SHPAPI_CALL
SHPCreate( const char * pszShapeFile, int nShapeType );
void SHPAPI_CALL
SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
double * padfMinBound, double * padfMaxBound );
SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
int SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
SHPObject SHPAPI_CALL1(*)
SHPReadObject( SHPHandle hSHP, int iShape );
int SHPAPI_CALL
SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
void SHPDestroyObject( SHPObject * psObject );
void SHPComputeExtents( SHPObject * psObject );
SHPObject *SHPCreateObject( int nSHPType, int nShapeId,
int nParts, int * panPartStart, int * panPartType,
int nVertices, double * padfX, double * padfY,
double * padfZ, double * padfM );
SHPObject *SHPCreateSimpleObject( int nSHPType, int nVertices,
double * padfX, double * padfY, double * padfZ );
void SHPAPI_CALL
SHPDestroyObject( SHPObject * psObject );
void SHPAPI_CALL
SHPComputeExtents( SHPObject * psObject );
SHPObject SHPAPI_CALL1(*)
SHPCreateObject( int nSHPType, int nShapeId,
int nParts, int * panPartStart, int * panPartType,
int nVertices, double * padfX, double * padfY,
double * padfZ, double * padfM );
SHPObject SHPAPI_CALL1(*)
SHPCreateSimpleObject( int nSHPType, int nVertices,
double * padfX, double * padfY, double * padfZ );
void SHPClose( SHPHandle hSHP );
int SHPAPI_CALL
SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
const char *SHPTypeName( int nSHPType );
const char *SHPPartTypeName( int nPartType );
void SHPAPI_CALL
SHPClose( SHPHandle hSHP );
const char SHPAPI_CALL1(*)
SHPTypeName( int nSHPType );
const char SHPAPI_CALL1(*)
SHPPartTypeName( int nPartType );
/* -------------------------------------------------------------------- */
/* Shape quadtree indexing API. */
/* -------------------------------------------------------------------- */
/* this can be two or four for binary or quad tree */
#define MAX_SUBNODE 4
typedef struct shape_tree_node
{
/* region covered by this node */
double adfBoundsMin[4];
double adfBoundsMax[4];
/* list of shapes stored at this node. The papsShapeObj pointers
or the whole list can be NULL */
int nShapeCount;
int *panShapeIds;
SHPObject **papsShapeObj;
int nSubNodes;
struct shape_tree_node *apsSubNode[MAX_SUBNODE];
} SHPTreeNode;
typedef struct
{
SHPHandle hSHP;
int nMaxDepth;
int nDimension;
SHPTreeNode *psRoot;
} SHPTree;
SHPTree SHPAPI_CALL1(*)
SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
double *padfBoundsMin, double *padfBoundsMax );
void SHPAPI_CALL
SHPDestroyTree( SHPTree * hTree );
int SHPAPI_CALL
SHPWriteTree( SHPTree *hTree, const char * pszFilename );
SHPTree SHPAPI_CALL
SHPReadTree( const char * pszFilename );
int SHPAPI_CALL
SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
int SHPAPI_CALL
SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
int SHPAPI_CALL
SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
void SHPAPI_CALL
SHPTreeTrimExtraNodes( SHPTree * hTree );
int SHPAPI_CALL1(*)
SHPTreeFindLikelyShapes( SHPTree * hTree,
double * padfBoundsMin,
double * padfBoundsMax,
int * );
int SHPAPI_CALL
SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
/************************************************************************/
/* DBF Support. */
@ -207,33 +409,73 @@ typedef enum {
FTString,
FTInteger,
FTDouble,
FTLogical,
FTInvalid
} DBFFieldType;
DBFHandle DBFOpen( const char * pszDBFFile, const char * pszAccess );
DBFHandle DBFCreate( const char * pszDBFFile );
#define XBASE_FLDHDR_SZ 32
int DBFGetFieldCount( DBFHandle psDBF );
int DBFGetRecordCount( DBFHandle psDBF );
int DBFAddField( DBFHandle hDBF, const char * pszFieldName,
DBFFieldType eType, int nWidth, int nDecimals );
DBFHandle SHPAPI_CALL
DBFOpen( const char * pszDBFFile, const char * pszAccess );
DBFHandle SHPAPI_CALL
DBFCreate( const char * pszDBFFile );
DBFFieldType DBFGetFieldInfo( DBFHandle psDBF, int iField,
char * pszFieldName,
int * pnWidth, int * pnDecimals );
int SHPAPI_CALL
DBFGetFieldCount( DBFHandle psDBF );
int SHPAPI_CALL
DBFGetRecordCount( DBFHandle psDBF );
int SHPAPI_CALL
DBFAddField( DBFHandle hDBF, const char * pszFieldName,
DBFFieldType eType, int nWidth, int nDecimals );
int DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
double DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
DBFFieldType SHPAPI_CALL
DBFGetFieldInfo( DBFHandle psDBF, int iField,
char * pszFieldName, int * pnWidth, int * pnDecimals );
int DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
int nFieldValue );
int DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
double dFieldValue );
int DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
const char * pszFieldValue );
int SHPAPI_CALL
DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
void DBFClose( DBFHandle hDBF );
int SHPAPI_CALL
DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
double SHPAPI_CALL
DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
const char SHPAPI_CALL1(*)
DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
const char SHPAPI_CALL1(*)
DBFReadLogicalAttribute( DBFHandle hDBF, int iShape, int iField );
int SHPAPI_CALL
DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
int SHPAPI_CALL
DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
int nFieldValue );
int SHPAPI_CALL
DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
double dFieldValue );
int SHPAPI_CALL
DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
const char * pszFieldValue );
int SHPAPI_CALL
DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
int SHPAPI_CALL
DBFWriteLogicalAttribute( DBFHandle hDBF, int iShape, int iField,
const char lFieldValue);
int SHPAPI_CALL
DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
void * pValue );
const char SHPAPI_CALL1(*)
DBFReadTuple(DBFHandle psDBF, int hEntity );
int SHPAPI_CALL
DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
DBFHandle SHPAPI_CALL
DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
void SHPAPI_CALL
DBFClose( DBFHandle hDBF );
char SHPAPI_CALL
DBFGetNativeFieldType( DBFHandle hDBF, int iField );
#ifdef __cplusplus
}

View file

@ -12,34 +12,6 @@ The Shapefile C Library provides the ability to write simple C programs
for reading, writing and updating (to a limited extent) ESRI Shapefiles,
and the associated attribute file (.dbf).<p>
<h2>Copyright</h2>
The source for the Shapefile C Library is (c) 1998 Frank Warmerdam,
and released under the following conditions. The intent is that anyone
can do anything with the code, but that I do not assume any liability, nor
express any warranty for this code. <p>
<quote>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:<p>
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.<p>
</quote>
<h2>Manifest</h2>
<ul>
@ -59,6 +31,9 @@ for the API for accessing the .dbf attribute files. <p>
<li> <b>shapefil.h</b>: Include file defining all the services of dbfopen.c
and shpopen.c.<p>
<li> <b>contrib/</b>: A directory of "in progress" contributed programs
from Carl Anderson.<p>
<li> <b>dbfcreate.c</b>: Simple example program for creating a new .dbf file.
<p>
@ -91,6 +66,13 @@ programs.<p>
<li> <b>shptest.c</b>: A simple test harnass to generate each of the supported
types of shapefiles. <p>
<li> <b>shptree.c</b>: Implements a simple quadtree algorithm for fast
spatial searches of shapefiles.<p>
<li> <b>shptreedump.c</b>: A simple mainly showing information on quad
trees build using the quad tree api.<p>
<li> <b>stream1.sh</b> - A test script, which should produce stream1.out.
Note this will only work if you have the example data downloaded.<p>
@ -99,6 +81,9 @@ Note this will only work if you have the example data downloaded.<p>
<li> <b>stream2.sh</b>: A test script, which should produce stream2.out.<p>
<li> <b>stream2.out</b>: Expected output of stream2.sh test script.<p>
<li> <b>pyshapelib-0.1</b>: Prototype contributed Python bindings.<p>
</ul>
<h2>What is a Shapefile?</h2>
@ -122,8 +107,38 @@ XXX.dbf - holds the attributes in xBase (dBase) format.
<h2>Release Notes</h2>
To get notification of new releases of Shapelib <i>subscribe</i> to
the project at www.freshmeat.net. This is currently the only reliable
way of finding out about new releases since there is no shapelib specific
mailing list.<p>
<b>Release 1.2.10</b>: Added SHPRewindObject() function, and shprewind utility
program. Added FTLogical, DBFReadLogicalAttribute() and
DBFWriteLogicalAttribute() (thanks to Olek Neyman). <p>
<b>Release 1.2.9</b>: Good support for reading and writing NULL fields
in .dbf files, good support for NULL shapes and addition of the
DBFGetFieldIndex() functions (all contributed by Jim Matthews).<p>
An upgraded shputils.c has been contributed by Bill Miller. Daniel
Morissette contributed DBFGetNativeFieldType(). Better error checking
for disk errors in dbfopen.c. Various other bug fixes and safety improvements.
<p>
<b>Release 1.2.8</b>: Added hacked libtool support (supplied by Jan)
and "rpm ready" install logic.<p>
<b>Release 1.2.7</b>: Fix record size (was 4 bytes too long). Modify
SHPReadObject() to handle null shapes properly. Use atof() instead of
sscanf(). Support .DBF as well as .dbf.<p>
<b>Release 1.2.6</b>: Now available under old MIT style license, or at the
users option, LGPL. Added the contrib directory of stuff from Carl Anderson
and the shptree.c API for quadtree based spatial searches.<p>
<b>Release 1.2.5</b>: SHPOpen() now forcably uses "rb" or "r+b" access string
to avoid common mistakes on Windows.<p>
to avoid common mistakes on Windows. Also fixed a serious bug with .dbf
files with a 'F' field type.<p>
<b>Release 1.2.4</b>: DBFOpen() will now automatically translate a .shp
extension to .dbf for convenience. SHPOpen() will try datasets with lower
@ -153,16 +168,51 @@ documentation.<p>
This library is maintained by me (Frank Warmerdam) on my own time. Please
send me bug patches and suggestions for the library. Email can be sent to
warmerda@home.com.<p>
warmerdam@pobox.com.<p>
The current status of the Shapelib code can be found somewhere off my
home page at http://members.home.com/warmerda.<p>
The current status of the Shapelib code can be found at
<a href="http://pobox.com/~warmerdam/root/projects/shapelib/">
http://pobox.com/~warmerdam/root/projects/shapelib/</a>. To find out about
new releases of Shapelib, select the "Subscribe to new releases" option
from the link at
<a href="http://freshmeat.net/projects/shapelib/">Freshmeat</a>.<p>
The shputils.c module was contributed by Bill Miller (NC-DOT) who can be
reached at bmiller@doh.dot.state.nc.us. I had to modify it substantially
to work with the 1.2 API, and I am not sure that it works as well as it
did when it was originally provided by Bill.<p>
<h2>Credits</h2>
I didn't start this section anywhere near soon enough, so alot of earlier
contributors to Shapelib are lost in pre-history.
<ul>
<li> Bill Miller (NY-DOT) for shputils.c
<li> Carl Anderson for the contents of the contrib directory, and
the "tuple" additions to dbfopen.c.
<li> Andrea Giacomelli for patches for dbfopen.c.
<li> Doug Matthews for portability improvements.
<li> Jan-Oliver Wagner for convincing me to make it available under LGPL,
shared library support, and various other patches.
<li> Dennis Christopher (of Avenza) for testing and bug fixes.
<li> Miko Syrjä (of 3D-system Oy) for a record size bug fix.
<li> Steven Lime and Curtis Hill for help with NULL shapes.
<li> Jim Matthews for support of NULL attributes in dbf files.
<li> <a href="http://www.pcigeomatics.com/">PCI Geomatics</a> who let me
release a modified version of their shapefile code in the beginning and
who hosted shapelib for years.
</ul>
<h2>In Memorium</h2>
I would like to dedicate Shapelib to the memory of Sol Katz. While I never
met him in person, his generous contributions to the GIS community took
many forms, including free distribution of a variety of GIS translators
with source. The fact that he used this Shapelib in some of his utilities,
and thanked me was a great encouragement to me. I hope I can do his memory
honour by trying to contribute in a similar fashion.<p>
<h2>Portability</h2>
The Shapefile C Library should port easily to 32bit systems with ANSI C
@ -175,6 +225,10 @@ such as MSDOS.<p>
The shputils.c module is contributed, and may not take the same approach
to portability as the rest of the package.<p>
On Linux, and most unix systems it should be possible to build and
install shapefile support as a shared library using the "lib" and "lib_install"
targets of the Makefile. Note that this Makefile doesn't use autoconf
mechanisms and will generally require some hand tailoring for your environment.
<h2>Limitations</h2>
@ -203,8 +257,76 @@ not used by ESRI.<p>
<li> The application must keep the .dbf file in sync with the .shp/.shx
files through appropriate use of the DBF and SHP APIs.<p>
<li> No support for the undocumented .sbn/.sbx spatial index files.<p>
</ul>
<h2>Copyright</h2>
The source for the Shapefile C Library is (c) 1998 Frank Warmerdam,
and released under the following conditions. The intent is that anyone
can do anything with the code, but that I do not assume any liability, nor
express any warranty for this code. <p>
As of Shapelib 1.2.6 the core portions of the library are made available
under two possible licenses. The licensee can choose to use the code
under either the Library GNU Public License (LGPL) described in
LICENSE.LGPL or under the following MIT style license. Any files in
the Shapelib distribution without explicit copyright license terms
(such as this documentation, the Makefile and so forth) should be
considered to have the following licensing terms. Some auxilary portions
of Shapelib, notably some of the components in the contrib directory
come under slightly different license restrictions. Check the source
files that you are actually using for conditions.<p>
<h3>Default License Terms</h3>
<quote>
Copyright (c) 1999, Frank Warmerdam<p>
This software is available under the following "MIT Style" license,
or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
option is discussed in more detail in shapelib.html.<p>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:<p>
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.<p>
</quote>
<h3>Shapelib Modifications</h3>
I am pleased to receive bug fixes, and improvements for Shapelib. Unless
the submissions indicate otherwise I will assume that changes submitted to
me remain under the the above "dual license" terms. If changes are made
to the library with the intention that those changes should be protected by
the LGPL then I should be informed upon submission. Note that I will not
generally incorporate changes into the core of Shapelib that are protected
under the LGPL as this would effectively limit the whole file and
distribution to LGPL terms.<p>
<h3>Opting for LGPL</h3>
For licensee's opting to use Shapelib under LGPL as opposed to the MIT
Style license above, and wishing to redistribute the software based on
Shapelib, I would ask that all "dual license" modules be updated to
indicate that only the LGPL (and not the MIT Style license) applies. This
action represents opting for the LGPL, and thereafter LGPL terms apply to
any redistribution and modification of the affected modules.<p>
</body>
</html>

View file

@ -17,9 +17,11 @@ accessed by the API functions. <p>
Shapes have types associated with them. The following is a list of the
different shapetypes supported by Shapefiles. At this time all shapes in
a Shapefile must be of the same type. <p>
a Shapefile must be of the same type (with the exception of NULL shapes). <p>
<pre>
#define SHPT_NULL 0
2D Shape Types (pre ArcView 3.x):
#define SHPT_POINT 1 Points
@ -161,6 +163,11 @@ SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
file, and may not be correct. For points the bounds are generated from
the single point since bounds aren't normally provided for point types.<p>
Generally the shapes returned will be of the type of the file as a whole.
However, any file may also contain type SHPT_NULL shapes which will have
no geometry. Generally speaking applications should skip rather than
preserve them, as they usually represented interactively deleted shapes.<p>
<!-------------------------------------------------------------------------->
<h2>SHPClose()</h2>
@ -347,5 +354,23 @@ void SHPDestroyObject( SHPObject *psObject );
SHPCreateSimpleObject(), SHPCreateObject() and returned from SHPReadObject().
<p>
<!-------------------------------------------------------------------------->
<h2>SHPRewindObject()</h2>
<pre>
int SHPRewindObject( SHPHandle hSHP, SHPObject *psObject );
hSHP: The shapefile (not used at this time).
psObject: The object to deallocate.
</pre>
This function will reverse any rings necessary in order to enforce the
shapefile restrictions on the required order of inner and outer rings in
the Shapefile specification. It returns TRUE if a change is made and FALSE
if no change is made. Only polygon objects will be affected though any
object may be passed.
<p>
</body>
</html>

View file

@ -1,14 +1,53 @@
/*
* Copyright (c) 1995 Frank Warmerdam
/******************************************************************************
* $Id: shpadd.c,v 1.13 2002/01/15 14:36:07 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Sample application for adding a shape to a shapefile.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shpadd.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.13 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.1 1999/08/24 21:13:01 curt
* Initial revision.
* Revision 1.12 2001/05/31 19:35:29 warmerda
* added support for writing null shapes
*
* Revision 1.11 2000/07/07 13:39:45 warmerda
* removed unused variables, and added system include files
*
* Revision 1.10 2000/05/24 15:09:22 warmerda
* Added logic to graw vertex lists of needed.
*
* Revision 1.9 1999/11/05 14:12:04 warmerda
* updated license terms
*
* Revision 1.8 1998/12/03 16:36:26 warmerda
* Use r+b rather than rb+ for binary access.
@ -34,22 +73,24 @@
*/
static char rcsid[] =
"$Id: shpadd.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: shpadd.c,v 1.13 2002/01/15 14:36:07 warmerda Exp $";
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
int main( int argc, char ** argv )
{
SHPHandle hSHP;
int nShapeType, nVertices, nParts, *panParts, i;
int nShapeType, nVertices, nParts, *panParts, i, nVMax;
double *padfX, *padfY;
SHPObject *psObject;
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
if( argc < 4 )
if( argc < 2 )
{
printf( "shpadd shp_file [[x y] [+]]*\n" );
exit( 1 );
@ -68,11 +109,15 @@ int main( int argc, char ** argv )
SHPGetInfo( hSHP, NULL, &nShapeType, NULL, NULL );
if( argc == 2 )
nShapeType = SHPT_NULL;
/* -------------------------------------------------------------------- */
/* Build a vertex/part list from the command line arguments. */
/* -------------------------------------------------------------------- */
padfX = (double *) malloc(sizeof(double) * 1000);
padfY = (double *) malloc(sizeof(double) * 1000);
nVMax = 1000;
padfX = (double *) malloc(sizeof(double) * nVMax);
padfY = (double *) malloc(sizeof(double) * nVMax);
nVertices = 0;
@ -94,6 +139,13 @@ int main( int argc, char ** argv )
}
else if( i < argc-1 )
{
if( nVertices == nVMax )
{
nVMax = nVMax * 2;
padfX = (double *) realloc(padfX,sizeof(double)*nVMax);
padfY = (double *) realloc(padfY,sizeof(double)*nVMax);
}
sscanf( argv[i], "%lg", padfX+nVertices );
sscanf( argv[i+1], "%lg", padfY+nVertices );
nVertices += 1;
@ -114,4 +166,6 @@ int main( int argc, char ** argv )
free( panParts );
free( padfX );
free( padfY );
return 0;
}

View file

@ -1,22 +1,55 @@
/*
* Copyright (c) 1995 Frank Warmerdam
/******************************************************************************
* $Id: shpcreate.c,v 1.5 2002/01/15 14:36:07 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Sample application for creating a new shapefile.
* Author: Frank Warmerdam, warmerdm@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shpcreate.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.5 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.1 1999/08/24 21:13:01 curt
* Initial revision.
* Revision 1.4 2000/07/07 13:39:45 warmerda
* removed unused variables, and added system include files
*
* Revision 1.2 1995/08/04 03:16:43 warmerda
* Revision 1.3 1999/11/05 14:12:04 warmerda
* updated license terms
*
* Revision 1.2 1995/08/04 03:16:43 warmerda
* Added header.
*
*/
static char rcsid[] =
"$Id: shpcreate.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: shpcreate.c,v 1.5 2002/01/15 14:36:07 warmerda Exp $";
#include "shapefil.h"
@ -25,7 +58,6 @@ int main( int argc, char ** argv )
{
SHPHandle hSHP;
int nShapeType;
double *padVertices;
/* -------------------------------------------------------------------- */
/* Display a usage message. */
@ -65,4 +97,6 @@ int main( int argc, char ** argv )
}
SHPClose( hSHP );
return 0;
}

View file

@ -1,14 +1,51 @@
/*
* Copyright (c) 1995 Frank Warmerdam
/******************************************************************************
* $Id: shpdump.c,v 1.10 2002/04/10 16:59:29 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Sample application for dumping contents of a shapefile to
* the terminal in human readable form.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shpdump.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.10 2002/04/10 16:59:29 warmerda
* added -validate switch
*
* Revision 1.1 1999/08/24 21:13:01 curt
* Initial revision.
* Revision 1.9 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.8 2000/07/07 13:39:45 warmerda
* removed unused variables, and added system include files
*
* Revision 1.7 1999/11/05 14:12:04 warmerda
* updated license terms
*
* Revision 1.6 1998/12/03 15:48:48 warmerda
* Added report of shapefile type, and total number of shapes.
@ -28,7 +65,7 @@
*/
static char rcsid[] =
"$Id: shpdump.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: shpdump.c,v 1.10 2002/04/10 16:59:29 warmerda Exp $";
#include "shapefil.h"
@ -36,16 +73,23 @@ int main( int argc, char ** argv )
{
SHPHandle hSHP;
int nShapeType, nEntities, i, iPart;
int nShapeType, nEntities, i, iPart, bValidate = 0,nInvalidCount=0;
const char *pszPlus;
double adfMinBound[4], adfMaxBound[4];
if( argc > 1 && strcmp(argv[1],"-validate") == 0 )
{
bValidate = 1;
argv++;
argc--;
}
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
if( argc != 2 )
{
printf( "shpdump shp_file\n" );
printf( "shpdump [-validate] shp_file\n" );
exit( 1 );
}
@ -68,8 +112,8 @@ int main( int argc, char ** argv )
printf( "Shapefile Type: %s # of Shapes: %d\n\n",
SHPTypeName( nShapeType ), nEntities );
printf( "File Bounds: (%12.3f,%12.3f,%lg,%lg)\n"
" to (%12.3f,%12.3f,%lg,%lg)\n",
printf( "File Bounds: (%12.3f,%12.3f,%g,%g)\n"
" to (%12.3f,%12.3f,%g,%g)\n",
adfMinBound[0],
adfMinBound[1],
adfMinBound[2],
@ -90,8 +134,8 @@ int main( int argc, char ** argv )
psShape = SHPReadObject( hSHP, i );
printf( "\nShape:%d (%s) nVertices=%d, nParts=%d\n"
" Bounds:(%12.3f,%12.3f, %lg, %lg)\n"
" to (%12.3f,%12.3f, %lg, %lg)\n",
" Bounds:(%12.3f,%12.3f, %g, %g)\n"
" to (%12.3f,%12.3f, %g, %g)\n",
i, SHPTypeName(psShape->nSHPType),
psShape->nVertices, psShape->nParts,
psShape->dfXMin, psShape->dfYMin,
@ -116,7 +160,7 @@ int main( int argc, char ** argv )
else
pszPlus = " ";
printf(" %s (%12.3f,%12.3f, %lg, %lg) %s \n",
printf(" %s (%12.3f,%12.3f, %g, %g) %s \n",
pszPlus,
psShape->padfX[j],
psShape->padfY[j],
@ -124,12 +168,29 @@ int main( int argc, char ** argv )
psShape->padfM[j],
pszPartType );
}
if( bValidate )
{
int nAltered = SHPRewindObject( hSHP, psShape );
if( nAltered > 0 )
{
printf( " %d rings wound in the wrong direction.\n",
nAltered );
nInvalidCount++;
}
}
SHPDestroyObject( psShape );
}
SHPClose( hSHP );
if( bValidate )
{
printf( "%d object has invalid ring orderings.\n", nInvalidCount );
}
#ifdef USE_DBMALLOC
malloc_dump(2);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,109 @@
/******************************************************************************
* $Id: shprewind.c,v 1.2 2002/04/10 17:23:11 warmerda Exp $
*
* Project: Shapelib
* Purpose: Utility to validate and reset the winding order of rings in
* polygon geometries to match the ordering required by spec.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2002, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shprewind.c,v $
* Revision 1.2 2002/04/10 17:23:11 warmerda
* copy from source to destination now
*
* Revision 1.1 2002/04/10 16:56:36 warmerda
* New
*
*/
#include "shapefil.h"
int main( int argc, char ** argv )
{
SHPHandle hSHP, hSHPOut;
int nShapeType, nEntities, i, nInvalidCount=0;
double adfMinBound[4], adfMaxBound[4];
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
if( argc != 3 )
{
printf( "shprewind in_shp_file out_shp_file\n" );
exit( 1 );
}
/* -------------------------------------------------------------------- */
/* Open the passed shapefile. */
/* -------------------------------------------------------------------- */
hSHP = SHPOpen( argv[1], "rb" );
if( hSHP == NULL )
{
printf( "Unable to open:%s\n", argv[1] );
exit( 1 );
}
SHPGetInfo( hSHP, &nEntities, &nShapeType, adfMinBound, adfMaxBound );
/* -------------------------------------------------------------------- */
/* Create output shapefile. */
/* -------------------------------------------------------------------- */
hSHPOut = SHPCreate( argv[2], nShapeType );
if( hSHPOut == NULL )
{
printf( "Unable to create:%s\n", argv[2] );
exit( 1 );
}
/* -------------------------------------------------------------------- */
/* Skim over the list of shapes, printing all the vertices. */
/* -------------------------------------------------------------------- */
for( i = 0; i < nEntities; i++ )
{
int j;
SHPObject *psShape;
psShape = SHPReadObject( hSHP, i );
if( SHPRewindObject( hSHP, psShape ) )
nInvalidCount++;
SHPWriteObject( hSHPOut, -1, psShape );
SHPDestroyObject( psShape );
}
SHPClose( hSHP );
SHPClose( hSHPOut );
printf( "%d objects rewound.\n", nInvalidCount );
exit( 0 );
}

View file

@ -1,14 +1,51 @@
/*
* Copyright (c) 1998 Frank Warmerdam
/******************************************************************************
* $Id: shptest.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose: Application for generating sample Shapefiles of various types.
* Used by the stream2.sh test script.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shptest.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.6 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.1 1999/08/24 21:13:01 curt
* Initial revision.
* Revision 1.5 2001/06/22 02:18:20 warmerda
* Added null shape support
*
* Revision 1.4 2000/07/07 13:39:45 warmerda
* removed unused variables, and added system include files
*
* Revision 1.3 1999/11/05 14:12:05 warmerda
* updated license terms
*
* Revision 1.2 1998/12/16 05:15:20 warmerda
* Added support for writing multipatch.
@ -19,8 +56,10 @@
*/
static char rcsid[] =
"$Id: shptest.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: shptest.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $";
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
/************************************************************************/
@ -208,10 +247,6 @@ static void Test_WriteArcPoly( int nSHPType, const char *pszFilename )
int main( int argc, char ** argv )
{
SHPHandle hSHP;
int nShapeType, nEntities, i, iPart;
const char *pszPlus;
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
@ -225,7 +260,10 @@ int main( int argc, char ** argv )
/* Figure out which test to run. */
/* -------------------------------------------------------------------- */
if( atoi(argv[1]) == 1 )
if( atoi(argv[1]) == 0 )
Test_WritePoints( SHPT_NULL, "test0.shp" );
else if( atoi(argv[1]) == 1 )
Test_WritePoints( SHPT_POINT, "test1.shp" );
else if( atoi(argv[1]) == 2 )
Test_WritePoints( SHPT_POINTZ, "test2.shp" );

679
src/Lib/shapelib/shptree.c Normal file
View file

@ -0,0 +1,679 @@
/******************************************************************************
* $Id: shptree.c,v 1.9 2003/01/28 15:53:41 warmerda Exp $
*
* Project: Shapelib
* Purpose: Implementation of quadtree building and searching functions.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shptree.c,v $
* Revision 1.9 2003/01/28 15:53:41 warmerda
* Avoid build warnings.
*
* Revision 1.8 2002/05/07 13:07:45 warmerda
* use qsort() - patch from Bernhard Herzog
*
* Revision 1.7 2002/01/15 14:36:07 warmerda
* updated email address
*
* Revision 1.6 2001/05/23 13:36:52 warmerda
* added use of SHPAPI_CALL
*
* Revision 1.5 1999/11/05 14:12:05 warmerda
* updated license terms
*
* Revision 1.4 1999/06/02 18:24:21 warmerda
* added trimming code
*
* Revision 1.3 1999/06/02 17:56:12 warmerda
* added quad'' subnode support for trees
*
* Revision 1.2 1999/05/18 19:11:11 warmerda
* Added example searching capability
*
* Revision 1.1 1999/05/18 17:49:20 warmerda
* New
*
*/
static char rcsid[] =
"$Id: shptree.c,v 1.9 2003/01/28 15:53:41 warmerda Exp $";
#include "shapefil.h"
#include <math.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
/* -------------------------------------------------------------------- */
/* If the following is 0.5, nodes will be split in half. If it */
/* is 0.6 then each subnode will contain 60% of the parent */
/* node, with 20% representing overlap. This can be help to */
/* prevent small objects on a boundary from shifting too high */
/* up the tree. */
/* -------------------------------------------------------------------- */
#define SHP_SPLIT_RATIO 0.55
/************************************************************************/
/* SfRealloc() */
/* */
/* A realloc cover function that will access a NULL pointer as */
/* a valid input. */
/************************************************************************/
static void * SfRealloc( void * pMem, int nNewSize )
{
if( pMem == NULL )
return( (void *) malloc(nNewSize) );
else
return( (void *) realloc(pMem,nNewSize) );
}
/************************************************************************/
/* SHPTreeNodeInit() */
/* */
/* Initialize a tree node. */
/************************************************************************/
static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
double * padfBoundsMax )
{
SHPTreeNode *psTreeNode;
psTreeNode = (SHPTreeNode *) malloc(sizeof(SHPTreeNode));
psTreeNode->nShapeCount = 0;
psTreeNode->panShapeIds = NULL;
psTreeNode->papsShapeObj = NULL;
psTreeNode->nSubNodes = 0;
if( padfBoundsMin != NULL )
memcpy( psTreeNode->adfBoundsMin, padfBoundsMin, sizeof(double) * 4 );
if( padfBoundsMax != NULL )
memcpy( psTreeNode->adfBoundsMax, padfBoundsMax, sizeof(double) * 4 );
return psTreeNode;
}
/************************************************************************/
/* SHPCreateTree() */
/************************************************************************/
SHPTree SHPAPI_CALL1(*)
SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
double *padfBoundsMin, double *padfBoundsMax )
{
SHPTree *psTree;
if( padfBoundsMin == NULL && hSHP == NULL )
return NULL;
/* -------------------------------------------------------------------- */
/* Allocate the tree object */
/* -------------------------------------------------------------------- */
psTree = (SHPTree *) malloc(sizeof(SHPTree));
psTree->hSHP = hSHP;
psTree->nMaxDepth = nMaxDepth;
psTree->nDimension = nDimension;
/* -------------------------------------------------------------------- */
/* If no max depth was defined, try to select a reasonable one */
/* that implies approximately 8 shapes per node. */
/* -------------------------------------------------------------------- */
if( psTree->nMaxDepth == 0 && hSHP != NULL )
{
int nMaxNodeCount = 1;
int nShapeCount;
SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
while( nMaxNodeCount*4 < nShapeCount )
{
psTree->nMaxDepth += 1;
nMaxNodeCount = nMaxNodeCount * 2;
}
}
/* -------------------------------------------------------------------- */
/* Allocate the root node. */
/* -------------------------------------------------------------------- */
psTree->psRoot = SHPTreeNodeCreate( padfBoundsMin, padfBoundsMax );
/* -------------------------------------------------------------------- */
/* Assign the bounds to the root node. If none are passed in, */
/* use the bounds of the provided file otherwise the create */
/* function will have already set the bounds. */
/* -------------------------------------------------------------------- */
if( padfBoundsMin == NULL )
{
SHPGetInfo( hSHP, NULL, NULL,
psTree->psRoot->adfBoundsMin,
psTree->psRoot->adfBoundsMax );
}
/* -------------------------------------------------------------------- */
/* If we have a file, insert all it's shapes into the tree. */
/* -------------------------------------------------------------------- */
if( hSHP != NULL )
{
int iShape, nShapeCount;
SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
for( iShape = 0; iShape < nShapeCount; iShape++ )
{
SHPObject *psShape;
psShape = SHPReadObject( hSHP, iShape );
SHPTreeAddShapeId( psTree, psShape );
SHPDestroyObject( psShape );
}
}
return psTree;
}
/************************************************************************/
/* SHPDestroyTreeNode() */
/************************************************************************/
static void SHPDestroyTreeNode( SHPTreeNode * psTreeNode )
{
int i;
for( i = 0; i < psTreeNode->nSubNodes; i++ )
{
if( psTreeNode->apsSubNode[i] != NULL )
SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
}
if( psTreeNode->panShapeIds != NULL )
free( psTreeNode->panShapeIds );
if( psTreeNode->papsShapeObj != NULL )
{
for( i = 0; i < psTreeNode->nShapeCount; i++ )
{
if( psTreeNode->papsShapeObj[i] != NULL )
SHPDestroyObject( psTreeNode->papsShapeObj[i] );
}
free( psTreeNode->papsShapeObj );
}
free( psTreeNode );
}
/************************************************************************/
/* SHPDestroyTree() */
/************************************************************************/
void SHPAPI_CALL
SHPDestroyTree( SHPTree * psTree )
{
SHPDestroyTreeNode( psTree->psRoot );
free( psTree );
}
/************************************************************************/
/* SHPCheckBoundsOverlap() */
/* */
/* Do the given boxes overlap at all? */
/************************************************************************/
int SHPAPI_CALL
SHPCheckBoundsOverlap( double * padfBox1Min, double * padfBox1Max,
double * padfBox2Min, double * padfBox2Max,
int nDimension )
{
int iDim;
for( iDim = 0; iDim < nDimension; iDim++ )
{
if( padfBox2Max[iDim] < padfBox1Min[iDim] )
return FALSE;
if( padfBox1Max[iDim] < padfBox2Min[iDim] )
return FALSE;
}
return TRUE;
}
/************************************************************************/
/* SHPCheckObjectContained() */
/* */
/* Does the given shape fit within the indicated extents? */
/************************************************************************/
static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
double * padfBoundsMin, double * padfBoundsMax )
{
if( psObject->dfXMin < padfBoundsMin[0]
|| psObject->dfXMax > padfBoundsMax[0] )
return FALSE;
if( psObject->dfYMin < padfBoundsMin[1]
|| psObject->dfYMax > padfBoundsMax[1] )
return FALSE;
if( nDimension == 2 )
return TRUE;
if( psObject->dfZMin < padfBoundsMin[2]
|| psObject->dfZMax < padfBoundsMax[2] )
return FALSE;
if( nDimension == 3 )
return TRUE;
if( psObject->dfMMin < padfBoundsMin[3]
|| psObject->dfMMax < padfBoundsMax[3] )
return FALSE;
return TRUE;
}
/************************************************************************/
/* SHPTreeSplitBounds() */
/* */
/* Split a region into two subregion evenly, cutting along the */
/* longest dimension. */
/************************************************************************/
void SHPAPI_CALL
SHPTreeSplitBounds( double *padfBoundsMinIn, double *padfBoundsMaxIn,
double *padfBoundsMin1, double * padfBoundsMax1,
double *padfBoundsMin2, double * padfBoundsMax2 )
{
/* -------------------------------------------------------------------- */
/* The output bounds will be very similar to the input bounds, */
/* so just copy over to start. */
/* -------------------------------------------------------------------- */
memcpy( padfBoundsMin1, padfBoundsMinIn, sizeof(double) * 4 );
memcpy( padfBoundsMax1, padfBoundsMaxIn, sizeof(double) * 4 );
memcpy( padfBoundsMin2, padfBoundsMinIn, sizeof(double) * 4 );
memcpy( padfBoundsMax2, padfBoundsMaxIn, sizeof(double) * 4 );
/* -------------------------------------------------------------------- */
/* Split in X direction. */
/* -------------------------------------------------------------------- */
if( (padfBoundsMaxIn[0] - padfBoundsMinIn[0])
> (padfBoundsMaxIn[1] - padfBoundsMinIn[1]) )
{
double dfRange = padfBoundsMaxIn[0] - padfBoundsMinIn[0];
padfBoundsMax1[0] = padfBoundsMinIn[0] + dfRange * SHP_SPLIT_RATIO;
padfBoundsMin2[0] = padfBoundsMaxIn[0] - dfRange * SHP_SPLIT_RATIO;
}
/* -------------------------------------------------------------------- */
/* Otherwise split in Y direction. */
/* -------------------------------------------------------------------- */
else
{
double dfRange = padfBoundsMaxIn[1] - padfBoundsMinIn[1];
padfBoundsMax1[1] = padfBoundsMinIn[1] + dfRange * SHP_SPLIT_RATIO;
padfBoundsMin2[1] = padfBoundsMaxIn[1] - dfRange * SHP_SPLIT_RATIO;
}
}
/************************************************************************/
/* SHPTreeNodeAddShapeId() */
/************************************************************************/
static int
SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
int nMaxDepth, int nDimension )
{
int i;
/* -------------------------------------------------------------------- */
/* If there are subnodes, then consider wiether this object */
/* will fit in them. */
/* -------------------------------------------------------------------- */
if( nMaxDepth > 1 && psTreeNode->nSubNodes > 0 )
{
for( i = 0; i < psTreeNode->nSubNodes; i++ )
{
if( SHPCheckObjectContained(psObject, nDimension,
psTreeNode->apsSubNode[i]->adfBoundsMin,
psTreeNode->apsSubNode[i]->adfBoundsMax))
{
return SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[i],
psObject, nMaxDepth-1,
nDimension );
}
}
}
/* -------------------------------------------------------------------- */
/* Otherwise, consider creating four subnodes if could fit into */
/* them, and adding to the appropriate subnode. */
/* -------------------------------------------------------------------- */
#if MAX_SUBNODE == 4
else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
{
double adfBoundsMinH1[4], adfBoundsMaxH1[4];
double adfBoundsMinH2[4], adfBoundsMaxH2[4];
double adfBoundsMin1[4], adfBoundsMax1[4];
double adfBoundsMin2[4], adfBoundsMax2[4];
double adfBoundsMin3[4], adfBoundsMax3[4];
double adfBoundsMin4[4], adfBoundsMax4[4];
SHPTreeSplitBounds( psTreeNode->adfBoundsMin,
psTreeNode->adfBoundsMax,
adfBoundsMinH1, adfBoundsMaxH1,
adfBoundsMinH2, adfBoundsMaxH2 );
SHPTreeSplitBounds( adfBoundsMinH1, adfBoundsMaxH1,
adfBoundsMin1, adfBoundsMax1,
adfBoundsMin2, adfBoundsMax2 );
SHPTreeSplitBounds( adfBoundsMinH2, adfBoundsMaxH2,
adfBoundsMin3, adfBoundsMax3,
adfBoundsMin4, adfBoundsMax4 );
if( SHPCheckObjectContained(psObject, nDimension,
adfBoundsMin1, adfBoundsMax1)
|| SHPCheckObjectContained(psObject, nDimension,
adfBoundsMin2, adfBoundsMax2)
|| SHPCheckObjectContained(psObject, nDimension,
adfBoundsMin3, adfBoundsMax3)
|| SHPCheckObjectContained(psObject, nDimension,
adfBoundsMin4, adfBoundsMax4) )
{
psTreeNode->nSubNodes = 4;
psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
adfBoundsMax1 );
psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
adfBoundsMax2 );
psTreeNode->apsSubNode[2] = SHPTreeNodeCreate( adfBoundsMin3,
adfBoundsMax3 );
psTreeNode->apsSubNode[3] = SHPTreeNodeCreate( adfBoundsMin4,
adfBoundsMax4 );
/* recurse back on this node now that it has subnodes */
return( SHPTreeNodeAddShapeId( psTreeNode, psObject,
nMaxDepth, nDimension ) );
}
}
#endif /* MAX_SUBNODE == 4 */
/* -------------------------------------------------------------------- */
/* Otherwise, consider creating two subnodes if could fit into */
/* them, and adding to the appropriate subnode. */
/* -------------------------------------------------------------------- */
#if MAX_SUBNODE == 2
else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
{
double adfBoundsMin1[4], adfBoundsMax1[4];
double adfBoundsMin2[4], adfBoundsMax2[4];
SHPTreeSplitBounds( psTreeNode->adfBoundsMin, psTreeNode->adfBoundsMax,
adfBoundsMin1, adfBoundsMax1,
adfBoundsMin2, adfBoundsMax2 );
if( SHPCheckObjectContained(psObject, nDimension,
adfBoundsMin1, adfBoundsMax1))
{
psTreeNode->nSubNodes = 2;
psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
adfBoundsMax1 );
psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
adfBoundsMax2 );
return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[0], psObject,
nMaxDepth - 1, nDimension ) );
}
else if( SHPCheckObjectContained(psObject, nDimension,
adfBoundsMin2, adfBoundsMax2) )
{
psTreeNode->nSubNodes = 2;
psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
adfBoundsMax1 );
psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
adfBoundsMax2 );
return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[1], psObject,
nMaxDepth - 1, nDimension ) );
}
}
#endif /* MAX_SUBNODE == 2 */
/* -------------------------------------------------------------------- */
/* If none of that worked, just add it to this nodes list. */
/* -------------------------------------------------------------------- */
psTreeNode->nShapeCount++;
psTreeNode->panShapeIds =
SfRealloc( psTreeNode->panShapeIds,
sizeof(int) * psTreeNode->nShapeCount );
psTreeNode->panShapeIds[psTreeNode->nShapeCount-1] = psObject->nShapeId;
if( psTreeNode->papsShapeObj != NULL )
{
psTreeNode->papsShapeObj =
SfRealloc( psTreeNode->papsShapeObj,
sizeof(void *) * psTreeNode->nShapeCount );
psTreeNode->papsShapeObj[psTreeNode->nShapeCount-1] = NULL;
}
return TRUE;
}
/************************************************************************/
/* SHPTreeAddShapeId() */
/* */
/* Add a shape to the tree, but don't keep a pointer to the */
/* object data, just keep the shapeid. */
/************************************************************************/
int SHPAPI_CALL
SHPTreeAddShapeId( SHPTree * psTree, SHPObject * psObject )
{
return( SHPTreeNodeAddShapeId( psTree->psRoot, psObject,
psTree->nMaxDepth, psTree->nDimension ) );
}
/************************************************************************/
/* SHPTreeCollectShapesIds() */
/* */
/* Work function implementing SHPTreeFindLikelyShapes() on a */
/* tree node by tree node basis. */
/************************************************************************/
void SHPAPI_CALL
SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
double * padfBoundsMin, double * padfBoundsMax,
int * pnShapeCount, int * pnMaxShapes,
int ** ppanShapeList )
{
int i;
/* -------------------------------------------------------------------- */
/* Does this node overlap the area of interest at all? If not, */
/* return without adding to the list at all. */
/* -------------------------------------------------------------------- */
if( !SHPCheckBoundsOverlap( psTreeNode->adfBoundsMin,
psTreeNode->adfBoundsMax,
padfBoundsMin,
padfBoundsMax,
hTree->nDimension ) )
return;
/* -------------------------------------------------------------------- */
/* Grow the list to hold the shapes on this node. */
/* -------------------------------------------------------------------- */
if( *pnShapeCount + psTreeNode->nShapeCount > *pnMaxShapes )
{
*pnMaxShapes = (*pnShapeCount + psTreeNode->nShapeCount) * 2 + 20;
*ppanShapeList = (int *)
SfRealloc(*ppanShapeList,sizeof(int) * *pnMaxShapes);
}
/* -------------------------------------------------------------------- */
/* Add the local nodes shapeids to the list. */
/* -------------------------------------------------------------------- */
for( i = 0; i < psTreeNode->nShapeCount; i++ )
{
(*ppanShapeList)[(*pnShapeCount)++] = psTreeNode->panShapeIds[i];
}
/* -------------------------------------------------------------------- */
/* Recurse to subnodes if they exist. */
/* -------------------------------------------------------------------- */
for( i = 0; i < psTreeNode->nSubNodes; i++ )
{
if( psTreeNode->apsSubNode[i] != NULL )
SHPTreeCollectShapeIds( hTree, psTreeNode->apsSubNode[i],
padfBoundsMin, padfBoundsMax,
pnShapeCount, pnMaxShapes,
ppanShapeList );
}
}
/************************************************************************/
/* SHPTreeFindLikelyShapes() */
/* */
/* Find all shapes within tree nodes for which the tree node */
/* bounding box overlaps the search box. The return value is */
/* an array of shapeids terminated by a -1. The shapeids will */
/* be in order, as hopefully this will result in faster (more */
/* sequential) reading from the file. */
/************************************************************************/
/* helper for qsort */
static int
compare_ints( const void * a, const void * b)
{
return (*(int*)a) - (*(int*)b);
}
int SHPAPI_CALL1(*)
SHPTreeFindLikelyShapes( SHPTree * hTree,
double * padfBoundsMin, double * padfBoundsMax,
int * pnShapeCount )
{
int *panShapeList=NULL, nMaxShapes = 0;
/* -------------------------------------------------------------------- */
/* Perform the search by recursive descent. */
/* -------------------------------------------------------------------- */
*pnShapeCount = 0;
SHPTreeCollectShapeIds( hTree, hTree->psRoot,
padfBoundsMin, padfBoundsMax,
pnShapeCount, &nMaxShapes,
&panShapeList );
/* -------------------------------------------------------------------- */
/* Sort the id array */
/* -------------------------------------------------------------------- */
qsort(panShapeList, *pnShapeCount, sizeof(int), compare_ints);
return panShapeList;
}
/************************************************************************/
/* SHPTreeNodeTrim() */
/* */
/* This is the recurve version of SHPTreeTrimExtraNodes() that */
/* walks the tree cleaning it up. */
/************************************************************************/
static int SHPTreeNodeTrim( SHPTreeNode * psTreeNode )
{
int i;
/* -------------------------------------------------------------------- */
/* Trim subtrees, and free subnodes that come back empty. */
/* -------------------------------------------------------------------- */
for( i = 0; i < psTreeNode->nSubNodes; i++ )
{
if( SHPTreeNodeTrim( psTreeNode->apsSubNode[i] ) )
{
SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
psTreeNode->apsSubNode[i] =
psTreeNode->apsSubNode[psTreeNode->nSubNodes-1];
psTreeNode->nSubNodes--;
i--; /* process the new occupant of this subnode entry */
}
}
/* -------------------------------------------------------------------- */
/* We should be trimmed if we have no subnodes, and no shapes. */
/* -------------------------------------------------------------------- */
return( psTreeNode->nSubNodes == 0 && psTreeNode->nShapeCount == 0 );
}
/************************************************************************/
/* SHPTreeTrimExtraNodes() */
/* */
/* Trim empty nodes from the tree. Note that we never trim an */
/* empty root node. */
/************************************************************************/
void SHPAPI_CALL
SHPTreeTrimExtraNodes( SHPTree * hTree )
{
SHPTreeNodeTrim( hTree->psRoot );
}

View file

@ -0,0 +1,398 @@
/******************************************************************************
* $Id: shptreedump.c,v 1.7 2002/04/10 16:59:12 warmerda Exp $
*
* Project: Shapelib
* Purpose: Mainline for creating and dumping an ASCII representation of
* a quadtree.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shptreedump.c,v $
* Revision 1.7 2002/04/10 16:59:12 warmerda
* fixed email
*
* Revision 1.6 1999/11/05 14:12:05 warmerda
* updated license terms
*
* Revision 1.5 1999/06/02 18:24:21 warmerda
* added trimming code
*
* Revision 1.4 1999/06/02 17:56:12 warmerda
* added quad'' subnode support for trees
*
* Revision 1.3 1999/05/18 19:13:13 warmerda
* Use fabs() instead of abs().
*
* Revision 1.2 1999/05/18 19:11:11 warmerda
* Added example searching capability
*
* Revision 1.1 1999/05/18 17:49:20 warmerda
* New
*
*/
static char rcsid[] =
"$Id: shptreedump.c,v 1.7 2002/04/10 16:59:12 warmerda Exp $";
#include "shapefil.h"
#include <assert.h>
#include <stdlib.h>
#include <math.h>
static void SHPTreeNodeDump( SHPTree *, SHPTreeNode *, const char *, int );
static void SHPTreeNodeSearchAndDump( SHPTree *, double *, double * );
/************************************************************************/
/* Usage() */
/************************************************************************/
static void Usage()
{
printf( "shptreedump [-maxdepth n] [-search xmin ymin xmax ymax]\n"
" [-v] shp_file\n" );
exit( 1 );
}
/************************************************************************/
/* main() */
/************************************************************************/
int main( int argc, char ** argv )
{
SHPHandle hSHP;
SHPTree *psTree;
int nExpandShapes = 0;
int nMaxDepth = 0;
int nDoSearch = 0;
double adfSearchMin[4], adfSearchMax[4];
/* -------------------------------------------------------------------- */
/* Consume flags. */
/* -------------------------------------------------------------------- */
while( argc > 1 )
{
if( strcmp(argv[1],"-v") == 0 )
{
nExpandShapes = 1;
argv++;
argc--;
}
else if( strcmp(argv[1],"-maxdepth") == 0 && argc > 2 )
{
nMaxDepth = atoi(argv[2]);
argv += 2;
argc -= 2;
}
else if( strcmp(argv[1],"-search") == 0 && argc > 5 )
{
nDoSearch = 1;
adfSearchMin[0] = atof(argv[2]);
adfSearchMin[1] = atof(argv[3]);
adfSearchMax[0] = atof(argv[4]);
adfSearchMax[1] = atof(argv[5]);
adfSearchMin[2] = adfSearchMax[2] = 0.0;
adfSearchMin[3] = adfSearchMax[3] = 0.0;
if( adfSearchMin[0] > adfSearchMax[0]
|| adfSearchMin[1] > adfSearchMax[1] )
{
printf( "Min greater than max in search criteria.\n" );
Usage();
}
argv += 5;
argc -= 5;
}
else
break;
}
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
if( argc < 2 )
{
Usage();
}
/* -------------------------------------------------------------------- */
/* Open the passed shapefile. */
/* -------------------------------------------------------------------- */
hSHP = SHPOpen( argv[1], "rb" );
if( hSHP == NULL )
{
printf( "Unable to open:%s\n", argv[1] );
exit( 1 );
}
/* -------------------------------------------------------------------- */
/* Build a quadtree structure for this file. */
/* -------------------------------------------------------------------- */
psTree = SHPCreateTree( hSHP, 2, nMaxDepth, NULL, NULL );
/* -------------------------------------------------------------------- */
/* Trim unused nodes from the tree. */
/* -------------------------------------------------------------------- */
SHPTreeTrimExtraNodes( psTree );
/* -------------------------------------------------------------------- */
/* Dump tree by recursive descent. */
/* -------------------------------------------------------------------- */
if( !nDoSearch )
SHPTreeNodeDump( psTree, psTree->psRoot, "", nExpandShapes );
/* -------------------------------------------------------------------- */
/* or do a search instead. */
/* -------------------------------------------------------------------- */
else
SHPTreeNodeSearchAndDump( psTree, adfSearchMin, adfSearchMax );
/* -------------------------------------------------------------------- */
/* cleanup */
/* -------------------------------------------------------------------- */
SHPDestroyTree( psTree );
SHPClose( hSHP );
#ifdef USE_DBMALLOC
malloc_dump(2);
#endif
exit( 0 );
}
/************************************************************************/
/* EmitCoordinate() */
/************************************************************************/
static void EmitCoordinate( double * padfCoord, int nDimension )
{
const char *pszFormat;
if( fabs(padfCoord[0]) < 180 && fabs(padfCoord[1]) < 180 )
pszFormat = "%.9f";
else
pszFormat = "%.2f";
printf( pszFormat, padfCoord[0] );
printf( "," );
printf( pszFormat, padfCoord[1] );
if( nDimension > 2 )
{
printf( "," );
printf( pszFormat, padfCoord[2] );
}
if( nDimension > 3 )
{
printf( "," );
printf( pszFormat, padfCoord[3] );
}
}
/************************************************************************/
/* EmitShape() */
/************************************************************************/
static void EmitShape( SHPObject * psObject, const char * pszPrefix,
int nDimension )
{
int i;
printf( "%s( Shape\n", pszPrefix );
printf( "%s ShapeId = %d\n", pszPrefix, psObject->nShapeId );
printf( "%s Min = (", pszPrefix );
EmitCoordinate( &(psObject->dfXMin), nDimension );
printf( ")\n" );
printf( "%s Max = (", pszPrefix );
EmitCoordinate( &(psObject->dfXMax), nDimension );
printf( ")\n" );
for( i = 0; i < psObject->nVertices; i++ )
{
double adfVertex[4];
printf( "%s Vertex[%d] = (", pszPrefix, i );
adfVertex[0] = psObject->padfX[i];
adfVertex[1] = psObject->padfY[i];
adfVertex[2] = psObject->padfZ[i];
adfVertex[3] = psObject->padfM[i];
EmitCoordinate( adfVertex, nDimension );
printf( ")\n" );
}
printf( "%s)\n", pszPrefix );
}
/************************************************************************/
/* SHPTreeNodeDump() */
/* */
/* Dump a tree node in a readable form. */
/************************************************************************/
static void SHPTreeNodeDump( SHPTree * psTree,
SHPTreeNode * psTreeNode,
const char * pszPrefix,
int nExpandShapes )
{
char szNextPrefix[150];
int i;
strcpy( szNextPrefix, pszPrefix );
if( strlen(pszPrefix) < sizeof(szNextPrefix) - 3 )
strcat( szNextPrefix, " " );
printf( "%s( SHPTreeNode\n", pszPrefix );
/* -------------------------------------------------------------------- */
/* Emit the bounds. */
/* -------------------------------------------------------------------- */
printf( "%s Min = (", pszPrefix );
EmitCoordinate( psTreeNode->adfBoundsMin, psTree->nDimension );
printf( ")\n" );
printf( "%s Max = (", pszPrefix );
EmitCoordinate( psTreeNode->adfBoundsMax, psTree->nDimension );
printf( ")\n" );
/* -------------------------------------------------------------------- */
/* Emit the list of shapes on this node. */
/* -------------------------------------------------------------------- */
if( nExpandShapes )
{
printf( "%s Shapes(%d):\n", pszPrefix, psTreeNode->nShapeCount );
for( i = 0; i < psTreeNode->nShapeCount; i++ )
{
SHPObject *psObject;
psObject = SHPReadObject( psTree->hSHP,
psTreeNode->panShapeIds[i] );
assert( psObject != NULL );
if( psObject != NULL )
{
EmitShape( psObject, szNextPrefix, psTree->nDimension );
}
SHPDestroyObject( psObject );
}
}
else
{
printf( "%s Shapes(%d): ", pszPrefix, psTreeNode->nShapeCount );
for( i = 0; i < psTreeNode->nShapeCount; i++ )
{
printf( "%d ", psTreeNode->panShapeIds[i] );
}
printf( "\n" );
}
/* -------------------------------------------------------------------- */
/* Emit subnodes. */
/* -------------------------------------------------------------------- */
for( i = 0; i < psTreeNode->nSubNodes; i++ )
{
if( psTreeNode->apsSubNode[i] != NULL )
SHPTreeNodeDump( psTree, psTreeNode->apsSubNode[i],
szNextPrefix, nExpandShapes );
}
printf( "%s)\n", pszPrefix );
return;
}
/************************************************************************/
/* SHPTreeNodeSearchAndDump() */
/************************************************************************/
static void SHPTreeNodeSearchAndDump( SHPTree * hTree,
double *padfBoundsMin,
double *padfBoundsMax )
{
int *panHits, nShapeCount, i;
/* -------------------------------------------------------------------- */
/* Perform the search for likely candidates. These are shapes */
/* that fall into a tree node whose bounding box intersects our */
/* area of interest. */
/* -------------------------------------------------------------------- */
panHits = SHPTreeFindLikelyShapes( hTree, padfBoundsMin, padfBoundsMax,
&nShapeCount );
/* -------------------------------------------------------------------- */
/* Read all of these shapes, and establish whether the shape's */
/* bounding box actually intersects the area of interest. Note */
/* that the bounding box could intersect the area of interest, */
/* and the shape itself still not cross it but we don't try to */
/* address that here. */
/* -------------------------------------------------------------------- */
for( i = 0; i < nShapeCount; i++ )
{
SHPObject *psObject;
psObject = SHPReadObject( hTree->hSHP, panHits[i] );
if( psObject == NULL )
continue;
if( !SHPCheckBoundsOverlap( padfBoundsMin, padfBoundsMax,
&(psObject->dfXMin),
&(psObject->dfXMax),
hTree->nDimension ) )
{
printf( "Shape %d: not in area of interest, but fetched.\n",
panHits[i] );
}
else
{
printf( "Shape %d: appears to be in area of interest.\n",
panHits[i] );
}
SHPDestroyObject( psObject );
}
if( nShapeCount == 0 )
printf( "No shapes found in search.\n" );
}

View file

@ -1,15 +1,70 @@
/*
* ORGINAL CODE WAS FROM "dbfdump.c", "shpdump.c", and "shpopen.c".
* Frank Warmerdam 1995
/******************************************************************************
* $Id: shputils.c,v 1.7 2003/02/25 17:20:22 warmerda Exp $
*
* This code is in the public domain.
* Project: Shapelib
* Purpose:
* Altered "shpdump" and "dbfdump" to allow two files to be appended.
* Other Functions:
* Selecting from the DBF before the write occurs.
* Change the UNITS between Feet and Meters and Shift X,Y.
* Clip and Erase boundary. The program only passes thru the
* data once.
*
* Bill Miller North Carolina - Department of Transporation
* Feb. 1997 -- bmiller@dot.state.nc.us
* There was not a lot of time to debug hidden problems;
* And the code is not very well organized or documented.
* The clip/erase function was not well tested.
* Oct. 2000 -- bmiller@dot.state.nc.us
* Fixed the problem when select is using numbers
* larger than short integer. It now reads long integer.
* NOTE: DBF files created using windows NT will read as a string with
* a length of 381 characters. This is a bug in "dbfopen".
*
*
* Author: Bill Miller (bmiller@dot.state.nc.us)
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* This software is available under the following "MIT Style" license,
* or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
* option is discussed in more detail in shapelib.html.
*
* --
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
* $Log: shputils.c,v $
* Revision 1.1 2000-02-09 19:51:46 curt
* Initial revision
* Revision 1.7 2003/02/25 17:20:22 warmerda
* Set psCShape to NULL after SHPDestroyObject() to avoid multi-frees of
* the same memory ... as submitted by Fred Fox.
*
* Revision 1.1 1999/08/24 21:13:01 curt
* Initial revision.
* Revision 1.6 2001/08/28 13:57:14 warmerda
* fixed DBFAddField return value check
*
* Revision 1.5 2000/11/02 13:52:48 warmerda
* major upgrade from Bill Miller
*
* Revision 1.4 1999/11/05 14:12:05 warmerda
* updated license terms
*
* Revision 1.3 1998/12/03 15:47:39 warmerda
* Did a bunch of rewriting to make it work with the V1.2 API.
@ -19,27 +74,10 @@
*
* Revision 1.1 1997/05/27 20:40:27 warmerda
* Initial revision
*
*
* Altered "shpdump" and "dbfdump" to allow two files to be appended.
* Other Functions:
* Selecting from the DBF before the write occurs.
* Change the UNITS between Feet and Meters and Shift X,Y.
* Clip and Erase boundary.
*
* Bill Miller NC-DOT -- Feb. 1997 -- bmiller@doh.dot.state.nc.us
* There was not a lot of time to debug hidden problems;
* And the code is not very well organized or documented.
* The clip/erase function was not well tested.
*
* PURPOSE: I needed a program to Append, Select, Change Unit, and
* Clip boundaries. The program only passes thru the
* data once.
*
*/
static char rcsid[] =
"$Id: shputils.c,v 1.1 2000-02-09 19:51:46 curt Exp $";
"$Id: shputils.c,v 1.7 2003/02/25 17:20:22 warmerda Exp $";
#include "shapefil.h"
#include "string.h"
@ -76,6 +114,7 @@ int i, ti, iWidth, iDecimals, iRecord;
int j, tj, jWidth, jDecimals, jRecord;
int found, newdbf;
void openfiles(void);
void setext(char *pt, char *ext);
int strncasecmp2(char *s1, char *s2, int n);
@ -84,33 +123,39 @@ void findselect(void);
void showitems(void);
int selectrec();
int check_theme_bnd();
int clip();
int clip_boundary();
void error();
/* -------------------------------------------------------------------- */
/* Variables for the DESCRIBE function */
/* -------------------------------------------------------------------- */
int ilist = FALSE, iall = FALSE;
/* -------------------------------------------------------------------- */
/* Variables for the SELECT function */
/* -------------------------------------------------------------------- */
char selectitem[40], *cpt;
int selectvalues[150];
int iselect = FALSE, iselectitem = -1, selcount=0;
int iunselect = FALSE;
int found = FALSE, newdbf = FALSE;
char selectitem[40], *cpt;
long int selectvalues[150], selcount=0;
int iselect = FALSE, iselectitem = -1;
int iunselect = FALSE;
/* -------------------------------------------------------------------- */
/* Variables for the CLIP and ERASE functions */
/* -------------------------------------------------------------------- */
double cxmin, cymin, cxmax, cymax;
int iclip = FALSE, ierase = FALSE;
int iclip = FALSE, ierase = FALSE;
int itouch = FALSE, iinside = FALSE, icut = FALSE;
int ibound = FALSE, ipoly = FALSE;
char clipfile[80];
/* -------------------------------------------------------------------- */
/* Variables for the UNIT function */
/* Variables for the FACTOR function */
/* -------------------------------------------------------------------- */
double factor = 1; /* NO FACTOR */
double infactor,outfactor,factor = 0; /* NO FACTOR */
int iunit = FALSE;
int ifactor = FALSE;
/* -------------------------------------------------------------------- */
/* Variables for the SHIFT function */
@ -125,12 +170,15 @@ int main( int argc, char ** argv )
/* -------------------------------------------------------------------- */
if( argc < 2 ) error();
strcpy(infile, argv[1]);
if (argc == 2 ) {
if (argc > 2) {
strcpy(outfile,argv[2]);
if (strncasecmp2(outfile, "LIST",0) == 0) { ilist = TRUE; }
if (strncasecmp2(outfile, "ALL",0) == 0) { iall = TRUE; }
}
if (ilist || iall || argc == 2 ) {
setext(infile, "shp");
printf("DESCRIBE: %s\n",infile);
strcpy(outfile,"");
} else {
strcpy(outfile,argv[2]);
}
/* -------------------------------------------------------------------- */
/* Look for other functions on the command line. (SELECT, UNIT) */
@ -161,7 +209,7 @@ int main( int argc, char ** argv )
selcount++;
}
iselect=TRUE;
}
} /*** End SEL & UNSEL ***/
else
if ((strncasecmp2(argv[i], "CLIP",4) == 0) ||
(strncasecmp2(argv[i], "ERASE",5) == 0))
@ -190,12 +238,7 @@ int main( int argc, char ** argv )
printf("Theme Clip Boundary: (%lf,%lf) - (%lf,%lf)\n",
cxmin, cymin, cxmax, cymax);
ibound=TRUE;
}
else if (strncasecmp2(argv[i], "POLY",4) == 0)
{
ipoly=TRUE;
}
else { /*** xmin,ymin,xmax,ymax ***/
} else { /*** xmin,ymin,xmax,ymax ***/
sscanf(argv[i],"%lf",&cymin);
i++;
if (i >= argc) error();
@ -207,46 +250,50 @@ int main( int argc, char ** argv )
}
i++;
if (i >= argc) error();
if (strncasecmp2(argv[i], "CUT",3) == 0) icut=TRUE;
else if (strncasecmp2(argv[i], "TOUCH",5) == 0) itouch=TRUE;
else if (strncasecmp2(argv[i], "INSIDE",6) == 0) iinside=TRUE;
if (strncasecmp2(argv[i], "CUT",3) == 0) icut=TRUE;
else if (strncasecmp2(argv[i], "TOUCH",5) == 0) itouch=TRUE;
else if (strncasecmp2(argv[i], "INSIDE",6) == 0) iinside=TRUE;
else error();
iclip=TRUE;
}
else
if (strncasecmp2(argv[i], "UNIT",4) == 0)
} /*** End CLIP & ERASE ***/
else if (strncasecmp2(argv[i], "FACTOR",0) == 0)
{
i++;
if (i >= argc) error();
if (strncasecmp2(argv[i], "METER",5) == 0)
factor=0.304800609601;
else
{
if (strncasecmp2(argv[i], "FEET",4) == 0)
factor=3.280833;
else
sscanf(argv[i],"%lf",&factor);
}
if (factor == 0) error();
iunit=TRUE;
printf("Output file coordinate values will be factored by %lg\n",factor);
i++;
if (i >= argc) error();
infactor=findunit(argv[i]);
if (infactor == 0) error();
iunit=TRUE;
i++;
if (i >= argc) error();
outfactor=findunit(argv[i]);
if (outfactor == 0)
{
sscanf(argv[i],"%lf",&factor);
if (factor == 0) error();
}
if (factor == 0)
{
if (infactor ==0)
{ puts("ERROR: Input unit must be defined before output unit"); exit(); }
factor=infactor/outfactor;
}
printf("Output file coordinate values will be factored by %lg\n",factor);
ifactor=(factor != 1); /* True if a valid factor */
} /*** End FACTOR ***/
else if (strncasecmp2(argv[i],"SHIFT",5) == 0)
{
i++;
if (i >= argc) error();
sscanf(argv[i],"%lf",&xshift);
i++;
if (i >= argc) error();
sscanf(argv[i],"%lf",&yshift);
iunit=TRUE;
printf("X Shift: %lg Y Shift: %lg\n",xshift,yshift);
} /*** End SHIFT ***/
else {
printf("ERROR: Unknown function %s\n",argv[i]); error();
}
else
if (strncasecmp2(argv[i],"SHIFT",5) == 0)
{
i++;
if (i >= argc) error();
sscanf(argv[i],"%lf",&xshift);
i++;
if (i >= argc) error();
sscanf(argv[i],"%lf",&yshift);
iunit=TRUE;
printf("X Shift: %lg Y Shift: %lg\n",xshift,yshift);
}
else
{
printf("ERROR: Unknown function %s\n",argv[i]); error();
}
}
/* -------------------------------------------------------------------- */
/* If there is no data in this file let the user know. */
@ -268,7 +315,7 @@ int main( int argc, char ** argv )
adfBoundsMax[0], adfBoundsMax[1],
nEntities, iRecord );
if (strcmp(outfile,"") == 0)
if (strcmp(outfile,"") == 0) /* Describe the shapefile; No other functions */
{
ti = DBFGetFieldCount( hDBF );
showitems();
@ -317,7 +364,7 @@ int main( int argc, char ** argv )
/* Clip coordinates of shapes if needed. */
/* -------------------------------------------------------------------- */
if (iclip)
if (clip() == 0) goto SKIP_RECORD; /** SKIP RECORD **/
if (clip_boundary() == 0) goto SKIP_RECORD; /** SKIP RECORD **/
/* -------------------------------------------------------------------- */
/* Read a DBF record and copy each field. */
@ -351,9 +398,9 @@ int main( int argc, char ** argv )
}
jRecord++;
/* -------------------------------------------------------------------- */
/* Change UNIT and SHIFT coordinates of shapes if needed. */
/* Change FACTOR and SHIFT coordinates of shapes if needed. */
/* -------------------------------------------------------------------- */
if (iunit)
if (iunit)
{
for( j = 0; j < psCShape->nVertices; j++ )
{
@ -370,6 +417,7 @@ int main( int argc, char ** argv )
SKIP_RECORD:
SHPDestroyObject( psCShape );
psCShape = NULL;
j=0;
}
@ -392,6 +440,15 @@ int main( int argc, char ** argv )
SHPClose( hSHPappend );
DBFClose( hDBF );
DBFClose( hDBFappend );
if (nEntitiesAppend == 0) {
puts("Remove the output files.");
setext(outfile, "dbf");
remove(outfile);
setext(outfile, "shp");
remove(outfile);
setext(outfile, "shx");
remove(outfile);
}
return( 0 );
}
@ -512,14 +569,14 @@ void mergefields()
for( i = 0; i < ti; i++ )
{
iType = DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals );
found=0;
found=FALSE;
{
for( j = 0; j < tj; j++ ) /* Search all field names for a match */
{
jType = DBFGetFieldInfo( hDBFappend, j, jszTitle, &jWidth, &jDecimals );
if (iType == jType && (strcmp(iszTitle, jszTitle) == 0) )
{
if (found == 1 || newdbf == 1)
if (found || newdbf)
{
if (i == j) pt[i]=j;
printf("Warning: Duplicate field name found (%s)\n",iszTitle);
@ -528,13 +585,13 @@ void mergefields()
}
else
{
pt[i]=j; found=1;
pt[i]=j; found=TRUE;
}
}
}
}
if (pt[i] == -1 && found == 0) /* Try to force into an existing field */
if (pt[i] == -1 && (! found) ) /* Try to force into an existing field */
{ /* Ignore the field name, width, and decimal places */
jType = DBFGetFieldInfo( hDBFappend, j, jszTitle, &jWidth, &jDecimals );
if (iType == jType)
@ -542,11 +599,12 @@ void mergefields()
pt[i]=i; found=1;
}
}
if (found == 0 && jRecord == 0) /* Add missing field to the append table */
if ( (! found) && jRecord == 0) /* Add missing field to the append table */
{ /* The output DBF must be is empty */
pt[i]=tj;
tj++;
if( !DBFAddField( hDBFappend, iszTitle, iType, iWidth, iDecimals ))
if( DBFAddField( hDBFappend, iszTitle, iType, iWidth, iDecimals )
== -1 )
{
printf( "Warning: DBFAddField(%s, TYPE:%d, WIDTH:%d DEC:%d, ITEM#:%d of %d) failed.\n",
iszTitle, iType, iWidth, iDecimals, (i+1), (ti+1) );
@ -569,7 +627,8 @@ void findselect()
if (iselectitem == -1)
{
printf("Warning: Item not found for selection (%s)\n",selectitem);
iselect = 0;
iselect = FALSE;
iall = FALSE;
showitems();
printf("Continued... (Selecting entire file)\n");
}
@ -579,23 +638,95 @@ void findselect()
void showitems()
{
printf("Available Items: ");
char stmp[40],slow[40],shigh[40];
double dtmp,dlow,dhigh,dsum,mean;
long int itmp,ilow,ihigh,isum;
long int maxrec;
char *pt;
printf("Available Items: (%d)",ti);
maxrec = DBFGetRecordCount(hDBF);
if (maxrec > 5000 && ! iall)
{ maxrec=5000; printf(" ** ESTIMATED RANGES (MEAN) For more records use \"All\""); }
else { printf(" RANGES (MEAN)"); }
for( i = 0; i < ti; i++ )
{
iType = DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals );
printf("%s, ",iszTitle);
switch( DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals ) )
{
case FTString:
strcpy(slow, "~");
strcpy(shigh,"\0");
printf("\n String %3d %-16s",iWidth,iszTitle);
for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
strncpy(stmp,DBFReadStringAttribute( hDBF, iRecord, i ),39);
if (strcmp(stmp,"!!") > 0) {
if (strncasecmp2(stmp,slow,0) < 0) strncpy(slow, stmp,39);
if (strncasecmp2(stmp,shigh,0) > 0) strncpy(shigh,stmp,39);
}
}
pt=slow+strlen(slow)-1;
while(*pt == ' ') { *pt='\0'; pt--; }
pt=shigh+strlen(shigh)-1;
while(*pt == ' ') { *pt='\0'; pt--; }
if (strncasecmp2(slow,shigh,0) < 0) printf("%s to %s",slow,shigh);
else if (strncasecmp2(slow,shigh,0) == 0) printf("= %s",slow);
else printf("No Values");
break;
case FTInteger:
printf("\n Integer %3d %-16s",iWidth,iszTitle);
ilow = 1999999999;
ihigh= -1999999999;
isum = 0;
for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
itmp = DBFReadIntegerAttribute( hDBF, iRecord, i );
if (ilow > itmp) ilow = itmp;
if (ihigh < itmp) ihigh = itmp;
isum = isum + itmp;
}
mean=isum/maxrec;
if (ilow < ihigh) printf("%d to %d \t(%.1f)",ilow,ihigh,mean);
else if (ilow == ihigh) printf("= %d",ilow);
else printf("No Values");
break;
case FTDouble:
printf("\n Real %3d,%d %-16s",iWidth,iDecimals,iszTitle);
dlow = 999999999999999.0;
dhigh= -999999999999999.0;
dsum = 0;
for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
dtmp = DBFReadDoubleAttribute( hDBF, iRecord, i );
if (dlow > dtmp) dlow = dtmp;
if (dhigh < dtmp) dhigh = dtmp;
dsum = dsum + dtmp;
}
mean=dsum/maxrec;
sprintf(stmp,"%%.%df to %%.%df \t(%%.%df)",iDecimals,iDecimals,iDecimals);
if (dlow < dhigh) printf(stmp,dlow,dhigh,mean);
else if (dlow == dhigh) {
sprintf(stmp,"= %%.%df",iDecimals);
printf(stmp,dlow);
}
else printf("No Values");
break;
}
}
printf("(total=%d)\n",ti);
printf("\n");
}
int selectrec()
{
int value, ty;
long int value, ty;
ty = DBFGetFieldInfo( hDBF, iselectitem, NULL, &iWidth, &iDecimals);
switch(ty)
{
case FTString:
puts("Invalid Item");
iselect=FALSE;
break;
case FTInteger:
value = DBFReadIntegerAttribute( hDBF, iRecord, iselectitem );
@ -607,6 +738,8 @@ int value, ty;
}
break;
case FTDouble:
puts("Invalid Item");
iselect=FALSE;
break;
}
if (iunselect) return(1); /* Skip this record */
@ -629,164 +762,120 @@ int check_theme_bnd()
( (adfBoundsMin[1] > cymax) && (adfBoundsMax[1] > cymax) ) )
{ /** Theme is totally outside clip area **/
if (ierase) iclip=FALSE; /** WRITE THEME (Clip not needed) **/
else nEntities=0; /** SKIP THEME **/
else nEntities=0; /** SKIP THEME **/
}
if (nEntities == 0)
puts("WARNING: Theme is outside the clip area."); /** SKIP THEME **/
}
int clip()
clip_boundary()
{
int outside=FALSE;
int j2=0, i2=0;
if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
(psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
{ /** Feature is totally inside clip area **/
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
if ( ( psCShape->dfXMax < cxmin ) ||
( psCShape->dfYMax < cymin ) ||
( psCShape->dfXMin > cxmax ) ||
( psCShape->dfYMin > cymax ) )
{ /** Feature is totally outside clip area **/
if (ierase) return(1); /** WRITE RECORD **/
else return(0); /** SKIP RECORD **/
}
if (itouch)
{
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
if (iinside)
{
if (ierase) return(1); /** WRITE RECORD **/
else return(0); /** SKIP RECORD **/
}
/*** SECOND check each vertex in the feature ***/
for( j2 = 0; j2 < psCShape->nVertices; j2++ )
{
if (psCShape->padfX[j2] < cxmin || psCShape->padfX[j2] > cxmax)
{
outside=TRUE;
}
else
{
if (psCShape->padfY[j2] < cymin || psCShape->padfY[j2] > cymax)
outside=TRUE;
else
outside=FALSE;
}
if (icut)
{
if (outside)
{
} else {
if (i2 != j2)
{
/* write vertex */
psCShape->padfX[i2] = psCShape->padfX[j2];
psCShape->padfY[i2] = psCShape->padfY[j2];
}
i2++;
}
}
else
if (outside) /* vertex is outside boundary */
{
if (iinside)
{
if (ierase) return(1); /** WRITE RECORD **/
else return(0); /** SKIP RECORD **/
}
}
else /* vertex is inside boundary */
{
if (itouch)
{
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
}
}
int inside;
int prev_outside;
int i2;
int j2;
if (icut)
{
j2 = psCShape->nVertices;
if (i2 < 2) return(0); /** SKIP RECORD **/
psCShape->nVertices = i2;
/*** FIRST check the boundary of the feature ***/
if ( ( (psCShape->dfXMin < cxmin) && (psCShape->dfXMax < cxmin) ) ||
( (psCShape->dfYMin < cymin) && (psCShape->dfYMax < cymin) ) ||
( (psCShape->dfXMin > cxmax) && (psCShape->dfXMax > cxmax) ) ||
( (psCShape->dfYMin > cymax) && (psCShape->dfYMax > cymax) ) )
{ /** Feature is totally outside clip area **/
if (ierase) return(1); /** WRITE RECORD **/
else return(0); /** SKIP RECORD **/
}
if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
(psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
{ /** Feature is totally inside clip area **/
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
if (iinside)
{ /** INSIDE * Feature might touch the boundary or could be outside **/
if (ierase) return(1); /** WRITE RECORD **/
else return(0); /** SKIP RECORD **/
}
if (itouch)
{ /** TOUCH **/
if ( ( (psCShape->dfXMin <= cxmin) || (psCShape->dfXMax >= cxmax) ) &&
(psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
{ /** Feature intersects the clip boundary only on the X axis **/
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
( (psCShape->dfYMin <= cymin) || (psCShape->dfYMax >= cymax) ) )
{ /** Feature intersects the clip boundary only on the Y axis **/
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
for( j2 = 0; j2 < psCShape->nVertices; j2++ )
{ /** At least one vertex must be inside the clip boundary **/
if ( (psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax) ||
(psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax) )
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
/** All vertices are outside the clip boundary **/
if (ierase) return(1); /** WRITE RECORD **/
else return(0); /** SKIP RECORD **/
} /** End TOUCH **/
if (icut)
{ /** CUT **/
/*** Check each vertex in the feature with the Boundary and "CUT" ***/
/*** THIS CODE WAS NOT COMPLETED! READ NOTE AT THE BOTTOM ***/
i2=0;
prev_outside=FALSE;
for( j2 = 0; j2 < psCShape->nVertices; j2++ )
{
inside = psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax &&
psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax ;
if (ierase) inside=(! inside);
if (inside)
{
if (i2 != j2)
{
if (prev_outside)
{
/*** AddIntersection(i2); /*** Add intersection ***/
prev_outside=FALSE;
}
psCShape->padfX[i2]=psCShape->padfX[j2]; /** move vertex **/
psCShape->padfY[i2]=psCShape->padfY[j2];
}
i2++;
} else {
if ( (! prev_outside) && (j2 > 0) )
{
/*** AddIntersection(i2); /*** Add intersection (Watch out for j2==i2-1) ***/
/*** Also a polygon may overlap twice and will split into a several parts ***/
prev_outside=TRUE;
}
}
}
printf("Vertices:%d OUT:%d Number of Parts:%d\n",
j2, psCShape->nVertices, psCShape->nParts );
}
if (itouch)
{
if (ierase) return(1); /** WRITE RECORD **/
else return(0); /** SKIP RECORD **/
}
if (iinside)
{
if (ierase) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
}
psCShape->nVertices,i2, psCShape->nParts );
psCShape->nVertices = i2;
if (i2 < 2) return(0); /** SKIP RECORD **/
/*** (WE ARE NOT CREATING INTERESECTIONS and some lines could be reduced to one point) **/
if (i2 == 0) return(0); /** SKIP RECORD **/
else return(1); /** WRITE RECORD **/
} /** End CUT **/
}
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
void error()
{
puts( "USAGE: shputils <DescribeShape>");
puts( "USAGE: shputils <InputShape> <AppendShape>" );
puts( " { <SELECT> <Item> <valuelist> }" );
puts( " { <UNSELECT> <Item> <valuelist> }" );
puts( " { <CLIP> <xmin> <ymin> <xmax> <ymax> <TOUCH|INSIDE|CUT> }" );
puts( " { <CLIP> <Theme> <BOUNDARY|POLYGON> <TOUCH|INSIDE|CUT> }" );
puts( " Clip functions for Cut and Polygon are not supported yet..." );
puts( " { <ERASE> <xmin> <ymin> <xmax> <ymax> <TOUCH|INSIDE|CUT> }" );
puts( " { <ERASE> <Theme> <BOUNDARY|POLYGON> <TOUCH|INSIDE|CUT> }" );
puts( " { <UNIT> <FEET|METERS|factor> }" );
puts( " { <SHIFT> <xshift> <yshift> }\n" );
puts( "The program will append to an existing shape file or it will" );
puts( "create a new file if needed." );
puts( "Only the items in the first output file will be preserved." );
puts( "When an item does not match with the append theme then the item");
puts( "might be placed to an existing item at the same position and type." );
puts( " OTHER FUNCTIONS:" );
puts( " - Select a group of shapes from a comma separated selection list.");
puts( " - UnSelect a group of shapes from a comma separated selection list.");
puts( " - Clip boundary extent or by theme boundary." );
puts( " Touch writes all the shapes that touch the boundary.");
puts( " Inside writes all the shapes that are completely within the boundary.");
puts( " *(N/A) Cut will cookie-cut shapes that are touching the boundary.");
puts( " Boundary clips are only the min and max of a theme boundary." );
puts( " *(N/A) Polygon clips use the polygons within a theme.");
puts( " - Erase boundary extent or by theme boundary." );
puts( " Erase is the direct opposite of the Clip function." );
puts( " - Change coordinate value units between meters and feet.");
puts( " There is no way to determine the input unit of a shape file.");
puts( " Skip this function if the shape file is already in the correct unit.");
puts( " Clip and Erase will be done before the unit is changed.");
puts( " A shift will be done after the unit is changed.");
puts( " - Shift X and Y coordinates.\n" );
puts( "Finally, There can only be one select or unselect in the command line.");
puts( " There can only be one clip or erase in the command line.");
puts( " There can only be one unit and only one shift in the command line.");
puts( "EX: shputils in.shp out.shp CLIP 10 10 90 90 Touch UNIT Feet SHIFT 40 40");
puts( " shputils in.shp out.shp SELECT countycode 3,5,9,13,17,27");
exit( 1 );
}
/************************************************************************/
/* strncasecmp2() */
@ -806,12 +895,11 @@ int j,i;
{
if (*s1 >= 'a' && *s1 <= 'z') {
j=*s1-32;
if (j != *s2) return(1);
}
else
{
j=*s1+32;
if (j != *s2) return(1);
if (j != *s2) return(*s1-*s2);
} else {
if (*s1 >= 'A' && *s1 <= 'Z') { j=*s1+32; }
else { j=*s1; }
if (j != *s2) return(*s1-*s2);
}
}
s1++;
@ -819,3 +907,144 @@ int j,i;
}
return(0);
}
#define NKEYS (sizeof(unitkeytab) / sizeof(struct unitkey))
findunit(unit)
char *unit;
{
struct unitkey {
char *name;
double value;
} unitkeytab[] = {
"CM", 39.37,
"CENTIMETER", 39.37,
"CENTIMETERS", 39.37, /** # of inches * 100 in unit **/
"METER", 3937,
"METERS", 3937,
"KM", 3937000,
"KILOMETER", 3937000,
"KILOMETERS", 3937000,
"INCH", 100,
"INCHES", 100,
"FEET", 1200,
"FOOT", 1200,
"YARD", 3600,
"YARDS", 3600,
"MILE", 6336000,
"MILES", 6336000
};
double unitfactor=0;
for (j = 0; j < NKEYS; j++) {
if (strncasecmp2(unit, unitkeytab[j].name, 0) == 0) unitfactor=unitkeytab[j].value;
}
return(unitfactor);
}
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
void error()
{
puts( "The program will append to an existing shape file or it will" );
puts( "create a new file if needed." );
puts( "Only the items in the first output file will be preserved." );
puts( "When an item does not match with the append theme then the item");
puts( "might be placed to an existing item at the same position and type." );
puts( " OTHER FUNCTIONS:" );
puts( " - Describe all items in the dbase file (Use ALL for more than 5000 recs.)");
puts( " - Select a group of shapes from a comma separated selection list.");
puts( " - UnSelect a group of shapes from a comma separated selection list.");
puts( " - Clip boundary extent or by theme boundary." );
puts( " Touch writes all the shapes that touch the boundary.");
puts( " Inside writes all the shapes that are completely within the boundary.");
puts( " Boundary clips are only the min and max of a theme boundary." );
puts( " - Erase boundary extent or by theme boundary." );
puts( " Erase is the direct opposite of the Clip function." );
puts( " - Change coordinate value units between meters and feet.");
puts( " There is no way to determine the input unit of a shape file.");
puts( " Skip this function if the shape file is already in the correct unit.");
puts( " Clip and Erase will be done before the unit is changed.");
puts( " A shift will be done after the unit is changed.");
puts( " - Shift X and Y coordinates.\n" );
puts( "Finally, There can only be one select or unselect in the command line.");
puts( " There can only be one clip or erase in the command line.");
puts( " There can only be one unit and only one shift in the command line.\n");
puts( "Ex: shputils in.shp out.shp SELECT countycode 3,5,9,13,17,27");
puts( " shputils in.shp out.shp CLIP 10 10 90 90 Touch FACTOR Meter Feet");
puts( " shputils in.shp out.shp FACTOR Meter 3.0");
puts( " shputils in.shp out.shp CLIP clip.shp Boundary Touch SHIFT 40 40");
puts( " shputils in.shp out.shp SELECT co 112 CLIP clip.shp Boundary Touch\n");
puts( "USAGE: shputils <DescribeShape> {ALL}");
puts( "USAGE: shputils <InputShape> <OutShape|AppendShape>" );
puts( " { <FACTOR> <FEET|MILES|METERS|KM> <FEET|MILES|METERS|KM|factor> }" );
puts( " { <SHIFT> <xshift> <yshift> }" );
puts( " { <SELECT|UNSEL> <Item> <valuelist> }" );
puts( " { <CLIP|ERASE> <xmin> <ymin> <xmax> <ymax> <TOUCH|INSIDE|CUT> }" );
puts( " { <CLIP|ERASE> <theme> <BOUNDARY> <TOUCH|INSIDE|CUT> }" );
puts( " Note: CUT is not complete and does not create intersections.");
puts( " For more information read programmer comment.");
/**** Clip functions for Polygon and Cut is not supported
There are several web pages that describe methods of doing this function.
It seem easy to impliment until you start writting code. I don't have the
time to add these functions but a did leave a simple cut routine in the
program that can be called by using CUT instead of TOUCH in the
CLIP or ERASE functions. It does not add the intersection of the line and
the clip box, so polygons could look incomplete and lines will come up short.
Information about clipping lines with a box:
http://www.csclub.uwaterloo.ca/u/mpslager/articles/sutherland/wr.html
Information about finding the intersection of two lines:
http://www.whisqu.se/per/docs/math28.htm
THE CODE LOOKS LIKE THIS:
********************************************************
void Intersect_Lines(float x0,float y0,float x1,float y1,
float x2,float y2,float x3,float y3,
float *xi,float *yi)
{
// this function computes the intersection of the sent lines
// and returns the intersection point, note that the function assumes
// the lines intersect. the function can handle vertical as well
// as horizontal lines. note the function isn't very clever, it simply
// applies the math, but we don't need speed since this is a
// pre-processing step
// The Intersect_lines program came from (http://www.whisqu.se/per/docs/math28.htm)
float a1,b1,c1, // constants of linear equations
a2,b2,c2,
det_inv, // the inverse of the determinant of the coefficientmatrix
m1,m2; // the slopes of each line
// compute slopes, note the cludge for infinity, however, this will
// be close enough
if ((x1-x0)!=0)
m1 = (y1-y0)/(x1-x0);
else
m1 = (float)1e+10; // close enough to infinity
if ((x3-x2)!=0)
m2 = (y3-y2)/(x3-x2);
else
m2 = (float)1e+10; // close enough to infinity
// compute constants
a1 = m1;
a2 = m2;
b1 = -1;
b2 = -1;
c1 = (y0-m1*x0);
c2 = (y2-m2*x2);
// compute the inverse of the determinate
det_inv = 1/(a1*b2 - a2*b1);
// use Kramers rule to compute xi and yi
*xi=((b1*c2 - b2*c1)*det_inv);
*yi=((a2*c1 - a1*c2)*det_inv);
} // end Intersect_Lines
**********************************************************/
exit( 1 );
}

View file

@ -1,26 +1,28 @@
#!/bin/sh
EG_DATA=/home/warmerda/www/projects/shapelib/eg_data
EG_DATA=/u/www/projects/shapelib/eg_data
echo -------------------------------------------------------------------------
echo Test 1: dump anno.shp
echo -------------------------------------------------------------------------
shpdump $EG_DATA/anno.shp | head -250
./shpdump $EG_DATA/anno.shp | head -250
echo -------------------------------------------------------------------------
echo Test 2: dump brklinz.shp
echo -------------------------------------------------------------------------
shpdump $EG_DATA/brklinz.shp | head -500
./shpdump $EG_DATA/brklinz.shp | head -500
echo -------------------------------------------------------------------------
echo Test 3: dump polygon.shp
echo -------------------------------------------------------------------------
shpdump $EG_DATA/polygon.shp | head -500
./shpdump $EG_DATA/polygon.shp | head -500
echo -------------------------------------------------------------------------
echo Test 4: dump pline.dbf - uses new F field type
echo -------------------------------------------------------------------------
dbfdump -m -h $EG_DATA/pline.dbf | head -50
./dbfdump -m -h $EG_DATA/pline.dbf | head -50
echo -------------------------------------------------------------------------
echo Test 5: NULL Shapes.
echo -------------------------------------------------------------------------
./shpdump $EG_DATA/csah.dbf | head -150

View file

@ -1,11 +1,11 @@
#!/bin/sh
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13; do
for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13; do
echo -----------------------------------------------------------------------
echo Test 2/$i
echo -----------------------------------------------------------------------
./shptest $i
shpdump test${i}.shp
./shpdump test${i}.shp
done