pgLatLon
annotate README.html @ 79:16787a19a325
Do not return CSTRING to static memory
Avoids wrong pfree under certain circumstances
(e.g. array_agg on empty EBOX or ECLUSTER).
Avoids wrong pfree under certain circumstances
(e.g. array_agg on empty EBOX or ECLUSTER).
| author | jbe |
|---|---|
| date | Thu Oct 23 10:16:01 2025 +0200 (3 days ago) |
| parents | 76b3fd3293fc |
| children | 8a08dc69de98 |
| rev | line source |
|---|---|
| jbe@74 | 1 <html><head><title>pgLatLon v0.15 documentation</title></head><body> |
| jbe@74 | 2 <h1>pgLatLon v0.15 documentation</h1> |
| jbe@0 | 3 |
| jbe@0 | 4 <p>pgLatLon is a spatial database extension for the PostgreSQL object-relational |
| jbe@0 | 5 database management system providing geographic data types and spatial indexing |
| jbe@0 | 6 for the WGS-84 spheroid.</p> |
| jbe@0 | 7 |
| jbe@32 | 8 <p>While many other spatial databases still use imprecise bounding boxes for |
| jbe@32 | 9 many operations, pgLatLon aims to support more precise calculations for all |
| jbe@32 | 10 implemented geographic operators. Efficient indexing of geographic objects |
| jbe@32 | 11 is provided using space-filling fractal curves. Optimizations on bit level |
| jbe@32 | 12 (including logarithmic compression) allow for a highly memory-efficient |
| jbe@32 | 13 non-overlapping index suitable for huge datasets.</p> |
| jbe@0 | 14 |
| jbe@11 | 15 <p>pgLatLon is a lightweight solution as it only depends on PostgreSQL itself (and |
| jbe@11 | 16 a C compiler for building).</p> |
| jbe@11 | 17 |
| jbe@0 | 18 <p>Unlike competing spatial extensions for PostgreSQL, pgLatLon is available under |
| jbe@0 | 19 the permissive MIT/X11 license to avoid problems with viral licenses like the |
| jbe@0 | 20 GPLv2/v3.</p> |
| jbe@0 | 21 |
| jbe@0 | 22 <h2>Installation</h2> |
| jbe@0 | 23 |
| jbe@0 | 24 <h3>Automatic installation</h3> |
| jbe@0 | 25 |
| jbe@0 | 26 <p>Prerequisites:</p> |
| jbe@0 | 27 |
| jbe@0 | 28 <ul> |
| jbe@0 | 29 <li>Ensure that the <code>pg_config</code> binary is in your path (shipped with PostgreSQL).</li> |
| jbe@0 | 30 <li>Ensure that GNU Make is available (either as <code>make</code> or <code>gmake</code>).</li> |
| jbe@0 | 31 </ul> |
| jbe@0 | 32 |
| jbe@0 | 33 <p>Then simply type:</p> |
| jbe@0 | 34 |
| jbe@0 | 35 <pre><code>make install |
| jbe@0 | 36 </code></pre> |
| jbe@0 | 37 |
| jbe@0 | 38 <h3>Manual installation</h3> |
| jbe@0 | 39 |
| jbe@0 | 40 <p>It is also possible to compile and install the extension without GNU Make as |
| jbe@0 | 41 follows:</p> |
| jbe@0 | 42 |
| jbe@74 | 43 <pre><code>cc -Wall -O2 -fPIC -shared -I `pg_config --includedir-server` -o latlon-v0010.so latlon-v0010.c |
| jbe@74 | 44 cp latlon-v0010.so `pg_config --pkglibdir` |
| jbe@0 | 45 cp latlon.control `pg_config --sharedir`/extension/ |
| jbe@13 | 46 cp latlon--*.sql `pg_config --sharedir`/extension/ |
| jbe@0 | 47 </code></pre> |
| jbe@0 | 48 |
| jbe@0 | 49 <h3>Loading the extension</h3> |
| jbe@0 | 50 |
| jbe@0 | 51 <p>After installation, you can create a database and load the extension as |
| jbe@0 | 52 follows:</p> |
| jbe@0 | 53 |
| jbe@0 | 54 <pre><code>% createdb test_database |
| jbe@0 | 55 % psql test_database |
| jbe@0 | 56 psql (9.5.4) |
| jbe@0 | 57 Type "help" for help. |
| jbe@0 | 58 |
| jbe@0 | 59 test_database=# CREATE EXTENSION latlon; |
| jbe@0 | 60 </code></pre> |
| jbe@0 | 61 |
| jbe@16 | 62 <h3>Updating</h3> |
| jbe@16 | 63 |
| jbe@16 | 64 <p>Before updating your database cluster to a new version of pgLatLon, you may |
| jbe@16 | 65 want to uninstall the old by calling "<code>make uninstall</code>" in the unpacked source |
| jbe@16 | 66 code directory of your old pgLatLon version. You may also manually delete the |
| jbe@16 | 67 <code>latlon-v????.so</code> files from your PostgreSQL library directory and the |
| jbe@16 | 68 <code>latlon.control</code> and <code>latlon--*.sql</code> files from your PostgreSQL extension |
| jbe@16 | 69 directory.</p> |
| jbe@16 | 70 |
| jbe@16 | 71 <p>The new version can be installed as described above. For altering an existing |
| jbe@16 | 72 database to use the installed new version (mandatory if you removed the old |
| jbe@16 | 73 version), execute the following SQL command in the respective databases:</p> |
| jbe@16 | 74 |
| jbe@16 | 75 <pre><code>ALTER EXTENSION latlon UPDATE; |
| jbe@16 | 76 </code></pre> |
| jbe@16 | 77 |
| jbe@16 | 78 <p>If the update contains modifications to operator classes, it may be necessary |
| jbe@16 | 79 to drop all indices on geographic data types first (you will get an error |
| jbe@16 | 80 message in this case). These indices can be re-created after the update.</p> |
| jbe@16 | 81 |
| jbe@16 | 82 <p>Note that taking several update steps at once (e.g. updating from version 0.2 |
| jbe@16 | 83 directly to version 0.4) requires the intermediate versions to be installed |
| jbe@16 | 84 (i.e. in this example version 0.3 would need to be installed). Whenever you |
| jbe@16 | 85 install or uninstall an intermediate or old version, make sure to afterwards |
| jbe@16 | 86 re-install the latest pgLatLon version to ensure that the <code>latlon.control</code> file |
| jbe@16 | 87 is available and points to the latest version.</p> |
| jbe@16 | 88 |
| jbe@16 | 89 <p>If the update contains modifications to the internal data representation |
| jbe@16 | 90 format, an update path might not be available. In this case, create a dump of |
| jbe@16 | 91 your database, delete your database, and restore it from your dump.</p> |
| jbe@16 | 92 |
| jbe@16 | 93 <p>Be sure to always keep backups of all your data before attempting to update.</p> |
| jbe@16 | 94 |
| jbe@0 | 95 <h2>Reference</h2> |
| jbe@0 | 96 |
| jbe@0 | 97 <h3>1. Types</h3> |
| jbe@0 | 98 |
| jbe@0 | 99 <p>pgLatLon provides four geographic types: <code>epoint</code>, <code>ebox</code>, <code>ecircle</code>, and |
| jbe@0 | 100 <code>ecluster</code>.</p> |
| jbe@0 | 101 |
| jbe@0 | 102 <h4><code>epoint</code></h4> |
| jbe@0 | 103 |
| jbe@33 | 104 <p>A point on the Earth spheroid (WGS-84).</p> |
| jbe@0 | 105 |
| jbe@0 | 106 <p>The text input format is <code>'[N|S]<float> [E|W]<float>'</code>, where each float is in |
| jbe@0 | 107 degrees. Note the required white space between the latitude and longitude |
| jbe@0 | 108 components. Each floating point number may have a sign, in which case <code>N</code>/<code>S</code> |
| jbe@0 | 109 or <code>E</code>/<code>W</code> are switched respectively (e.g. <code>E-5</code> is the same as <code>W5</code>).</p> |
| jbe@0 | 110 |
| jbe@0 | 111 <p>An <code>epoint</code> may also be created from two floating point numbers by calling |
| jbe@0 | 112 <code>epoint(latitude, longitude)</code>, where positive latitudes are used for the |
| jbe@0 | 113 northern hemisphere, negative latitudes are used for the southern hemisphere, |
| jbe@0 | 114 positive longitudes indicate positions east of the prime meridian, and negative |
| jbe@0 | 115 longitudes indicate positions west of the prime meridian.</p> |
| jbe@0 | 116 |
| jbe@0 | 117 <p>Latitudes exceeding -90 or +90 degrees are truncated to -90 or +90 |
| jbe@0 | 118 respectively, in which case a warning will be issued. Longitudes exceeding -180 |
| jbe@0 | 119 or +180 degrees will be converted to values between -180 and +180 (both |
| jbe@0 | 120 inclusive) by adding or substracting a multiple of 360 degrees, in which case a |
| jbe@0 | 121 notice will be issued.</p> |
| jbe@0 | 122 |
| jbe@0 | 123 <p>If the latitude is -90 or +90 (south pole or north pole), a longitude value is |
| jbe@0 | 124 still stored in the datum, and if a point is on the prime meridian or the |
| jbe@0 | 125 180th meridian, the east/west bit is also stored in the datum. In case of the |
| jbe@0 | 126 prime meridian, this is done by storing a floating point value of -0 for |
| jbe@0 | 127 0 degrees west and a value of +0 for 0 degrees east. In case of the |
| jbe@0 | 128 180th meridian, this is done by storing -180 or +180 respectively. The equality |
| jbe@33 | 129 operator, however, returns true when the same points on Earth are described, |
| jbe@0 | 130 i.e. the longitude is ignored for the poles, and 180 degrees west is considered |
| jbe@0 | 131 to be equal to 180 degrees east.</p> |
| jbe@0 | 132 |
| jbe@0 | 133 <h4><code>ebox</code></h4> |
| jbe@0 | 134 |
| jbe@33 | 135 <p>An area on Earth demarcated by a southern and northern latitude, and a western |
| jbe@0 | 136 and eastern longitude (all given in WGS-84).</p> |
| jbe@0 | 137 |
| jbe@0 | 138 <p>The text input format is |
| jbe@0 | 139 <code>'{N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float>'</code>, where each float is in |
| jbe@0 | 140 degrees. The ordering of the four white-space separated blocks is not |
| jbe@0 | 141 significant. To include the 180th meridian, one longitude boundary must be |
| jbe@0 | 142 equal to or exceed <code>W180</code> or <code>E180</code>, e.g. <code>'N10 N20 E170 E190'</code>.</p> |
| jbe@0 | 143 |
| jbe@0 | 144 <p>A special value is the empty area, denoted by the text represenation <code>'empty'</code>. |
| jbe@0 | 145 Such an <code>ebox</code> does not contain any point.</p> |
| jbe@0 | 146 |
| jbe@0 | 147 <p>An <code>ebox</code> may also be created from four floating point numbers by calling |
| jbe@0 | 148 <code>ebox(min_latitude, max_latitude, min_longitude, max_longitude)</code>, where |
| jbe@0 | 149 positive values are used for north and east, and negative values are used for |
| jbe@0 | 150 south and west. If <code>min_latitude</code> is strictly greater than <code>max_latitude</code>, an |
| jbe@0 | 151 empty <code>ebox</code> is created. If <code>min_longitude</code> is greater than <code>max_longitude</code> and |
| jbe@0 | 152 if both longitudes are between -180 and +180 degrees, then the area oriented in |
| jbe@0 | 153 such way that the 180th meridian is included.</p> |
| jbe@0 | 154 |
| jbe@0 | 155 <p>If the longitude span is less than 120 degrees, an <code>ebox</code> may be alternatively |
| jbe@0 | 156 created from two <code>epoints</code> in the following way: <code>ebox(epoint(lat1, lon1), |
| jbe@0 | 157 epoint(lat2, lon2))</code>. In this case <code>lat1</code> and <code>lat2</code> as well as <code>lon1</code> and |
| jbe@0 | 158 <code>lon2</code> can be swapped without any impact.</p> |
| jbe@0 | 159 |
| jbe@0 | 160 <h4><code>ecircle</code></h4> |
| jbe@0 | 161 |
| jbe@0 | 162 <p>An area containing all points not farther away from a given center point |
| jbe@0 | 163 (WGS-84) than a given radius.</p> |
| jbe@0 | 164 |
| jbe@0 | 165 <p>The text input format is <code>'{N|S}<float> {E|W}<float> <float>'</code>, where the first |
| jbe@0 | 166 two floats denote the center point in degrees and the third float denotes the |
| jbe@0 | 167 radius in meters. A radius equal to minus infinity denotes an empty circle |
| jbe@0 | 168 which contains no point at all (despite having a center), while a radius equal |
| jbe@0 | 169 to zero denotes a circle that includes a single point.</p> |
| jbe@0 | 170 |
| jbe@0 | 171 <p>An <code>ecircle</code> may also be created by calling <code>ecircle(epoint(...), radius)</code> or |
| jbe@0 | 172 from three floating point numbers by calling <code>ecircle(latitude, longitude, |
| jbe@0 | 173 radius)</code>.</p> |
| jbe@0 | 174 |
| jbe@0 | 175 <h4><code>ecluster</code></h4> |
| jbe@0 | 176 |
| jbe@0 | 177 <p>A collection of points, paths, polygons, and outlines on the WGS-84 spheroid. |
| jbe@0 | 178 Each path, polygon, or outline must cover a longitude range of less than |
| jbe@0 | 179 180 degrees to avoid ambiguities.</p> |
| jbe@0 | 180 |
| jbe@0 | 181 <p>The text input format is a white-space separated list of the following items:</p> |
| jbe@0 | 182 |
| jbe@0 | 183 <ul> |
| jbe@0 | 184 <li><code>point ({N|S}<float> {E|W}<float>)</code></li> |
| jbe@0 | 185 <li><code>path ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)</code></li> |
| jbe@0 | 186 <li><code>outline ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)</code></li> |
| jbe@0 | 187 <li><code>polygon ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)</code></li> |
| jbe@0 | 188 </ul> |
| jbe@0 | 189 |
| jbe@0 | 190 <p>Paths are open by default (i.e. there is no connection from the last point in |
| jbe@0 | 191 the list to the first point in the list). Outlines and polygons, in contrast, |
| jbe@0 | 192 are automatically closed (i.e. there is a line segment from the last point in |
| jbe@0 | 193 the list to the first point in the list) which means the first point should not |
| jbe@0 | 194 be repeated as last point in the list. Polygons are filled, outlines are not.</p> |
| jbe@0 | 195 |
| jbe@0 | 196 <h3>2. Indices</h3> |
| jbe@0 | 197 |
| jbe@0 | 198 <p>Two kinds of indices are supported: B-tree and GiST indices.</p> |
| jbe@0 | 199 |
| jbe@0 | 200 <h4>B-tree indices</h4> |
| jbe@0 | 201 |
| jbe@0 | 202 <p>A B-tree index can be used for simple equality searches and is supported by the |
| jbe@0 | 203 <code>epoint</code>, <code>ebox</code>, and <code>ecircle</code> data types. B-tree indices can not be used for |
| jbe@0 | 204 geographic searches.</p> |
| jbe@0 | 205 |
| jbe@0 | 206 <h4>GiST indices</h4> |
| jbe@0 | 207 |
| jbe@0 | 208 <p>For geographic searches, GiST indices must be used. The <code>epoint</code>, <code>ecircle</code>, |
| jbe@0 | 209 and <code>ecluster</code> data types support GiST indexing. A GiST index for geographic |
| jbe@0 | 210 searches can be created as follows:</p> |
| jbe@0 | 211 |
| jbe@0 | 212 <pre><code>CREATE TABLE tbl ( |
| jbe@0 | 213 id serial4 PRIMARY KEY, |
| jbe@0 | 214 loc epoint NOT NULL ); |
| jbe@0 | 215 |
| jbe@0 | 216 CREATE INDEX name_of_index ON tbl USING gist (loc); |
| jbe@0 | 217 </code></pre> |
| jbe@0 | 218 |
| jbe@0 | 219 <p>GiST indices also support nearest neighbor searches when using the distance |
| jbe@0 | 220 operator (<code><-></code>) in the ORDER BY clause.</p> |
| jbe@0 | 221 |
| jbe@0 | 222 <h4>Indices on other data types (e.g. GeoJSON)</h4> |
| jbe@0 | 223 |
| jbe@0 | 224 <p>Note that further types can be indexed by using an index on an expression with |
| jbe@0 | 225 a conversion function. One conversion function provided by pgLatLon is the |
| jbe@49 | 226 <code>GeoJSON_to_ecluster(jsonb, text)</code> function:</p> |
| jbe@0 | 227 |
| jbe@0 | 228 <pre><code>CREATE TABLE tbl ( |
| jbe@0 | 229 id serial4 PRIMARY KEY, |
| jbe@0 | 230 loc jsonb NOT NULL ); |
| jbe@0 | 231 |
| jbe@58 | 232 CREATE INDEX name_of_index ON tbl USING gist ((GeoJSON_to_ecluster("loc"))); |
| jbe@0 | 233 </code></pre> |
| jbe@0 | 234 |
| jbe@0 | 235 <p>When using the conversion function in an expression, the index will be used |
| jbe@0 | 236 automatically:</p> |
| jbe@0 | 237 |
| jbe@0 | 238 <pre><code>SELECT * FROM tbl WHERE GeoJSON_to_ecluster("loc") && 'N50 E10 10000'::ecircle; |
| jbe@0 | 239 </code></pre> |
| jbe@0 | 240 |
| jbe@0 | 241 <h3>3. Operators</h3> |
| jbe@0 | 242 |
| jbe@0 | 243 <h4>Equality operator <code>=</code></h4> |
| jbe@0 | 244 |
| jbe@0 | 245 <p>Tests if two geographic objects are equal.</p> |
| jbe@0 | 246 |
| jbe@0 | 247 <p>The longitude is ignored for the poles, and 180 degrees west is considered to |
| jbe@0 | 248 be equal to 180 degrees east.</p> |
| jbe@0 | 249 |
| jbe@0 | 250 <p>For boxes and circles, two empty objects are considered equal. (Note that a |
| jbe@0 | 251 circle is not empty if the radius is zero but only if it is negative infinity, |
| jbe@0 | 252 i.e. smaller than zero.) Two circles with a positive infinite radius are also |
| jbe@0 | 253 considered equal.</p> |
| jbe@0 | 254 |
| jbe@0 | 255 <p>Implemented for:</p> |
| jbe@0 | 256 |
| jbe@0 | 257 <ul> |
| jbe@0 | 258 <li><code>epoint = epoint</code></li> |
| jbe@0 | 259 <li><code>ebox = ebox</code></li> |
| jbe@0 | 260 <li><code>ecircle = ecircle</code></li> |
| jbe@0 | 261 </ul> |
| jbe@0 | 262 |
| jbe@0 | 263 <p>The negation is the inequality operator (<code><></code> or <code>!=</code>).</p> |
| jbe@0 | 264 |
| jbe@0 | 265 <h4>Linear ordering operators <code><<<</code>, <code><<<=</code>, <code>>>>=</code>, <code>>>></code></h4> |
| jbe@0 | 266 |
| jbe@0 | 267 <p>These operators create an arbitrary (but well-defined) linear ordering of |
| jbe@0 | 268 geographic objects, which is used internally for B-tree indexing and merge |
| jbe@0 | 269 joins. These operators will usually not be used by an application programmer.</p> |
| jbe@0 | 270 |
| jbe@0 | 271 <h4>Overlap operator <code>&&</code></h4> |
| jbe@0 | 272 |
| jbe@0 | 273 <p>Tests if two geographic objects have at least one point in common. Currently |
| jbe@0 | 274 implemented for:</p> |
| jbe@0 | 275 |
| jbe@0 | 276 <ul> |
| jbe@0 | 277 <li><code>epoint && ebox</code></li> |
| jbe@0 | 278 <li><code>epoint && ecircle</code></li> |
| jbe@0 | 279 <li><code>epoint && ecluster</code></li> |
| jbe@0 | 280 <li><code>ebox && ebox</code></li> |
| jbe@16 | 281 <li><code>ebox && ecircle</code></li> |
| jbe@16 | 282 <li><code>ebox && ecluster</code></li> |
| jbe@0 | 283 <li><code>ecircle && ecircle</code></li> |
| jbe@0 | 284 <li><code>ecircle && ecluster</code></li> |
| jbe@16 | 285 <li><code>ecluster && ecluster</code></li> |
| jbe@0 | 286 </ul> |
| jbe@0 | 287 |
| jbe@20 | 288 <p>The <code>&&</code> operator is commutative, i.e. "<code>a && b</code>" is the same as "<code>b && a</code>". |
| jbe@20 | 289 Each commutation is supported as well.</p> |
| jbe@0 | 290 |
| jbe@11 | 291 <h4>Lossy overlap operator <code>&&+</code></h4> |
| jbe@11 | 292 |
| jbe@11 | 293 <p>Tests if two geographic objects may have at least one point in common. Opposed |
| jbe@11 | 294 to the <code>&&</code> operator, the <code>&&+</code> operator may return false positives and is |
| jbe@11 | 295 currently implemented for:</p> |
| jbe@11 | 296 |
| jbe@11 | 297 <ul> |
| jbe@11 | 298 <li><code>epoint &&+ ecluster</code></li> |
| jbe@11 | 299 <li><code>ebox &&+ ecircle</code></li> |
| jbe@11 | 300 <li><code>ebox &&+ ecluster</code></li> |
| jbe@11 | 301 <li><code>ecircle &&+ ecluster</code></li> |
| jbe@11 | 302 <li><code>ecluster &&+ ecluster</code></li> |
| jbe@11 | 303 </ul> |
| jbe@11 | 304 |
| jbe@20 | 305 <p>The <code>&&+</code> operator is commutative, i.e. "<code>a &&+ b</code>" is the same as "<code>b &&+ a</code>". |
| jbe@16 | 306 Each commutation is supported as well.</p> |
| jbe@11 | 307 |
| jbe@11 | 308 <p>Where two data types support both the <code>&&</code> and the <code>&&+</code> operator, the <code>&&+</code> |
| jbe@11 | 309 operator computes faster.</p> |
| jbe@11 | 310 |
| jbe@16 | 311 <h4>Contains operator <code>@></code></h4> |
| jbe@16 | 312 |
| jbe@16 | 313 <p>Tests if the object right of the operator is contained in the object left of |
| jbe@16 | 314 the operator. Currently implemented for:</p> |
| jbe@16 | 315 |
| jbe@16 | 316 <ul> |
| jbe@16 | 317 <li><code>ebox @> epoint</code> (alias for <code>&&</code>)</li> |
| jbe@20 | 318 <li><code>ebox @> ebox</code></li> |
| jbe@16 | 319 <li><code>ebox @> ecluster</code></li> |
| jbe@16 | 320 <li><code>ecluster @> epoint</code> (alias for <code>&&</code>)</li> |
| jbe@16 | 321 <li><code>ecluster @> ebox</code></li> |
| jbe@16 | 322 <li><code>ecluster @> ecluster</code></li> |
| jbe@16 | 323 </ul> |
| jbe@16 | 324 |
| jbe@20 | 325 <p>The commutator of <code>@></code> ("contains") is <code><@</code> ("is contained in"), i.e. |
| jbe@20 | 326 "<code>a @> b</code>" is the same as "<code>b <@ a</code>".</p> |
| jbe@20 | 327 |
| jbe@20 | 328 <p>Whether the perimeter of an object is taken into account is undefined and may |
| jbe@20 | 329 differ between the left and the right hand side of the operator. The current |
| jbe@65 | 330 implementation (where not an alias for <code>&&</code>) returns true only if an object is |
| jbe@65 | 331 contained completely within the other object, not touching its perimeter, |
| jbe@65 | 332 paths, outlines, or any singular points.</p> |
| jbe@16 | 333 |
| jbe@0 | 334 <h4>Distance operator <code><-></code></h4> |
| jbe@0 | 335 |
| jbe@0 | 336 <p>Calculates the shortest distance between two geographic objects in meters (zero |
| jbe@0 | 337 if the objects are overlapping). Currently implemented for:</p> |
| jbe@0 | 338 |
| jbe@0 | 339 <ul> |
| jbe@0 | 340 <li><code>epoint <-> epoint</code></li> |
| jbe@16 | 341 <li><code>epoint <-> ebox</code></li> |
| jbe@0 | 342 <li><code>epoint <-> ecircle</code></li> |
| jbe@0 | 343 <li><code>epoint <-> ecluster</code></li> |
| jbe@16 | 344 <li><code>ebox <-> ebox</code></li> |
| jbe@16 | 345 <li><code>ebox <-> ecircle</code></li> |
| jbe@16 | 346 <li><code>ebox <-> ecluster</code></li> |
| jbe@0 | 347 <li><code>ecircle <-> ecircle</code></li> |
| jbe@0 | 348 <li><code>ecircle <-> ecluster</code></li> |
| jbe@16 | 349 <li><code>ecluster <-> ecluster</code></li> |
| jbe@0 | 350 </ul> |
| jbe@0 | 351 |
| jbe@20 | 352 <p>The <code><-></code> operator is commutative, i.e. "<code>a <-> b</code>" is the same as "<code>b <-> a</code>". |
| jbe@0 | 353 Each commutation is supported as well.</p> |
| jbe@0 | 354 |
| jbe@0 | 355 <p>For short distances, the result is very accurate (i.e. respects the dimensions |
| jbe@0 | 356 of the WGS-84 spheroid). For longer distances in the order of magnitude of |
| jbe@33 | 357 Earth's radius or greater, the value is only approximate (but the error is |
| jbe@0 | 358 still less than 0.2% as long as no polygons with very long edges are involved).</p> |
| jbe@0 | 359 |
| jbe@0 | 360 <p>The functions <code>distance(epoint, epoint)</code> and <code>distance(ecluster, epoint)</code> can |
| jbe@0 | 361 be used as an alias for this operator.</p> |
| jbe@0 | 362 |
| jbe@0 | 363 <p>Note: In case of radial searches with a fixed radius, this operator should |
| jbe@0 | 364 not be used. Instead, an <code>ecircle</code> should be created and used in combination |
| jbe@0 | 365 with the overlap operator (<code>&&</code>). Alternatively, the functions |
| jbe@0 | 366 <code>distance_within(epoint, epoint, float8)</code> or <code>distance_within(ecluster, epoint, |
| jbe@0 | 367 float8)</code> can be used for fixed-radius searches.</p> |
| jbe@0 | 368 |
| jbe@0 | 369 <h3>4. Functions</h3> |
| jbe@0 | 370 |
| jbe@0 | 371 <h4><code>center(circle)</code></h4> |
| jbe@0 | 372 |
| jbe@0 | 373 <p>Returns the center of an <code>ecircle</code> as an <code>epoint</code>.</p> |
| jbe@0 | 374 |
| jbe@0 | 375 <h4><code>distance(epoint, epoint)</code></h4> |
| jbe@0 | 376 |
| jbe@0 | 377 <p>Calculates the distance between two <code>epoint</code> datums in meters. This function is |
| jbe@0 | 378 an alias for the distance operator <code><-></code>.</p> |
| jbe@0 | 379 |
| jbe@0 | 380 <p>Note: In case of radial searches with a fixed radius, this function should not be |
| jbe@0 | 381 used. Use <code>distance_within(epoint, epoint, float8)</code> instead.</p> |
| jbe@0 | 382 |
| jbe@0 | 383 <h4><code>distance(ecluster, epoint)</code></h4> |
| jbe@0 | 384 |
| jbe@0 | 385 <p>Calculates the distance from an <code>ecluster</code> to an <code>epoint</code> in meters. This |
| jbe@0 | 386 function is an alias for the distance operator <code><-></code>.</p> |
| jbe@0 | 387 |
| jbe@0 | 388 <p>Note: In case of radial searches with a fixed radius, this function should not be |
| jbe@0 | 389 used. Use <code>distance_within(epoint, epoint, float8)</code> instead.</p> |
| jbe@0 | 390 |
| jbe@0 | 391 <h4><code>distance_within(</code>variable <code>epoint,</code> fixed <code>epoint,</code> radius <code>float8)</code></h4> |
| jbe@0 | 392 |
| jbe@0 | 393 <p>Checks if the distance between two <code>epoint</code> datums is not greater than a given |
| jbe@0 | 394 value (search radius).</p> |
| jbe@0 | 395 |
| jbe@0 | 396 <p>Note: In case of radial searches with a fixed radius, the first argument must |
| jbe@0 | 397 be used for the table column, while the second argument must be used for the |
| jbe@0 | 398 search center. Otherwise an existing index cannot be used.</p> |
| jbe@0 | 399 |
| jbe@0 | 400 <h4><code>distance_within(</code>variable <code>ecluster,</code> fixed <code>epoint,</code> radius <code>float8)</code></h4> |
| jbe@0 | 401 |
| jbe@0 | 402 <p>Checks if the distance from an <code>ecluster</code> to an <code>epoint</code> is not greater than a |
| jbe@0 | 403 given value (search radius).</p> |
| jbe@0 | 404 |
| jbe@0 | 405 <h4><code>ebox(</code>latmin <code>float8,</code> latmax <code>float8,</code> lonmin <code>float8,</code> lonmax <code>float8)</code></h4> |
| jbe@0 | 406 |
| jbe@0 | 407 <p>Creates a new <code>ebox</code> with the given boundaries. |
| jbe@0 | 408 See "1. Types", subsection <code>ebox</code> for details.</p> |
| jbe@0 | 409 |
| jbe@0 | 410 <h4><code>ebox(epoint, epoint)</code></h4> |
| jbe@0 | 411 |
| jbe@0 | 412 <p>Creates a new <code>ebox</code>. This function may only be used if the longitude |
| jbe@0 | 413 difference is less than or equal to 120 degrees. |
| jbe@0 | 414 See "1. Types", subsection <code>ebox</code> for details.</p> |
| jbe@0 | 415 |
| jbe@0 | 416 <h4><code>ecircle(epoint, float8)</code></h4> |
| jbe@0 | 417 |
| jbe@0 | 418 <p>Creates an <code>ecircle</code> with the given center point and radius.</p> |
| jbe@0 | 419 |
| jbe@0 | 420 <h4><code>ecircle(</code>latitude <code>float8,</code> longitude <code>float8,</code> radius <code>float8)</code></h4> |
| jbe@0 | 421 |
| jbe@0 | 422 <p>Creates an <code>ecircle</code> with the given center point and radius.</p> |
| jbe@0 | 423 |
| jbe@0 | 424 <h4><code>ecluster_concat(ecluster, ecluster)</code></h4> |
| jbe@0 | 425 |
| jbe@0 | 426 <p>Combines two clusters to form a new <code>ecluster</code> by uniting all entries of both |
| jbe@0 | 427 clusters. Note that two overlapping areas of polygons annihilate each other |
| jbe@0 | 428 (which may be used to create polygons with holes).</p> |
| jbe@0 | 429 |
| jbe@0 | 430 <h4><code>ecluster_concat(ecluster[])</code></h4> |
| jbe@0 | 431 |
| jbe@0 | 432 <p>Creates a new <code>ecluster</code> that unites all entries of all clusters in the passed |
| jbe@0 | 433 array. Note that two overlapping areas of polygons annihilate each other (which |
| jbe@0 | 434 may be used to create polygons with holes).</p> |
| jbe@0 | 435 |
| jbe@0 | 436 <h4><code>ecluster_create_multipoint(epoint[])</code></h4> |
| jbe@0 | 437 |
| jbe@0 | 438 <p>Creates a new <code>ecluster</code> which contains multiple points.</p> |
| jbe@0 | 439 |
| jbe@0 | 440 <h4><code>ecluster_create_outline(epoint[])</code></h4> |
| jbe@0 | 441 |
| jbe@0 | 442 <p>Creates a new <code>ecluster</code> that is an outline given by the passed points.</p> |
| jbe@0 | 443 |
| jbe@0 | 444 <h4><code>ecluster_create_path(epoint[])</code></h4> |
| jbe@0 | 445 |
| jbe@0 | 446 <p>Creates a new <code>ecluster</code> that is a path given by the passed points.</p> |
| jbe@0 | 447 |
| jbe@0 | 448 <h4><code>ecluster_create_polygon(epoint[])</code></h4> |
| jbe@0 | 449 |
| jbe@0 | 450 <p>Creates a new <code>ecluster</code> that is a polygon given by the passed points.</p> |
| jbe@0 | 451 |
| jbe@0 | 452 <h4><code>ecluster_extract_outlines(ecluster)</code></h4> |
| jbe@0 | 453 |
| jbe@0 | 454 <p>Set-returning function that returns the outlines of an <code>ecluster</code> as <code>epoint[]</code> |
| jbe@0 | 455 rows.</p> |
| jbe@0 | 456 |
| jbe@0 | 457 <h4><code>ecluster_extract_paths(ecluster)</code></h4> |
| jbe@0 | 458 |
| jbe@0 | 459 <p>Set-returning function that returns the paths of an <code>ecluster</code> as <code>epoint[]</code> |
| jbe@0 | 460 rows.</p> |
| jbe@0 | 461 |
| jbe@0 | 462 <h4><code>ecluster_extract_points(ecluster)</code></h4> |
| jbe@0 | 463 |
| jbe@0 | 464 <p>Set-returning function that returns the points of an <code>ecluster</code> as <code>epoint</code> |
| jbe@0 | 465 rows.</p> |
| jbe@0 | 466 |
| jbe@0 | 467 <h4><code>ecluster_extract_polygons(ecluster)</code></h4> |
| jbe@0 | 468 |
| jbe@0 | 469 <p>Set-returning function that returns the polygons of an <code>ecluster</code> as <code>epoint[]</code> |
| jbe@0 | 470 rows.</p> |
| jbe@0 | 471 |
| jbe@0 | 472 <h4><code>empty_ebox</code>()</h4> |
| jbe@0 | 473 |
| jbe@0 | 474 <p>Returns the empty <code>ebox</code>. |
| jbe@0 | 475 See "1. Types", subsection <code>ebox</code> for details.</p> |
| jbe@0 | 476 |
| jbe@0 | 477 <h4><code>epoint(</code>latitude <code>float8,</code> longitude <code>float8)</code></h4> |
| jbe@0 | 478 |
| jbe@0 | 479 <p>Returns an <code>epoint</code> with the given latitude and longitude.</p> |
| jbe@0 | 480 |
| jbe@0 | 481 <h4><code>epoint_latlon(</code>latitude <code>float8,</code> longitude <code>float8)</code></h4> |
| jbe@0 | 482 |
| jbe@0 | 483 <p>Alias for <code>epoint(float8, float8)</code>.</p> |
| jbe@0 | 484 |
| jbe@0 | 485 <h4><code>epoint_lonlat(</code>longitude <code>float8,</code> latitude <code>float8)</code></h4> |
| jbe@0 | 486 |
| jbe@0 | 487 <p>Same as <code>epoint(float8, float8)</code> but with arguments reversed.</p> |
| jbe@0 | 488 |
| jbe@42 | 489 <h4><code>fair_distance(ecluster, epoint,</code> samples <code>int4 = 10000)</code></h4> |
| jbe@42 | 490 |
| jbe@42 | 491 <p>When working with user-generated content, users may be tempted to create |
| jbe@42 | 492 intentionally oversized objects in order to optimize search results in an |
| jbe@42 | 493 unfair manner. The <code>fair_distance</code> function aims to handle this by returning an |
| jbe@42 | 494 adjusted distance (i.e. distance increased by a penalty) if a geographic object |
| jbe@42 | 495 (the <code>ecluster</code>) consists of more than one point.</p> |
| jbe@42 | 496 |
| jbe@42 | 497 <p>The first argument to this function is an <code>ecluster</code>, the second argument is a |
| jbe@42 | 498 search point (<code>epoint</code>), and the third argument is an interger related to the |
| jbe@42 | 499 precision (higher precision will require more computation time).</p> |
| jbe@42 | 500 |
| jbe@42 | 501 <p>The penalty by which the returned distance is increased fulfills (at least) the |
| jbe@42 | 502 following properties:</p> |
| jbe@42 | 503 |
| jbe@42 | 504 <ul> |
| jbe@46 | 505 <li>The penalty function is continuous (except noise created by numerical |
| jbe@46 | 506 integration, see paragraph after this list) as long as no objects are added |
| jbe@46 | 507 to or removed from the <code>ecluster</code>. That particularly means: small changes in |
| jbe@46 | 508 the search point (second argument) cause only small changes in the result.</li> |
| jbe@46 | 509 <li>For search points far away from the <code>ecluster</code> (i.e. large distances compared |
| jbe@46 | 510 to the dimensions of the <code>ecluster</code>), the penalty approaches zero, i.e. the |
| jbe@46 | 511 behavior of the <code>fair_distance</code> function approaches the behavior of the |
| jbe@46 | 512 <code>distance</code> function.</li> |
| jbe@42 | 513 <li>If the <code>ecluster</code> consists of a set of points, the penalty for a search point |
| jbe@46 | 514 close to one of those points (closer than half of the minimum distance |
| jbe@46 | 515 between each pair of points in the <code>ecluster</code>) is chosen in such a way that |
| jbe@46 | 516 the adjusted distance is equal to the distance from the search point to the |
| jbe@42 | 517 closest point in the <code>ecluster</code> multiplied by the square root of the count of |
| jbe@42 | 518 points in the <code>ecluster</code>.</li> |
| jbe@46 | 519 <li>If the <code>ecluster</code> does not cover any area (i.e. only consists of points, |
| jbe@46 | 520 paths, and/or outlines), and if the search point (second argument) overlaps |
| jbe@46 | 521 with the <code>ecluster</code>, then the penalty (and thus the result) is zero.</li> |
| jbe@46 | 522 <li>The integral (or average) of the square of the fair distance value (result of |
| jbe@46 | 523 this function) over all possible search points is independent of the |
| jbe@46 | 524 <code>ecluster</code> as long as the <code>ecluster</code> does not cover more than a half of |
| jbe@46 | 525 earth's surface.</li> |
| jbe@42 | 526 </ul> |
| jbe@42 | 527 |
| jbe@46 | 528 <p>The function uses numerical integration to compute the result. The third |
| jbe@46 | 529 parameter (which defaults to 10000) can be used to adjust the number of samples |
| jbe@46 | 530 taken. A higher sample count increases precision as well as execution time of |
| jbe@46 | 531 the function. Because this function internally uses a spherical model of earth |
| jbe@46 | 532 for certain steps of the calculation, the precision cannot be increased |
| jbe@46 | 533 unboundedly.</p> |
| jbe@46 | 534 |
| jbe@46 | 535 <p>Despite the limitations explained above, it is ensured that the penalty is |
| jbe@46 | 536 always positive, i.e. results returned by the <code>fair_distance</code> function are |
| jbe@46 | 537 always equal to or greater than the results returned by the <code>distance</code> |
| jbe@46 | 538 function regardless of stochastic effects. Furthermore, all results are |
| jbe@46 | 539 deterministic and reproducible with the same version of pgLatLon.</p> |
| jbe@42 | 540 |
| jbe@0 | 541 <h4><code>GeoJSON_to_epoint(jsonb, text)</code></h4> |
| jbe@0 | 542 |
| jbe@0 | 543 <p>Maps a GeoJSON object of type "Point" or "Feature" (which contains a |
| jbe@0 | 544 "Point") to an <code>epoint</code> datum. For any other JSON objects, NULL is returned.</p> |
| jbe@0 | 545 |
| jbe@0 | 546 <p>The second parameter (which defaults to <code>epoint_lonlat</code>) may be set to a name |
| jbe@0 | 547 of a conversion function that transforms two coordinates (two <code>float8</code> |
| jbe@0 | 548 parameters) to an <code>epoint</code>.</p> |
| jbe@0 | 549 |
| jbe@0 | 550 <h4><code>GeoJSON_to_ecluster(jsonb, text)</code></h4> |
| jbe@0 | 551 |
| jbe@0 | 552 <p>Maps a (valid) GeoJSON object to an <code>ecluster</code>. Note that this function |
| jbe@0 | 553 does not check whether the JSONB object is a valid GeoJSON object.</p> |
| jbe@0 | 554 |
| jbe@0 | 555 <p>The second parameter (which defaults to <code>epoint_lonlat</code>) may be set to a name |
| jbe@0 | 556 of a conversion function that transforms two coordinates (two <code>float8</code> |
| jbe@0 | 557 parameters) to an <code>epoint</code>.</p> |
| jbe@0 | 558 |
| jbe@0 | 559 <h4><code>max_latitude(ebox)</code></h4> |
| jbe@0 | 560 |
| jbe@0 | 561 <p>Returns the northern boundary of a given <code>ebox</code> in degrees between -90 and +90.</p> |
| jbe@0 | 562 |
| jbe@0 | 563 <h4><code>max_longitude(ebox)</code></h4> |
| jbe@0 | 564 |
| jbe@0 | 565 <p>Returns the eastern boundary of a given <code>ebox</code> in degrees between -180 and +180 |
| jbe@0 | 566 (both inclusive).</p> |
| jbe@0 | 567 |
| jbe@0 | 568 <h4><code>min_latitude(ebox)</code></h4> |
| jbe@0 | 569 |
| jbe@0 | 570 <p>Returns the southern boundary of a given <code>ebox</code> in degrees between -90 and +90.</p> |
| jbe@0 | 571 |
| jbe@0 | 572 <h4><code>min_longitude(ebox)</code></h4> |
| jbe@0 | 573 |
| jbe@0 | 574 <p>Returns the western boundary of a given <code>ebox</code> in degrees between -180 and +180 |
| jbe@0 | 575 (both inclusive).</p> |
| jbe@0 | 576 |
| jbe@0 | 577 <h4><code>latitude(epoint)</code></h4> |
| jbe@0 | 578 |
| jbe@0 | 579 <p>Returns the latitude value of an <code>epoint</code> in degrees between -90 and +90.</p> |
| jbe@0 | 580 |
| jbe@0 | 581 <h4><code>longitude(epoint)</code></h4> |
| jbe@0 | 582 |
| jbe@0 | 583 <p>Returns the longitude value of an <code>epoint</code> in degrees between -180 and +180 |
| jbe@0 | 584 (both inclusive).</p> |
| jbe@0 | 585 |
| jbe@0 | 586 <h4><code>radius(ecircle)</code></h4> |
| jbe@0 | 587 |
| jbe@0 | 588 <p>Returns the radius of an <code>ecircle</code> in meters.</p> |
| jbe@0 | 589 </body></html> |