shp 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|