pgLatLon
diff README.md @ 81:b0e17a5a0258
Renamed README.mkd to README.md
| author | jbe |
|---|---|
| date | Thu Oct 23 15:15:56 2025 +0200 (3 days ago) |
| parents | README.mkd@76b3fd3293fc |
| children | 037e28f426e7 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/README.md Thu Oct 23 15:15:56 2025 +0200 1.3 @@ -0,0 +1,570 @@ 1.4 +pgLatLon v0.15 documentation 1.5 +============================ 1.6 + 1.7 +pgLatLon is a spatial database extension for the PostgreSQL object-relational 1.8 +database management system providing geographic data types and spatial indexing 1.9 +for the WGS-84 spheroid. 1.10 + 1.11 +While many other spatial databases still use imprecise bounding boxes for 1.12 +many operations, pgLatLon aims to support more precise calculations for all 1.13 +implemented geographic operators. Efficient indexing of geographic objects 1.14 +is provided using space-filling fractal curves. Optimizations on bit level 1.15 +(including logarithmic compression) allow for a highly memory-efficient 1.16 +non-overlapping index suitable for huge datasets. 1.17 + 1.18 +pgLatLon is a lightweight solution as it only depends on PostgreSQL itself (and 1.19 +a C compiler for building). 1.20 + 1.21 +Unlike competing spatial extensions for PostgreSQL, pgLatLon is available under 1.22 +the permissive MIT/X11 license to avoid problems with viral licenses like the 1.23 +GPLv2/v3. 1.24 + 1.25 + 1.26 +Installation 1.27 +------------ 1.28 + 1.29 +### Automatic installation 1.30 + 1.31 +Prerequisites: 1.32 + 1.33 +* Ensure that the `pg_config` binary is in your path (shipped with PostgreSQL). 1.34 +* Ensure that GNU Make is available (either as `make` or `gmake`). 1.35 + 1.36 +Then simply type: 1.37 + 1.38 + make install 1.39 + 1.40 +### Manual installation 1.41 + 1.42 +It is also possible to compile and install the extension without GNU Make as 1.43 +follows: 1.44 + 1.45 + cc -Wall -O2 -fPIC -shared -I `pg_config --includedir-server` -o latlon-v0010.so latlon-v0010.c 1.46 + cp latlon-v0010.so `pg_config --pkglibdir` 1.47 + cp latlon.control `pg_config --sharedir`/extension/ 1.48 + cp latlon--*.sql `pg_config --sharedir`/extension/ 1.49 + 1.50 +### Loading the extension 1.51 + 1.52 +After installation, you can create a database and load the extension as 1.53 +follows: 1.54 + 1.55 + % createdb test_database 1.56 + % psql test_database 1.57 + psql (9.5.4) 1.58 + Type "help" for help. 1.59 + 1.60 + test_database=# CREATE EXTENSION latlon; 1.61 + 1.62 +### Updating 1.63 + 1.64 +Before updating your database cluster to a new version of pgLatLon, you may 1.65 +want to uninstall the old by calling "`make uninstall`" in the unpacked source 1.66 +code directory of your old pgLatLon version. You may also manually delete the 1.67 +`latlon-v????.so` files from your PostgreSQL library directory and the 1.68 +`latlon.control` and `latlon--*.sql` files from your PostgreSQL extension 1.69 +directory. 1.70 + 1.71 +The new version can be installed as described above. For altering an existing 1.72 +database to use the installed new version (mandatory if you removed the old 1.73 +version), execute the following SQL command in the respective databases: 1.74 + 1.75 + ALTER EXTENSION latlon UPDATE; 1.76 + 1.77 +If the update contains modifications to operator classes, it may be necessary 1.78 +to drop all indices on geographic data types first (you will get an error 1.79 +message in this case). These indices can be re-created after the update. 1.80 + 1.81 +Note that taking several update steps at once (e.g. updating from version 0.2 1.82 +directly to version 0.4) requires the intermediate versions to be installed 1.83 +(i.e. in this example version 0.3 would need to be installed). Whenever you 1.84 +install or uninstall an intermediate or old version, make sure to afterwards 1.85 +re-install the latest pgLatLon version to ensure that the `latlon.control` file 1.86 +is available and points to the latest version. 1.87 + 1.88 +If the update contains modifications to the internal data representation 1.89 +format, an update path might not be available. In this case, create a dump of 1.90 +your database, delete your database, and restore it from your dump. 1.91 + 1.92 +Be sure to always keep backups of all your data before attempting to update. 1.93 + 1.94 + 1.95 +Reference 1.96 +--------- 1.97 + 1.98 +### 1. Types 1.99 + 1.100 +pgLatLon provides four geographic types: `epoint`, `ebox`, `ecircle`, and 1.101 +`ecluster`. 1.102 + 1.103 +#### `epoint` 1.104 + 1.105 +A point on the Earth spheroid (WGS-84). 1.106 + 1.107 +The text input format is `'[N|S]<float> [E|W]<float>'`, where each float is in 1.108 +degrees. Note the required white space between the latitude and longitude 1.109 +components. Each floating point number may have a sign, in which case `N`/`S` 1.110 +or `E`/`W` are switched respectively (e.g. `E-5` is the same as `W5`). 1.111 + 1.112 +An `epoint` may also be created from two floating point numbers by calling 1.113 +`epoint(latitude, longitude)`, where positive latitudes are used for the 1.114 +northern hemisphere, negative latitudes are used for the southern hemisphere, 1.115 +positive longitudes indicate positions east of the prime meridian, and negative 1.116 +longitudes indicate positions west of the prime meridian. 1.117 + 1.118 +Latitudes exceeding -90 or +90 degrees are truncated to -90 or +90 1.119 +respectively, in which case a warning will be issued. Longitudes exceeding -180 1.120 +or +180 degrees will be converted to values between -180 and +180 (both 1.121 +inclusive) by adding or substracting a multiple of 360 degrees, in which case a 1.122 +notice will be issued. 1.123 + 1.124 +If the latitude is -90 or +90 (south pole or north pole), a longitude value is 1.125 +still stored in the datum, and if a point is on the prime meridian or the 1.126 +180th meridian, the east/west bit is also stored in the datum. In case of the 1.127 +prime meridian, this is done by storing a floating point value of -0 for 1.128 +0 degrees west and a value of +0 for 0 degrees east. In case of the 1.129 +180th meridian, this is done by storing -180 or +180 respectively. The equality 1.130 +operator, however, returns true when the same points on Earth are described, 1.131 +i.e. the longitude is ignored for the poles, and 180 degrees west is considered 1.132 +to be equal to 180 degrees east. 1.133 + 1.134 +#### `ebox` 1.135 + 1.136 +An area on Earth demarcated by a southern and northern latitude, and a western 1.137 +and eastern longitude (all given in WGS-84). 1.138 + 1.139 +The text input format is 1.140 +`'{N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float>'`, where each float is in 1.141 +degrees. The ordering of the four white-space separated blocks is not 1.142 +significant. To include the 180th meridian, one longitude boundary must be 1.143 +equal to or exceed `W180` or `E180`, e.g. `'N10 N20 E170 E190'`. 1.144 + 1.145 +A special value is the empty area, denoted by the text represenation `'empty'`. 1.146 +Such an `ebox` does not contain any point. 1.147 + 1.148 +An `ebox` may also be created from four floating point numbers by calling 1.149 +`ebox(min_latitude, max_latitude, min_longitude, max_longitude)`, where 1.150 +positive values are used for north and east, and negative values are used for 1.151 +south and west. If `min_latitude` is strictly greater than `max_latitude`, an 1.152 +empty `ebox` is created. If `min_longitude` is greater than `max_longitude` and 1.153 +if both longitudes are between -180 and +180 degrees, then the area oriented in 1.154 +such way that the 180th meridian is included. 1.155 + 1.156 +If the longitude span is less than 120 degrees, an `ebox` may be alternatively 1.157 +created from two `epoints` in the following way: `ebox(epoint(lat1, lon1), 1.158 +epoint(lat2, lon2))`. In this case `lat1` and `lat2` as well as `lon1` and 1.159 +`lon2` can be swapped without any impact. 1.160 + 1.161 +#### `ecircle` 1.162 + 1.163 +An area containing all points not farther away from a given center point 1.164 +(WGS-84) than a given radius. 1.165 + 1.166 +The text input format is `'{N|S}<float> {E|W}<float> <float>'`, where the first 1.167 +two floats denote the center point in degrees and the third float denotes the 1.168 +radius in meters. A radius equal to minus infinity denotes an empty circle 1.169 +which contains no point at all (despite having a center), while a radius equal 1.170 +to zero denotes a circle that includes a single point. 1.171 + 1.172 +An `ecircle` may also be created by calling `ecircle(epoint(...), radius)` or 1.173 +from three floating point numbers by calling `ecircle(latitude, longitude, 1.174 +radius)`. 1.175 + 1.176 +#### `ecluster` 1.177 + 1.178 +A collection of points, paths, polygons, and outlines on the WGS-84 spheroid. 1.179 +Each path, polygon, or outline must cover a longitude range of less than 1.180 +180 degrees to avoid ambiguities. 1.181 + 1.182 +The text input format is a white-space separated list of the following items: 1.183 + 1.184 +* `point ({N|S}<float> {E|W}<float>)` 1.185 +* `path ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)` 1.186 +* `outline ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)` 1.187 +* `polygon ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)` 1.188 + 1.189 +Paths are open by default (i.e. there is no connection from the last point in 1.190 +the list to the first point in the list). Outlines and polygons, in contrast, 1.191 +are automatically closed (i.e. there is a line segment from the last point in 1.192 +the list to the first point in the list) which means the first point should not 1.193 +be repeated as last point in the list. Polygons are filled, outlines are not. 1.194 + 1.195 +### 2. Indices 1.196 + 1.197 +Two kinds of indices are supported: B-tree and GiST indices. 1.198 + 1.199 +#### B-tree indices 1.200 + 1.201 +A B-tree index can be used for simple equality searches and is supported by the 1.202 +`epoint`, `ebox`, and `ecircle` data types. B-tree indices can not be used for 1.203 +geographic searches. 1.204 + 1.205 +#### GiST indices 1.206 + 1.207 +For geographic searches, GiST indices must be used. The `epoint`, `ecircle`, 1.208 +and `ecluster` data types support GiST indexing. A GiST index for geographic 1.209 +searches can be created as follows: 1.210 + 1.211 + CREATE TABLE tbl ( 1.212 + id serial4 PRIMARY KEY, 1.213 + loc epoint NOT NULL ); 1.214 + 1.215 + CREATE INDEX name_of_index ON tbl USING gist (loc); 1.216 + 1.217 +GiST indices also support nearest neighbor searches when using the distance 1.218 +operator (`<->`) in the ORDER BY clause. 1.219 + 1.220 +#### Indices on other data types (e.g. GeoJSON) 1.221 + 1.222 +Note that further types can be indexed by using an index on an expression with 1.223 +a conversion function. One conversion function provided by pgLatLon is the 1.224 +`GeoJSON_to_ecluster(jsonb, text)` function: 1.225 + 1.226 + CREATE TABLE tbl ( 1.227 + id serial4 PRIMARY KEY, 1.228 + loc jsonb NOT NULL ); 1.229 + 1.230 + CREATE INDEX name_of_index ON tbl USING gist ((GeoJSON_to_ecluster("loc"))); 1.231 + 1.232 +When using the conversion function in an expression, the index will be used 1.233 +automatically: 1.234 + 1.235 + SELECT * FROM tbl WHERE GeoJSON_to_ecluster("loc") && 'N50 E10 10000'::ecircle; 1.236 + 1.237 +### 3. Operators 1.238 + 1.239 +#### Equality operator `=` 1.240 + 1.241 +Tests if two geographic objects are equal. 1.242 + 1.243 +The longitude is ignored for the poles, and 180 degrees west is considered to 1.244 +be equal to 180 degrees east. 1.245 + 1.246 +For boxes and circles, two empty objects are considered equal. (Note that a 1.247 +circle is not empty if the radius is zero but only if it is negative infinity, 1.248 +i.e. smaller than zero.) Two circles with a positive infinite radius are also 1.249 +considered equal. 1.250 + 1.251 +Implemented for: 1.252 + 1.253 +* `epoint = epoint` 1.254 +* `ebox = ebox` 1.255 +* `ecircle = ecircle` 1.256 + 1.257 +The negation is the inequality operator (`<>` or `!=`). 1.258 + 1.259 +#### Linear ordering operators `<<<`, `<<<=`, `>>>=`, `>>>` 1.260 + 1.261 +These operators create an arbitrary (but well-defined) linear ordering of 1.262 +geographic objects, which is used internally for B-tree indexing and merge 1.263 +joins. These operators will usually not be used by an application programmer. 1.264 + 1.265 +#### Overlap operator `&&` 1.266 + 1.267 +Tests if two geographic objects have at least one point in common. Currently 1.268 +implemented for: 1.269 + 1.270 +* `epoint && ebox` 1.271 +* `epoint && ecircle` 1.272 +* `epoint && ecluster` 1.273 +* `ebox && ebox` 1.274 +* `ebox && ecircle` 1.275 +* `ebox && ecluster` 1.276 +* `ecircle && ecircle` 1.277 +* `ecircle && ecluster` 1.278 +* `ecluster && ecluster` 1.279 + 1.280 +The `&&` operator is commutative, i.e. "`a && b`" is the same as "`b && a`". 1.281 +Each commutation is supported as well. 1.282 + 1.283 +#### Lossy overlap operator `&&+` 1.284 + 1.285 +Tests if two geographic objects may have at least one point in common. Opposed 1.286 +to the `&&` operator, the `&&+` operator may return false positives and is 1.287 +currently implemented for: 1.288 + 1.289 +* `epoint &&+ ecluster` 1.290 +* `ebox &&+ ecircle` 1.291 +* `ebox &&+ ecluster` 1.292 +* `ecircle &&+ ecluster` 1.293 +* `ecluster &&+ ecluster` 1.294 + 1.295 +The `&&+` operator is commutative, i.e. "`a &&+ b`" is the same as "`b &&+ a`". 1.296 +Each commutation is supported as well. 1.297 + 1.298 +Where two data types support both the `&&` and the `&&+` operator, the `&&+` 1.299 +operator computes faster. 1.300 + 1.301 +#### Contains operator `@>` 1.302 + 1.303 +Tests if the object right of the operator is contained in the object left of 1.304 +the operator. Currently implemented for: 1.305 + 1.306 +* `ebox @> epoint` (alias for `&&`) 1.307 +* `ebox @> ebox` 1.308 +* `ebox @> ecluster` 1.309 +* `ecluster @> epoint` (alias for `&&`) 1.310 +* `ecluster @> ebox` 1.311 +* `ecluster @> ecluster` 1.312 + 1.313 +The commutator of `@>` ("contains") is `<@` ("is contained in"), i.e. 1.314 +"`a @> b`" is the same as "`b <@ a`". 1.315 + 1.316 +Whether the perimeter of an object is taken into account is undefined and may 1.317 +differ between the left and the right hand side of the operator. The current 1.318 +implementation (where not an alias for `&&`) returns true only if an object is 1.319 +contained completely within the other object, not touching its perimeter, 1.320 +paths, outlines, or any singular points. 1.321 + 1.322 +#### Distance operator `<->` 1.323 + 1.324 +Calculates the shortest distance between two geographic objects in meters (zero 1.325 +if the objects are overlapping). Currently implemented for: 1.326 + 1.327 +* `epoint <-> epoint` 1.328 +* `epoint <-> ebox` 1.329 +* `epoint <-> ecircle` 1.330 +* `epoint <-> ecluster` 1.331 +* `ebox <-> ebox` 1.332 +* `ebox <-> ecircle` 1.333 +* `ebox <-> ecluster` 1.334 +* `ecircle <-> ecircle` 1.335 +* `ecircle <-> ecluster` 1.336 +* `ecluster <-> ecluster` 1.337 + 1.338 +The `<->` operator is commutative, i.e. "`a <-> b`" is the same as "`b <-> a`". 1.339 +Each commutation is supported as well. 1.340 + 1.341 +For short distances, the result is very accurate (i.e. respects the dimensions 1.342 +of the WGS-84 spheroid). For longer distances in the order of magnitude of 1.343 +Earth's radius or greater, the value is only approximate (but the error is 1.344 +still less than 0.2% as long as no polygons with very long edges are involved). 1.345 + 1.346 +The functions `distance(epoint, epoint)` and `distance(ecluster, epoint)` can 1.347 +be used as an alias for this operator. 1.348 + 1.349 +Note: In case of radial searches with a fixed radius, this operator should 1.350 +not be used. Instead, an `ecircle` should be created and used in combination 1.351 +with the overlap operator (`&&`). Alternatively, the functions 1.352 +`distance_within(epoint, epoint, float8)` or `distance_within(ecluster, epoint, 1.353 +float8)` can be used for fixed-radius searches. 1.354 + 1.355 +### 4. Functions 1.356 + 1.357 +#### `center(circle)` 1.358 + 1.359 +Returns the center of an `ecircle` as an `epoint`. 1.360 + 1.361 +#### `distance(epoint, epoint)` 1.362 + 1.363 +Calculates the distance between two `epoint` datums in meters. This function is 1.364 +an alias for the distance operator `<->`. 1.365 + 1.366 +Note: In case of radial searches with a fixed radius, this function should not be 1.367 +used. Use `distance_within(epoint, epoint, float8)` instead. 1.368 + 1.369 +#### `distance(ecluster, epoint)` 1.370 + 1.371 +Calculates the distance from an `ecluster` to an `epoint` in meters. This 1.372 +function is an alias for the distance operator `<->`. 1.373 + 1.374 +Note: In case of radial searches with a fixed radius, this function should not be 1.375 +used. Use `distance_within(epoint, epoint, float8)` instead. 1.376 + 1.377 +#### `distance_within(`variable `epoint,` fixed `epoint,` radius `float8)` 1.378 + 1.379 +Checks if the distance between two `epoint` datums is not greater than a given 1.380 +value (search radius). 1.381 + 1.382 +Note: In case of radial searches with a fixed radius, the first argument must 1.383 +be used for the table column, while the second argument must be used for the 1.384 +search center. Otherwise an existing index cannot be used. 1.385 + 1.386 +#### `distance_within(`variable `ecluster,` fixed `epoint,` radius `float8)` 1.387 + 1.388 +Checks if the distance from an `ecluster` to an `epoint` is not greater than a 1.389 +given value (search radius). 1.390 + 1.391 +#### `ebox(`latmin `float8,` latmax `float8,` lonmin `float8,` lonmax `float8)` 1.392 + 1.393 +Creates a new `ebox` with the given boundaries. 1.394 +See "1. Types", subsection `ebox` for details. 1.395 + 1.396 +#### `ebox(epoint, epoint)` 1.397 + 1.398 +Creates a new `ebox`. This function may only be used if the longitude 1.399 +difference is less than or equal to 120 degrees. 1.400 +See "1. Types", subsection `ebox` for details. 1.401 + 1.402 +#### `ecircle(epoint, float8)` 1.403 + 1.404 +Creates an `ecircle` with the given center point and radius. 1.405 + 1.406 +#### `ecircle(`latitude `float8,` longitude `float8,` radius `float8)` 1.407 + 1.408 +Creates an `ecircle` with the given center point and radius. 1.409 + 1.410 +#### `ecluster_concat(ecluster, ecluster)` 1.411 + 1.412 +Combines two clusters to form a new `ecluster` by uniting all entries of both 1.413 +clusters. Note that two overlapping areas of polygons annihilate each other 1.414 +(which may be used to create polygons with holes). 1.415 + 1.416 +#### `ecluster_concat(ecluster[])` 1.417 + 1.418 +Creates a new `ecluster` that unites all entries of all clusters in the passed 1.419 +array. Note that two overlapping areas of polygons annihilate each other (which 1.420 +may be used to create polygons with holes). 1.421 + 1.422 +#### `ecluster_create_multipoint(epoint[])` 1.423 + 1.424 +Creates a new `ecluster` which contains multiple points. 1.425 + 1.426 +#### `ecluster_create_outline(epoint[])` 1.427 + 1.428 +Creates a new `ecluster` that is an outline given by the passed points. 1.429 + 1.430 +#### `ecluster_create_path(epoint[])` 1.431 + 1.432 +Creates a new `ecluster` that is a path given by the passed points. 1.433 + 1.434 +#### `ecluster_create_polygon(epoint[])` 1.435 + 1.436 +Creates a new `ecluster` that is a polygon given by the passed points. 1.437 + 1.438 +#### `ecluster_extract_outlines(ecluster)` 1.439 + 1.440 +Set-returning function that returns the outlines of an `ecluster` as `epoint[]` 1.441 +rows. 1.442 + 1.443 +#### `ecluster_extract_paths(ecluster)` 1.444 + 1.445 +Set-returning function that returns the paths of an `ecluster` as `epoint[]` 1.446 +rows. 1.447 + 1.448 +#### `ecluster_extract_points(ecluster)` 1.449 + 1.450 +Set-returning function that returns the points of an `ecluster` as `epoint` 1.451 +rows. 1.452 + 1.453 +#### `ecluster_extract_polygons(ecluster)` 1.454 + 1.455 +Set-returning function that returns the polygons of an `ecluster` as `epoint[]` 1.456 +rows. 1.457 + 1.458 +#### `empty_ebox`() 1.459 + 1.460 +Returns the empty `ebox`. 1.461 +See "1. Types", subsection `ebox` for details. 1.462 + 1.463 +#### `epoint(`latitude `float8,` longitude `float8)` 1.464 + 1.465 +Returns an `epoint` with the given latitude and longitude. 1.466 + 1.467 +#### `epoint_latlon(`latitude `float8,` longitude `float8)` 1.468 + 1.469 +Alias for `epoint(float8, float8)`. 1.470 + 1.471 +#### `epoint_lonlat(`longitude `float8,` latitude `float8)` 1.472 + 1.473 +Same as `epoint(float8, float8)` but with arguments reversed. 1.474 + 1.475 +#### `fair_distance(ecluster, epoint,` samples `int4 = 10000)` 1.476 + 1.477 +When working with user-generated content, users may be tempted to create 1.478 +intentionally oversized objects in order to optimize search results in an 1.479 +unfair manner. The `fair_distance` function aims to handle this by returning an 1.480 +adjusted distance (i.e. distance increased by a penalty) if a geographic object 1.481 +(the `ecluster`) consists of more than one point. 1.482 + 1.483 +The first argument to this function is an `ecluster`, the second argument is a 1.484 +search point (`epoint`), and the third argument is an interger related to the 1.485 +precision (higher precision will require more computation time). 1.486 + 1.487 +The penalty by which the returned distance is increased fulfills (at least) the 1.488 +following properties: 1.489 + 1.490 +* The penalty function is continuous (except noise created by numerical 1.491 + integration, see paragraph after this list) as long as no objects are added 1.492 + to or removed from the `ecluster`. That particularly means: small changes in 1.493 + the search point (second argument) cause only small changes in the result. 1.494 +* For search points far away from the `ecluster` (i.e. large distances compared 1.495 + to the dimensions of the `ecluster`), the penalty approaches zero, i.e. the 1.496 + behavior of the `fair_distance` function approaches the behavior of the 1.497 + `distance` function. 1.498 +* If the `ecluster` consists of a set of points, the penalty for a search point 1.499 + close to one of those points (closer than half of the minimum distance 1.500 + between each pair of points in the `ecluster`) is chosen in such a way that 1.501 + the adjusted distance is equal to the distance from the search point to the 1.502 + closest point in the `ecluster` multiplied by the square root of the count of 1.503 + points in the `ecluster`. 1.504 +* If the `ecluster` does not cover any area (i.e. only consists of points, 1.505 + paths, and/or outlines), and if the search point (second argument) overlaps 1.506 + with the `ecluster`, then the penalty (and thus the result) is zero. 1.507 +* The integral (or average) of the square of the fair distance value (result of 1.508 + this function) over all possible search points is independent of the 1.509 + `ecluster` as long as the `ecluster` does not cover more than a half of 1.510 + earth's surface. 1.511 + 1.512 +The function uses numerical integration to compute the result. The third 1.513 +parameter (which defaults to 10000) can be used to adjust the number of samples 1.514 +taken. A higher sample count increases precision as well as execution time of 1.515 +the function. Because this function internally uses a spherical model of earth 1.516 +for certain steps of the calculation, the precision cannot be increased 1.517 +unboundedly. 1.518 + 1.519 +Despite the limitations explained above, it is ensured that the penalty is 1.520 +always positive, i.e. results returned by the `fair_distance` function are 1.521 +always equal to or greater than the results returned by the `distance` 1.522 +function regardless of stochastic effects. Furthermore, all results are 1.523 +deterministic and reproducible with the same version of pgLatLon. 1.524 + 1.525 +#### `GeoJSON_to_epoint(jsonb, text)` 1.526 + 1.527 +Maps a GeoJSON object of type "Point" or "Feature" (which contains a 1.528 +"Point") to an `epoint` datum. For any other JSON objects, NULL is returned. 1.529 + 1.530 +The second parameter (which defaults to `epoint_lonlat`) may be set to a name 1.531 +of a conversion function that transforms two coordinates (two `float8` 1.532 +parameters) to an `epoint`. 1.533 + 1.534 +#### `GeoJSON_to_ecluster(jsonb, text)` 1.535 + 1.536 +Maps a (valid) GeoJSON object to an `ecluster`. Note that this function 1.537 +does not check whether the JSONB object is a valid GeoJSON object. 1.538 + 1.539 +The second parameter (which defaults to `epoint_lonlat`) may be set to a name 1.540 +of a conversion function that transforms two coordinates (two `float8` 1.541 +parameters) to an `epoint`. 1.542 + 1.543 +#### `max_latitude(ebox)` 1.544 + 1.545 +Returns the northern boundary of a given `ebox` in degrees between -90 and +90. 1.546 + 1.547 +#### `max_longitude(ebox)` 1.548 + 1.549 +Returns the eastern boundary of a given `ebox` in degrees between -180 and +180 1.550 +(both inclusive). 1.551 + 1.552 +#### `min_latitude(ebox)` 1.553 + 1.554 +Returns the southern boundary of a given `ebox` in degrees between -90 and +90. 1.555 + 1.556 +#### `min_longitude(ebox)` 1.557 + 1.558 +Returns the western boundary of a given `ebox` in degrees between -180 and +180 1.559 +(both inclusive). 1.560 + 1.561 +#### `latitude(epoint)` 1.562 + 1.563 +Returns the latitude value of an `epoint` in degrees between -90 and +90. 1.564 + 1.565 +#### `longitude(epoint)` 1.566 + 1.567 +Returns the longitude value of an `epoint` in degrees between -180 and +180 1.568 +(both inclusive). 1.569 + 1.570 +#### `radius(ecircle)` 1.571 + 1.572 +Returns the radius of an `ecircle` in meters. 1.573 +