shp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +34 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/LICENSE +28 -0
- data/README.md +30 -0
- data/Rakefile +23 -0
- data/ext/shp/base.hpp +113 -0
- data/ext/shp/dbf.cpp +381 -0
- data/ext/shp/dbf.hpp +44 -0
- data/ext/shp/extconf.rb +13 -0
- data/ext/shp/shape_object.cpp +58 -0
- data/ext/shp/shape_object.hpp +27 -0
- data/ext/shp/shapefile.cpp +299 -0
- data/ext/shp/shapefile.hpp +35 -0
- data/ext/shp/shapelib/.cvsignore +15 -0
- data/ext/shp/shapelib/ChangeLog +450 -0
- data/ext/shp/shapelib/HOWTO-RELEASE +16 -0
- data/ext/shp/shapelib/LICENSE.LGPL +483 -0
- data/ext/shp/shapelib/Makefile +113 -0
- data/ext/shp/shapelib/README +41 -0
- data/ext/shp/shapelib/README.tree +172 -0
- data/ext/shp/shapelib/contrib/.cvsignore +12 -0
- data/ext/shp/shapelib/contrib/Makefile +66 -0
- data/ext/shp/shapelib/contrib/ShapeFileII.pas +234 -0
- data/ext/shp/shapelib/contrib/Shape_PointInPoly.cpp +238 -0
- data/ext/shp/shapelib/contrib/Shape_PointInPoly_README.txt +59 -0
- data/ext/shp/shapelib/contrib/csv2shp.c +558 -0
- data/ext/shp/shapelib/contrib/dbfcat.c +166 -0
- data/ext/shp/shapelib/contrib/dbfinfo.c +106 -0
- data/ext/shp/shapelib/contrib/makefile.vc +34 -0
- data/ext/shp/shapelib/contrib/my_nan.h +46 -0
- data/ext/shp/shapelib/contrib/shpcat.c +100 -0
- data/ext/shp/shapelib/contrib/shpcentrd.c +159 -0
- data/ext/shp/shapelib/contrib/shpdata.c +129 -0
- data/ext/shp/shapelib/contrib/shpdxf.c +340 -0
- data/ext/shp/shapelib/contrib/shpfix.c +110 -0
- data/ext/shp/shapelib/contrib/shpgeo.c +1595 -0
- data/ext/shp/shapelib/contrib/shpgeo.h +154 -0
- data/ext/shp/shapelib/contrib/shpinfo.c +113 -0
- data/ext/shp/shapelib/contrib/shpproj.c +260 -0
- data/ext/shp/shapelib/contrib/shpsort.c +605 -0
- data/ext/shp/shapelib/contrib/shpsort.txt +44 -0
- data/ext/shp/shapelib/contrib/shpwkb.c +123 -0
- data/ext/shp/shapelib/contrib/tests/shpproj.sh +38 -0
- data/ext/shp/shapelib/dbfopen.c +2221 -0
- data/ext/shp/shapelib/makefile.vc +86 -0
- data/ext/shp/shapelib/makeshape.sh +21 -0
- data/ext/shp/shapelib/mkdist.sh +37 -0
- data/ext/shp/shapelib/mkinstalldirs +38 -0
- data/ext/shp/shapelib/mkrelease.sh +55 -0
- data/ext/shp/shapelib/safileio.c +286 -0
- data/ext/shp/shapelib/shapefil.h +647 -0
- data/ext/shp/shapelib/shapelib.def +46 -0
- data/ext/shp/shapelib/shpopen.c +2388 -0
- data/ext/shp/shapelib/shptree.c +1187 -0
- data/ext/shp/shapelib/shputils.c +1072 -0
- data/ext/shp/shapelib/stream1.out +1465 -0
- data/ext/shp/shapelib/stream1.sh +28 -0
- data/ext/shp/shapelib/stream2.out +530 -0
- data/ext/shp/shapelib/stream2.sh +11 -0
- data/ext/shp/shapelib/stream3.out +37 -0
- data/ext/shp/shapelib/web/.cvsignore +2 -0
- data/ext/shp/shapelib/web/codepage.html +403 -0
- data/ext/shp/shapelib/web/dbf_api.html +436 -0
- data/ext/shp/shapelib/web/index.html +235 -0
- data/ext/shp/shapelib/web/license.html +78 -0
- data/ext/shp/shapelib/web/manifest.html +87 -0
- data/ext/shp/shapelib/web/release.html +80 -0
- data/ext/shp/shapelib/web/shapelib-tools.html +352 -0
- data/ext/shp/shapelib/web/shp_api.html +376 -0
- data/ext/shp/shp.cpp +19 -0
- data/ext/shp/shp.hpp +47 -0
- data/lib/shp.rb +35 -0
- data/lib/shp/version.rb +3 -0
- data/shp.gemspec +23 -0
- data/spec/shp_spec.rb +127 -0
- metadata +176 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
/******************************************************************************
|
2
|
+
* Copyright (c) 1999, Carl Anderson
|
3
|
+
*
|
4
|
+
* This code is based in part on the earlier work of Frank Warmerdam
|
5
|
+
*
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a
|
7
|
+
* copy of this software and associated documentation files (the "Software"),
|
8
|
+
* to deal in the Software without restriction, including without limitation
|
9
|
+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
10
|
+
* and/or sell copies of the Software, and to permit persons to whom the
|
11
|
+
* Software is furnished to do so, subject to the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be included
|
14
|
+
* in all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
17
|
+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19
|
+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
22
|
+
* DEALINGS IN THE SOFTWARE.
|
23
|
+
******************************************************************************
|
24
|
+
* shpfix
|
25
|
+
*
|
26
|
+
*
|
27
|
+
* gcc -c shpfix.c shpopen.c -o shpfix
|
28
|
+
*
|
29
|
+
* Utility program to fix nulls and inconsistencies in Shapefiles
|
30
|
+
* as happens from time to time
|
31
|
+
*
|
32
|
+
* Simply load and rewrite each record, parameter fixrex allow user to null
|
33
|
+
* a particularly nasty record if needed
|
34
|
+
*
|
35
|
+
*/
|
36
|
+
|
37
|
+
#include <stdlib.h>
|
38
|
+
#include <string.h>
|
39
|
+
#include "shapefil.h"
|
40
|
+
|
41
|
+
int main( int argc, char ** argv )
|
42
|
+
|
43
|
+
{
|
44
|
+
SHPHandle hSHP, cSHP;
|
45
|
+
int nShapeType, cShapeType, nEntities, i;
|
46
|
+
double adBounds[4];
|
47
|
+
SHPObject *shape;
|
48
|
+
int fix_rec;
|
49
|
+
|
50
|
+
/* -------------------------------------------------------------------- */
|
51
|
+
/* Display a usage message. */
|
52
|
+
/* -------------------------------------------------------------------- */
|
53
|
+
if( argc <= 3 )
|
54
|
+
{
|
55
|
+
printf( "shpfix shpfile new_file <Record# to Blank>\n" );
|
56
|
+
exit( 1 );
|
57
|
+
}
|
58
|
+
|
59
|
+
fix_rec = atoi (argv[3]);
|
60
|
+
fix_rec --;
|
61
|
+
|
62
|
+
/* -------------------------------------------------------------------- */
|
63
|
+
/* Open the passed shapefile. */
|
64
|
+
/* -------------------------------------------------------------------- */
|
65
|
+
hSHP = SHPOpen( argv[1], "rb+" );
|
66
|
+
|
67
|
+
if( hSHP == NULL )
|
68
|
+
{
|
69
|
+
printf( "Unable to open:%s\n", argv[1] );
|
70
|
+
exit( 1 );
|
71
|
+
}
|
72
|
+
|
73
|
+
SHPGetInfo( hSHP, &nEntities, &nShapeType, NULL, NULL );
|
74
|
+
|
75
|
+
|
76
|
+
/* -------------------------------------------------------------------- */
|
77
|
+
/* Open the passed shapefile. */
|
78
|
+
/* -------------------------------------------------------------------- */
|
79
|
+
cSHP = SHPCreate( argv[2], nShapeType );
|
80
|
+
|
81
|
+
if( cSHP == NULL )
|
82
|
+
{
|
83
|
+
printf( "Unable to open:%s\n", argv[2] );
|
84
|
+
exit( 1 );
|
85
|
+
}
|
86
|
+
|
87
|
+
SHPGetInfo( cSHP, NULL, &cShapeType, &(adBounds[0]), &(adBounds[2]) );
|
88
|
+
|
89
|
+
|
90
|
+
/* -------------------------------------------------------------------- */
|
91
|
+
/* Skim over the list of shapes, printing all the vertices. */
|
92
|
+
/* -------------------------------------------------------------------- */
|
93
|
+
|
94
|
+
for( i = 0; i < nEntities; i++ )
|
95
|
+
{
|
96
|
+
|
97
|
+
shape = SHPReadObject( hSHP, i );
|
98
|
+
if ( i == fix_rec )
|
99
|
+
{ shape->nParts = 0;
|
100
|
+
shape->nVertices = 0;
|
101
|
+
}
|
102
|
+
SHPWriteObject( cSHP, -1, shape );
|
103
|
+
SHPDestroyObject ( shape );
|
104
|
+
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
SHPClose ( hSHP );
|
109
|
+
SHPClose ( cSHP );
|
110
|
+
}
|
@@ -0,0 +1,1595 @@
|
|
1
|
+
/******************************************************************************
|
2
|
+
* Copyright (c) 1999, Carl Anderson
|
3
|
+
*
|
4
|
+
* This code is based in part on the earlier work of Frank Warmerdam
|
5
|
+
*
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a
|
7
|
+
* copy of this software and associated documentation files (the "Software"),
|
8
|
+
* to deal in the Software without restriction, including without limitation
|
9
|
+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
10
|
+
* and/or sell copies of the Software, and to permit persons to whom the
|
11
|
+
* Software is furnished to do so, subject to the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be included
|
14
|
+
* in all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
17
|
+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19
|
+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
22
|
+
* DEALINGS IN THE SOFTWARE.
|
23
|
+
******************************************************************************
|
24
|
+
*
|
25
|
+
* requires shapelib 1.2
|
26
|
+
* gcc shpproj shpopen.o dbfopen.o -lm -lproj -o shpproj
|
27
|
+
*
|
28
|
+
* this may require linking with the PROJ4 projection library available from
|
29
|
+
*
|
30
|
+
* http://www.remotesensing.org/proj
|
31
|
+
*
|
32
|
+
* use -DPROJ4 to compile in Projection support
|
33
|
+
*
|
34
|
+
* $Log: shpgeo.c,v $
|
35
|
+
* Revision 1.13 2011-07-24 03:17:46 fwarmerdam
|
36
|
+
* include string.h and stdlib.h where needed in contrib (#2146)
|
37
|
+
*
|
38
|
+
* Revision 1.12 2007-09-03 23:17:46 fwarmerdam
|
39
|
+
* fix SHPDimension() function
|
40
|
+
*
|
41
|
+
* Revision 1.11 2006/11/06 20:45:58 fwarmerdam
|
42
|
+
* Fixed SHPProject.
|
43
|
+
*
|
44
|
+
* Revision 1.10 2006/11/06 20:44:58 fwarmerdam
|
45
|
+
* SHPProject() uses pj_transform now
|
46
|
+
*
|
47
|
+
* Revision 1.9 2006/01/25 15:33:50 fwarmerdam
|
48
|
+
* fixed ppsC assignment maptools bug 1263
|
49
|
+
*
|
50
|
+
* Revision 1.8 2002/01/15 14:36:56 warmerda
|
51
|
+
* upgrade to use proj_api.h
|
52
|
+
*
|
53
|
+
* Revision 1.7 2002/01/11 15:22:04 warmerda
|
54
|
+
* fix many warnings. Lots of this code is cruft.
|
55
|
+
*
|
56
|
+
* Revision 1.6 2001/08/30 13:42:31 warmerda
|
57
|
+
* avoid use of auto initialization of PT for VC++
|
58
|
+
*
|
59
|
+
* Revision 1.5 2000/04/26 13:24:06 warmerda
|
60
|
+
* made projUV handling safer
|
61
|
+
*
|
62
|
+
* Revision 1.4 2000/04/26 13:17:15 warmerda
|
63
|
+
* check if projUV or UV
|
64
|
+
*
|
65
|
+
* Revision 1.3 2000/03/17 14:15:16 warmerda
|
66
|
+
* Don't try to use system nan.h ... doesn't always exist.
|
67
|
+
*
|
68
|
+
* Revision 1.2 1999/05/26 02:56:31 candrsn
|
69
|
+
* updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
|
70
|
+
*
|
71
|
+
*/
|
72
|
+
|
73
|
+
#include <stdlib.h>
|
74
|
+
#include <string.h>
|
75
|
+
#include "shapefil.h"
|
76
|
+
|
77
|
+
#ifndef NAN
|
78
|
+
#include "my_nan.h"
|
79
|
+
#endif
|
80
|
+
|
81
|
+
#include "shpgeo.h"
|
82
|
+
|
83
|
+
|
84
|
+
/* I'm using some shorthand throughout this file
|
85
|
+
* R+ is a Clockwise Ring and is the positive portion of an object
|
86
|
+
* R- is a CounterClockwise Ring and is a hole in a R+
|
87
|
+
* A complex object is one having at least one R-
|
88
|
+
* A compound object is one having more than one R+
|
89
|
+
* A simple object has one and only one element (R+ or R-)
|
90
|
+
*
|
91
|
+
* The closed ring constraint is for polygons and assumed here
|
92
|
+
* Arcs or LineStrings I am calling Rings (generically open or closed)
|
93
|
+
* Point types are vertices or lists of vertices but not Rings
|
94
|
+
*
|
95
|
+
* SHPT_POLYGON, SHPT_POLYGONZ, SHPT_POLYGONM and SHPT_MULTIPATCH
|
96
|
+
* can have SHPObjects that are compound as well as complex
|
97
|
+
*
|
98
|
+
* SHP_POINT and its Z and M derivatives are strictly simple
|
99
|
+
* MULTI_POINT, SHPT_ARC and their derivatives may be simple or compound
|
100
|
+
*
|
101
|
+
*/
|
102
|
+
|
103
|
+
|
104
|
+
/* **************************************************************************
|
105
|
+
* asFileName
|
106
|
+
*
|
107
|
+
* utility function, toss part of filename after last dot
|
108
|
+
*
|
109
|
+
* **************************************************************************/
|
110
|
+
char * asFileName ( const char *fil, char *ext ) {
|
111
|
+
char pszBasename[120];
|
112
|
+
static char pszFullname[120];
|
113
|
+
int i;
|
114
|
+
/* -------------------------------------------------------------------- */
|
115
|
+
/* Compute the base (layer) name. If there is any extension */
|
116
|
+
/* on the passed in filename we will strip it off. */
|
117
|
+
/* -------------------------------------------------------------------- */
|
118
|
+
// pszFullname = (char*) malloc(( strlen(fil)+5 ));
|
119
|
+
// pszBasename = (char *) malloc(strlen(fil)+5);
|
120
|
+
strcpy( pszBasename, fil );
|
121
|
+
for( i = strlen(pszBasename)-1;
|
122
|
+
i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
|
123
|
+
&& pszBasename[i] != '\\';
|
124
|
+
i-- ) {}
|
125
|
+
|
126
|
+
if( pszBasename[i] == '.' )
|
127
|
+
pszBasename[i] = '\0';
|
128
|
+
|
129
|
+
/* -------------------------------------------------------------------- */
|
130
|
+
/* Note that files pulled from */
|
131
|
+
/* a PC to Unix with upper case filenames won't work! */
|
132
|
+
/* -------------------------------------------------------------------- */
|
133
|
+
// pszFullname = (char *) malloc(strlen(pszBasename) + 5);
|
134
|
+
sprintf( pszFullname, "%s.%s", pszBasename, ext );
|
135
|
+
|
136
|
+
return ( pszFullname );
|
137
|
+
}
|
138
|
+
|
139
|
+
|
140
|
+
/************************************************************************/
|
141
|
+
/* SfRealloc() */
|
142
|
+
/* */
|
143
|
+
/* A realloc cover function that will access a NULL pointer as */
|
144
|
+
/* a valid input. */
|
145
|
+
/************************************************************************/
|
146
|
+
/* copied directly from shpopen.c -- maybe expose this in shapefil.h */
|
147
|
+
static void * SfRealloc( void * pMem, int nNewSize )
|
148
|
+
|
149
|
+
{
|
150
|
+
if( pMem == NULL )
|
151
|
+
return( (void *) malloc(nNewSize) );
|
152
|
+
else
|
153
|
+
return( (void *) realloc(pMem,nNewSize) );
|
154
|
+
}
|
155
|
+
|
156
|
+
|
157
|
+
/* **************************************************************************
|
158
|
+
* SHPPRoject
|
159
|
+
*
|
160
|
+
* Project points using projection handles, for use with PROJ4.3
|
161
|
+
*
|
162
|
+
* act as a wrapper to protect against library changes in PROJ
|
163
|
+
*
|
164
|
+
* **************************************************************************/
|
165
|
+
int SHPProject ( SHPObject *psCShape, projPJ inproj, projPJ outproj ) {
|
166
|
+
#ifdef PROJ4
|
167
|
+
|
168
|
+
int j;
|
169
|
+
|
170
|
+
if ( pj_is_latlong(inproj) ) {
|
171
|
+
for(j=0; j < psCShape->nVertices; j++) {
|
172
|
+
psCShape->padfX[j] *= DEG_TO_RAD;
|
173
|
+
psCShape->padfY[j] *= DEG_TO_RAD;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
pj_transform(inproj, outproj, psCShape->nVertices, 0, psCShape->padfX,
|
178
|
+
psCShape->padfY, NULL);
|
179
|
+
|
180
|
+
if ( pj_is_latlong(outproj) ) {
|
181
|
+
for(j=0; j < psCShape->nVertices; j++) {
|
182
|
+
psCShape->padfX[j] *= RAD_TO_DEG;
|
183
|
+
psCShape->padfY[j] *= RAD_TO_DEG;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
/* Recompute new Extents of projected Object */
|
188
|
+
SHPComputeExtents ( psCShape );
|
189
|
+
#endif
|
190
|
+
|
191
|
+
return ( 1 );
|
192
|
+
}
|
193
|
+
|
194
|
+
|
195
|
+
/* **************************************************************************
|
196
|
+
* SHPSetProjection
|
197
|
+
*
|
198
|
+
* establish a projection handle for use with PROJ4.3
|
199
|
+
*
|
200
|
+
* act as a wrapper to protect against library changes in PROJ
|
201
|
+
*
|
202
|
+
* **************************************************************************/
|
203
|
+
projPJ SHPSetProjection ( int param_cnt, char **params ) {
|
204
|
+
#ifdef PROJ4
|
205
|
+
projPJ *p = NULL;
|
206
|
+
|
207
|
+
if ( param_cnt > 0 && params[0] )
|
208
|
+
{ p = pj_init ( param_cnt, params ); }
|
209
|
+
|
210
|
+
return ( p );
|
211
|
+
#else
|
212
|
+
return ( NULL );
|
213
|
+
#endif
|
214
|
+
}
|
215
|
+
|
216
|
+
|
217
|
+
/* **************************************************************************
|
218
|
+
* SHPFreeProjection
|
219
|
+
*
|
220
|
+
* release a projection handle for use with PROJ4.3
|
221
|
+
*
|
222
|
+
* act as a wrapper to protect against library changes in PROJ
|
223
|
+
*
|
224
|
+
* **************************************************************************/
|
225
|
+
int SHPFreeProjection ( projPJ p) {
|
226
|
+
#ifdef PROJ4
|
227
|
+
if ( p )
|
228
|
+
pj_free ( p );
|
229
|
+
#endif
|
230
|
+
return ( 1 );
|
231
|
+
}
|
232
|
+
|
233
|
+
|
234
|
+
/* **************************************************************************
|
235
|
+
* SHPOGisType
|
236
|
+
*
|
237
|
+
* Convert Both ways from and to OGIS Geometry Types
|
238
|
+
*
|
239
|
+
* **************************************************************************/
|
240
|
+
int SHPOGisType ( int GeomType, int toOGis) {
|
241
|
+
|
242
|
+
if ( toOGis == 0 ) /* connect OGis -> SHP types */
|
243
|
+
switch (GeomType) {
|
244
|
+
case (OGIST_POINT): return ( SHPT_POINT ); break;
|
245
|
+
case (OGIST_LINESTRING): return ( SHPT_ARC ); break;
|
246
|
+
case (OGIST_POLYGON): return ( SHPT_POLYGON ); break;
|
247
|
+
case (OGIST_MULTIPOINT): return ( SHPT_MULTIPOINT ); break;
|
248
|
+
case (OGIST_MULTILINE): return ( SHPT_ARC ); break;
|
249
|
+
case (OGIST_MULTIPOLYGON): return ( SHPT_POLYGON ); break;
|
250
|
+
}
|
251
|
+
else /* ok so its SHP->OGis types */
|
252
|
+
switch (GeomType) {
|
253
|
+
case (SHPT_POINT): return ( OGIST_POINT ); break;
|
254
|
+
case (SHPT_POINTM): return ( OGIST_POINT ); break;
|
255
|
+
case (SHPT_POINTZ): return ( OGIST_POINT ); break;
|
256
|
+
case (SHPT_ARC): return ( OGIST_LINESTRING );break;
|
257
|
+
case (SHPT_ARCZ): return ( OGIST_LINESTRING );break;
|
258
|
+
case (SHPT_ARCM): return ( OGIST_LINESTRING );break;
|
259
|
+
case (SHPT_POLYGON): return ( OGIST_MULTIPOLYGON );break;
|
260
|
+
case (SHPT_POLYGONZ): return ( OGIST_MULTIPOLYGON );break;
|
261
|
+
case (SHPT_POLYGONM): return ( OGIST_MULTIPOLYGON );break;
|
262
|
+
case (SHPT_MULTIPOINT): return ( OGIST_MULTIPOINT );break;
|
263
|
+
case (SHPT_MULTIPOINTZ): return ( OGIST_MULTIPOINT );break;
|
264
|
+
case (SHPT_MULTIPOINTM): return ( OGIST_MULTIPOINT );break;
|
265
|
+
case (SHPT_MULTIPATCH): return ( OGIST_GEOMCOLL ); break;
|
266
|
+
}
|
267
|
+
|
268
|
+
return 0;
|
269
|
+
}
|
270
|
+
|
271
|
+
|
272
|
+
/* **************************************************************************
|
273
|
+
* SHPReadSHPStream
|
274
|
+
*
|
275
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
276
|
+
*
|
277
|
+
* **************************************************************************/
|
278
|
+
int SHPReadSHPStream ( SHPObject *psCShape, char *stream_obj) {
|
279
|
+
|
280
|
+
int obj_storage;
|
281
|
+
int my_order, need_swap =0, GeoType ;
|
282
|
+
int use_Z = 0;
|
283
|
+
int use_M = 0;
|
284
|
+
|
285
|
+
need_swap = stream_obj[0];
|
286
|
+
my_order = 1;
|
287
|
+
my_order = ((char*) (&my_order))[0];
|
288
|
+
need_swap = need_swap & my_order;
|
289
|
+
|
290
|
+
if ( need_swap )
|
291
|
+
swapW (stream_obj, (void*) &GeoType, sizeof (GeoType) );
|
292
|
+
else
|
293
|
+
memcpy (stream_obj, &GeoType, sizeof (GeoType) );
|
294
|
+
|
295
|
+
|
296
|
+
if ( need_swap ) {
|
297
|
+
|
298
|
+
} else {
|
299
|
+
memcpy (stream_obj, &(psCShape->nSHPType), sizeof (psCShape->nSHPType) );
|
300
|
+
memcpy (stream_obj, &(psCShape->nShapeId), sizeof (psCShape->nShapeId) );
|
301
|
+
memcpy (stream_obj, &(psCShape->nVertices), sizeof (psCShape->nVertices) );
|
302
|
+
memcpy (stream_obj, &(psCShape->nParts), sizeof (psCShape->nParts) );
|
303
|
+
memcpy (stream_obj, &(psCShape->dfXMin), sizeof (psCShape->dfXMin) );
|
304
|
+
memcpy (stream_obj, &(psCShape->dfYMin), sizeof (psCShape->dfYMin) );
|
305
|
+
memcpy (stream_obj, &(psCShape->dfXMax), sizeof (psCShape->dfXMax) );
|
306
|
+
memcpy (stream_obj, &(psCShape->dfYMax), sizeof (psCShape->dfYMax) );
|
307
|
+
if ( use_Z ) {
|
308
|
+
memcpy (stream_obj, &(psCShape->dfZMin), sizeof (psCShape->dfZMin) );
|
309
|
+
memcpy (stream_obj, &(psCShape->dfZMax), sizeof (psCShape->dfZMax) );
|
310
|
+
}
|
311
|
+
|
312
|
+
memcpy (stream_obj, psCShape->panPartStart, psCShape->nParts * sizeof (int) );
|
313
|
+
memcpy (stream_obj, psCShape->panPartType, psCShape->nParts * sizeof (int) );
|
314
|
+
|
315
|
+
/* get X and Y coordinate arrarys */
|
316
|
+
memcpy (stream_obj, psCShape->padfX, psCShape->nVertices * 2 * sizeof (double) );
|
317
|
+
|
318
|
+
/* get Z coordinate array if used */
|
319
|
+
if ( use_Z )
|
320
|
+
memcpy (stream_obj, psCShape->padfZ, psCShape->nVertices * 2 * sizeof (double) );
|
321
|
+
/* get Measure coordinate array if used */
|
322
|
+
if ( use_M )
|
323
|
+
memcpy (stream_obj, psCShape->padfM, psCShape->nVertices * 2 * sizeof (double) );
|
324
|
+
} /* end put data without swap */
|
325
|
+
|
326
|
+
return (0);
|
327
|
+
}
|
328
|
+
|
329
|
+
|
330
|
+
/* **************************************************************************
|
331
|
+
* SHPWriteSHPStream
|
332
|
+
*
|
333
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
334
|
+
*
|
335
|
+
* **************************************************************************/
|
336
|
+
int SHPWriteSHPStream ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
|
337
|
+
|
338
|
+
int obj_storage = 0;
|
339
|
+
int need_swap = 0, my_order, GeoType;
|
340
|
+
int use_Z = 0;
|
341
|
+
int use_M = 0;
|
342
|
+
|
343
|
+
need_swap = 1;
|
344
|
+
need_swap = ((char*) (&need_swap))[0];
|
345
|
+
|
346
|
+
realloc (stream_obj, obj_storage );
|
347
|
+
|
348
|
+
if ( need_swap ) {
|
349
|
+
|
350
|
+
} else {
|
351
|
+
memcpy (stream_obj, psCShape, 4 * sizeof (int) );
|
352
|
+
memcpy (stream_obj, psCShape, 4 * sizeof (double) );
|
353
|
+
if ( use_Z )
|
354
|
+
memcpy (stream_obj, psCShape, 2 * sizeof (double) );
|
355
|
+
if ( use_M )
|
356
|
+
memcpy (stream_obj, psCShape, 2 * sizeof (double) );
|
357
|
+
|
358
|
+
memcpy (stream_obj, psCShape, psCShape->nParts * 2 * sizeof (int) );
|
359
|
+
memcpy (stream_obj, psCShape, psCShape->nVertices * 2 * sizeof (double) );
|
360
|
+
if ( use_Z )
|
361
|
+
memcpy (stream_obj, psCShape, psCShape->nVertices * 2 * sizeof (double) );
|
362
|
+
if ( use_M )
|
363
|
+
memcpy (stream_obj, psCShape, psCShape->nVertices * 2 * sizeof (double) );
|
364
|
+
}
|
365
|
+
|
366
|
+
return (0);
|
367
|
+
}
|
368
|
+
|
369
|
+
|
370
|
+
/* **************************************************************************
|
371
|
+
* WKBStreamWrite
|
372
|
+
*
|
373
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
374
|
+
*
|
375
|
+
* **************************************************************************/
|
376
|
+
int WKBStreamWrite ( WKBStreamObj* wso, void* this, int tcount, int tsize ) {
|
377
|
+
|
378
|
+
if ( wso->NeedSwap )
|
379
|
+
SwapG ( &(wso->wStream[wso->StreamPos]), this, tcount, tsize );
|
380
|
+
else
|
381
|
+
memcpy ( &(wso->wStream[wso->StreamPos]), this, tsize * tcount );
|
382
|
+
|
383
|
+
wso->StreamPos += tsize;
|
384
|
+
|
385
|
+
return 0;
|
386
|
+
}
|
387
|
+
|
388
|
+
|
389
|
+
|
390
|
+
/* **************************************************************************
|
391
|
+
* WKBStreamRead
|
392
|
+
*
|
393
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
394
|
+
*
|
395
|
+
* **************************************************************************/
|
396
|
+
int WKBStreamRead ( WKBStreamObj* wso, void* this, int tcount, int tsize ) {
|
397
|
+
|
398
|
+
if ( wso->NeedSwap )
|
399
|
+
SwapG ( this, &(wso->wStream[wso->StreamPos]), tcount, tsize );
|
400
|
+
else
|
401
|
+
memcpy ( this, &(wso->wStream[wso->StreamPos]), tsize * tcount );
|
402
|
+
|
403
|
+
wso->StreamPos += tsize;
|
404
|
+
|
405
|
+
return 0;
|
406
|
+
}
|
407
|
+
|
408
|
+
|
409
|
+
|
410
|
+
/* **************************************************************************
|
411
|
+
* SHPReadOGisWKB
|
412
|
+
*
|
413
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
414
|
+
*
|
415
|
+
* **************************************************************************/
|
416
|
+
SHPObject* SHPReadOGisWKB ( WKBStreamObj *stream_obj) {
|
417
|
+
SHPObject *psCShape;
|
418
|
+
char WKB_order;
|
419
|
+
int need_swap = 0, my_order, GeoType = 0;
|
420
|
+
int use_Z = 0, use_M = 0;
|
421
|
+
int nSHPType, thisDim;
|
422
|
+
|
423
|
+
WKBStreamRead ( stream_obj, &WKB_order, 1, sizeof(char));
|
424
|
+
my_order = 1;
|
425
|
+
my_order = ((char*) (&my_order))[0];
|
426
|
+
stream_obj->NeedSwap = !(WKB_order & my_order);
|
427
|
+
|
428
|
+
/* convert OGis Types to SHP types */
|
429
|
+
nSHPType = SHPOGisType ( GeoType, 0 );
|
430
|
+
|
431
|
+
WKBStreamRead ( stream_obj, &GeoType, 1, sizeof(int));
|
432
|
+
|
433
|
+
thisDim = SHPDimension ( nSHPType );
|
434
|
+
|
435
|
+
if ( thisDim && SHPD_AREA )
|
436
|
+
{ psCShape = SHPReadOGisPolygon ( stream_obj ); }
|
437
|
+
else {
|
438
|
+
if ( thisDim && SHPD_LINE )
|
439
|
+
{ psCShape = SHPReadOGisLine ( stream_obj ); }
|
440
|
+
else {
|
441
|
+
if ( thisDim && SHPD_POINT )
|
442
|
+
{ psCShape = SHPReadOGisPoint ( stream_obj ); }
|
443
|
+
}
|
444
|
+
}
|
445
|
+
|
446
|
+
|
447
|
+
return (0);
|
448
|
+
}
|
449
|
+
|
450
|
+
|
451
|
+
|
452
|
+
/* **************************************************************************
|
453
|
+
* SHPWriteOGisWKB
|
454
|
+
*
|
455
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
456
|
+
*
|
457
|
+
* **************************************************************************/
|
458
|
+
int SHPWriteOGisWKB ( WKBStreamObj* stream_obj, SHPObject *psCShape ) {
|
459
|
+
|
460
|
+
int need_swap = 0, my_order, GeoType, thisDim;
|
461
|
+
int use_Z = 0, use_M = 0;
|
462
|
+
char LSB = 1;
|
463
|
+
/* indicate that this WKB is in LSB Order */
|
464
|
+
|
465
|
+
/* OGis WKB can handle either byte order, but if I get to choose I'd
|
466
|
+
/* rather have it predicatable system-to-system */
|
467
|
+
|
468
|
+
if ( stream_obj ) {
|
469
|
+
if ( stream_obj->wStream )
|
470
|
+
free ( stream_obj->wStream );
|
471
|
+
} else
|
472
|
+
{ stream_obj = calloc ( 3, sizeof (int ) ); }
|
473
|
+
|
474
|
+
/* object size needs to be 9 bytes for the wrapper, and for each polygon */
|
475
|
+
/* another 9 bytes all plus twice the total number of vertices */
|
476
|
+
/* times the sizeof (double) and just pad with 10 more chars for fun */
|
477
|
+
stream_obj->wStream = calloc (1, (9 * (psCShape->nParts + 1)) +
|
478
|
+
( sizeof(double) * 2 * psCShape->nVertices ) + 10 );
|
479
|
+
|
480
|
+
#ifdef DEBUG2
|
481
|
+
printf (" I just allocated %d bytes to wkbObj \n",
|
482
|
+
sizeof (int) + sizeof (int) + sizeof(int) +
|
483
|
+
( sizeof(int) * psCShape->nParts + 1 ) +
|
484
|
+
( sizeof(double) * 2 * psCShape->nVertices ) + 10 );
|
485
|
+
#endif
|
486
|
+
|
487
|
+
my_order = 1;
|
488
|
+
my_order = ((char*) (&my_order))[0];
|
489
|
+
/* Need to swap if this system is not LSB (Intel Order) */
|
490
|
+
stream_obj->NeedSwap = ( my_order != LSB );
|
491
|
+
|
492
|
+
stream_obj->StreamPos = 0;
|
493
|
+
|
494
|
+
|
495
|
+
#ifdef DEBUG2
|
496
|
+
printf ("this system is (%d) LSB recorded as needSwap %d\n",my_order, stream_obj->NeedSwap);
|
497
|
+
#endif
|
498
|
+
|
499
|
+
WKBStreamWrite ( stream_obj, & LSB, 1, sizeof(char) );
|
500
|
+
|
501
|
+
#ifdef DEBUG2
|
502
|
+
printf ("this system in (%d) LSB \n");
|
503
|
+
#endif
|
504
|
+
|
505
|
+
|
506
|
+
/* convert SHP Types to OGis types */
|
507
|
+
GeoType = SHPOGisType ( psCShape->nSHPType, 1 );
|
508
|
+
WKBStreamWrite ( stream_obj, &GeoType, 1, sizeof(int) );
|
509
|
+
|
510
|
+
thisDim = SHPDimension ( psCShape->nSHPType );
|
511
|
+
|
512
|
+
if ( thisDim && SHPD_AREA )
|
513
|
+
{ SHPWriteOGisPolygon ( stream_obj, psCShape ); }
|
514
|
+
else {
|
515
|
+
if ( thisDim && SHPD_LINE )
|
516
|
+
{ SHPWriteOGisLine ( stream_obj, psCShape ); }
|
517
|
+
else {
|
518
|
+
if ( thisDim && SHPD_POINT )
|
519
|
+
{ SHPWriteOGisPoint ( stream_obj, psCShape ); }
|
520
|
+
}
|
521
|
+
}
|
522
|
+
|
523
|
+
#ifdef DEBUG2
|
524
|
+
printf("(SHPWriteOGisWKB) outta here when stream pos is %d \n", stream_obj->StreamPos);
|
525
|
+
#endif
|
526
|
+
return (0);
|
527
|
+
}
|
528
|
+
|
529
|
+
|
530
|
+
/* **************************************************************************
|
531
|
+
* SHPWriteOGisPolygon
|
532
|
+
*
|
533
|
+
* for this pass code to more generic OGis MultiPolygon Type
|
534
|
+
* later add support for OGis Polygon Type
|
535
|
+
*
|
536
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
537
|
+
*
|
538
|
+
* **************************************************************************/
|
539
|
+
int SHPWriteOGisPolygon ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
|
540
|
+
SHPObject **ppsC;
|
541
|
+
SHPObject *psC;
|
542
|
+
int rPart, ring, rVertices, cpart, cParts, nextring, i, j;
|
543
|
+
char Flag = 1;
|
544
|
+
int GeoType = OGIST_POLYGON;
|
545
|
+
|
546
|
+
/* cant have more than nParts complex objects in this object */
|
547
|
+
ppsC = calloc ( psCShape->nParts, sizeof(int) );
|
548
|
+
|
549
|
+
|
550
|
+
nextring = 0;
|
551
|
+
cParts=0;
|
552
|
+
while ( nextring >= 0 ) {
|
553
|
+
ppsC[cParts] = SHPUnCompound ( psCShape, &nextring );
|
554
|
+
cParts++;
|
555
|
+
}
|
556
|
+
|
557
|
+
#ifdef DEBUG2
|
558
|
+
printf ("(SHPWriteOGisPolygon) Uncompounded into %d parts \n", cParts);
|
559
|
+
#endif
|
560
|
+
|
561
|
+
WKBStreamWrite ( stream_obj, &cParts, 1, sizeof(int) );
|
562
|
+
|
563
|
+
for ( cpart = 0; cpart < cParts; cpart++) {
|
564
|
+
|
565
|
+
WKBStreamWrite ( stream_obj, & Flag, 1, sizeof(char) );
|
566
|
+
WKBStreamWrite ( stream_obj, & GeoType, 1, sizeof(int) );
|
567
|
+
|
568
|
+
psC = (SHPObject*) ppsC[cpart];
|
569
|
+
WKBStreamWrite ( stream_obj, &(psC->nParts), 1, sizeof(int) );
|
570
|
+
|
571
|
+
for ( ring = 0; (ring < (psC->nParts)) && (psC->nParts > 0); ring ++) {
|
572
|
+
if ( ring < (psC->nParts-2) )
|
573
|
+
{ rVertices = psC->panPartStart[ring+1] - psC->panPartStart[ring]; }
|
574
|
+
else
|
575
|
+
{ rVertices = psC->nVertices - psC->panPartStart[ring]; }
|
576
|
+
#ifdef DEBUG2
|
577
|
+
printf ("(SHPWriteOGisPolygon) scanning part %d, ring %d %d vtxs \n",
|
578
|
+
cpart, ring, rVertices);
|
579
|
+
#endif
|
580
|
+
rPart = psC->panPartStart[ring];
|
581
|
+
WKBStreamWrite ( stream_obj, &rVertices, 1, sizeof(int) );
|
582
|
+
for ( j=rPart; j < (rPart + rVertices); j++ ) {
|
583
|
+
WKBStreamWrite ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
|
584
|
+
WKBStreamWrite ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
|
585
|
+
} /* for each vertex */
|
586
|
+
} /* for each ring */
|
587
|
+
} /* for each complex part */
|
588
|
+
|
589
|
+
#ifdef DEBUG2
|
590
|
+
printf ("(SHPWriteOGisPolygon) outta here \n");
|
591
|
+
#endif
|
592
|
+
return (1);
|
593
|
+
}
|
594
|
+
|
595
|
+
|
596
|
+
/* **************************************************************************
|
597
|
+
* SHPWriteOGisLine
|
598
|
+
*
|
599
|
+
* for this pass code to more generic OGis MultiXXXXXXX Type
|
600
|
+
* later add support for OGis LineString Type
|
601
|
+
*
|
602
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
603
|
+
*
|
604
|
+
* **************************************************************************/
|
605
|
+
int SHPWriteOGisLine ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
|
606
|
+
|
607
|
+
return ( SHPWriteOGisPolygon( stream_obj, psCShape ));
|
608
|
+
}
|
609
|
+
|
610
|
+
|
611
|
+
/* **************************************************************************
|
612
|
+
* SHPWriteOGisPoint
|
613
|
+
*
|
614
|
+
* for this pass code to more generic OGis MultiPoint Type
|
615
|
+
* later add support for OGis Point Type
|
616
|
+
*
|
617
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
618
|
+
*
|
619
|
+
* **************************************************************************/
|
620
|
+
int SHPWriteOGisPoint ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
|
621
|
+
int j;
|
622
|
+
|
623
|
+
WKBStreamWrite ( stream_obj, &(psCShape->nVertices), 1, sizeof(int) );
|
624
|
+
|
625
|
+
for ( j=0; j < psCShape->nVertices; j++ ) {
|
626
|
+
WKBStreamWrite ( stream_obj, &(psCShape->padfX[j]), 1, sizeof(double) );
|
627
|
+
WKBStreamWrite ( stream_obj, &(psCShape->padfY[j]), 1, sizeof(double) );
|
628
|
+
} /* for each vertex */
|
629
|
+
|
630
|
+
return (1);
|
631
|
+
}
|
632
|
+
|
633
|
+
|
634
|
+
|
635
|
+
/* **************************************************************************
|
636
|
+
* SHPReadOGisPolygon
|
637
|
+
*
|
638
|
+
* for this pass code to more generic OGis MultiPolygon Type
|
639
|
+
* later add support for OGis Polygon Type
|
640
|
+
*
|
641
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
642
|
+
*
|
643
|
+
* **************************************************************************/
|
644
|
+
SHPObject* SHPReadOGisPolygon ( WKBStreamObj *stream_obj ) {
|
645
|
+
SHPObject **ppsC;
|
646
|
+
SHPObject *psC;
|
647
|
+
int rPart, ring, rVertices, cpart, cParts, nextring, i, j;
|
648
|
+
int totParts, totVertices, pRings, nParts;
|
649
|
+
|
650
|
+
psC = SHPCreateObject ( SHPT_POLYGON, -1, 0, NULL, NULL, 0,
|
651
|
+
NULL, NULL, NULL, NULL );
|
652
|
+
/* initialize a blank SHPObject */
|
653
|
+
|
654
|
+
WKBStreamRead ( stream_obj, &cParts, 1, sizeof(char) );
|
655
|
+
|
656
|
+
totParts = cParts;
|
657
|
+
totVertices = 0;
|
658
|
+
|
659
|
+
SfRealloc ( psC->panPartStart, cParts * sizeof(int));
|
660
|
+
SfRealloc ( psC->panPartType, cParts * sizeof(int));
|
661
|
+
|
662
|
+
for ( cpart = 0; cpart < cParts; cpart++) {
|
663
|
+
WKBStreamRead ( stream_obj, &nParts, 1, sizeof(int) );
|
664
|
+
pRings = nParts;
|
665
|
+
/* pRings is the number of rings prior to the Ring loop below */
|
666
|
+
|
667
|
+
if ( nParts > 1 ) {
|
668
|
+
totParts += nParts - 1;
|
669
|
+
SfRealloc ( psC->panPartStart, totParts * sizeof(int));
|
670
|
+
SfRealloc ( psC->panPartType, totParts * sizeof(int));
|
671
|
+
}
|
672
|
+
|
673
|
+
rPart = 0;
|
674
|
+
for ( ring = 0; ring < (nParts - 1); ring ++) {
|
675
|
+
WKBStreamRead ( stream_obj, &rVertices, 1, sizeof(int) );
|
676
|
+
totVertices += rVertices;
|
677
|
+
|
678
|
+
psC->panPartStart[ring+pRings] = rPart;
|
679
|
+
if ( ring == 0 )
|
680
|
+
{ psC->panPartType[ring + pRings] = SHPP_OUTERRING; }
|
681
|
+
else
|
682
|
+
{ psC->panPartType[ring + pRings] = SHPP_INNERRING; }
|
683
|
+
|
684
|
+
SfRealloc ( psC->padfX, totVertices * sizeof (double));
|
685
|
+
SfRealloc ( psC->padfY, totVertices * sizeof (double));
|
686
|
+
|
687
|
+
for ( j=rPart; j < (rPart + rVertices); j++ ) {
|
688
|
+
WKBStreamRead ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
|
689
|
+
WKBStreamRead ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
|
690
|
+
} /* for each vertex */
|
691
|
+
rPart += rVertices;
|
692
|
+
|
693
|
+
} /* for each ring */
|
694
|
+
|
695
|
+
} /* for each complex part */
|
696
|
+
|
697
|
+
return ( psC );
|
698
|
+
|
699
|
+
}
|
700
|
+
|
701
|
+
|
702
|
+
/* **************************************************************************
|
703
|
+
* SHPReadOGisLine
|
704
|
+
*
|
705
|
+
* for this pass code to more generic OGis MultiLineString Type
|
706
|
+
* later add support for OGis LineString Type
|
707
|
+
*
|
708
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
709
|
+
*
|
710
|
+
* **************************************************************************/
|
711
|
+
SHPObject* SHPReadOGisLine ( WKBStreamObj *stream_obj ) {
|
712
|
+
SHPObject **ppsC;
|
713
|
+
SHPObject *psC;
|
714
|
+
int rPart, ring, rVertices, cpart, cParts, nextring, i, j;
|
715
|
+
int totParts, totVertices, pRings, nParts;
|
716
|
+
|
717
|
+
psC = SHPCreateObject ( SHPT_ARC, -1, 0, NULL, NULL, 0,
|
718
|
+
NULL, NULL, NULL, NULL );
|
719
|
+
/* initialize a blank SHPObject */
|
720
|
+
|
721
|
+
WKBStreamRead ( stream_obj, &cParts, 1, sizeof(int) );
|
722
|
+
|
723
|
+
totParts = cParts;
|
724
|
+
totVertices = 0;
|
725
|
+
|
726
|
+
SfRealloc ( psC->panPartStart, cParts * sizeof(int));
|
727
|
+
SfRealloc ( psC->panPartType, cParts * sizeof(int));
|
728
|
+
|
729
|
+
for ( cpart = 0; cpart < cParts; cpart++) {
|
730
|
+
WKBStreamRead ( stream_obj, &nParts, 1, sizeof(int) );
|
731
|
+
pRings = totParts;
|
732
|
+
/* pRings is the number of rings prior to the Ring loop below */
|
733
|
+
|
734
|
+
if ( nParts > 1 ) {
|
735
|
+
totParts += nParts - 1;
|
736
|
+
SfRealloc ( psC->panPartStart, totParts * sizeof(int));
|
737
|
+
SfRealloc ( psC->panPartType, totParts * sizeof(int));
|
738
|
+
}
|
739
|
+
|
740
|
+
rPart = 0;
|
741
|
+
for ( ring = 0; ring < (nParts - 1); ring ++) {
|
742
|
+
WKBStreamRead ( stream_obj, &rVertices, 1, sizeof(int) );
|
743
|
+
totVertices += rVertices;
|
744
|
+
|
745
|
+
psC->panPartStart[ring+pRings] = rPart;
|
746
|
+
if ( ring == 0 )
|
747
|
+
{ psC->panPartType[ring + pRings] = SHPP_OUTERRING; }
|
748
|
+
else
|
749
|
+
{ psC->panPartType[ring + pRings] = SHPP_INNERRING; }
|
750
|
+
|
751
|
+
SfRealloc ( psC->padfX, totVertices * sizeof (double));
|
752
|
+
SfRealloc ( psC->padfY, totVertices * sizeof (double));
|
753
|
+
|
754
|
+
for ( j=rPart; j < (rPart + rVertices); j++ ) {
|
755
|
+
WKBStreamRead ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
|
756
|
+
WKBStreamRead ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
|
757
|
+
} /* for each vertex */
|
758
|
+
rPart += rVertices;
|
759
|
+
|
760
|
+
} /* for each ring */
|
761
|
+
|
762
|
+
} /* for each complex part */
|
763
|
+
|
764
|
+
return ( psC );
|
765
|
+
}
|
766
|
+
|
767
|
+
|
768
|
+
/* **************************************************************************
|
769
|
+
* SHPReadOGisPoint
|
770
|
+
*
|
771
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
772
|
+
*
|
773
|
+
* **************************************************************************/
|
774
|
+
SHPObject* SHPReadOGisPoint ( WKBStreamObj *stream_obj ) {
|
775
|
+
SHPObject *psC;
|
776
|
+
int nVertices, j;
|
777
|
+
|
778
|
+
psC = SHPCreateObject ( SHPT_MULTIPOINT, -1, 0, NULL, NULL, 0,
|
779
|
+
NULL, NULL, NULL, NULL );
|
780
|
+
/* initialize a blank SHPObject */
|
781
|
+
|
782
|
+
WKBStreamRead ( stream_obj, &nVertices, 1, sizeof(int) );
|
783
|
+
|
784
|
+
SfRealloc ( psC->padfX, nVertices * sizeof (double));
|
785
|
+
SfRealloc ( psC->padfY, nVertices * sizeof (double));
|
786
|
+
|
787
|
+
for ( j=0; j < nVertices; j++ ) {
|
788
|
+
WKBStreamRead ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
|
789
|
+
WKBStreamRead ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
|
790
|
+
} /* for each vertex */
|
791
|
+
|
792
|
+
return ( psC );
|
793
|
+
}
|
794
|
+
|
795
|
+
|
796
|
+
|
797
|
+
|
798
|
+
/* **************************************************************************
|
799
|
+
* RingReadOGisWKB
|
800
|
+
*
|
801
|
+
* this accepts OGisLineStrings which are basic building blocks
|
802
|
+
*
|
803
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
804
|
+
*
|
805
|
+
* **************************************************************************/
|
806
|
+
int RingReadOgisWKB ( SHPObject *psCShape, char *stream_obj) {
|
807
|
+
return 0;
|
808
|
+
}
|
809
|
+
|
810
|
+
|
811
|
+
/* **************************************************************************
|
812
|
+
* RingWriteOGisWKB
|
813
|
+
*
|
814
|
+
* this emits OGisLineStrings which are basic building blocks
|
815
|
+
*
|
816
|
+
* Encapsulate entire SHPObject for use with Postgresql
|
817
|
+
*
|
818
|
+
* **************************************************************************/
|
819
|
+
int RingWriteOgisWKB ( SHPObject *psCShape, char *stream_obj) {
|
820
|
+
|
821
|
+
return 0;
|
822
|
+
}
|
823
|
+
|
824
|
+
|
825
|
+
/* **************************************************************************
|
826
|
+
* SHPDimension
|
827
|
+
*
|
828
|
+
* Return the Dimensionality of the SHPObject
|
829
|
+
* a handy utility function
|
830
|
+
*
|
831
|
+
* **************************************************************************/
|
832
|
+
int SHPDimension ( int SHPType ) {
|
833
|
+
int dimension;
|
834
|
+
|
835
|
+
dimension = 0;
|
836
|
+
|
837
|
+
switch ( SHPType ) {
|
838
|
+
case SHPT_POINT : dimension = SHPD_POINT; break;
|
839
|
+
case SHPT_ARC : dimension = SHPD_LINE; break;
|
840
|
+
case SHPT_POLYGON : dimension = SHPD_AREA; break;
|
841
|
+
case SHPT_MULTIPOINT : dimension = SHPD_POINT; break;
|
842
|
+
case SHPT_POINTZ : dimension = SHPD_POINT | SHPD_Z; break;
|
843
|
+
case SHPT_ARCZ : dimension = SHPD_LINE | SHPD_Z; break;
|
844
|
+
case SHPT_POLYGONZ : dimension = SHPD_AREA | SHPD_Z; break;
|
845
|
+
case SHPT_MULTIPOINTZ : dimension = SHPD_POINT | SHPD_Z; break;
|
846
|
+
case SHPT_POINTM : dimension = SHPD_POINT | SHPD_MEASURE; break;
|
847
|
+
case SHPT_ARCM : dimension = SHPD_LINE | SHPD_MEASURE; break;
|
848
|
+
case SHPT_POLYGONM : dimension = SHPD_AREA | SHPD_MEASURE; break;
|
849
|
+
case SHPT_MULTIPOINTM : dimension = SHPD_POINT | SHPD_MEASURE; break;
|
850
|
+
case SHPT_MULTIPATCH : dimension = SHPD_AREA; break;
|
851
|
+
}
|
852
|
+
|
853
|
+
return ( dimension );
|
854
|
+
}
|
855
|
+
|
856
|
+
|
857
|
+
/* **************************************************************************
|
858
|
+
* SHPPointinPoly_2d
|
859
|
+
*
|
860
|
+
* Return a Point inside an R+ of a potentially
|
861
|
+
* complex/compound SHPObject suitable for labelling
|
862
|
+
* return only one point even if if is a compound object
|
863
|
+
*
|
864
|
+
* reject non area SHP Types
|
865
|
+
*
|
866
|
+
* **************************************************************************/
|
867
|
+
PT SHPPointinPoly_2d ( SHPObject *psCShape ) {
|
868
|
+
PT *sPT, rPT;
|
869
|
+
|
870
|
+
if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
|
871
|
+
{
|
872
|
+
rPT.x = NAN;
|
873
|
+
rPT.y = NAN;
|
874
|
+
return rPT;
|
875
|
+
}
|
876
|
+
|
877
|
+
sPT = SHPPointsinPoly_2d ( psCShape );
|
878
|
+
|
879
|
+
if ( sPT ) {
|
880
|
+
rPT.x = sPT[0].x;
|
881
|
+
rPT.y = sPT[0].y;
|
882
|
+
} else {
|
883
|
+
rPT.x = NAN;
|
884
|
+
rPT.y = NAN;
|
885
|
+
}
|
886
|
+
return ( rPT );
|
887
|
+
}
|
888
|
+
|
889
|
+
|
890
|
+
/* **************************************************************************
|
891
|
+
* SHPPointsinPoly_2d
|
892
|
+
*
|
893
|
+
* Return a Point inside each R+ of a potentially
|
894
|
+
* complex/compound SHPObject suitable for labelling
|
895
|
+
* return one point for each R+ even if it is a compound object
|
896
|
+
*
|
897
|
+
* reject non area SHP Types
|
898
|
+
*
|
899
|
+
* **************************************************************************/
|
900
|
+
PT* SHPPointsinPoly_2d ( SHPObject *psCShape ) {
|
901
|
+
PT *PIP = NULL;
|
902
|
+
int cRing;
|
903
|
+
SHPObject *psO, *psInt, *CLine;
|
904
|
+
double *CLx, *CLy;
|
905
|
+
int *CLstt, *CLst, nPIP, ring, rMpart, ring_vtx, ring_nVertices;
|
906
|
+
double rLen, rLenMax;
|
907
|
+
|
908
|
+
if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
|
909
|
+
return ( NULL );
|
910
|
+
|
911
|
+
while ( psO = SHPUnCompound (psCShape, &cRing)) {
|
912
|
+
CLx = calloc ( 4, sizeof(double));
|
913
|
+
CLy = calloc ( 4, sizeof(double));
|
914
|
+
CLst = calloc ( 2, sizeof(int));
|
915
|
+
CLstt = calloc ( 2, sizeof(int));
|
916
|
+
|
917
|
+
/* a horizontal & vertical compound line though the middle of the */
|
918
|
+
/* extents */
|
919
|
+
CLx [0] = psO->dfXMin;
|
920
|
+
CLy [0] = (psO->dfYMin + psO->dfYMax ) * 0.5;
|
921
|
+
CLx [1] = psO->dfXMax;
|
922
|
+
CLy [1] = (psO->dfYMin + psO->dfYMax ) * 0.5;
|
923
|
+
|
924
|
+
CLx [2] = (psO->dfXMin + psO->dfXMax ) * 0.5;
|
925
|
+
CLy [2] = psO->dfYMin;
|
926
|
+
CLx [3] = (psO->dfXMin + psO->dfXMax ) * 0.5;
|
927
|
+
CLy [3] = psO->dfYMax;
|
928
|
+
|
929
|
+
CLst[0] = 0; CLst[1] = 2;
|
930
|
+
CLstt[0] = SHPP_RING; CLstt[1] = SHPP_RING;
|
931
|
+
|
932
|
+
CLine = SHPCreateObject ( SHPT_POINT, -1, 2, CLst, CLstt, 4,
|
933
|
+
CLx, CLy, NULL, NULL );
|
934
|
+
|
935
|
+
/* with the H & V centrline compound object, intersect it with the OBJ */
|
936
|
+
psInt = SHPIntersect_2d ( CLine, psO );
|
937
|
+
/* return SHP type is lowest common dimensionality of the input types */
|
938
|
+
|
939
|
+
|
940
|
+
/* find the longest linestring returned by the intersection */
|
941
|
+
ring_vtx = psInt->nVertices ;
|
942
|
+
for ( ring = (psInt->nParts - 1); ring >= 0; ring-- ) {
|
943
|
+
ring_nVertices = ring_vtx - psInt->panPartStart[ring];
|
944
|
+
|
945
|
+
rLen += RingLength_2d ( ring_nVertices,
|
946
|
+
(double*) &(psInt->padfX [psInt->panPartStart[ring]]),
|
947
|
+
(double*) &(psInt->padfY [psInt->panPartStart[ring]]) );
|
948
|
+
|
949
|
+
if ( rLen > rLenMax )
|
950
|
+
{ rLenMax = rLen;
|
951
|
+
rMpart = psInt->panPartStart[ring];
|
952
|
+
}
|
953
|
+
ring_vtx = psInt->panPartStart[ring];
|
954
|
+
}
|
955
|
+
|
956
|
+
/* add the centerpoint of the longest ARC of the intersection to the */
|
957
|
+
/* PIP list */
|
958
|
+
nPIP ++;
|
959
|
+
SfRealloc ( PIP, sizeof(double) * 2 * nPIP);
|
960
|
+
PIP[nPIP].x = (psInt ->padfX [rMpart] + psInt ->padfX [rMpart]) * 0.5;
|
961
|
+
PIP[nPIP].y = (psInt ->padfY [rMpart] + psInt ->padfY [rMpart]) * 0.5;
|
962
|
+
|
963
|
+
SHPDestroyObject ( psO );
|
964
|
+
SHPDestroyObject ( CLine );
|
965
|
+
|
966
|
+
/* does SHPCreateobject use preallocated memory or does it copy the */
|
967
|
+
/* contents. To be safe conditionally release CLx, CLy, CLst, CLstt */
|
968
|
+
if ( CLx ) free ( CLx );
|
969
|
+
if ( CLy ) free ( CLy );
|
970
|
+
if ( CLst ) free ( CLst );
|
971
|
+
if ( CLstt ) free ( CLstt );
|
972
|
+
}
|
973
|
+
|
974
|
+
return ( PIP );
|
975
|
+
}
|
976
|
+
|
977
|
+
|
978
|
+
/* **************************************************************************
|
979
|
+
* SHPCentrd_2d
|
980
|
+
*
|
981
|
+
* Return the single mathematical / geometric centroid of a potentially
|
982
|
+
* complex/compound SHPObject
|
983
|
+
*
|
984
|
+
* reject non area SHP Types
|
985
|
+
*
|
986
|
+
* **************************************************************************/
|
987
|
+
PT SHPCentrd_2d ( SHPObject *psCShape ) {
|
988
|
+
int ring, ringPrev, ring_nVertices, rStart;
|
989
|
+
double Area, ringArea;
|
990
|
+
PT ringCentrd, C;
|
991
|
+
|
992
|
+
|
993
|
+
if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
|
994
|
+
{
|
995
|
+
C.x = NAN;
|
996
|
+
C.y = NAN;
|
997
|
+
return C;
|
998
|
+
}
|
999
|
+
|
1000
|
+
#ifdef DEBUG
|
1001
|
+
printf ("for Object with %d vtx, %d parts [ %d, %d] \n",
|
1002
|
+
psCShape->nVertices, psCShape->nParts,
|
1003
|
+
psCShape->panPartStart[0],psCShape->panPartStart[1]);
|
1004
|
+
#endif
|
1005
|
+
|
1006
|
+
Area = 0;
|
1007
|
+
C.x = 0.0;
|
1008
|
+
C.y = 0.0;
|
1009
|
+
|
1010
|
+
/* for each ring in compound / complex object calc the ring cntrd */
|
1011
|
+
|
1012
|
+
ringPrev = psCShape->nVertices;
|
1013
|
+
for ( ring = (psCShape->nParts - 1); ring >= 0; ring-- ) {
|
1014
|
+
rStart = psCShape->panPartStart[ring];
|
1015
|
+
ring_nVertices = ringPrev - rStart;
|
1016
|
+
|
1017
|
+
RingCentroid_2d ( ring_nVertices, (double*) &(psCShape->padfX [rStart]),
|
1018
|
+
(double*) &(psCShape->padfY [rStart]), &ringCentrd, &ringArea);
|
1019
|
+
|
1020
|
+
#ifdef DEBUG
|
1021
|
+
printf ("(SHPCentrd_2d) Ring %d, vtxs %d, area: %f, ring centrd %f, %f \n",
|
1022
|
+
ring, ring_nVertices, ringArea, ringCentrd.x, ringCentrd.y);
|
1023
|
+
#endif
|
1024
|
+
|
1025
|
+
/* use Superposition of these rings to build a composite Centroid */
|
1026
|
+
/* sum the ring centrds * ringAreas, at the end divide by total area */
|
1027
|
+
C.x += ringCentrd.x * ringArea;
|
1028
|
+
C.y += ringCentrd.y * ringArea;
|
1029
|
+
Area += ringArea;
|
1030
|
+
ringPrev = rStart;
|
1031
|
+
}
|
1032
|
+
|
1033
|
+
/* hold on the division by AREA until were at the end */
|
1034
|
+
C.x = C.x / Area;
|
1035
|
+
C.y = C.y / Area;
|
1036
|
+
#ifdef DEBUG
|
1037
|
+
printf ("SHPCentrd_2d) Overall Area: %f, Centrd %f, %f \n",
|
1038
|
+
Area, C.x, C.y);
|
1039
|
+
#endif
|
1040
|
+
return ( C );
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
|
1044
|
+
/* **************************************************************************
|
1045
|
+
* RingCentroid_2d
|
1046
|
+
*
|
1047
|
+
* Return the mathematical / geometric centroid of a single closed ring
|
1048
|
+
*
|
1049
|
+
* **************************************************************************/
|
1050
|
+
int RingCentroid_2d ( int nVertices, double *a, double *b, PT *C, double *Area ) {
|
1051
|
+
int iv,jv;
|
1052
|
+
int sign_x, sign_y;
|
1053
|
+
double dy_Area, dx_Area, Cx_accum, Cy_accum, ppx, ppy;
|
1054
|
+
double x_base, y_base, x, y;
|
1055
|
+
|
1056
|
+
/* the centroid of a closed Ring is defined as
|
1057
|
+
*
|
1058
|
+
* Cx = sum (cx * dArea ) / Total Area
|
1059
|
+
* and
|
1060
|
+
* Cy = sum (cy * dArea ) / Total Area
|
1061
|
+
*/
|
1062
|
+
|
1063
|
+
x_base = a[0];
|
1064
|
+
y_base = b[0];
|
1065
|
+
|
1066
|
+
Cy_accum = 0.0;
|
1067
|
+
Cx_accum = 0.0;
|
1068
|
+
|
1069
|
+
ppx = a[1] - x_base;
|
1070
|
+
ppy = b[1] - y_base;
|
1071
|
+
*Area = 0;
|
1072
|
+
|
1073
|
+
/* Skip the closing vector */
|
1074
|
+
for ( iv = 2; iv <= nVertices - 2; iv++ ) {
|
1075
|
+
x = a[iv] - x_base;
|
1076
|
+
y = b[iv] - y_base;
|
1077
|
+
|
1078
|
+
/* calc the area and centroid of triangle built out of an arbitrary */
|
1079
|
+
/* base_point on the ring and each successive pair on the ring */
|
1080
|
+
|
1081
|
+
/* Area of a triangle is the cross product of its defining vectors */
|
1082
|
+
/* Centroid of a triangle is the average of its vertices */
|
1083
|
+
|
1084
|
+
dx_Area = ((x * ppy) - (y * ppx)) * 0.5;
|
1085
|
+
*Area += dx_Area;
|
1086
|
+
|
1087
|
+
Cx_accum += ( ppx + x ) * dx_Area;
|
1088
|
+
Cy_accum += ( ppy + y ) * dx_Area;
|
1089
|
+
#ifdef DEBUG2
|
1090
|
+
printf("(ringcentrd_2d) Pp( %f, %f), P(%f, %f)\n", ppx, ppy, x, y);
|
1091
|
+
printf("(ringcentrd_2d) dA: %f, sA: %f, Cx: %f, Cy: %f \n",
|
1092
|
+
dx_Area, *Area, Cx_accum, Cy_accum);
|
1093
|
+
#endif
|
1094
|
+
ppx = x;
|
1095
|
+
ppy = y;
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
#ifdef DEBUG2
|
1099
|
+
printf("(ringcentrd_2d) Cx: %f, Cy: %f \n",
|
1100
|
+
( Cx_accum / ( *Area * 3) ), ( Cy_accum / (*Area * 3) ));
|
1101
|
+
#endif
|
1102
|
+
|
1103
|
+
/* adjust back to world coords */
|
1104
|
+
C->x = ( Cx_accum / ( *Area * 3)) + x_base;
|
1105
|
+
C->y = ( Cy_accum / ( *Area * 3)) + y_base;
|
1106
|
+
|
1107
|
+
return ( 1 );
|
1108
|
+
}
|
1109
|
+
|
1110
|
+
|
1111
|
+
|
1112
|
+
|
1113
|
+
/* **************************************************************************
|
1114
|
+
* SHPRingDir_2d
|
1115
|
+
*
|
1116
|
+
* Test Polygon for CW / CCW ( R+ / R- )
|
1117
|
+
*
|
1118
|
+
* return 1 for R+
|
1119
|
+
* return -1 for R-
|
1120
|
+
* return 0 for error
|
1121
|
+
* **************************************************************************/
|
1122
|
+
int SHPRingDir_2d ( SHPObject *psCShape, int Ring ) {
|
1123
|
+
int i, ti, last_vtx;
|
1124
|
+
double tX;
|
1125
|
+
double *a, *b;
|
1126
|
+
double dx0, dx1, dy0, dy1, v1, v2 ,v3;
|
1127
|
+
|
1128
|
+
tX = 0.0;
|
1129
|
+
a = psCShape->padfX;
|
1130
|
+
b = psCShape->padfY;
|
1131
|
+
|
1132
|
+
if ( Ring >= psCShape->nParts ) return ( 0 );
|
1133
|
+
|
1134
|
+
if ( Ring >= psCShape->nParts -1 )
|
1135
|
+
{ last_vtx = psCShape->nVertices; }
|
1136
|
+
else
|
1137
|
+
{ last_vtx = psCShape->panPartStart[Ring + 1]; }
|
1138
|
+
|
1139
|
+
/* All vertices at the corners of the extrema (rightmost lowest, leftmost lowest, */
|
1140
|
+
/* topmost rightest, ...) must be less than pi wide. If they werent they couldnt be */
|
1141
|
+
/* extrema. */
|
1142
|
+
/* of course the following will fail if the Extents are even a little wrong */
|
1143
|
+
|
1144
|
+
for ( i = psCShape->panPartStart[Ring]; i < last_vtx; i++ ) {
|
1145
|
+
if ( b[i] == psCShape->dfYMax && a[i] > tX )
|
1146
|
+
{ ti = i; }
|
1147
|
+
}
|
1148
|
+
|
1149
|
+
#ifdef DEBUG2
|
1150
|
+
printf ("(shpgeo:SHPRingDir) highest Rightmost Pt is vtx %d (%f, %f)\n", ti, a[ti], b[ti]);
|
1151
|
+
#endif
|
1152
|
+
|
1153
|
+
/* cross product */
|
1154
|
+
/* the sign of the cross product of two vectors indicates the right or left half-plane */
|
1155
|
+
/* which we can use to indicate Ring Dir */
|
1156
|
+
if ( ti > psCShape->panPartStart[Ring] & ti < last_vtx )
|
1157
|
+
{ dx0 = a[ti-1] - a[ti];
|
1158
|
+
dx1 = a[ti+1] - a[ti];
|
1159
|
+
dy0 = b[ti-1] - b[ti];
|
1160
|
+
dy1 = b[ti+1] - b[ti];
|
1161
|
+
}
|
1162
|
+
else
|
1163
|
+
/* if the tested vertex is at the origin then continue from 0 */
|
1164
|
+
{ dx1 = a[1] - a[0];
|
1165
|
+
dx0 = a[last_vtx] - a[0];
|
1166
|
+
dy1 = b[1] - b[0];
|
1167
|
+
dy0 = b[last_vtx] - b[0];
|
1168
|
+
}
|
1169
|
+
|
1170
|
+
// v1 = ( (dy0 * 0) - (0 * dy1) );
|
1171
|
+
// v2 = ( (0 * dx1) - (dx0 * 0) );
|
1172
|
+
/* these above are always zero so why do the math */
|
1173
|
+
v3 = ( (dx0 * dy1) - (dx1 * dy0) );
|
1174
|
+
|
1175
|
+
#ifdef DEBUG2
|
1176
|
+
printf ("(shpgeo:SHPRingDir) cross product for vtx %d was %f \n", ti, v3);
|
1177
|
+
#endif
|
1178
|
+
|
1179
|
+
if ( v3 > 0 )
|
1180
|
+
{ return (1); }
|
1181
|
+
else
|
1182
|
+
{ return (-1); }
|
1183
|
+
}
|
1184
|
+
|
1185
|
+
|
1186
|
+
|
1187
|
+
/* **************************************************************************
|
1188
|
+
* SHPArea_2d
|
1189
|
+
*
|
1190
|
+
* Calculate the XY Area of Polygon ( can be compound / complex )
|
1191
|
+
*
|
1192
|
+
* **************************************************************************/
|
1193
|
+
double SHPArea_2d ( SHPObject *psCShape ) {
|
1194
|
+
double cArea;
|
1195
|
+
int ring, ring_vtx, ringDir, ring_nVertices;
|
1196
|
+
|
1197
|
+
cArea = 0;
|
1198
|
+
if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
|
1199
|
+
return ( -1 );
|
1200
|
+
|
1201
|
+
|
1202
|
+
/* Walk each ring adding its signed Area, R- will return a negative */
|
1203
|
+
/* area, so we don't have to test for them */
|
1204
|
+
|
1205
|
+
/* I just start at the last ring and work down to the first */
|
1206
|
+
ring_vtx = psCShape->nVertices ;
|
1207
|
+
for ( ring = (psCShape->nParts - 1); ring >= 0; ring-- ) {
|
1208
|
+
ring_nVertices = ring_vtx - psCShape->panPartStart[ring];
|
1209
|
+
|
1210
|
+
#ifdef DEBUG2
|
1211
|
+
printf("(shpgeo:SHPArea_2d) part %d, vtx %d \n", ring, ring_nVertices);
|
1212
|
+
#endif
|
1213
|
+
cArea += RingArea_2d ( ring_nVertices,
|
1214
|
+
(double*) &(psCShape->padfX [psCShape->panPartStart[ring]]),
|
1215
|
+
(double*) &(psCShape->padfY [psCShape->panPartStart[ring]]) );
|
1216
|
+
|
1217
|
+
ring_vtx = psCShape->panPartStart[ring];
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
#ifdef DEBUG2
|
1221
|
+
printf ("(shpgeo:SHPArea_2d) Area = %f \n", cArea);
|
1222
|
+
#endif
|
1223
|
+
|
1224
|
+
/* Area is signed, negative Areas are R- */
|
1225
|
+
return ( cArea );
|
1226
|
+
|
1227
|
+
}
|
1228
|
+
|
1229
|
+
|
1230
|
+
/* **************************************************************************
|
1231
|
+
* SHPLength_2d
|
1232
|
+
*
|
1233
|
+
* Calculate the Planar ( XY ) Length of Polygon ( can be compound / complex )
|
1234
|
+
* or Polyline ( can be compound ). Length on Polygon is its Perimeter
|
1235
|
+
*
|
1236
|
+
* **************************************************************************/
|
1237
|
+
double SHPLength_2d ( SHPObject *psCShape ) {
|
1238
|
+
double Length;
|
1239
|
+
int i, j;
|
1240
|
+
double dx, dy;
|
1241
|
+
|
1242
|
+
if ( !(SHPDimension (psCShape->nSHPType) & (SHPD_AREA || SHPD_LINE)) )
|
1243
|
+
return ( (double) -1 );
|
1244
|
+
|
1245
|
+
Length = 0;
|
1246
|
+
j = 1;
|
1247
|
+
for ( i = 1; i < psCShape->nVertices; i++ ) {
|
1248
|
+
if ( psCShape->panPartStart[j] == i )
|
1249
|
+
{ j ++; }
|
1250
|
+
/* skip the moves with "pen up" from ring to ring */
|
1251
|
+
else
|
1252
|
+
{
|
1253
|
+
dx = psCShape->padfX[i] - psCShape->padfX[i-1];
|
1254
|
+
dy = psCShape->padfY[i] - psCShape->padfY[i-1];
|
1255
|
+
Length += sqrt ( ( dx * dx ) + ( dy * dy ) );
|
1256
|
+
}
|
1257
|
+
/* simplify this equation */
|
1258
|
+
}
|
1259
|
+
|
1260
|
+
return ( Length );
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
|
1264
|
+
/* **************************************************************************
|
1265
|
+
* RingLength_2d
|
1266
|
+
*
|
1267
|
+
* Calculate the Planar ( XY ) Length of Polygon ( can be compound / complex )
|
1268
|
+
* or Polyline ( can be compound ). Length of Polygon is its Perimeter
|
1269
|
+
*
|
1270
|
+
* **************************************************************************/
|
1271
|
+
double RingLength_2d ( int nVertices, double *a, double *b ) {
|
1272
|
+
double Length;
|
1273
|
+
int i, j;
|
1274
|
+
double dx, dy;
|
1275
|
+
|
1276
|
+
Length = 0;
|
1277
|
+
j = 1;
|
1278
|
+
for ( i = 1; i < nVertices; i++ ) {
|
1279
|
+
dx = a[i] - b[i-1];
|
1280
|
+
dy = b[i] - b[i-1];
|
1281
|
+
Length += sqrt ( ( dx * dx ) + ( dy * dy ) );
|
1282
|
+
/* simplify this equation */
|
1283
|
+
}
|
1284
|
+
|
1285
|
+
return ( Length );
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
|
1289
|
+
/* **************************************************************************
|
1290
|
+
* RingArea_2d
|
1291
|
+
*
|
1292
|
+
* Calculate the Planar Area of a single closed ring
|
1293
|
+
*
|
1294
|
+
* **************************************************************************/
|
1295
|
+
double RingArea_2d ( int nVertices, double *a, double *b ) {
|
1296
|
+
int iv,jv;
|
1297
|
+
double ppx, ppy;
|
1298
|
+
static double Area;
|
1299
|
+
double dx_Area;
|
1300
|
+
double x_base, y_base, x, y;
|
1301
|
+
|
1302
|
+
x_base = a[0];
|
1303
|
+
y_base = b[0];
|
1304
|
+
|
1305
|
+
ppx = a[1] - x_base;
|
1306
|
+
ppy = b[1] - y_base;
|
1307
|
+
Area = 0.0;
|
1308
|
+
#ifdef DEBUG2
|
1309
|
+
printf("(shpgeo:RingArea) %d vertices \n", nVertices);
|
1310
|
+
#endif
|
1311
|
+
for ( iv = 2; iv <= ( nVertices - 1 ); iv++ ) {
|
1312
|
+
x = a[iv] - x_base;
|
1313
|
+
y = b[iv] - y_base;
|
1314
|
+
|
1315
|
+
/* Area of a triangle is the cross product of its defining vectors */
|
1316
|
+
|
1317
|
+
dx_Area = ((x * ppy) - (y * ppx)) * 0.5;
|
1318
|
+
|
1319
|
+
Area += dx_Area;
|
1320
|
+
#ifdef DEBUG2
|
1321
|
+
printf ("(shpgeo:RingArea) dxArea %f sArea %f for pt(%f, %f)\n",
|
1322
|
+
dx_Area, Area, x, y);
|
1323
|
+
#endif
|
1324
|
+
|
1325
|
+
ppx = x;
|
1326
|
+
ppy = y;
|
1327
|
+
}
|
1328
|
+
|
1329
|
+
#ifdef DEBUG2
|
1330
|
+
printf ("(shpgeo:RingArea) total RingArea %f \n", Area);
|
1331
|
+
#endif
|
1332
|
+
return ( Area );
|
1333
|
+
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
|
1337
|
+
|
1338
|
+
/* **************************************************************************
|
1339
|
+
* SHPUnCompound
|
1340
|
+
*
|
1341
|
+
* ESRI calls this function explode
|
1342
|
+
* Return a non compound ( possibly complex ) object
|
1343
|
+
*
|
1344
|
+
* ring_number is R+ number corresponding to object
|
1345
|
+
*
|
1346
|
+
*
|
1347
|
+
* ignore complexity in Z dimension for now
|
1348
|
+
*
|
1349
|
+
* **************************************************************************/
|
1350
|
+
SHPObject* SHPUnCompound ( SHPObject *psCShape, int * ringNumber ) {
|
1351
|
+
int ringDir, ring, lRing;
|
1352
|
+
|
1353
|
+
if ( (*ringNumber >= psCShape->nParts) || *ringNumber == -1 ) {
|
1354
|
+
*ringNumber = -1;
|
1355
|
+
return (NULL);
|
1356
|
+
}
|
1357
|
+
|
1358
|
+
|
1359
|
+
if ( *ringNumber == (psCShape->nParts - 1) ) {
|
1360
|
+
*ringNumber = -1;
|
1361
|
+
return ( SHPClone(psCShape, (psCShape->nParts - 1), -1) );
|
1362
|
+
}
|
1363
|
+
|
1364
|
+
lRing = *ringNumber;
|
1365
|
+
ringDir = -1;
|
1366
|
+
for ( ring = (lRing + 1); (ring < psCShape->nParts) && ( ringDir < 0 ); ring ++)
|
1367
|
+
ringDir = SHPRingDir_2d ( psCShape, ring);
|
1368
|
+
|
1369
|
+
if ( ring == psCShape->nParts )
|
1370
|
+
*ringNumber = -1;
|
1371
|
+
else
|
1372
|
+
*ringNumber = ring;
|
1373
|
+
/* I am strictly assuming that all R- parts of a complex object
|
1374
|
+
* directly follow their R+, so when we hit a new R+ its a
|
1375
|
+
* new part of a compound object
|
1376
|
+
* a SHPClean may be needed to enforce this as it is not part
|
1377
|
+
* of ESRI's definition of a SHPfile
|
1378
|
+
*/
|
1379
|
+
|
1380
|
+
#ifdef DEBUG2
|
1381
|
+
printf ("(SHPUnCompound) asked for ring %d, lastring is %d \n", lRing, ring);
|
1382
|
+
#endif
|
1383
|
+
return ( SHPClone(psCShape, lRing, ring ) );
|
1384
|
+
|
1385
|
+
}
|
1386
|
+
|
1387
|
+
|
1388
|
+
/* **************************************************************************
|
1389
|
+
* SHPIntersect_2d
|
1390
|
+
*
|
1391
|
+
*
|
1392
|
+
* prototype only for now
|
1393
|
+
*
|
1394
|
+
* return object with lowest common dimensionality of objects
|
1395
|
+
*
|
1396
|
+
* **************************************************************************/
|
1397
|
+
SHPObject* SHPIntersect_2d ( SHPObject* a, SHPObject* b ) {
|
1398
|
+
SHPObject *C;
|
1399
|
+
|
1400
|
+
if ( (SHPDimension(a->nSHPType) && SHPD_POINT) || ( SHPDimension(b->nSHPType) && SHPD_POINT ) )
|
1401
|
+
return ( NULL );
|
1402
|
+
/* there is no intersect function like this for points */
|
1403
|
+
|
1404
|
+
C = SHPClone ( a, 0 , -1 );
|
1405
|
+
|
1406
|
+
return ( C);
|
1407
|
+
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
|
1411
|
+
|
1412
|
+
/* **************************************************************************
|
1413
|
+
* SHPClean
|
1414
|
+
*
|
1415
|
+
* Test and fix normalization problems in shapes
|
1416
|
+
* Different tests need to be implemented for different SHPTypes
|
1417
|
+
* SHPT_POLYGON check ring directions CW / CCW ( R+ / R- )
|
1418
|
+
* put all R- after the R+ they are members of
|
1419
|
+
* i.e. each complex object is completed before the
|
1420
|
+
* next object is started
|
1421
|
+
* check for closed rings
|
1422
|
+
* ring must not intersect itself, even on edge
|
1423
|
+
*
|
1424
|
+
* no other types implemented yet
|
1425
|
+
*
|
1426
|
+
* not sure why but return object in place
|
1427
|
+
* use for object casting and object verification
|
1428
|
+
* **************************************************************************/
|
1429
|
+
int SHPClean ( SHPObject *psCShape ) {
|
1430
|
+
|
1431
|
+
|
1432
|
+
return (0);
|
1433
|
+
}
|
1434
|
+
|
1435
|
+
|
1436
|
+
/* **************************************************************************
|
1437
|
+
* SHPClone
|
1438
|
+
*
|
1439
|
+
* Clone a SHPObject, replicating all data
|
1440
|
+
*
|
1441
|
+
* **************************************************************************/
|
1442
|
+
SHPObject* SHPClone ( SHPObject *psCShape, int lowPart, int highPart ) {
|
1443
|
+
SHPObject *psObject;
|
1444
|
+
int newParts, newVertices;
|
1445
|
+
#ifdef DEBUG
|
1446
|
+
int i;
|
1447
|
+
#endif
|
1448
|
+
|
1449
|
+
if ( highPart >= psCShape->nParts || highPart == -1 )
|
1450
|
+
highPart = psCShape->nParts ;
|
1451
|
+
|
1452
|
+
#ifdef DEBUG
|
1453
|
+
printf (" cloning SHP (%d parts) from ring %d upto ring %d \n",
|
1454
|
+
psCShape->nParts, lowPart, highPart);
|
1455
|
+
#endif
|
1456
|
+
|
1457
|
+
newParts = highPart - lowPart;
|
1458
|
+
if ( newParts == 0 ) { return ( NULL ); }
|
1459
|
+
|
1460
|
+
psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
|
1461
|
+
psObject->nSHPType = psCShape->nSHPType;
|
1462
|
+
psObject->nShapeId = psCShape->nShapeId;
|
1463
|
+
|
1464
|
+
psObject->nParts = newParts;
|
1465
|
+
if ( psCShape->padfX ) {
|
1466
|
+
psObject->panPartStart = (int*) calloc (newParts, sizeof (int));
|
1467
|
+
memcpy ( psObject->panPartStart, psCShape->panPartStart,
|
1468
|
+
newParts * sizeof (int) );
|
1469
|
+
}
|
1470
|
+
if ( psCShape->padfX ) {
|
1471
|
+
psObject->panPartType = (int*) calloc (newParts, sizeof (int));
|
1472
|
+
memcpy ( psObject->panPartType,
|
1473
|
+
(int *) &(psCShape->panPartType[lowPart]),
|
1474
|
+
newParts * sizeof (int) );
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
if ( highPart != psCShape->nParts ) {
|
1478
|
+
newVertices = psCShape->panPartStart[highPart] -
|
1479
|
+
psCShape->panPartStart[lowPart];
|
1480
|
+
}
|
1481
|
+
else
|
1482
|
+
{ newVertices = psCShape->nVertices - psCShape->panPartStart[lowPart]; }
|
1483
|
+
|
1484
|
+
|
1485
|
+
#ifdef DEBUG
|
1486
|
+
if ( highPart = psCShape->nParts )
|
1487
|
+
i = psCShape->nVertices;
|
1488
|
+
else
|
1489
|
+
i = psCShape->panPartStart[highPart];
|
1490
|
+
printf (" from part %d (%d) to %d (%d) is %d vertices \n",
|
1491
|
+
lowPart, psCShape->panPartStart[lowPart], highPart,
|
1492
|
+
i, newVertices);
|
1493
|
+
#endif
|
1494
|
+
psObject->nVertices = newVertices;
|
1495
|
+
if ( psCShape->padfX ) {
|
1496
|
+
psObject->padfX = (double*) calloc (newVertices, sizeof (double));
|
1497
|
+
memcpy ( psObject->padfX,
|
1498
|
+
(double *) &(psCShape->padfX[psCShape->panPartStart[lowPart]]),
|
1499
|
+
newVertices * sizeof (double) );
|
1500
|
+
}
|
1501
|
+
if ( psCShape->padfY ) {
|
1502
|
+
psObject->padfY = (double*) calloc (newVertices, sizeof (double));
|
1503
|
+
memcpy ( psObject->padfY,
|
1504
|
+
(double *) &(psCShape->padfY[psCShape->panPartStart[lowPart]]),
|
1505
|
+
newVertices * sizeof (double) );
|
1506
|
+
}
|
1507
|
+
if ( psCShape->padfZ ) {
|
1508
|
+
psObject->padfZ = (double*) calloc (newVertices, sizeof (double));
|
1509
|
+
memcpy ( psObject->padfZ,
|
1510
|
+
(double *) &(psCShape->padfZ[psCShape->panPartStart[lowPart]]),
|
1511
|
+
newVertices * sizeof (double) );
|
1512
|
+
}
|
1513
|
+
if ( psCShape->padfM ) {
|
1514
|
+
psObject->padfM = (double*) calloc (newVertices, sizeof (double));
|
1515
|
+
memcpy ( psObject->padfM,
|
1516
|
+
(double *) &(psCShape->padfM[psCShape->panPartStart[lowPart]]),
|
1517
|
+
newVertices * sizeof (double) );
|
1518
|
+
}
|
1519
|
+
|
1520
|
+
psObject->dfXMin = psCShape->dfXMin;
|
1521
|
+
psObject->dfYMin = psCShape->dfYMin;
|
1522
|
+
psObject->dfZMin = psCShape->dfZMin;
|
1523
|
+
psObject->dfMMin = psCShape->dfMMin;
|
1524
|
+
|
1525
|
+
psObject->dfXMax = psCShape->dfXMax;
|
1526
|
+
psObject->dfYMax = psCShape->dfYMax;
|
1527
|
+
psObject->dfZMax = psCShape->dfZMax;
|
1528
|
+
psObject->dfMMax = psCShape->dfMMax;
|
1529
|
+
|
1530
|
+
SHPComputeExtents ( psObject );
|
1531
|
+
return ( psObject );
|
1532
|
+
}
|
1533
|
+
|
1534
|
+
|
1535
|
+
|
1536
|
+
/************************************************************************/
|
1537
|
+
/* SwapG */
|
1538
|
+
/* */
|
1539
|
+
/* Swap a 2, 4 or 8 byte word. */
|
1540
|
+
/************************************************************************/
|
1541
|
+
void SwapG( void *so, void *in, int this_cnt, int this_size ) {
|
1542
|
+
int i, j;
|
1543
|
+
unsigned char temp;
|
1544
|
+
|
1545
|
+
/* return to a new pointer otherwise it would invalidate existing data */
|
1546
|
+
/* as prevent further use of it */
|
1547
|
+
|
1548
|
+
for( j=0; j < this_cnt; j++ )
|
1549
|
+
{
|
1550
|
+
for( i=0; i < this_size/2; i++ )
|
1551
|
+
{
|
1552
|
+
((unsigned char *) so)[i] = ((unsigned char *) in)[this_size-i-1];
|
1553
|
+
((unsigned char *) so)[this_size-i-1] = ((unsigned char *) in)[i];
|
1554
|
+
}
|
1555
|
+
}
|
1556
|
+
}
|
1557
|
+
|
1558
|
+
|
1559
|
+
/* **************************************************************************
|
1560
|
+
* SwapW
|
1561
|
+
*
|
1562
|
+
* change byte order on an array of 16 bit words
|
1563
|
+
* need to change this over to shapelib, Frank Warmerdam's functions
|
1564
|
+
*
|
1565
|
+
* **************************************************************************/
|
1566
|
+
void swapW (void *so, unsigned char *in, long bytes) {
|
1567
|
+
int i, j;
|
1568
|
+
unsigned char map[4] = {3,2,1,0};
|
1569
|
+
unsigned char *out;
|
1570
|
+
|
1571
|
+
out = so;
|
1572
|
+
for (i=0; i <= (bytes/4); i++)
|
1573
|
+
for (j=0; j < 4; j++)
|
1574
|
+
out[(i*4)+map[j]] = in[(i*4)+j];
|
1575
|
+
}
|
1576
|
+
|
1577
|
+
|
1578
|
+
/* **************************************************************************
|
1579
|
+
* SwapD
|
1580
|
+
*
|
1581
|
+
* change byte order on an array of (double) 32 bit words
|
1582
|
+
* need to change this over to shapelib, Frank Warmerdam's functons
|
1583
|
+
*
|
1584
|
+
* **************************************************************************/
|
1585
|
+
void swapD (void *so, unsigned char *in, long bytes) {
|
1586
|
+
int i, j;
|
1587
|
+
unsigned char map[8] = {7,6,5,4,3,2,1,0};
|
1588
|
+
unsigned char *out;
|
1589
|
+
|
1590
|
+
out = so;
|
1591
|
+
for (i=0; i <= (bytes/8); i++)
|
1592
|
+
for (j=0; j < 8; j++)
|
1593
|
+
out[(i*8)+map[j]] = in[(i*8)+j];
|
1594
|
+
}
|
1595
|
+
|