pgLatLon
changeset 20:8a8d6dc44337
Changed/fixed behavior of "contains" operator regarding perimeters; Added "contains" operator for ebox type; Minor changes in README
author | jbe |
---|---|
date | Mon Sep 12 18:00:52 2016 +0200 (2016-09-12) |
parents | bd166e5e02cb |
children | 54e207df65b7 |
files | GNUmakefile README.html README.mkd latlon--0.4--0.5.sql latlon--0.5.sql latlon-v0005.c latlon.control |
line diff
1.1 --- a/GNUmakefile Fri Sep 09 23:44:28 2016 +0200 1.2 +++ b/GNUmakefile Mon Sep 12 18:00:52 2016 +0200 1.3 @@ -1,5 +1,5 @@ 1.4 EXTENSION = latlon 1.5 -DATA = latlon--0.3--0.4.sql latlon--0.4.sql latlon--0.5.sql 1.6 +DATA = latlon--0.3--0.4.sql latlon--0.4.sql latlon--0.4--0.5.sql latlon--0.5.sql 1.7 MODULES = latlon-v0004 latlon-v0005 1.8 1.9 PG_CONFIG = pg_config
2.1 --- a/README.html Fri Sep 09 23:44:28 2016 +0200 2.2 +++ b/README.html Mon Sep 12 18:00:52 2016 +0200 2.3 @@ -1,5 +1,5 @@ 2.4 -<html><head><title>pgLatLon v0.4 documentation</title></head><body> 2.5 -<h1>pgLatLon v0.4 documentation</h1> 2.6 +<html><head><title>pgLatLon v0.5 documentation</title></head><body> 2.7 +<h1>pgLatLon v0.5 documentation</h1> 2.8 2.9 <p>pgLatLon is a spatial database extension for the PostgreSQL object-relational 2.10 database management system providing geographic data types and spatial indexing 2.11 @@ -40,8 +40,8 @@ 2.12 <p>It is also possible to compile and install the extension without GNU Make as 2.13 follows:</p> 2.14 2.15 -<pre><code>cc -Wall -O2 -fPIC -shared -I `pg_config --includedir-server` -o latlon-v0003.so latlon-v0003.c 2.16 -cp latlon-v0003.so `pg_config --pkglibdir` 2.17 +<pre><code>cc -Wall -O2 -fPIC -shared -I `pg_config --includedir-server` -o latlon-v0005.so latlon-v0005.c 2.18 +cp latlon-v0005.so `pg_config --pkglibdir` 2.19 cp latlon.control `pg_config --sharedir`/extension/ 2.20 cp latlon--*.sql `pg_config --sharedir`/extension/ 2.21 </code></pre> 2.22 @@ -285,8 +285,8 @@ 2.23 <li><code>ecluster && ecluster</code></li> 2.24 </ul> 2.25 2.26 -<p>The <code>&&</code> operator is commutative, i.e. <code>a && b</code> is the same as <code>b && a</code>. Each 2.27 -commutation is supported as well.</p> 2.28 +<p>The <code>&&</code> operator is commutative, i.e. "<code>a && b</code>" is the same as "<code>b && a</code>". 2.29 +Each commutation is supported as well.</p> 2.30 2.31 <h4>Lossy overlap operator <code>&&+</code></h4> 2.32 2.33 @@ -302,7 +302,7 @@ 2.34 <li><code>ecluster &&+ ecluster</code></li> 2.35 </ul> 2.36 2.37 -<p>The <code>&&+</code> operator is commutative, i.e. <code>a &&+ b</code> is the same as <code>b &&+ a</code>. 2.38 +<p>The <code>&&+</code> operator is commutative, i.e. "<code>a &&+ b</code>" is the same as "<code>b &&+ a</code>". 2.39 Each commutation is supported as well.</p> 2.40 2.41 <p>Where two data types support both the <code>&&</code> and the <code>&&+</code> operator, the <code>&&+</code> 2.42 @@ -315,14 +315,21 @@ 2.43 2.44 <ul> 2.45 <li><code>ebox @> epoint</code> (alias for <code>&&</code>)</li> 2.46 +<li><code>ebox @> ebox</code></li> 2.47 <li><code>ebox @> ecluster</code></li> 2.48 <li><code>ecluster @> epoint</code> (alias for <code>&&</code>)</li> 2.49 <li><code>ecluster @> ebox</code></li> 2.50 <li><code>ecluster @> ecluster</code></li> 2.51 </ul> 2.52 2.53 -<p>The commutator of <code>@></code> ("contains") is <code><@</code> ("is contained in"), i.e. <code>a @> b</code> 2.54 -is the same as <code>b <@ a</code>.</p> 2.55 +<p>The commutator of <code>@></code> ("contains") is <code><@</code> ("is contained in"), i.e. 2.56 +"<code>a @> b</code>" is the same as "<code>b <@ a</code>".</p> 2.57 + 2.58 +<p>Whether the perimeter of an object is taken into account is undefined and may 2.59 +differ between the left and the right hand side of the operator. The current 2.60 +implementation returns true only if an object is contained completely within 2.61 +the other object, not touching its perimeter, paths, outlines, or any singular 2.62 +points.</p> 2.63 2.64 <h4>Distance operator <code><-></code></h4> 2.65 2.66 @@ -342,7 +349,7 @@ 2.67 <li><code>ecluster <-> ecluster</code></li> 2.68 </ul> 2.69 2.70 -<p>The <code><-></code> operator is commutative, i.e. <code>a <-> b</code> is the same as <code>b <-> a</code>. 2.71 +<p>The <code><-></code> operator is commutative, i.e. "<code>a <-> b</code>" is the same as "<code>b <-> a</code>". 2.72 Each commutation is supported as well.</p> 2.73 2.74 <p>For short distances, the result is very accurate (i.e. respects the dimensions
3.1 --- a/README.mkd Fri Sep 09 23:44:28 2016 +0200 3.2 +++ b/README.mkd Mon Sep 12 18:00:52 2016 +0200 3.3 @@ -1,4 +1,4 @@ 3.4 -pgLatLon v0.4 documentation 3.5 +pgLatLon v0.5 documentation 3.6 =========================== 3.7 3.8 pgLatLon is a spatial database extension for the PostgreSQL object-relational 3.9 @@ -39,8 +39,8 @@ 3.10 It is also possible to compile and install the extension without GNU Make as 3.11 follows: 3.12 3.13 - cc -Wall -O2 -fPIC -shared -I `pg_config --includedir-server` -o latlon-v0003.so latlon-v0003.c 3.14 - cp latlon-v0003.so `pg_config --pkglibdir` 3.15 + cc -Wall -O2 -fPIC -shared -I `pg_config --includedir-server` -o latlon-v0005.so latlon-v0005.c 3.16 + cp latlon-v0005.so `pg_config --pkglibdir` 3.17 cp latlon.control `pg_config --sharedir`/extension/ 3.18 cp latlon--*.sql `pg_config --sharedir`/extension/ 3.19 3.20 @@ -274,8 +274,8 @@ 3.21 * `ecircle && ecluster` 3.22 * `ecluster && ecluster` 3.23 3.24 -The `&&` operator is commutative, i.e. `a && b` is the same as `b && a`. Each 3.25 -commutation is supported as well. 3.26 +The `&&` operator is commutative, i.e. "`a && b`" is the same as "`b && a`". 3.27 +Each commutation is supported as well. 3.28 3.29 #### Lossy overlap operator `&&+` 3.30 3.31 @@ -289,7 +289,7 @@ 3.32 * `ecircle &&+ ecluster` 3.33 * `ecluster &&+ ecluster` 3.34 3.35 -The `&&+` operator is commutative, i.e. `a &&+ b` is the same as `b &&+ a`. 3.36 +The `&&+` operator is commutative, i.e. "`a &&+ b`" is the same as "`b &&+ a`". 3.37 Each commutation is supported as well. 3.38 3.39 Where two data types support both the `&&` and the `&&+` operator, the `&&+` 3.40 @@ -301,13 +301,20 @@ 3.41 the operator. Currently implemented for: 3.42 3.43 * `ebox @> epoint` (alias for `&&`) 3.44 +* `ebox @> ebox` 3.45 * `ebox @> ecluster` 3.46 * `ecluster @> epoint` (alias for `&&`) 3.47 * `ecluster @> ebox` 3.48 * `ecluster @> ecluster` 3.49 3.50 -The commutator of `@>` ("contains") is `<@` ("is contained in"), i.e. `a @> b` 3.51 -is the same as `b <@ a`. 3.52 +The commutator of `@>` ("contains") is `<@` ("is contained in"), i.e. 3.53 +"`a @> b`" is the same as "`b <@ a`". 3.54 + 3.55 +Whether the perimeter of an object is taken into account is undefined and may 3.56 +differ between the left and the right hand side of the operator. The current 3.57 +implementation returns true only if an object is contained completely within 3.58 +the other object, not touching its perimeter, paths, outlines, or any singular 3.59 +points. 3.60 3.61 #### Distance operator `<->` 3.62 3.63 @@ -325,7 +332,7 @@ 3.64 * `ecircle <-> ecluster` 3.65 * `ecluster <-> ecluster` 3.66 3.67 -The `<->` operator is commutative, i.e. `a <-> b` is the same as `b <-> a`. 3.68 +The `<->` operator is commutative, i.e. "`a <-> b`" is the same as "`b <-> a`". 3.69 Each commutation is supported as well. 3.70 3.71 For short distances, the result is very accurate (i.e. respects the dimensions
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/latlon--0.4--0.5.sql Mon Sep 12 18:00:52 2016 +0200 4.3 @@ -0,0 +1,457 @@ 4.4 + 4.5 +CREATE OR REPLACE FUNCTION ekey_point_in_dummy(cstring) 4.6 + RETURNS ekey_point 4.7 + LANGUAGE C IMMUTABLE STRICT 4.8 + AS '$libdir/latlon-v0005', 'pgl_notimpl'; 4.9 + 4.10 +CREATE OR REPLACE FUNCTION ekey_point_out_dummy(ekey_point) 4.11 + RETURNS cstring 4.12 + LANGUAGE C IMMUTABLE STRICT 4.13 + AS '$libdir/latlon-v0005', 'pgl_notimpl'; 4.14 + 4.15 +CREATE OR REPLACE FUNCTION ekey_area_in_dummy(cstring) 4.16 + RETURNS ekey_area 4.17 + LANGUAGE C IMMUTABLE STRICT 4.18 + AS '$libdir/latlon-v0005', 'pgl_notimpl'; 4.19 + 4.20 +CREATE OR REPLACE FUNCTION ekey_area_out_dummy(ekey_area) 4.21 + RETURNS cstring 4.22 + LANGUAGE C IMMUTABLE STRICT 4.23 + AS '$libdir/latlon-v0005', 'pgl_notimpl'; 4.24 + 4.25 +CREATE OR REPLACE FUNCTION epoint_in(cstring) 4.26 + RETURNS epoint 4.27 + LANGUAGE C IMMUTABLE STRICT 4.28 + AS '$libdir/latlon-v0005', 'pgl_epoint_in'; 4.29 + 4.30 +CREATE OR REPLACE FUNCTION ebox_in(cstring) 4.31 + RETURNS ebox 4.32 + LANGUAGE C IMMUTABLE STRICT 4.33 + AS '$libdir/latlon-v0005', 'pgl_ebox_in'; 4.34 + 4.35 +CREATE OR REPLACE FUNCTION ecircle_in(cstring) 4.36 + RETURNS ecircle 4.37 + LANGUAGE C IMMUTABLE STRICT 4.38 + AS '$libdir/latlon-v0005', 'pgl_ecircle_in'; 4.39 + 4.40 +CREATE OR REPLACE FUNCTION ecluster_in(cstring) 4.41 + RETURNS ecluster 4.42 + LANGUAGE C IMMUTABLE STRICT 4.43 + AS '$libdir/latlon-v0005', 'pgl_ecluster_in'; 4.44 + 4.45 +CREATE OR REPLACE FUNCTION epoint_out(epoint) 4.46 + RETURNS cstring 4.47 + LANGUAGE C IMMUTABLE STRICT 4.48 + AS '$libdir/latlon-v0005', 'pgl_epoint_out'; 4.49 + 4.50 +CREATE OR REPLACE FUNCTION ebox_out(ebox) 4.51 + RETURNS cstring 4.52 + LANGUAGE C IMMUTABLE STRICT 4.53 + AS '$libdir/latlon-v0005', 'pgl_ebox_out'; 4.54 + 4.55 +CREATE OR REPLACE FUNCTION ecircle_out(ecircle) 4.56 + RETURNS cstring 4.57 + LANGUAGE C IMMUTABLE STRICT 4.58 + AS '$libdir/latlon-v0005', 'pgl_ecircle_out'; 4.59 + 4.60 +CREATE OR REPLACE FUNCTION ecluster_out(ecluster) 4.61 + RETURNS cstring 4.62 + LANGUAGE C IMMUTABLE STRICT 4.63 + AS '$libdir/latlon-v0005', 'pgl_ecluster_out'; 4.64 + 4.65 +CREATE OR REPLACE FUNCTION epoint_recv(internal) 4.66 + RETURNS epoint 4.67 + LANGUAGE C IMMUTABLE STRICT 4.68 + AS '$libdir/latlon-v0005', 'pgl_epoint_recv'; 4.69 + 4.70 +CREATE OR REPLACE FUNCTION ebox_recv(internal) 4.71 + RETURNS ebox 4.72 + LANGUAGE C IMMUTABLE STRICT 4.73 + AS '$libdir/latlon-v0005', 'pgl_ebox_recv'; 4.74 + 4.75 +CREATE OR REPLACE FUNCTION ecircle_recv(internal) 4.76 + RETURNS ecircle 4.77 + LANGUAGE C IMMUTABLE STRICT 4.78 + AS '$libdir/latlon-v0005', 'pgl_ecircle_recv'; 4.79 + 4.80 +CREATE OR REPLACE FUNCTION epoint_send(epoint) 4.81 + RETURNS bytea 4.82 + LANGUAGE C IMMUTABLE STRICT 4.83 + AS '$libdir/latlon-v0005', 'pgl_epoint_send'; 4.84 + 4.85 +CREATE OR REPLACE FUNCTION ebox_send(ebox) 4.86 + RETURNS bytea 4.87 + LANGUAGE C IMMUTABLE STRICT 4.88 + AS '$libdir/latlon-v0005', 'pgl_ebox_send'; 4.89 + 4.90 +CREATE OR REPLACE FUNCTION ecircle_send(ecircle) 4.91 + RETURNS bytea 4.92 + LANGUAGE C IMMUTABLE STRICT 4.93 + AS '$libdir/latlon-v0005', 'pgl_ecircle_send'; 4.94 + 4.95 +CREATE OR REPLACE FUNCTION epoint_btree_lt(epoint, epoint) 4.96 + RETURNS boolean 4.97 + LANGUAGE C IMMUTABLE STRICT 4.98 + AS '$libdir/latlon-v0005', 'pgl_btree_epoint_lt'; 4.99 + 4.100 +CREATE OR REPLACE FUNCTION epoint_btree_le(epoint, epoint) 4.101 + RETURNS boolean 4.102 + LANGUAGE C IMMUTABLE STRICT 4.103 + AS '$libdir/latlon-v0005', 'pgl_btree_epoint_le'; 4.104 + 4.105 +CREATE OR REPLACE FUNCTION epoint_btree_eq(epoint, epoint) 4.106 + RETURNS boolean 4.107 + LANGUAGE C IMMUTABLE STRICT 4.108 + AS '$libdir/latlon-v0005', 'pgl_btree_epoint_eq'; 4.109 + 4.110 +CREATE OR REPLACE FUNCTION epoint_btree_ne(epoint, epoint) 4.111 + RETURNS boolean 4.112 + LANGUAGE C IMMUTABLE STRICT 4.113 + AS '$libdir/latlon-v0005', 'pgl_btree_epoint_ne'; 4.114 + 4.115 +CREATE OR REPLACE FUNCTION epoint_btree_ge(epoint, epoint) 4.116 + RETURNS boolean 4.117 + LANGUAGE C IMMUTABLE STRICT 4.118 + AS '$libdir/latlon-v0005', 'pgl_btree_epoint_ge'; 4.119 + 4.120 +CREATE OR REPLACE FUNCTION epoint_btree_gt(epoint, epoint) 4.121 + RETURNS boolean 4.122 + LANGUAGE C IMMUTABLE STRICT 4.123 + AS '$libdir/latlon-v0005', 'pgl_btree_epoint_gt'; 4.124 + 4.125 +CREATE OR REPLACE FUNCTION epoint_btree_cmp(epoint, epoint) 4.126 + RETURNS int4 4.127 + LANGUAGE C IMMUTABLE STRICT 4.128 + AS '$libdir/latlon-v0005', 'pgl_btree_epoint_cmp'; 4.129 + 4.130 +CREATE OR REPLACE FUNCTION ebox_btree_lt(ebox, ebox) 4.131 + RETURNS boolean 4.132 + LANGUAGE C IMMUTABLE STRICT 4.133 + AS '$libdir/latlon-v0005', 'pgl_btree_ebox_lt'; 4.134 + 4.135 +CREATE OR REPLACE FUNCTION ebox_btree_le(ebox, ebox) 4.136 + RETURNS boolean 4.137 + LANGUAGE C IMMUTABLE STRICT 4.138 + AS '$libdir/latlon-v0005', 'pgl_btree_ebox_le'; 4.139 + 4.140 +CREATE OR REPLACE FUNCTION ebox_btree_eq(ebox, ebox) 4.141 + RETURNS boolean 4.142 + LANGUAGE C IMMUTABLE STRICT 4.143 + AS '$libdir/latlon-v0005', 'pgl_btree_ebox_eq'; 4.144 + 4.145 +CREATE OR REPLACE FUNCTION ebox_btree_ne(ebox, ebox) 4.146 + RETURNS boolean 4.147 + LANGUAGE C IMMUTABLE STRICT 4.148 + AS '$libdir/latlon-v0005', 'pgl_btree_ebox_ne'; 4.149 + 4.150 +CREATE OR REPLACE FUNCTION ebox_btree_ge(ebox, ebox) 4.151 + RETURNS boolean 4.152 + LANGUAGE C IMMUTABLE STRICT 4.153 + AS '$libdir/latlon-v0005', 'pgl_btree_ebox_ge'; 4.154 + 4.155 +CREATE OR REPLACE FUNCTION ebox_btree_gt(ebox, ebox) 4.156 + RETURNS boolean 4.157 + LANGUAGE C IMMUTABLE STRICT 4.158 + AS '$libdir/latlon-v0005', 'pgl_btree_ebox_gt'; 4.159 + 4.160 +CREATE OR REPLACE FUNCTION ebox_btree_cmp(ebox, ebox) 4.161 + RETURNS int4 4.162 + LANGUAGE C IMMUTABLE STRICT 4.163 + AS '$libdir/latlon-v0005', 'pgl_btree_ebox_cmp'; 4.164 + 4.165 +CREATE OR REPLACE FUNCTION ecircle_btree_lt(ecircle, ecircle) 4.166 + RETURNS boolean 4.167 + LANGUAGE C IMMUTABLE STRICT 4.168 + AS '$libdir/latlon-v0005', 'pgl_btree_ecircle_lt'; 4.169 + 4.170 +CREATE OR REPLACE FUNCTION ecircle_btree_le(ecircle, ecircle) 4.171 + RETURNS boolean 4.172 + LANGUAGE C IMMUTABLE STRICT 4.173 + AS '$libdir/latlon-v0005', 'pgl_btree_ecircle_le'; 4.174 + 4.175 +CREATE OR REPLACE FUNCTION ecircle_btree_eq(ecircle, ecircle) 4.176 + RETURNS boolean 4.177 + LANGUAGE C IMMUTABLE STRICT 4.178 + AS '$libdir/latlon-v0005', 'pgl_btree_ecircle_eq'; 4.179 + 4.180 +CREATE OR REPLACE FUNCTION ecircle_btree_ne(ecircle, ecircle) 4.181 + RETURNS boolean 4.182 + LANGUAGE C IMMUTABLE STRICT 4.183 + AS '$libdir/latlon-v0005', 'pgl_btree_ecircle_ne'; 4.184 + 4.185 +CREATE OR REPLACE FUNCTION ecircle_btree_ge(ecircle, ecircle) 4.186 + RETURNS boolean 4.187 + LANGUAGE C IMMUTABLE STRICT 4.188 + AS '$libdir/latlon-v0005', 'pgl_btree_ecircle_ge'; 4.189 + 4.190 +CREATE OR REPLACE FUNCTION ecircle_btree_gt(ecircle, ecircle) 4.191 + RETURNS boolean 4.192 + LANGUAGE C IMMUTABLE STRICT 4.193 + AS '$libdir/latlon-v0005', 'pgl_btree_ecircle_gt'; 4.194 + 4.195 +CREATE OR REPLACE FUNCTION ecircle_btree_cmp(ecircle, ecircle) 4.196 + RETURNS int4 4.197 + LANGUAGE C IMMUTABLE STRICT 4.198 + AS '$libdir/latlon-v0005', 'pgl_btree_ecircle_cmp'; 4.199 + 4.200 +CREATE OR REPLACE FUNCTION cast_epoint_to_ebox(epoint) 4.201 + RETURNS ebox 4.202 + LANGUAGE C IMMUTABLE STRICT 4.203 + AS '$libdir/latlon-v0005', 'pgl_epoint_to_ebox'; 4.204 + 4.205 +CREATE OR REPLACE FUNCTION cast_epoint_to_ecircle(epoint) 4.206 + RETURNS ecircle 4.207 + LANGUAGE C IMMUTABLE STRICT 4.208 + AS '$libdir/latlon-v0005', 'pgl_epoint_to_ecircle'; 4.209 + 4.210 +CREATE OR REPLACE FUNCTION cast_epoint_to_ecluster(epoint) 4.211 + RETURNS ecluster 4.212 + LANGUAGE C IMMUTABLE STRICT 4.213 + AS '$libdir/latlon-v0005', 'pgl_epoint_to_ecluster'; 4.214 + 4.215 +CREATE OR REPLACE FUNCTION cast_ebox_to_ecluster(ebox) 4.216 + RETURNS ecluster 4.217 + LANGUAGE C IMMUTABLE STRICT 4.218 + AS '$libdir/latlon-v0005', 'pgl_ebox_to_ecluster'; 4.219 + 4.220 +CREATE OR REPLACE FUNCTION epoint(float8, float8) 4.221 + RETURNS epoint 4.222 + LANGUAGE C IMMUTABLE STRICT 4.223 + AS '$libdir/latlon-v0005', 'pgl_create_epoint'; 4.224 + 4.225 +CREATE OR REPLACE FUNCTION empty_ebox() 4.226 + RETURNS ebox 4.227 + LANGUAGE C IMMUTABLE STRICT 4.228 + AS '$libdir/latlon-v0005', 'pgl_create_empty_ebox'; 4.229 + 4.230 +CREATE OR REPLACE FUNCTION ebox(float8, float8, float8, float8) 4.231 + RETURNS ebox 4.232 + LANGUAGE C IMMUTABLE STRICT 4.233 + AS '$libdir/latlon-v0005', 'pgl_create_ebox'; 4.234 + 4.235 +CREATE OR REPLACE FUNCTION ebox(epoint, epoint) 4.236 + RETURNS ebox 4.237 + LANGUAGE C IMMUTABLE STRICT 4.238 + AS '$libdir/latlon-v0005', 'pgl_create_ebox_from_epoints'; 4.239 + 4.240 +CREATE OR REPLACE FUNCTION ecircle(float8, float8, float8) 4.241 + RETURNS ecircle 4.242 + LANGUAGE C IMMUTABLE STRICT 4.243 + AS '$libdir/latlon-v0005', 'pgl_create_ecircle'; 4.244 + 4.245 +CREATE OR REPLACE FUNCTION ecircle(epoint, float8) 4.246 + RETURNS ecircle 4.247 + LANGUAGE C IMMUTABLE STRICT 4.248 + AS '$libdir/latlon-v0005', 'pgl_create_ecircle_from_epoint'; 4.249 + 4.250 +CREATE OR REPLACE FUNCTION latitude(epoint) 4.251 + RETURNS float8 4.252 + LANGUAGE C IMMUTABLE STRICT 4.253 + AS '$libdir/latlon-v0005', 'pgl_epoint_lat'; 4.254 + 4.255 +CREATE OR REPLACE FUNCTION longitude(epoint) 4.256 + RETURNS float8 4.257 + LANGUAGE C IMMUTABLE STRICT 4.258 + AS '$libdir/latlon-v0005', 'pgl_epoint_lon'; 4.259 + 4.260 +CREATE OR REPLACE FUNCTION min_latitude(ebox) 4.261 + RETURNS float8 4.262 + LANGUAGE C IMMUTABLE STRICT 4.263 + AS '$libdir/latlon-v0005', 'pgl_ebox_lat_min'; 4.264 + 4.265 +CREATE OR REPLACE FUNCTION max_latitude(ebox) 4.266 + RETURNS float8 4.267 + LANGUAGE C IMMUTABLE STRICT 4.268 + AS '$libdir/latlon-v0005', 'pgl_ebox_lat_max'; 4.269 + 4.270 +CREATE OR REPLACE FUNCTION min_longitude(ebox) 4.271 + RETURNS float8 4.272 + LANGUAGE C IMMUTABLE STRICT 4.273 + AS '$libdir/latlon-v0005', 'pgl_ebox_lon_min'; 4.274 + 4.275 +CREATE OR REPLACE FUNCTION max_longitude(ebox) 4.276 + RETURNS float8 4.277 + LANGUAGE C IMMUTABLE STRICT 4.278 + AS '$libdir/latlon-v0005', 'pgl_ebox_lon_max'; 4.279 + 4.280 +CREATE OR REPLACE FUNCTION center(ecircle) 4.281 + RETURNS epoint 4.282 + LANGUAGE C IMMUTABLE STRICT 4.283 + AS '$libdir/latlon-v0005', 'pgl_ecircle_center'; 4.284 + 4.285 +CREATE OR REPLACE FUNCTION radius(ecircle) 4.286 + RETURNS float8 4.287 + LANGUAGE C IMMUTABLE STRICT 4.288 + AS '$libdir/latlon-v0005', 'pgl_ecircle_radius'; 4.289 + 4.290 +CREATE OR REPLACE FUNCTION epoint_ebox_overlap_proc(epoint, ebox) 4.291 + RETURNS boolean 4.292 + LANGUAGE C IMMUTABLE STRICT 4.293 + AS '$libdir/latlon-v0005', 'pgl_epoint_ebox_overlap'; 4.294 + 4.295 +CREATE OR REPLACE FUNCTION epoint_ecircle_overlap_proc(epoint, ecircle) 4.296 + RETURNS boolean 4.297 + LANGUAGE C IMMUTABLE STRICT 4.298 + AS '$libdir/latlon-v0005', 'pgl_epoint_ecircle_overlap'; 4.299 + 4.300 +CREATE OR REPLACE FUNCTION epoint_ecluster_overlap_proc(epoint, ecluster) 4.301 + RETURNS boolean 4.302 + LANGUAGE C IMMUTABLE STRICT 4.303 + AS '$libdir/latlon-v0005', 'pgl_epoint_ecluster_overlap'; 4.304 + 4.305 +CREATE OR REPLACE FUNCTION epoint_ecluster_may_overlap_proc(epoint, ecluster) 4.306 + RETURNS boolean 4.307 + LANGUAGE C IMMUTABLE STRICT 4.308 + AS '$libdir/latlon-v0005', 'pgl_epoint_ecluster_may_overlap'; 4.309 + 4.310 +CREATE OR REPLACE FUNCTION ebox_overlap_proc(ebox, ebox) 4.311 + RETURNS boolean 4.312 + LANGUAGE C IMMUTABLE STRICT 4.313 + AS '$libdir/latlon-v0005', 'pgl_ebox_overlap'; 4.314 + 4.315 +CREATE OR REPLACE FUNCTION ebox_ecircle_may_overlap_proc(ebox, ecircle) 4.316 + RETURNS boolean 4.317 + LANGUAGE C IMMUTABLE STRICT 4.318 + AS '$libdir/latlon-v0005', 'pgl_ebox_ecircle_may_overlap'; 4.319 + 4.320 +CREATE OR REPLACE FUNCTION ebox_ecluster_may_overlap_proc(ebox, ecluster) 4.321 + RETURNS boolean 4.322 + LANGUAGE C IMMUTABLE STRICT 4.323 + AS '$libdir/latlon-v0005', 'pgl_ebox_ecluster_may_overlap'; 4.324 + 4.325 +CREATE OR REPLACE FUNCTION ecircle_overlap_proc(ecircle, ecircle) 4.326 + RETURNS boolean 4.327 + LANGUAGE C IMMUTABLE STRICT 4.328 + AS '$libdir/latlon-v0005', 'pgl_ecircle_overlap'; 4.329 + 4.330 +CREATE OR REPLACE FUNCTION ecircle_ecluster_overlap_proc(ecircle, ecluster) 4.331 + RETURNS boolean 4.332 + LANGUAGE C IMMUTABLE STRICT 4.333 + AS '$libdir/latlon-v0005', 'pgl_ecircle_ecluster_overlap'; 4.334 + 4.335 +CREATE OR REPLACE FUNCTION ecircle_ecluster_may_overlap_proc(ecircle, ecluster) 4.336 + RETURNS boolean 4.337 + LANGUAGE C IMMUTABLE STRICT 4.338 + AS '$libdir/latlon-v0005', 'pgl_ecircle_ecluster_may_overlap'; 4.339 + 4.340 +CREATE OR REPLACE FUNCTION ecluster_overlap_proc(ecluster, ecluster) 4.341 + RETURNS boolean 4.342 + LANGUAGE C IMMUTABLE STRICT 4.343 + AS '$libdir/latlon-v0005', 'pgl_ecluster_overlap'; 4.344 + 4.345 +CREATE OR REPLACE FUNCTION ecluster_may_overlap_proc(ecluster, ecluster) 4.346 + RETURNS boolean 4.347 + LANGUAGE C IMMUTABLE STRICT 4.348 + AS '$libdir/latlon-v0005', 'pgl_ecluster_may_overlap'; 4.349 + 4.350 +CREATE OR REPLACE FUNCTION ecluster_contains_proc(ecluster, ecluster) 4.351 + RETURNS boolean 4.352 + LANGUAGE C IMMUTABLE STRICT 4.353 + AS '$libdir/latlon-v0005', 'pgl_ecluster_contains'; 4.354 + 4.355 +CREATE OR REPLACE FUNCTION epoint_distance_proc(epoint, epoint) 4.356 + RETURNS float8 4.357 + LANGUAGE C IMMUTABLE STRICT 4.358 + AS '$libdir/latlon-v0005', 'pgl_epoint_distance'; 4.359 + 4.360 +CREATE OR REPLACE FUNCTION epoint_ecircle_distance_proc(epoint, ecircle) 4.361 + RETURNS float8 4.362 + LANGUAGE C IMMUTABLE STRICT 4.363 + AS '$libdir/latlon-v0005', 'pgl_epoint_ecircle_distance'; 4.364 + 4.365 +CREATE OR REPLACE FUNCTION epoint_ecluster_distance_proc(epoint, ecluster) 4.366 + RETURNS float8 4.367 + LANGUAGE C IMMUTABLE STRICT 4.368 + AS '$libdir/latlon-v0005', 'pgl_epoint_ecluster_distance'; 4.369 + 4.370 +CREATE OR REPLACE FUNCTION ecircle_distance_proc(ecircle, ecircle) 4.371 + RETURNS float8 4.372 + LANGUAGE C IMMUTABLE STRICT 4.373 + AS '$libdir/latlon-v0005', 'pgl_ecircle_distance'; 4.374 + 4.375 +CREATE OR REPLACE FUNCTION ecircle_ecluster_distance_proc(ecircle, ecluster) 4.376 + RETURNS float8 4.377 + LANGUAGE C IMMUTABLE STRICT 4.378 + AS '$libdir/latlon-v0005', 'pgl_ecircle_ecluster_distance'; 4.379 + 4.380 +CREATE OR REPLACE FUNCTION ecluster_distance_proc(ecluster, ecluster) 4.381 + RETURNS float8 4.382 + LANGUAGE C IMMUTABLE STRICT 4.383 + AS '$libdir/latlon-v0005', 'pgl_ecluster_distance'; 4.384 + 4.385 +CREATE FUNCTION ebox_contains_castwrap(ebox, ebox) 4.386 + RETURNS boolean 4.387 + LANGUAGE sql IMMUTABLE AS 'SELECT $1::ecluster @> $2::ecluster'; 4.388 + 4.389 +CREATE OPERATOR @> ( 4.390 + leftarg = ebox, 4.391 + rightarg = ebox, 4.392 + procedure = ebox_contains_castwrap, 4.393 + commutator = <@, 4.394 + restrict = areasel, 4.395 + join = areajoinsel 4.396 +); 4.397 + 4.398 +CREATE FUNCTION ebox_contains_swapped_castwrap(ebox, ebox) 4.399 + RETURNS boolean 4.400 + LANGUAGE sql IMMUTABLE AS 'SELECT $2::ecluster @> $1::ecluster'; 4.401 + 4.402 +CREATE OPERATOR <@ ( 4.403 + leftarg = ebox, 4.404 + rightarg = ebox, 4.405 + procedure = ebox_contains_swapped_castwrap, 4.406 + commutator = @>, 4.407 + restrict = areasel, 4.408 + join = areajoinsel 4.409 +); 4.410 + 4.411 +CREATE OR REPLACE FUNCTION pgl_gist_consistent(internal, internal, smallint, oid, internal) 4.412 + RETURNS boolean 4.413 + LANGUAGE C STRICT 4.414 + AS '$libdir/latlon-v0005', 'pgl_gist_consistent'; 4.415 + 4.416 +CREATE OR REPLACE FUNCTION pgl_gist_union(internal, internal) 4.417 + RETURNS internal 4.418 + LANGUAGE C STRICT 4.419 + AS '$libdir/latlon-v0005', 'pgl_gist_union'; 4.420 + 4.421 +CREATE OR REPLACE FUNCTION pgl_gist_compress_epoint(internal) 4.422 + RETURNS internal 4.423 + LANGUAGE C STRICT 4.424 + AS '$libdir/latlon-v0005', 'pgl_gist_compress_epoint'; 4.425 + 4.426 +CREATE OR REPLACE FUNCTION pgl_gist_compress_ecircle(internal) 4.427 + RETURNS internal 4.428 + LANGUAGE C STRICT 4.429 + AS '$libdir/latlon-v0005', 'pgl_gist_compress_ecircle'; 4.430 + 4.431 +CREATE OR REPLACE FUNCTION pgl_gist_compress_ecluster(internal) 4.432 + RETURNS internal 4.433 + LANGUAGE C STRICT 4.434 + AS '$libdir/latlon-v0005', 'pgl_gist_compress_ecluster'; 4.435 + 4.436 +CREATE OR REPLACE FUNCTION pgl_gist_decompress(internal) 4.437 + RETURNS internal 4.438 + LANGUAGE C STRICT 4.439 + AS '$libdir/latlon-v0005', 'pgl_gist_decompress'; 4.440 + 4.441 +CREATE OR REPLACE FUNCTION pgl_gist_penalty(internal, internal, internal) 4.442 + RETURNS internal 4.443 + LANGUAGE C STRICT 4.444 + AS '$libdir/latlon-v0005', 'pgl_gist_penalty'; 4.445 + 4.446 +CREATE OR REPLACE FUNCTION pgl_gist_picksplit(internal, internal) 4.447 + RETURNS internal 4.448 + LANGUAGE C STRICT 4.449 + AS '$libdir/latlon-v0005', 'pgl_gist_picksplit'; 4.450 + 4.451 +CREATE OR REPLACE FUNCTION pgl_gist_same(internal, internal, internal) 4.452 + RETURNS internal 4.453 + LANGUAGE C STRICT 4.454 + AS '$libdir/latlon-v0005', 'pgl_gist_same'; 4.455 + 4.456 +CREATE OR REPLACE FUNCTION pgl_gist_distance(internal, internal, smallint, oid) 4.457 + RETURNS internal 4.458 + LANGUAGE C STRICT 4.459 + AS '$libdir/latlon-v0005', 'pgl_gist_distance'; 4.460 +
5.1 --- a/latlon--0.5.sql Fri Sep 09 23:44:28 2016 +0200 5.2 +++ b/latlon--0.5.sql Mon Sep 12 18:00:52 2016 +0200 5.3 @@ -1134,6 +1134,32 @@ 5.4 join = areajoinsel 5.5 ); 5.6 5.7 +CREATE FUNCTION ebox_contains_castwrap(ebox, ebox) 5.8 + RETURNS boolean 5.9 + LANGUAGE sql IMMUTABLE AS 'SELECT $1::ecluster @> $2::ecluster'; 5.10 + 5.11 +CREATE OPERATOR @> ( 5.12 + leftarg = ebox, 5.13 + rightarg = ebox, 5.14 + procedure = ebox_contains_castwrap, 5.15 + commutator = <@, 5.16 + restrict = areasel, 5.17 + join = areajoinsel 5.18 +); 5.19 + 5.20 +CREATE FUNCTION ebox_contains_swapped_castwrap(ebox, ebox) 5.21 + RETURNS boolean 5.22 + LANGUAGE sql IMMUTABLE AS 'SELECT $2::ecluster @> $1::ecluster'; 5.23 + 5.24 +CREATE OPERATOR <@ ( 5.25 + leftarg = ebox, 5.26 + rightarg = ebox, 5.27 + procedure = ebox_contains_swapped_castwrap, 5.28 + commutator = @>, 5.29 + restrict = areasel, 5.30 + join = areajoinsel 5.31 +); 5.32 + 5.33 CREATE FUNCTION ebox_ecluster_contains_castwrap(ebox, ecluster) 5.34 RETURNS boolean 5.35 LANGUAGE sql IMMUTABLE AS 'SELECT $1::ecluster @> $2';
6.1 --- a/latlon-v0005.c Fri Sep 09 23:44:28 2016 +0200 6.2 +++ b/latlon-v0005.c Mon Sep 12 18:00:52 2016 +0200 6.3 @@ -489,7 +489,13 @@ 6.4 } 6.5 6.6 /* check if point is inside cluster */ 6.7 -static bool pgl_point_in_cluster(pgl_point *point, pgl_cluster *cluster) { 6.8 +/* (if point is on perimeter, then true is returned if and only if 6.9 + strict == false) */ 6.10 +static bool pgl_point_in_cluster( 6.11 + pgl_point *point, 6.12 + pgl_cluster *cluster, 6.13 + bool strict 6.14 +) { 6.15 int i, j, k; /* i: entry, j: point in entry, k: next point in entry */ 6.16 int entrytype; /* type of entry */ 6.17 int npoints; /* number of points in entry */ 6.18 @@ -504,8 +510,11 @@ 6.19 int counter = 0; /* counter for intersections east of point */ 6.20 /* iterate over all entries */ 6.21 for (i=0; i<cluster->nentries; i++) { 6.22 - /* get properties of entry */ 6.23 + /* get type of entry */ 6.24 entrytype = cluster->entries[i].entrytype; 6.25 + /* skip all entries but polygons if perimeters are excluded */ 6.26 + if (strict && entrytype != PGL_ENTRY_POLYGON) continue; 6.27 + /* get points of entry */ 6.28 npoints = cluster->entries[i].npoints; 6.29 points = PGL_ENTRY_POINTS(cluster, i); 6.30 /* determine east/west orientation of first point of entry and calculate 6.31 @@ -521,8 +530,8 @@ 6.32 else if (lon_dir > 0 && lon0 < lon_break) lon0 = pgl_round(lon0 + 360); 6.33 /* iterate over all edges and vertices */ 6.34 for (j=0; j<npoints; j++) { 6.35 - /* return true if point is on vertex of polygon */ 6.36 - if (pgl_point_cmp(point, &(points[j])) == 0) return true; 6.37 + /* return if point is on vertex of polygon */ 6.38 + if (pgl_point_cmp(point, &(points[j])) == 0) return !strict; 6.39 /* calculate index of next vertex */ 6.40 k = (j+1) % npoints; 6.41 /* skip last edge unless entry is (closed) outline or polygon */ 6.42 @@ -549,17 +558,17 @@ 6.43 /* consider longitude wrap-around for next vertex */ 6.44 if (lon_dir < 0 && lon2 > lon_break) lon2 = pgl_round(lon2 - 360); 6.45 else if (lon_dir > 0 && lon2 < lon_break) lon2 = pgl_round(lon2 + 360); 6.46 - /* return true if point is on horizontal (west to east) edge of polygon */ 6.47 + /* return if point is on horizontal (west to east) edge of polygon */ 6.48 if ( 6.49 lat0 == lat1 && lat0 == lat2 && 6.50 ( (lon0 >= lon1 && lon0 <= lon2) || (lon0 >= lon2 && lon0 <= lon1) ) 6.51 - ) return true; 6.52 + ) return !strict; 6.53 /* check if edge crosses east/west line of point */ 6.54 if ((lat1 < lat0 && lat2 >= lat0) || (lat2 < lat0 && lat1 >= lat0)) { 6.55 /* calculate longitude of intersection */ 6.56 lon = (lon1 * (lat2-lat0) + lon2 * (lat0-lat1)) / (lat2-lat1); 6.57 - /* return true if intersection goes (approximately) through point */ 6.58 - if (pgl_round(lon) == lon0) return true; 6.59 + /* return if intersection goes (approximately) through point */ 6.60 + if (pgl_round(lon) == lon0) return !strict; 6.61 /* count intersection if east of point and entry is polygon*/ 6.62 if (entrytype == PGL_ENTRY_POLYGON && lon > lon0) counter++; 6.63 } 6.64 @@ -569,8 +578,9 @@ 6.65 return counter & 1; 6.66 } 6.67 6.68 -/* check if all points of the second cluster are inside the first cluster */ 6.69 -static inline bool pgl_all_cluster_points_in_cluster( 6.70 +/* check if all points of the second cluster are strictly inside the first 6.71 + cluster */ 6.72 +static inline bool pgl_all_cluster_points_strictly_in_cluster( 6.73 pgl_cluster *outer, pgl_cluster *inner 6.74 ) { 6.75 int i, j; /* i: entry, j: point in entry */ 6.76 @@ -584,7 +594,7 @@ 6.77 /* iterate over all points in entry of "inner" cluster */ 6.78 for (j=0; j<npoints; j++) { 6.79 /* return false if one point of inner cluster is not in outer cluster */ 6.80 - if (!pgl_point_in_cluster(points+j, outer)) return false; 6.81 + if (!pgl_point_in_cluster(points+j, outer, true)) return false; 6.82 } 6.83 } 6.84 /* otherwise return true */ 6.85 @@ -606,36 +616,33 @@ 6.86 /* iterate over all points in entry of "inner" cluster */ 6.87 for (j=0; j<npoints; j++) { 6.88 /* return true if one point of inner cluster is in outer cluster */ 6.89 - if (pgl_point_in_cluster(points+j, outer)) return true; 6.90 + if (pgl_point_in_cluster(points+j, outer, false)) return true; 6.91 } 6.92 } 6.93 /* otherwise return false */ 6.94 return false; 6.95 } 6.96 6.97 -/* check if line segment crosses line */ 6.98 -/* returns -1 if yes, 1 if no, and 0 in corner cases */ 6.99 -/* NOTE: each line (segment) must have a length greater than zero */ 6.100 -static inline double pgl_lseg_crosses_line( 6.101 +/* check if line segment strictly crosses line (not just touching) */ 6.102 +static inline bool pgl_lseg_crosses_line( 6.103 double seg_x1, double seg_y1, double seg_x2, double seg_y2, 6.104 - double line_x1, double line_y1, double line_x2, double line_y2, 6.105 - bool strict 6.106 + double line_x1, double line_y1, double line_x2, double line_y2 6.107 ) { 6.108 - double value = ( 6.109 - (seg_x1-line_x1) * (line_y2-line_y1) - 6.110 - (seg_y1-line_y1) * (line_x2-line_x1) 6.111 - ) * ( 6.112 - (seg_x2-line_x1) * (line_y2-line_y1) - 6.113 - (seg_y2-line_y1) * (line_x2-line_x1) 6.114 - ); 6.115 - if (strict) return value < 0; 6.116 - else return value <= 0; 6.117 + return ( 6.118 + ( 6.119 + (seg_x1-line_x1) * (line_y2-line_y1) - 6.120 + (seg_y1-line_y1) * (line_x2-line_x1) 6.121 + ) * ( 6.122 + (seg_x2-line_x1) * (line_y2-line_y1) - 6.123 + (seg_y2-line_y1) * (line_x2-line_x1) 6.124 + ) 6.125 + ) < 0; 6.126 } 6.127 6.128 -/* check if paths and outlines of two clusters overlap */ 6.129 -/* (set strict to true to disregard corner cases) */ 6.130 +/* check if paths and outlines of two clusters strictly overlap (not just 6.131 + touching) */ 6.132 static bool pgl_outlines_overlap( 6.133 - pgl_cluster *cluster1, pgl_cluster *cluster2, bool strict 6.134 + pgl_cluster *cluster1, pgl_cluster *cluster2 6.135 ) { 6.136 int i1, j1, k1; /* i: entry, j: point in entry, k: next point in entry */ 6.137 int i2, j2, k2; 6.138 @@ -758,12 +765,10 @@ 6.139 if ( 6.140 pgl_lseg_crosses_line( 6.141 lat11, lon11, lat12, lon12, 6.142 - lat21, lon21, lat22, lon22, 6.143 - strict 6.144 + lat21, lon21, lat22, lon22 6.145 ) && pgl_lseg_crosses_line( 6.146 lat21, lon21, lat22, lon22, 6.147 - lat11, lon11, lat12, lon12, 6.148 - strict 6.149 + lat11, lon11, lat12, lon12 6.150 ) 6.151 ) { 6.152 return true; 6.153 @@ -778,8 +783,9 @@ 6.154 6.155 /* check if second cluster is completely contained in first cluster */ 6.156 static bool pgl_cluster_in_cluster(pgl_cluster *outer, pgl_cluster *inner) { 6.157 - if (!pgl_all_cluster_points_in_cluster(outer, inner)) return false; 6.158 - if (pgl_outlines_overlap(outer, inner, true)) return false; 6.159 + if (!pgl_all_cluster_points_strictly_in_cluster(outer, inner)) return false; 6.160 + if (pgl_any_cluster_points_in_cluster(inner, outer)) return false; 6.161 + if (pgl_outlines_overlap(outer, inner)) return false; 6.162 return true; 6.163 } 6.164 6.165 @@ -789,7 +795,7 @@ 6.166 ) { 6.167 if (pgl_any_cluster_points_in_cluster(cluster1, cluster2)) return true; 6.168 if (pgl_any_cluster_points_in_cluster(cluster2, cluster1)) return true; 6.169 - if (pgl_outlines_overlap(cluster1, cluster2, false)) return true; 6.170 + if (pgl_outlines_overlap(cluster1, cluster2)) return true; 6.171 return false; 6.172 } 6.173 6.174 @@ -812,7 +818,7 @@ 6.175 double dist; /* distance calculated in one step */ 6.176 double min_dist = INFINITY; /* minimum distance */ 6.177 /* distance is zero if point is contained in cluster */ 6.178 - if (pgl_point_in_cluster(point, cluster)) return 0; 6.179 + if (pgl_point_in_cluster(point, cluster, false)) return 0; 6.180 /* iterate over all entries */ 6.181 for (i=0; i<cluster->nentries; i++) { 6.182 /* get properties of entry */ 6.183 @@ -2343,7 +2349,7 @@ 6.184 cluster->bounding.center.lat, cluster->bounding.center.lon 6.185 ) > cluster->bounding.radius 6.186 ) retval = false; 6.187 - else retval = pgl_point_in_cluster(point, cluster); 6.188 + else retval = pgl_point_in_cluster(point, cluster, false); 6.189 PG_FREE_IF_COPY(cluster, 1); 6.190 PG_RETURN_BOOL(retval); 6.191 }