geo_coder 0.1.0
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.
- data/Gemfile +12 -0
- data/Gemfile.lock +32 -0
- data/History.txt +6 -0
- data/Makefile +13 -0
- data/Manifest.txt +18 -0
- data/README.rdoc +197 -0
- data/Rakefile +53 -0
- data/TODO.txt +8 -0
- data/VERSION +1 -0
- data/bin/build_indexes +8 -0
- data/bin/rebuild_cluster +22 -0
- data/bin/rebuild_metaphones +23 -0
- data/bin/tiger_import +59 -0
- data/demos/demo/app/ext/geocodewrap.rb +84 -0
- data/demos/demo/app/views/index.builder +13 -0
- data/demos/demo/app/views/index.erb +71 -0
- data/demos/demo/config.ru +12 -0
- data/demos/demo/config/bootstraps.rb +130 -0
- data/demos/demo/config/geoenvironment.rb +25 -0
- data/demos/demo/geocoder_helper.rb +12 -0
- data/demos/demo/geocom_geocode.rb +10 -0
- data/demos/demo/main.rb +3 -0
- data/demos/demo/rakefile.rb +17 -0
- data/demos/demo/tmp/restart.txt +0 -0
- data/demos/simpledemo/views/index.builder +13 -0
- data/demos/simpledemo/views/index.erb +69 -0
- data/demos/simpledemo/ws.rb +83 -0
- data/doc/Makefile +7 -0
- data/doc/html4css1.css +279 -0
- data/doc/lookup.rst +193 -0
- data/doc/parsing.rst +125 -0
- data/doc/voidspace.css +147 -0
- data/geo_coder.gemspec +172 -0
- data/lib/geocoder/us.rb +21 -0
- data/lib/geocoder/us/address.rb +290 -0
- data/lib/geocoder/us/constants.rb +670 -0
- data/lib/geocoder/us/database.rb +745 -0
- data/lib/geocoder/us/import.rb +181 -0
- data/lib/geocoder/us/import/tiger.rb +13 -0
- data/lib/geocoder/us/numbers.rb +58 -0
- data/navteq/README +4 -0
- data/navteq/convert.sql +37 -0
- data/navteq/navteq_import +39 -0
- data/navteq/prepare.sql +92 -0
- data/sql/cluster.sql +16 -0
- data/sql/convert.sql +80 -0
- data/sql/create.sql +37 -0
- data/sql/index.sql +12 -0
- data/sql/place.csv +104944 -0
- data/sql/place.sql +104948 -0
- data/sql/setup.sql +78 -0
- data/src/Makefile +13 -0
- data/src/README +14 -0
- data/src/liblwgeom/Makefile +75 -0
- data/src/liblwgeom/box2d.c +54 -0
- data/src/liblwgeom/lex.yy.c +4799 -0
- data/src/liblwgeom/liblwgeom.h +1405 -0
- data/src/liblwgeom/lwalgorithm.c +946 -0
- data/src/liblwgeom/lwalgorithm.h +52 -0
- data/src/liblwgeom/lwcircstring.c +759 -0
- data/src/liblwgeom/lwcollection.c +541 -0
- data/src/liblwgeom/lwcompound.c +118 -0
- data/src/liblwgeom/lwcurvepoly.c +86 -0
- data/src/liblwgeom/lwgeom.c +886 -0
- data/src/liblwgeom/lwgeom_api.c +2201 -0
- data/src/liblwgeom/lwgparse.c +1219 -0
- data/src/liblwgeom/lwgunparse.c +1054 -0
- data/src/liblwgeom/lwline.c +525 -0
- data/src/liblwgeom/lwmcurve.c +125 -0
- data/src/liblwgeom/lwmline.c +137 -0
- data/src/liblwgeom/lwmpoint.c +138 -0
- data/src/liblwgeom/lwmpoly.c +141 -0
- data/src/liblwgeom/lwmsurface.c +129 -0
- data/src/liblwgeom/lwpoint.c +439 -0
- data/src/liblwgeom/lwpoly.c +579 -0
- data/src/liblwgeom/lwsegmentize.c +1047 -0
- data/src/liblwgeom/lwutil.c +369 -0
- data/src/liblwgeom/measures.c +861 -0
- data/src/liblwgeom/postgis_config.h +93 -0
- data/src/liblwgeom/ptarray.c +847 -0
- data/src/liblwgeom/vsprintf.c +179 -0
- data/src/liblwgeom/wktparse.h +126 -0
- data/src/liblwgeom/wktparse.lex +74 -0
- data/src/liblwgeom/wktparse.tab.c +2353 -0
- data/src/liblwgeom/wktparse.tab.h +145 -0
- data/src/liblwgeom/wktparse.y +385 -0
- data/src/libsqlite3_geocoder/Makefile +22 -0
- data/src/libsqlite3_geocoder/Makefile.nix +15 -0
- data/src/libsqlite3_geocoder/Makefile.redhat +15 -0
- data/src/libsqlite3_geocoder/extension.c +121 -0
- data/src/libsqlite3_geocoder/extension.h +13 -0
- data/src/libsqlite3_geocoder/levenshtein.c +42 -0
- data/src/libsqlite3_geocoder/metaphon.c +278 -0
- data/src/libsqlite3_geocoder/util.c +37 -0
- data/src/libsqlite3_geocoder/wkb_compress.c +54 -0
- data/src/metaphone/Makefile +7 -0
- data/src/metaphone/README +49 -0
- data/src/metaphone/extension.c +37 -0
- data/src/metaphone/metaphon.c +251 -0
- data/src/shp2sqlite/Makefile +37 -0
- data/src/shp2sqlite/Makefile.nix +36 -0
- data/src/shp2sqlite/Makefile.redhat +35 -0
- data/src/shp2sqlite/dbfopen.c +1595 -0
- data/src/shp2sqlite/getopt.c +695 -0
- data/src/shp2sqlite/getopt.h +127 -0
- data/src/shp2sqlite/shapefil.h +500 -0
- data/src/shp2sqlite/shp2sqlite.c +1974 -0
- data/src/shp2sqlite/shpopen.c +1894 -0
- data/tests/address.rb +236 -0
- data/tests/benchmark.rb +20 -0
- data/tests/constants.rb +57 -0
- data/tests/data/address-sample.csv +52 -0
- data/tests/data/db-test.csv +57 -0
- data/tests/data/locations.csv +4 -0
- data/tests/database.rb +137 -0
- data/tests/generate.rb +34 -0
- data/tests/numbers.rb +46 -0
- data/tests/run.rb +11 -0
- metadata +237 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
* $Id: lwcompound.c 3639 2009-02-04 00:28:37Z pramsey $
|
|
3
|
+
*
|
|
4
|
+
* PostGIS - Spatial Types for PostgreSQL
|
|
5
|
+
* http://postgis.refractions.net
|
|
6
|
+
* Copyright 2001-2006 Refractions Research Inc.
|
|
7
|
+
*
|
|
8
|
+
* This is free software; you can redistribute and/or modify it under
|
|
9
|
+
* the terms of the GNU General Public Licence. See the COPYING file.
|
|
10
|
+
*
|
|
11
|
+
**********************************************************************/
|
|
12
|
+
|
|
13
|
+
#include <stdio.h>
|
|
14
|
+
#include <stdlib.h>
|
|
15
|
+
#include <string.h>
|
|
16
|
+
#include "liblwgeom.h"
|
|
17
|
+
|
|
18
|
+
LWCOMPOUND *
|
|
19
|
+
lwcompound_deserialize(uchar *serialized)
|
|
20
|
+
{
|
|
21
|
+
LWCOMPOUND *result;
|
|
22
|
+
LWGEOM_INSPECTED *insp;
|
|
23
|
+
int type = lwgeom_getType(serialized[0]);
|
|
24
|
+
int i;
|
|
25
|
+
|
|
26
|
+
if(type != COMPOUNDTYPE)
|
|
27
|
+
{
|
|
28
|
+
lwerror("lwcompound_deserialize called on non compound: %d", type);
|
|
29
|
+
return NULL;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
insp = lwgeom_inspect(serialized);
|
|
33
|
+
|
|
34
|
+
result = lwalloc(sizeof(LWCOMPOUND));
|
|
35
|
+
result->type = insp->type;
|
|
36
|
+
result->SRID = insp->SRID;
|
|
37
|
+
result->ngeoms = insp->ngeometries;
|
|
38
|
+
result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
|
|
39
|
+
|
|
40
|
+
if(lwgeom_hasBBOX(serialized[0]))
|
|
41
|
+
{
|
|
42
|
+
result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
|
|
43
|
+
memcpy(result->bbox, serialized + 1, sizeof(BOX2DFLOAT4));
|
|
44
|
+
}
|
|
45
|
+
else result->bbox = NULL;
|
|
46
|
+
|
|
47
|
+
for(i = 0; i < insp->ngeometries; i++)
|
|
48
|
+
{
|
|
49
|
+
if(lwgeom_getType(insp->sub_geoms[i][0]) == LINETYPE)
|
|
50
|
+
result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]);
|
|
51
|
+
else
|
|
52
|
+
result->geoms[i] = (LWGEOM *)lwcircstring_deserialize(insp->sub_geoms[i]);
|
|
53
|
+
if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type))
|
|
54
|
+
{
|
|
55
|
+
lwerror("Mixed dimensions (compound: %d, line/circularstring %d:%d)",
|
|
56
|
+
TYPE_NDIMS(result->type), i,
|
|
57
|
+
TYPE_NDIMS(result->geoms[i]->type)
|
|
58
|
+
);
|
|
59
|
+
lwfree(result);
|
|
60
|
+
return NULL;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/*
|
|
67
|
+
* Add 'what' to this string at position 'where'
|
|
68
|
+
* where=0 == prepend
|
|
69
|
+
* where=-1 == append
|
|
70
|
+
* Returns a COMPOUND or a GEOMETRYCOLLECTION
|
|
71
|
+
*/
|
|
72
|
+
LWGEOM *
|
|
73
|
+
lwcompound_add(const LWCOMPOUND *to, uint32 where, const LWGEOM *what)
|
|
74
|
+
{
|
|
75
|
+
LWCOLLECTION *col;
|
|
76
|
+
LWGEOM **geoms;
|
|
77
|
+
int newtype;
|
|
78
|
+
|
|
79
|
+
LWDEBUG(2, "lwcompound_add called.");
|
|
80
|
+
|
|
81
|
+
if(where != -1 && where != 0)
|
|
82
|
+
{
|
|
83
|
+
lwerror("lwcompound_add only supports 0 or -1 as a second argument, not %d", where);
|
|
84
|
+
return NULL;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* dimensions compatibility are checked by caller */
|
|
88
|
+
|
|
89
|
+
/* Construct geoms array */
|
|
90
|
+
geoms = lwalloc(sizeof(LWGEOM *)*2);
|
|
91
|
+
if(where == -1) /* append */
|
|
92
|
+
{
|
|
93
|
+
geoms[0] = lwgeom_clone((LWGEOM *)to);
|
|
94
|
+
geoms[1] = lwgeom_clone(what);
|
|
95
|
+
}
|
|
96
|
+
else /* prepend */
|
|
97
|
+
{
|
|
98
|
+
geoms[0] = lwgeom_clone(what);
|
|
99
|
+
geoms[1] = lwgeom_clone((LWGEOM *)to);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* reset SRID and wantbbox flag from component types */
|
|
103
|
+
geoms[0]->SRID = geoms[1]->SRID = -1;
|
|
104
|
+
TYPE_SETHASSRID(geoms[0]->type, 0);
|
|
105
|
+
TYPE_SETHASSRID(geoms[1]->type, 0);
|
|
106
|
+
TYPE_SETHASBBOX(geoms[0]->type, 0);
|
|
107
|
+
TYPE_SETHASBBOX(geoms[1]->type, 0);
|
|
108
|
+
|
|
109
|
+
/* Find appropriate geom type */
|
|
110
|
+
if(TYPE_GETTYPE(what->type) == LINETYPE || TYPE_GETTYPE(what->type) == CIRCSTRINGTYPE) newtype = COMPOUNDTYPE;
|
|
111
|
+
else newtype = COLLECTIONTYPE;
|
|
112
|
+
|
|
113
|
+
col = lwcollection_construct(newtype,
|
|
114
|
+
to->SRID, NULL, 2, geoms);
|
|
115
|
+
|
|
116
|
+
return (LWGEOM *)col;
|
|
117
|
+
}
|
|
118
|
+
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
* $Id: lwcurvepoly.c 3639 2009-02-04 00:28:37Z pramsey $
|
|
3
|
+
*
|
|
4
|
+
* PostGIS - Spatial Types for PostgreSQL
|
|
5
|
+
* http://postgis.refractions.net
|
|
6
|
+
* Copyright 2001-2006 Refractions Research Inc.
|
|
7
|
+
*
|
|
8
|
+
* This is free software; you can redistribute and/or modify it under
|
|
9
|
+
* the terms of the GNU General Public Licence. See the COPYING file.
|
|
10
|
+
*
|
|
11
|
+
**********************************************************************/
|
|
12
|
+
|
|
13
|
+
/* basic LWCURVEPOLY manipulation */
|
|
14
|
+
|
|
15
|
+
#include <stdio.h>
|
|
16
|
+
#include <stdlib.h>
|
|
17
|
+
#include <string.h>
|
|
18
|
+
#include "liblwgeom.h"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
LWCURVEPOLY *
|
|
22
|
+
lwcurvepoly_deserialize(uchar *srl)
|
|
23
|
+
{
|
|
24
|
+
LWCURVEPOLY *result;
|
|
25
|
+
LWGEOM_INSPECTED *insp;
|
|
26
|
+
int type = lwgeom_getType(srl[0]);
|
|
27
|
+
int i;
|
|
28
|
+
|
|
29
|
+
LWDEBUG(3, "lwcurvepoly_deserialize called.");
|
|
30
|
+
|
|
31
|
+
if(type != CURVEPOLYTYPE)
|
|
32
|
+
{
|
|
33
|
+
lwerror("lwcurvepoly_deserialize called on NON curvepoly: %d",
|
|
34
|
+
type);
|
|
35
|
+
return NULL;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
insp = lwgeom_inspect(srl);
|
|
39
|
+
|
|
40
|
+
result = lwalloc(sizeof(LWCURVEPOLY));
|
|
41
|
+
result->type = insp->type;
|
|
42
|
+
result->SRID = insp->SRID;
|
|
43
|
+
result->nrings = insp->ngeometries;
|
|
44
|
+
result->rings = lwalloc(sizeof(LWGEOM *)*insp->ngeometries);
|
|
45
|
+
|
|
46
|
+
if(lwgeom_hasBBOX(srl[0]))
|
|
47
|
+
{
|
|
48
|
+
result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
|
|
49
|
+
memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4));
|
|
50
|
+
}
|
|
51
|
+
else result->bbox = NULL;
|
|
52
|
+
|
|
53
|
+
for(i = 0; i < insp->ngeometries; i++)
|
|
54
|
+
{
|
|
55
|
+
result->rings[i] = lwgeom_deserialize(insp->sub_geoms[i]);
|
|
56
|
+
if(lwgeom_getType(result->rings[i]->type) != CIRCSTRINGTYPE
|
|
57
|
+
&& lwgeom_getType(result->rings[i]->type) != LINETYPE)
|
|
58
|
+
{
|
|
59
|
+
lwerror("Only Circularstrings and Linestrings are currently supported as rings, not %s (%d)", lwgeom_typename(result->rings[i]->type), result->rings[i]->type);
|
|
60
|
+
lwfree(result);
|
|
61
|
+
lwfree(insp);
|
|
62
|
+
return NULL;
|
|
63
|
+
}
|
|
64
|
+
if(TYPE_NDIMS(result->rings[i]->type) != TYPE_NDIMS(result->type))
|
|
65
|
+
{
|
|
66
|
+
lwerror("Mixed dimensions (curvepoly %d, ring %d)",
|
|
67
|
+
TYPE_NDIMS(result->type), i,
|
|
68
|
+
TYPE_NDIMS(result->rings[i]->type));
|
|
69
|
+
lwfree(result);
|
|
70
|
+
lwfree(insp);
|
|
71
|
+
return NULL;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
LWGEOM *
|
|
78
|
+
lwcurvepoly_add(const LWCURVEPOLY *to, uint32 where, const LWGEOM *what)
|
|
79
|
+
{
|
|
80
|
+
/* TODO */
|
|
81
|
+
lwerror("lwcurvepoly_add not yet implemented.");
|
|
82
|
+
return NULL;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
@@ -0,0 +1,886 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
* $Id: lwgeom.c 3812 2009-03-09 14:36:15Z pramsey $
|
|
3
|
+
*
|
|
4
|
+
* PostGIS - Spatial Types for PostgreSQL
|
|
5
|
+
* http://postgis.refractions.net
|
|
6
|
+
* Copyright 2001-2006 Refractions Research Inc.
|
|
7
|
+
*
|
|
8
|
+
* This is free software; you can redistribute and/or modify it under
|
|
9
|
+
* the terms of the GNU General Public Licence. See the COPYING file.
|
|
10
|
+
*
|
|
11
|
+
**********************************************************************/
|
|
12
|
+
|
|
13
|
+
#include <stdio.h>
|
|
14
|
+
#include <stdlib.h>
|
|
15
|
+
#include <stdarg.h>
|
|
16
|
+
|
|
17
|
+
#include "liblwgeom.h"
|
|
18
|
+
#include "wktparse.h"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
LWGEOM *
|
|
22
|
+
lwgeom_deserialize(uchar *srl)
|
|
23
|
+
{
|
|
24
|
+
int type = lwgeom_getType(srl[0]);
|
|
25
|
+
|
|
26
|
+
LWDEBUGF(2, "lwgeom_deserialize got %d - %s", type, lwgeom_typename(type));
|
|
27
|
+
|
|
28
|
+
switch (type)
|
|
29
|
+
{
|
|
30
|
+
case POINTTYPE:
|
|
31
|
+
return (LWGEOM *)lwpoint_deserialize(srl);
|
|
32
|
+
case LINETYPE:
|
|
33
|
+
return (LWGEOM *)lwline_deserialize(srl);
|
|
34
|
+
case CIRCSTRINGTYPE:
|
|
35
|
+
return (LWGEOM *)lwcircstring_deserialize(srl);
|
|
36
|
+
case POLYGONTYPE:
|
|
37
|
+
return (LWGEOM *)lwpoly_deserialize(srl);
|
|
38
|
+
case MULTIPOINTTYPE:
|
|
39
|
+
return (LWGEOM *)lwmpoint_deserialize(srl);
|
|
40
|
+
case MULTILINETYPE:
|
|
41
|
+
return (LWGEOM *)lwmline_deserialize(srl);
|
|
42
|
+
case MULTIPOLYGONTYPE:
|
|
43
|
+
return (LWGEOM *)lwmpoly_deserialize(srl);
|
|
44
|
+
case COLLECTIONTYPE:
|
|
45
|
+
return (LWGEOM *)lwcollection_deserialize(srl);
|
|
46
|
+
case COMPOUNDTYPE:
|
|
47
|
+
return (LWGEOM *)lwcompound_deserialize(srl);
|
|
48
|
+
case CURVEPOLYTYPE:
|
|
49
|
+
return (LWGEOM *)lwcurvepoly_deserialize(srl);
|
|
50
|
+
case MULTICURVETYPE:
|
|
51
|
+
return (LWGEOM *)lwmcurve_deserialize(srl);
|
|
52
|
+
case MULTISURFACETYPE:
|
|
53
|
+
return (LWGEOM *)lwmsurface_deserialize(srl);
|
|
54
|
+
default:
|
|
55
|
+
lwerror("Unknown geometry type: %d", type);
|
|
56
|
+
|
|
57
|
+
return NULL;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
size_t
|
|
63
|
+
lwgeom_serialize_size(LWGEOM *lwgeom)
|
|
64
|
+
{
|
|
65
|
+
int type = TYPE_GETTYPE(lwgeom->type);
|
|
66
|
+
|
|
67
|
+
LWDEBUGF(2, "lwgeom_serialize_size(%s) called", lwgeom_typename(type));
|
|
68
|
+
|
|
69
|
+
switch (type)
|
|
70
|
+
{
|
|
71
|
+
case POINTTYPE:
|
|
72
|
+
return lwpoint_serialize_size((LWPOINT *)lwgeom);
|
|
73
|
+
case LINETYPE:
|
|
74
|
+
return lwline_serialize_size((LWLINE *)lwgeom);
|
|
75
|
+
case POLYGONTYPE:
|
|
76
|
+
return lwpoly_serialize_size((LWPOLY *)lwgeom);
|
|
77
|
+
case CIRCSTRINGTYPE:
|
|
78
|
+
return lwcircstring_serialize_size((LWCIRCSTRING *)lwgeom);
|
|
79
|
+
case CURVEPOLYTYPE:
|
|
80
|
+
case COMPOUNDTYPE:
|
|
81
|
+
case MULTIPOINTTYPE:
|
|
82
|
+
case MULTILINETYPE:
|
|
83
|
+
case MULTICURVETYPE:
|
|
84
|
+
case MULTIPOLYGONTYPE:
|
|
85
|
+
case MULTISURFACETYPE:
|
|
86
|
+
case COLLECTIONTYPE:
|
|
87
|
+
return lwcollection_serialize_size((LWCOLLECTION *)lwgeom);
|
|
88
|
+
default:
|
|
89
|
+
lwerror("Unknown geometry type: %d", type);
|
|
90
|
+
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void
|
|
96
|
+
lwgeom_serialize_buf(LWGEOM *lwgeom, uchar *buf, size_t *retsize)
|
|
97
|
+
{
|
|
98
|
+
int type = TYPE_GETTYPE(lwgeom->type);
|
|
99
|
+
|
|
100
|
+
LWDEBUGF(2, "lwgeom_serialize_buf called with a %s",
|
|
101
|
+
lwgeom_typename(type));
|
|
102
|
+
|
|
103
|
+
switch (type)
|
|
104
|
+
{
|
|
105
|
+
case POINTTYPE:
|
|
106
|
+
lwpoint_serialize_buf((LWPOINT *)lwgeom, buf, retsize);
|
|
107
|
+
break;
|
|
108
|
+
case LINETYPE:
|
|
109
|
+
lwline_serialize_buf((LWLINE *)lwgeom, buf, retsize);
|
|
110
|
+
break;
|
|
111
|
+
case POLYGONTYPE:
|
|
112
|
+
lwpoly_serialize_buf((LWPOLY *)lwgeom, buf, retsize);
|
|
113
|
+
break;
|
|
114
|
+
case CIRCSTRINGTYPE:
|
|
115
|
+
lwcircstring_serialize_buf((LWCIRCSTRING *)lwgeom, buf, retsize);
|
|
116
|
+
break;
|
|
117
|
+
case CURVEPOLYTYPE:
|
|
118
|
+
case COMPOUNDTYPE:
|
|
119
|
+
case MULTIPOINTTYPE:
|
|
120
|
+
case MULTILINETYPE:
|
|
121
|
+
case MULTICURVETYPE:
|
|
122
|
+
case MULTIPOLYGONTYPE:
|
|
123
|
+
case MULTISURFACETYPE:
|
|
124
|
+
case COLLECTIONTYPE:
|
|
125
|
+
lwcollection_serialize_buf((LWCOLLECTION *)lwgeom, buf,
|
|
126
|
+
retsize);
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
lwerror("Unknown geometry type: %d", type);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
uchar *
|
|
136
|
+
lwgeom_serialize(LWGEOM *lwgeom)
|
|
137
|
+
{
|
|
138
|
+
size_t size = lwgeom_serialize_size(lwgeom);
|
|
139
|
+
size_t retsize;
|
|
140
|
+
uchar *serialized = lwalloc(size);
|
|
141
|
+
|
|
142
|
+
lwgeom_serialize_buf(lwgeom, serialized, &retsize);
|
|
143
|
+
|
|
144
|
+
#if POSTGIS_DEBUG_LEVEL > 0
|
|
145
|
+
if ( retsize != size )
|
|
146
|
+
{
|
|
147
|
+
lwerror("lwgeom_serialize: computed size %d, returned size %d",
|
|
148
|
+
size, retsize);
|
|
149
|
+
}
|
|
150
|
+
#endif
|
|
151
|
+
|
|
152
|
+
return serialized;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* Force Right-hand-rule on LWGEOM polygons */
|
|
156
|
+
void
|
|
157
|
+
lwgeom_forceRHR(LWGEOM *lwgeom)
|
|
158
|
+
{
|
|
159
|
+
LWCOLLECTION *coll;
|
|
160
|
+
int i;
|
|
161
|
+
|
|
162
|
+
switch (TYPE_GETTYPE(lwgeom->type))
|
|
163
|
+
{
|
|
164
|
+
case POLYGONTYPE:
|
|
165
|
+
lwpoly_forceRHR((LWPOLY *)lwgeom);
|
|
166
|
+
return;
|
|
167
|
+
|
|
168
|
+
case MULTIPOLYGONTYPE:
|
|
169
|
+
case COLLECTIONTYPE:
|
|
170
|
+
coll = (LWCOLLECTION *)lwgeom;
|
|
171
|
+
for (i=0; i<coll->ngeoms; i++)
|
|
172
|
+
lwgeom_forceRHR(coll->geoms[i]);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Reverse vertex order of LWGEOM */
|
|
178
|
+
void
|
|
179
|
+
lwgeom_reverse(LWGEOM *lwgeom)
|
|
180
|
+
{
|
|
181
|
+
int i;
|
|
182
|
+
LWCOLLECTION *col;
|
|
183
|
+
|
|
184
|
+
switch (TYPE_GETTYPE(lwgeom->type))
|
|
185
|
+
{
|
|
186
|
+
case LINETYPE:
|
|
187
|
+
lwline_reverse((LWLINE *)lwgeom);
|
|
188
|
+
return;
|
|
189
|
+
case POLYGONTYPE:
|
|
190
|
+
lwpoly_reverse((LWPOLY *)lwgeom);
|
|
191
|
+
return;
|
|
192
|
+
case MULTILINETYPE:
|
|
193
|
+
case MULTIPOLYGONTYPE:
|
|
194
|
+
case COLLECTIONTYPE:
|
|
195
|
+
col = (LWCOLLECTION *)lwgeom;
|
|
196
|
+
for (i=0; i<col->ngeoms; i++)
|
|
197
|
+
lwgeom_reverse(col->geoms[i]);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
BOX3D *lwgeom_compute_box3d(const LWGEOM *lwgeom)
|
|
203
|
+
{
|
|
204
|
+
if( ! lwgeom ) return NULL;
|
|
205
|
+
|
|
206
|
+
switch(TYPE_GETTYPE(lwgeom->type))
|
|
207
|
+
{
|
|
208
|
+
case POINTTYPE:
|
|
209
|
+
return lwpoint_compute_box3d((LWPOINT *)lwgeom);
|
|
210
|
+
case LINETYPE:
|
|
211
|
+
return lwline_compute_box3d((LWLINE *)lwgeom);
|
|
212
|
+
case CIRCSTRINGTYPE:
|
|
213
|
+
return lwcircstring_compute_box3d((LWCIRCSTRING *)lwgeom);
|
|
214
|
+
case POLYGONTYPE:
|
|
215
|
+
return lwpoly_compute_box3d((LWPOLY *)lwgeom);
|
|
216
|
+
case COMPOUNDTYPE:
|
|
217
|
+
case CURVEPOLYTYPE:
|
|
218
|
+
case MULTIPOINTTYPE:
|
|
219
|
+
case MULTILINETYPE:
|
|
220
|
+
case MULTICURVETYPE:
|
|
221
|
+
case MULTIPOLYGONTYPE:
|
|
222
|
+
case MULTISURFACETYPE:
|
|
223
|
+
case COLLECTIONTYPE:
|
|
224
|
+
return lwcollection_compute_box3d((LWCOLLECTION *)lwgeom);
|
|
225
|
+
}
|
|
226
|
+
/* Never get here, please. */
|
|
227
|
+
return NULL;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
int
|
|
231
|
+
lwgeom_compute_box2d_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf)
|
|
232
|
+
{
|
|
233
|
+
LWDEBUGF(2, "lwgeom_compute_box2d_p called of %p of type %d.", lwgeom, TYPE_GETTYPE(lwgeom->type));
|
|
234
|
+
|
|
235
|
+
switch(TYPE_GETTYPE(lwgeom->type))
|
|
236
|
+
{
|
|
237
|
+
case POINTTYPE:
|
|
238
|
+
return lwpoint_compute_box2d_p((LWPOINT *)lwgeom, buf);
|
|
239
|
+
case LINETYPE:
|
|
240
|
+
return lwline_compute_box2d_p((LWLINE *)lwgeom, buf);
|
|
241
|
+
case CIRCSTRINGTYPE:
|
|
242
|
+
return lwcircstring_compute_box2d_p((LWCIRCSTRING *)lwgeom, buf);
|
|
243
|
+
case POLYGONTYPE:
|
|
244
|
+
return lwpoly_compute_box2d_p((LWPOLY *)lwgeom, buf);
|
|
245
|
+
case COMPOUNDTYPE:
|
|
246
|
+
case CURVEPOLYTYPE:
|
|
247
|
+
case MULTIPOINTTYPE:
|
|
248
|
+
case MULTILINETYPE:
|
|
249
|
+
case MULTICURVETYPE:
|
|
250
|
+
case MULTIPOLYGONTYPE:
|
|
251
|
+
case MULTISURFACETYPE:
|
|
252
|
+
case COLLECTIONTYPE:
|
|
253
|
+
return lwcollection_compute_box2d_p((LWCOLLECTION *)lwgeom, buf);
|
|
254
|
+
}
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/*
|
|
259
|
+
* dont forget to lwfree() result
|
|
260
|
+
*/
|
|
261
|
+
BOX2DFLOAT4 *
|
|
262
|
+
lwgeom_compute_box2d(LWGEOM *lwgeom)
|
|
263
|
+
{
|
|
264
|
+
BOX2DFLOAT4 *result = lwalloc(sizeof(BOX2DFLOAT4));
|
|
265
|
+
if ( lwgeom_compute_box2d_p(lwgeom, result) ) return result;
|
|
266
|
+
else {
|
|
267
|
+
lwfree(result);
|
|
268
|
+
return NULL;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
LWPOINT *
|
|
273
|
+
lwgeom_as_lwpoint(LWGEOM *lwgeom)
|
|
274
|
+
{
|
|
275
|
+
if ( TYPE_GETTYPE(lwgeom->type) == POINTTYPE )
|
|
276
|
+
return (LWPOINT *)lwgeom;
|
|
277
|
+
else return NULL;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
LWLINE *
|
|
281
|
+
lwgeom_as_lwline(LWGEOM *lwgeom)
|
|
282
|
+
{
|
|
283
|
+
if ( TYPE_GETTYPE(lwgeom->type) == LINETYPE )
|
|
284
|
+
return (LWLINE *)lwgeom;
|
|
285
|
+
else return NULL;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
LWCIRCSTRING *
|
|
289
|
+
lwgeom_as_lwcircstring(LWGEOM *lwgeom)
|
|
290
|
+
{
|
|
291
|
+
if( TYPE_GETTYPE(lwgeom->type) == CIRCSTRINGTYPE )
|
|
292
|
+
return (LWCIRCSTRING *)lwgeom;
|
|
293
|
+
else return NULL;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
LWPOLY *
|
|
297
|
+
lwgeom_as_lwpoly(LWGEOM *lwgeom)
|
|
298
|
+
{
|
|
299
|
+
if ( TYPE_GETTYPE(lwgeom->type) == POLYGONTYPE )
|
|
300
|
+
return (LWPOLY *)lwgeom;
|
|
301
|
+
else return NULL;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
LWCOLLECTION *
|
|
305
|
+
lwgeom_as_lwcollection(LWGEOM *lwgeom)
|
|
306
|
+
{
|
|
307
|
+
if ( TYPE_GETTYPE(lwgeom->type) >= MULTIPOINTTYPE
|
|
308
|
+
&& TYPE_GETTYPE(lwgeom->type) <= COLLECTIONTYPE)
|
|
309
|
+
return (LWCOLLECTION *)lwgeom;
|
|
310
|
+
else return NULL;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
LWMPOINT *
|
|
314
|
+
lwgeom_as_lwmpoint(LWGEOM *lwgeom)
|
|
315
|
+
{
|
|
316
|
+
if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOINTTYPE )
|
|
317
|
+
return (LWMPOINT *)lwgeom;
|
|
318
|
+
else return NULL;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
LWMLINE *
|
|
322
|
+
lwgeom_as_lwmline(LWGEOM *lwgeom)
|
|
323
|
+
{
|
|
324
|
+
if ( TYPE_GETTYPE(lwgeom->type) == MULTILINETYPE )
|
|
325
|
+
return (LWMLINE *)lwgeom;
|
|
326
|
+
else return NULL;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
LWMPOLY *
|
|
330
|
+
lwgeom_as_lwmpoly(LWGEOM *lwgeom)
|
|
331
|
+
{
|
|
332
|
+
if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOLYGONTYPE )
|
|
333
|
+
return (LWMPOLY *)lwgeom;
|
|
334
|
+
else return NULL;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj) { return (LWGEOM *)obj; }
|
|
338
|
+
LWGEOM *lwmline_as_lwgeom(LWMLINE *obj) { return (LWGEOM *)obj; }
|
|
339
|
+
LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj) { return (LWGEOM *)obj; }
|
|
340
|
+
LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj) { return (LWGEOM *)obj; }
|
|
341
|
+
LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj) { return (LWGEOM *)obj; }
|
|
342
|
+
LWGEOM *lwline_as_lwgeom(LWLINE *obj) { return (LWGEOM *)obj; }
|
|
343
|
+
LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj) { return (LWGEOM *)obj; }
|
|
344
|
+
|
|
345
|
+
void
|
|
346
|
+
lwgeom_release(LWGEOM *lwgeom)
|
|
347
|
+
{
|
|
348
|
+
uint32 i;
|
|
349
|
+
LWCOLLECTION *col;
|
|
350
|
+
|
|
351
|
+
#ifdef INTEGRITY_CHECKS
|
|
352
|
+
if ( ! lwgeom )
|
|
353
|
+
lwerror("lwgeom_release: someone called on 0x0");
|
|
354
|
+
#endif
|
|
355
|
+
|
|
356
|
+
/* Drop bounding box (always a copy) */
|
|
357
|
+
if ( lwgeom->bbox ) {
|
|
358
|
+
LWDEBUG(3, "lwgeom_release: releasing bbox.");
|
|
359
|
+
|
|
360
|
+
lwfree(lwgeom->bbox);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* Collection */
|
|
364
|
+
if ( (col=lwgeom_as_lwcollection(lwgeom)) )
|
|
365
|
+
{
|
|
366
|
+
LWDEBUG(3, "lwgeom_release: Releasing collection.");
|
|
367
|
+
|
|
368
|
+
for (i=0; i<col->ngeoms; i++)
|
|
369
|
+
{
|
|
370
|
+
lwgeom_release(col->geoms[i]);
|
|
371
|
+
}
|
|
372
|
+
lwfree(lwgeom);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* Single element */
|
|
376
|
+
else lwfree(lwgeom);
|
|
377
|
+
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
/* Clone an LWGEOM object. POINTARRAY are not copied. */
|
|
382
|
+
LWGEOM *
|
|
383
|
+
lwgeom_clone(const LWGEOM *lwgeom)
|
|
384
|
+
{
|
|
385
|
+
LWDEBUGF(2, "lwgeom_clone called with %p, %d", lwgeom, TYPE_GETTYPE(lwgeom->type));
|
|
386
|
+
|
|
387
|
+
switch(TYPE_GETTYPE(lwgeom->type))
|
|
388
|
+
{
|
|
389
|
+
case POINTTYPE:
|
|
390
|
+
return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
|
|
391
|
+
case LINETYPE:
|
|
392
|
+
return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
|
|
393
|
+
case CIRCSTRINGTYPE:
|
|
394
|
+
return (LWGEOM *)lwcircstring_clone((LWCIRCSTRING *)lwgeom);
|
|
395
|
+
case POLYGONTYPE:
|
|
396
|
+
return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
|
|
397
|
+
case COMPOUNDTYPE:
|
|
398
|
+
case CURVEPOLYTYPE:
|
|
399
|
+
case MULTIPOINTTYPE:
|
|
400
|
+
case MULTILINETYPE:
|
|
401
|
+
case MULTICURVETYPE:
|
|
402
|
+
case MULTIPOLYGONTYPE:
|
|
403
|
+
case MULTISURFACETYPE:
|
|
404
|
+
case COLLECTIONTYPE:
|
|
405
|
+
return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
|
|
406
|
+
default:
|
|
407
|
+
return NULL;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/*
|
|
412
|
+
* Add 'what' to 'to' at position 'where'
|
|
413
|
+
*
|
|
414
|
+
* where=0 == prepend
|
|
415
|
+
* where=-1 == append
|
|
416
|
+
* Appended-to LWGEOM gets a new type based on new condition.
|
|
417
|
+
* Mix of dimensions is not allowed (TODO: allow it?).
|
|
418
|
+
*/
|
|
419
|
+
LWGEOM *
|
|
420
|
+
lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what)
|
|
421
|
+
{
|
|
422
|
+
if ( TYPE_NDIMS(what->type) != TYPE_NDIMS(to->type) )
|
|
423
|
+
{
|
|
424
|
+
lwerror("lwgeom_add: mixed dimensions not supported");
|
|
425
|
+
return NULL;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
LWDEBUGF(2, "lwgeom_add(%s, %d, %s) called",
|
|
429
|
+
lwgeom_typename(TYPE_GETTYPE(to->type)),
|
|
430
|
+
where,
|
|
431
|
+
lwgeom_typename(TYPE_GETTYPE(what->type)));
|
|
432
|
+
|
|
433
|
+
switch(TYPE_GETTYPE(to->type))
|
|
434
|
+
{
|
|
435
|
+
case POINTTYPE:
|
|
436
|
+
return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what);
|
|
437
|
+
case LINETYPE:
|
|
438
|
+
return (LWGEOM *)lwline_add((const LWLINE *)to, where, what);
|
|
439
|
+
|
|
440
|
+
case CIRCSTRINGTYPE:
|
|
441
|
+
return (LWGEOM *)lwcircstring_add((const LWCIRCSTRING *)to, where, what);
|
|
442
|
+
|
|
443
|
+
case POLYGONTYPE:
|
|
444
|
+
return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what);
|
|
445
|
+
|
|
446
|
+
case COMPOUNDTYPE:
|
|
447
|
+
return (LWGEOM *)lwcompound_add((const LWCOMPOUND *)to, where, what);
|
|
448
|
+
|
|
449
|
+
case CURVEPOLYTYPE:
|
|
450
|
+
return (LWGEOM *)lwcurvepoly_add((const LWCURVEPOLY *)to, where, what);
|
|
451
|
+
|
|
452
|
+
case MULTIPOINTTYPE:
|
|
453
|
+
return (LWGEOM *)lwmpoint_add((const LWMPOINT *)to,
|
|
454
|
+
where, what);
|
|
455
|
+
|
|
456
|
+
case MULTILINETYPE:
|
|
457
|
+
return (LWGEOM *)lwmline_add((const LWMLINE *)to,
|
|
458
|
+
where, what);
|
|
459
|
+
|
|
460
|
+
case MULTICURVETYPE:
|
|
461
|
+
return (LWGEOM *)lwmcurve_add((const LWMCURVE *)to,
|
|
462
|
+
where, what);
|
|
463
|
+
|
|
464
|
+
case MULTIPOLYGONTYPE:
|
|
465
|
+
return (LWGEOM *)lwmpoly_add((const LWMPOLY *)to,
|
|
466
|
+
where, what);
|
|
467
|
+
|
|
468
|
+
case MULTISURFACETYPE:
|
|
469
|
+
return (LWGEOM *)lwmsurface_add((const LWMSURFACE *)to,
|
|
470
|
+
where, what);
|
|
471
|
+
|
|
472
|
+
case COLLECTIONTYPE:
|
|
473
|
+
return (LWGEOM *)lwcollection_add(
|
|
474
|
+
(const LWCOLLECTION *)to, where, what);
|
|
475
|
+
|
|
476
|
+
default:
|
|
477
|
+
lwerror("lwgeom_add: unknown geometry type: %d",
|
|
478
|
+
TYPE_GETTYPE(to->type));
|
|
479
|
+
return NULL;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
/*
|
|
485
|
+
* Return an alloced string
|
|
486
|
+
*/
|
|
487
|
+
char *
|
|
488
|
+
lwgeom_to_ewkt(LWGEOM *lwgeom, int flags)
|
|
489
|
+
{
|
|
490
|
+
LWGEOM_UNPARSER_RESULT lwg_unparser_result;
|
|
491
|
+
uchar *serialized = lwgeom_serialize(lwgeom);
|
|
492
|
+
int result;
|
|
493
|
+
|
|
494
|
+
if ( ! serialized ) {
|
|
495
|
+
lwerror("Error serializing geom %p", lwgeom);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
result = unparse_WKT(&lwg_unparser_result, serialized, lwalloc, lwfree, flags);
|
|
499
|
+
lwfree(serialized);
|
|
500
|
+
|
|
501
|
+
return lwg_unparser_result.wkoutput;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/*
|
|
505
|
+
* Return an alloced string
|
|
506
|
+
*/
|
|
507
|
+
char *
|
|
508
|
+
lwgeom_to_hexwkb(LWGEOM *lwgeom, int flags, unsigned int byteorder)
|
|
509
|
+
{
|
|
510
|
+
LWGEOM_UNPARSER_RESULT lwg_unparser_result;
|
|
511
|
+
uchar *serialized = lwgeom_serialize(lwgeom);
|
|
512
|
+
int result;
|
|
513
|
+
|
|
514
|
+
result = unparse_WKB(&lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder,1);
|
|
515
|
+
|
|
516
|
+
lwfree(serialized);
|
|
517
|
+
return lwg_unparser_result.wkoutput;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/*
|
|
521
|
+
* Return an alloced string
|
|
522
|
+
*/
|
|
523
|
+
uchar *
|
|
524
|
+
lwgeom_to_ewkb(LWGEOM *lwgeom, int flags, char byteorder, size_t *outsize)
|
|
525
|
+
{
|
|
526
|
+
LWGEOM_UNPARSER_RESULT lwg_unparser_result;
|
|
527
|
+
uchar *serialized = lwgeom_serialize(lwgeom);
|
|
528
|
+
int result;
|
|
529
|
+
|
|
530
|
+
/*
|
|
531
|
+
* We cast return to "unsigned" char as we are
|
|
532
|
+
* requesting a "binary" output, not HEX
|
|
533
|
+
* (last argument set to 0)
|
|
534
|
+
*/
|
|
535
|
+
result = unparse_WKB(&lwg_unparser_result, serialized, lwalloc, lwfree,
|
|
536
|
+
flags, byteorder, 0);
|
|
537
|
+
lwfree(serialized);
|
|
538
|
+
return (uchar *)lwg_unparser_result.wkoutput;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/*
|
|
542
|
+
* Make an LWGEOM object from a EWKB binary representation.
|
|
543
|
+
* Currently highly unoptimized as it:
|
|
544
|
+
* - convert EWKB to HEXEWKB
|
|
545
|
+
* - construct PG_LWGEOM
|
|
546
|
+
* - deserialize it
|
|
547
|
+
*/
|
|
548
|
+
LWGEOM *
|
|
549
|
+
lwgeom_from_ewkb(uchar *ewkb, int flags, size_t size)
|
|
550
|
+
{
|
|
551
|
+
size_t hexewkblen = size*2;
|
|
552
|
+
char *hexewkb;
|
|
553
|
+
long int i;
|
|
554
|
+
int result;
|
|
555
|
+
LWGEOM *ret;
|
|
556
|
+
LWGEOM_PARSER_RESULT lwg_parser_result;
|
|
557
|
+
|
|
558
|
+
/* "HEXify" the EWKB */
|
|
559
|
+
hexewkb = lwalloc(hexewkblen+1);
|
|
560
|
+
for (i=0; i<size; ++i) deparse_hex(ewkb[i], &hexewkb[i*2]);
|
|
561
|
+
hexewkb[hexewkblen] = '\0';
|
|
562
|
+
|
|
563
|
+
/* Rely on grammar parser to construct a LWGEOM */
|
|
564
|
+
result = serialized_lwgeom_from_ewkt(&lwg_parser_result, hexewkb, flags);
|
|
565
|
+
if (result)
|
|
566
|
+
lwerror("%s", (char *)lwg_parser_result.message);
|
|
567
|
+
|
|
568
|
+
/* Free intermediate HEXified representation */
|
|
569
|
+
lwfree(hexewkb);
|
|
570
|
+
|
|
571
|
+
/* Deserialize */
|
|
572
|
+
ret = lwgeom_deserialize(lwg_parser_result.serialized_lwgeom);
|
|
573
|
+
|
|
574
|
+
return ret;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/*
|
|
578
|
+
* Make an LWGEOM object from a EWKT representation.
|
|
579
|
+
*/
|
|
580
|
+
LWGEOM *
|
|
581
|
+
lwgeom_from_ewkt(char *ewkt, int flags)
|
|
582
|
+
{
|
|
583
|
+
int result;
|
|
584
|
+
LWGEOM *ret;
|
|
585
|
+
LWGEOM_PARSER_RESULT lwg_parser_result;
|
|
586
|
+
|
|
587
|
+
/* Rely on grammar parser to construct a LWGEOM */
|
|
588
|
+
result = serialized_lwgeom_from_ewkt(&lwg_parser_result, ewkt, flags);
|
|
589
|
+
if (result)
|
|
590
|
+
lwerror("%s", (char *)lwg_parser_result.message);
|
|
591
|
+
|
|
592
|
+
/* Deserialize */
|
|
593
|
+
ret = lwgeom_deserialize(lwg_parser_result.serialized_lwgeom);
|
|
594
|
+
|
|
595
|
+
return ret;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/*
|
|
599
|
+
* Parser functions for working with serialized LWGEOMs. Useful for cases where
|
|
600
|
+
* the function input is already serialized, e.g. some input and output functions
|
|
601
|
+
*/
|
|
602
|
+
|
|
603
|
+
/*
|
|
604
|
+
* Make a serialzed LWGEOM object from a WKT input string
|
|
605
|
+
*/
|
|
606
|
+
int
|
|
607
|
+
serialized_lwgeom_from_ewkt(LWGEOM_PARSER_RESULT *lwg_parser_result, char *wkt_input, int flags)
|
|
608
|
+
{
|
|
609
|
+
|
|
610
|
+
int result = parse_lwg(lwg_parser_result, wkt_input, flags,
|
|
611
|
+
lwalloc, lwerror);
|
|
612
|
+
|
|
613
|
+
LWDEBUGF(2, "serialized_lwgeom_from_ewkt with %s",wkt_input);
|
|
614
|
+
|
|
615
|
+
return result;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/*
|
|
619
|
+
* Return an alloced string
|
|
620
|
+
*/
|
|
621
|
+
int
|
|
622
|
+
serialized_lwgeom_to_ewkt(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags)
|
|
623
|
+
{
|
|
624
|
+
int result;
|
|
625
|
+
|
|
626
|
+
result = unparse_WKT(lwg_unparser_result, serialized, lwalloc, lwfree, flags);
|
|
627
|
+
|
|
628
|
+
return result;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/*
|
|
632
|
+
* Return an alloced string
|
|
633
|
+
*/
|
|
634
|
+
int
|
|
635
|
+
serialized_lwgeom_from_hexwkb(LWGEOM_PARSER_RESULT *lwg_parser_result, char *hexwkb_input, int flags)
|
|
636
|
+
{
|
|
637
|
+
/* NOTE: it is actually the same combined WKT/WKB parser that decodes HEXEWKB into LWGEOMs! */
|
|
638
|
+
int result = parse_lwg(lwg_parser_result, hexwkb_input, flags,
|
|
639
|
+
lwalloc, lwerror);
|
|
640
|
+
|
|
641
|
+
LWDEBUGF(2, "serialized_lwgeom_from_hexwkb with %s", hexwkb_input);
|
|
642
|
+
|
|
643
|
+
return result;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/*
|
|
647
|
+
* Return an alloced string
|
|
648
|
+
*/
|
|
649
|
+
int
|
|
650
|
+
serialized_lwgeom_to_hexwkb(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags, unsigned int byteorder)
|
|
651
|
+
{
|
|
652
|
+
int result;
|
|
653
|
+
|
|
654
|
+
result = unparse_WKB(lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder, 1);
|
|
655
|
+
|
|
656
|
+
return result;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/*
|
|
660
|
+
* Return an alloced string
|
|
661
|
+
*/
|
|
662
|
+
int
|
|
663
|
+
serialized_lwgeom_to_ewkb(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags, unsigned int byteorder)
|
|
664
|
+
{
|
|
665
|
+
int result;
|
|
666
|
+
|
|
667
|
+
result = unparse_WKB(lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder, 0);
|
|
668
|
+
|
|
669
|
+
return result;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/*
|
|
673
|
+
* geom1 same as geom2
|
|
674
|
+
* iff
|
|
675
|
+
* + have same type
|
|
676
|
+
* + have same # objects
|
|
677
|
+
* + have same bvol
|
|
678
|
+
* + each object in geom1 has a corresponding object in geom2 (see above)
|
|
679
|
+
*/
|
|
680
|
+
char
|
|
681
|
+
lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
|
|
682
|
+
{
|
|
683
|
+
LWDEBUGF(2, "lwgeom_same(%s, %s) called",
|
|
684
|
+
lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)),
|
|
685
|
+
lwgeom_typename(TYPE_GETTYPE(lwgeom2->type)));
|
|
686
|
+
|
|
687
|
+
if ( TYPE_GETTYPE(lwgeom1->type) != TYPE_GETTYPE(lwgeom2->type) )
|
|
688
|
+
{
|
|
689
|
+
LWDEBUG(3, " type differ");
|
|
690
|
+
|
|
691
|
+
return 0;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
if ( TYPE_GETZM(lwgeom1->type) != TYPE_GETZM(lwgeom2->type) )
|
|
695
|
+
{
|
|
696
|
+
LWDEBUG(3, " ZM flags differ");
|
|
697
|
+
|
|
698
|
+
return 0;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/* Check boxes if both already computed */
|
|
702
|
+
if ( lwgeom1->bbox && lwgeom2->bbox )
|
|
703
|
+
{
|
|
704
|
+
/*lwnotice("bbox1:%p, bbox2:%p", lwgeom1->bbox, lwgeom2->bbox);*/
|
|
705
|
+
if ( ! box2d_same(lwgeom1->bbox, lwgeom2->bbox) )
|
|
706
|
+
{
|
|
707
|
+
LWDEBUG(3, " bounding boxes differ");
|
|
708
|
+
|
|
709
|
+
return 0;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/* geoms have same type, invoke type-specific function */
|
|
714
|
+
switch(TYPE_GETTYPE(lwgeom1->type))
|
|
715
|
+
{
|
|
716
|
+
case POINTTYPE:
|
|
717
|
+
return lwpoint_same((LWPOINT *)lwgeom1,
|
|
718
|
+
(LWPOINT *)lwgeom2);
|
|
719
|
+
case LINETYPE:
|
|
720
|
+
return lwline_same((LWLINE *)lwgeom1,
|
|
721
|
+
(LWLINE *)lwgeom2);
|
|
722
|
+
case POLYGONTYPE:
|
|
723
|
+
return lwpoly_same((LWPOLY *)lwgeom1,
|
|
724
|
+
(LWPOLY *)lwgeom2);
|
|
725
|
+
case MULTIPOINTTYPE:
|
|
726
|
+
case MULTILINETYPE:
|
|
727
|
+
case MULTIPOLYGONTYPE:
|
|
728
|
+
case COLLECTIONTYPE:
|
|
729
|
+
return lwcollection_same((LWCOLLECTION *)lwgeom1,
|
|
730
|
+
(LWCOLLECTION *)lwgeom2);
|
|
731
|
+
default:
|
|
732
|
+
lwerror("lwgeom_same: unsupported geometry type: %s",
|
|
733
|
+
lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)));
|
|
734
|
+
return 0;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
void
|
|
740
|
+
lwgeom_changed(LWGEOM *lwgeom)
|
|
741
|
+
{
|
|
742
|
+
if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
|
|
743
|
+
lwgeom->bbox = NULL;
|
|
744
|
+
TYPE_SETHASBBOX(lwgeom->type, 0);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
void
|
|
748
|
+
lwgeom_drop_bbox(LWGEOM *lwgeom)
|
|
749
|
+
{
|
|
750
|
+
if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
|
|
751
|
+
lwgeom->bbox = NULL;
|
|
752
|
+
TYPE_SETHASBBOX(lwgeom->type, 0);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/*
|
|
756
|
+
* Ensure there's a box in the LWGEOM.
|
|
757
|
+
* If the box is already there just return,
|
|
758
|
+
* else compute it.
|
|
759
|
+
*/
|
|
760
|
+
void
|
|
761
|
+
lwgeom_add_bbox(LWGEOM *lwgeom)
|
|
762
|
+
{
|
|
763
|
+
if ( lwgeom->bbox ) return;
|
|
764
|
+
lwgeom->bbox = lwgeom_compute_box2d(lwgeom);
|
|
765
|
+
TYPE_SETHASBBOX(lwgeom->type, 1);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
void
|
|
769
|
+
lwgeom_dropSRID(LWGEOM *lwgeom)
|
|
770
|
+
{
|
|
771
|
+
TYPE_SETHASSRID(lwgeom->type, 0);
|
|
772
|
+
lwgeom->SRID = -1;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
LWGEOM *
|
|
776
|
+
lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
|
|
777
|
+
{
|
|
778
|
+
switch(TYPE_GETTYPE(lwgeom->type))
|
|
779
|
+
{
|
|
780
|
+
case LINETYPE:
|
|
781
|
+
return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom,
|
|
782
|
+
dist);
|
|
783
|
+
case POLYGONTYPE:
|
|
784
|
+
return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom,
|
|
785
|
+
dist);
|
|
786
|
+
case MULTILINETYPE:
|
|
787
|
+
case MULTIPOLYGONTYPE:
|
|
788
|
+
case COLLECTIONTYPE:
|
|
789
|
+
return (LWGEOM *)lwcollection_segmentize2d(
|
|
790
|
+
(LWCOLLECTION *)lwgeom, dist);
|
|
791
|
+
|
|
792
|
+
default:
|
|
793
|
+
return lwgeom_clone(lwgeom);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
void
|
|
798
|
+
lwgeom_longitude_shift(LWGEOM *lwgeom)
|
|
799
|
+
{
|
|
800
|
+
int i;
|
|
801
|
+
switch(TYPE_GETTYPE(lwgeom->type))
|
|
802
|
+
{
|
|
803
|
+
LWPOINT *point;
|
|
804
|
+
LWLINE *line;
|
|
805
|
+
LWPOLY *poly;
|
|
806
|
+
LWCOLLECTION *coll;
|
|
807
|
+
|
|
808
|
+
case POINTTYPE:
|
|
809
|
+
point = (LWPOINT *)lwgeom;
|
|
810
|
+
ptarray_longitude_shift(point->point);
|
|
811
|
+
return;
|
|
812
|
+
case LINETYPE:
|
|
813
|
+
line = (LWLINE *)lwgeom;
|
|
814
|
+
ptarray_longitude_shift(line->points);
|
|
815
|
+
return;
|
|
816
|
+
case POLYGONTYPE:
|
|
817
|
+
poly = (LWPOLY *)lwgeom;
|
|
818
|
+
for (i=0; i<poly->nrings; i++)
|
|
819
|
+
ptarray_longitude_shift(poly->rings[i]);
|
|
820
|
+
return;
|
|
821
|
+
case MULTIPOINTTYPE:
|
|
822
|
+
case MULTILINETYPE:
|
|
823
|
+
case MULTIPOLYGONTYPE:
|
|
824
|
+
case COLLECTIONTYPE:
|
|
825
|
+
coll = (LWCOLLECTION *)lwgeom;
|
|
826
|
+
for (i=0; i<coll->ngeoms; i++)
|
|
827
|
+
lwgeom_longitude_shift(coll->geoms[i]);
|
|
828
|
+
return;
|
|
829
|
+
default:
|
|
830
|
+
lwerror("%s:%d: unsupported geom type: %s",
|
|
831
|
+
__FILE__, __LINE__,
|
|
832
|
+
lwgeom_typename(TYPE_GETTYPE(lwgeom->type)));
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
int
|
|
838
|
+
lwgeom_contains_subgeoms(int type)
|
|
839
|
+
{
|
|
840
|
+
/* Return TRUE if the geometry may contain sub-geometries, i.e. it is a MULTI* or COMPOUNDCURVE */
|
|
841
|
+
switch(type)
|
|
842
|
+
{
|
|
843
|
+
case MULTIPOINTTYPE:
|
|
844
|
+
case MULTILINETYPE:
|
|
845
|
+
case MULTIPOLYGONTYPE:
|
|
846
|
+
case COLLECTIONTYPE:
|
|
847
|
+
case COMPOUNDTYPE:
|
|
848
|
+
case MULTICURVETYPE:
|
|
849
|
+
case MULTISURFACETYPE:
|
|
850
|
+
return -1;
|
|
851
|
+
break;
|
|
852
|
+
|
|
853
|
+
default:
|
|
854
|
+
return 0;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
void lwgeom_free(LWGEOM *lwgeom) {
|
|
859
|
+
|
|
860
|
+
switch(TYPE_GETTYPE(lwgeom->type))
|
|
861
|
+
{
|
|
862
|
+
case POINTTYPE:
|
|
863
|
+
lwpoint_free((LWPOINT *)lwgeom);
|
|
864
|
+
break;
|
|
865
|
+
case LINETYPE:
|
|
866
|
+
lwline_free((LWLINE *)lwgeom);
|
|
867
|
+
break;
|
|
868
|
+
case POLYGONTYPE:
|
|
869
|
+
lwpoly_free((LWPOLY *)lwgeom);
|
|
870
|
+
break;
|
|
871
|
+
case MULTIPOINTTYPE:
|
|
872
|
+
lwmpoint_free((LWMPOINT *)lwgeom);
|
|
873
|
+
break;
|
|
874
|
+
case MULTILINETYPE:
|
|
875
|
+
lwmline_free((LWMLINE *)lwgeom);
|
|
876
|
+
break;
|
|
877
|
+
case MULTIPOLYGONTYPE:
|
|
878
|
+
lwmpoly_free((LWMPOLY *)lwgeom);
|
|
879
|
+
break;
|
|
880
|
+
case COLLECTIONTYPE:
|
|
881
|
+
lwcollection_free((LWCOLLECTION *)lwgeom);
|
|
882
|
+
break;
|
|
883
|
+
}
|
|
884
|
+
return;
|
|
885
|
+
|
|
886
|
+
};
|