pgLatLon

changeset 81:b0e17a5a0258

Renamed README.mkd to README.md
author jbe
date Thu Oct 23 15:15:56 2025 +0200 (2 days ago)
parents b9cdc74a90db
children 8a08dc69de98
files README.md README.mkd make-doc.sh
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 +
     2.1 --- a/README.mkd	Thu Oct 23 10:39:05 2025 +0200
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,570 +0,0 @@
     2.4 -pgLatLon v0.15 documentation
     2.5 -============================
     2.6 -
     2.7 -pgLatLon is a spatial database extension for the PostgreSQL object-relational
     2.8 -database management system providing geographic data types and spatial indexing
     2.9 -for the WGS-84 spheroid.
    2.10 -
    2.11 -While many other spatial databases still use imprecise bounding boxes for
    2.12 -many operations, pgLatLon aims to support more precise calculations for all
    2.13 -implemented geographic operators. Efficient indexing of geographic objects
    2.14 -is provided using space-filling fractal curves. Optimizations on bit level
    2.15 -(including logarithmic compression) allow for a highly memory-efficient
    2.16 -non-overlapping index suitable for huge datasets.
    2.17 -
    2.18 -pgLatLon is a lightweight solution as it only depends on PostgreSQL itself (and
    2.19 -a C compiler for building).
    2.20 -
    2.21 -Unlike competing spatial extensions for PostgreSQL, pgLatLon is available under
    2.22 -the permissive MIT/X11 license to avoid problems with viral licenses like the
    2.23 -GPLv2/v3.
    2.24 -
    2.25 -
    2.26 -Installation
    2.27 -------------
    2.28 -
    2.29 -### Automatic installation
    2.30 -
    2.31 -Prerequisites:
    2.32 -
    2.33 -* Ensure that the `pg_config` binary is in your path (shipped with PostgreSQL).
    2.34 -* Ensure that GNU Make is available (either as `make` or `gmake`).
    2.35 -
    2.36 -Then simply type:
    2.37 -
    2.38 -    make install
    2.39 -
    2.40 -### Manual installation    
    2.41 -
    2.42 -It is also possible to compile and install the extension without GNU Make as
    2.43 -follows:
    2.44 -
    2.45 -    cc -Wall -O2 -fPIC -shared -I `pg_config --includedir-server` -o latlon-v0010.so latlon-v0010.c
    2.46 -    cp latlon-v0010.so `pg_config --pkglibdir`
    2.47 -    cp latlon.control `pg_config --sharedir`/extension/
    2.48 -    cp latlon--*.sql `pg_config --sharedir`/extension/
    2.49 -
    2.50 -### Loading the extension
    2.51 -
    2.52 -After installation, you can create a database and load the extension as
    2.53 -follows:
    2.54 -
    2.55 -    % createdb test_database
    2.56 -    % psql test_database
    2.57 -    psql (9.5.4)
    2.58 -    Type "help" for help.
    2.59 -
    2.60 -    test_database=# CREATE EXTENSION latlon;
    2.61 -
    2.62 -### Updating
    2.63 -
    2.64 -Before updating your database cluster to a new version of pgLatLon, you may
    2.65 -want to uninstall the old by calling "`make uninstall`" in the unpacked source
    2.66 -code directory of your old pgLatLon version. You may also manually delete the
    2.67 -`latlon-v????.so` files from your PostgreSQL library directory and the
    2.68 -`latlon.control` and `latlon--*.sql` files from your PostgreSQL extension
    2.69 -directory.
    2.70 -
    2.71 -The new version can be installed as described above. For altering an existing
    2.72 -database to use the installed new version (mandatory if you removed the old
    2.73 -version), execute the following SQL command in the respective databases:
    2.74 -
    2.75 -    ALTER EXTENSION latlon UPDATE;
    2.76 -
    2.77 -If the update contains modifications to operator classes, it may be necessary
    2.78 -to drop all indices on geographic data types first (you will get an error
    2.79 -message in this case). These indices can be re-created after the update.
    2.80 -
    2.81 -Note that taking several update steps at once (e.g. updating from version 0.2
    2.82 -directly to version 0.4) requires the intermediate versions to be installed
    2.83 -(i.e. in this example version 0.3 would need to be installed). Whenever you
    2.84 -install or uninstall an intermediate or old version, make sure to afterwards
    2.85 -re-install the latest pgLatLon version to ensure that the `latlon.control` file
    2.86 -is available and points to the latest version.
    2.87 -
    2.88 -If the update contains modifications to the internal data representation
    2.89 -format, an update path might not be available. In this case, create a dump of
    2.90 -your database, delete your database, and restore it from your dump.
    2.91 -
    2.92 -Be sure to always keep backups of all your data before attempting to update.
    2.93 -
    2.94 -
    2.95 -Reference
    2.96 ----------
    2.97 -
    2.98 -### 1. Types
    2.99 -
   2.100 -pgLatLon provides four geographic types: `epoint`, `ebox`, `ecircle`, and
   2.101 -`ecluster`.
   2.102 -
   2.103 -#### `epoint`
   2.104 -
   2.105 -A point on the Earth spheroid (WGS-84).
   2.106 -
   2.107 -The text input format is `'[N|S]<float> [E|W]<float>'`, where each float is in
   2.108 -degrees. Note the required white space between the latitude and longitude
   2.109 -components.  Each floating point number may have a sign, in which case `N`/`S`
   2.110 -or `E`/`W` are switched respectively (e.g. `E-5` is the same as `W5`).
   2.111 -
   2.112 -An `epoint` may also be created from two floating point numbers by calling
   2.113 -`epoint(latitude, longitude)`, where positive latitudes are used for the
   2.114 -northern hemisphere, negative latitudes are used for the southern hemisphere,
   2.115 -positive longitudes indicate positions east of the prime meridian, and negative
   2.116 -longitudes indicate positions west of the prime meridian.
   2.117 -
   2.118 -Latitudes exceeding -90 or +90 degrees are truncated to -90 or +90
   2.119 -respectively, in which case a warning will be issued. Longitudes exceeding -180
   2.120 -or +180 degrees will be converted to values between -180 and +180 (both
   2.121 -inclusive) by adding or substracting a multiple of 360 degrees, in which case a
   2.122 -notice will be issued.
   2.123 -
   2.124 -If the latitude is -90 or +90 (south pole or north pole), a longitude value is
   2.125 -still stored in the datum, and if a point is on the prime meridian or the
   2.126 -180th meridian, the east/west bit is also stored in the datum. In case of the
   2.127 -prime meridian, this is done by storing a floating point value of -0 for
   2.128 -0 degrees west and a value of +0 for 0 degrees east. In case of the
   2.129 -180th meridian, this is done by storing -180 or +180 respectively. The equality
   2.130 -operator, however, returns true when the same points on Earth are described,
   2.131 -i.e. the longitude is ignored for the poles, and 180 degrees west is considered
   2.132 -to be equal to 180 degrees east.
   2.133 -
   2.134 -#### `ebox`
   2.135 -
   2.136 -An area on Earth demarcated by a southern and northern latitude, and a western
   2.137 -and eastern longitude (all given in WGS-84).
   2.138 -
   2.139 -The text input format is
   2.140 -`'{N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float>'`, where each float is in
   2.141 -degrees. The ordering of the four white-space separated blocks is not
   2.142 -significant. To include the 180th meridian, one longitude boundary must be
   2.143 -equal to or exceed `W180` or `E180`, e.g. `'N10 N20 E170 E190'`.
   2.144 -
   2.145 -A special value is the empty area, denoted by the text represenation `'empty'`.
   2.146 -Such an `ebox` does not contain any point.
   2.147 -
   2.148 -An `ebox` may also be created from four floating point numbers by calling
   2.149 -`ebox(min_latitude, max_latitude, min_longitude, max_longitude)`, where
   2.150 -positive values are used for north and east, and negative values are used for
   2.151 -south and west. If `min_latitude` is strictly greater than `max_latitude`, an
   2.152 -empty `ebox` is created. If `min_longitude` is greater than `max_longitude` and
   2.153 -if both longitudes are between -180 and +180 degrees, then the area oriented in
   2.154 -such way that the 180th meridian is included.
   2.155 -
   2.156 -If the longitude span is less than 120 degrees, an `ebox` may be alternatively
   2.157 -created from two `epoints` in the following way: `ebox(epoint(lat1, lon1),
   2.158 -epoint(lat2, lon2))`. In this case `lat1` and `lat2` as well as `lon1` and
   2.159 -`lon2` can be swapped without any impact.
   2.160 -
   2.161 -#### `ecircle`
   2.162 -
   2.163 -An area containing all points not farther away from a given center point
   2.164 -(WGS-84) than a given radius.
   2.165 -
   2.166 -The text input format is `'{N|S}<float> {E|W}<float> <float>'`, where the first
   2.167 -two floats denote the center point in degrees and the third float denotes the
   2.168 -radius in meters. A radius equal to minus infinity denotes an empty circle
   2.169 -which contains no point at all (despite having a center), while a radius equal
   2.170 -to zero denotes a circle that includes a single point.
   2.171 -
   2.172 -An `ecircle` may also be created by calling `ecircle(epoint(...), radius)` or
   2.173 -from three floating point numbers by calling `ecircle(latitude, longitude,
   2.174 -radius)`.
   2.175 -
   2.176 -#### `ecluster`
   2.177 -
   2.178 -A collection of points, paths, polygons, and outlines on the WGS-84 spheroid.
   2.179 -Each path, polygon, or outline must cover a longitude range of less than
   2.180 -180 degrees to avoid ambiguities.
   2.181 -
   2.182 -The text input format is a white-space separated list of the following items:
   2.183 -
   2.184 -* `point   ({N|S}<float> {E|W}<float>)`
   2.185 -* `path    ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)`
   2.186 -* `outline ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)`
   2.187 -* `polygon ({N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> {N|S}<float> {E|W}<float> ...)`
   2.188 -
   2.189 -Paths are open by default (i.e. there is no connection from the last point in
   2.190 -the list to the first point in the list). Outlines and polygons, in contrast,
   2.191 -are automatically closed (i.e. there is a line segment from the last point in
   2.192 -the list to the first point in the list) which means the first point should not
   2.193 -be repeated as last point in the list. Polygons are filled, outlines are not.
   2.194 -
   2.195 -### 2. Indices
   2.196 -
   2.197 -Two kinds of indices are supported: B-tree and GiST indices.
   2.198 -
   2.199 -#### B-tree indices
   2.200 -
   2.201 -A B-tree index can be used for simple equality searches and is supported by the
   2.202 -`epoint`, `ebox`, and `ecircle` data types. B-tree indices can not be used for
   2.203 -geographic searches.
   2.204 -
   2.205 -#### GiST indices
   2.206 -
   2.207 -For geographic searches, GiST indices must be used. The `epoint`, `ecircle`,
   2.208 -and `ecluster` data types support GiST indexing. A GiST index for geographic
   2.209 -searches can be created as follows:
   2.210 -
   2.211 -    CREATE TABLE tbl (
   2.212 -            id              serial4         PRIMARY KEY,
   2.213 -            loc             epoint          NOT NULL );
   2.214 -
   2.215 -    CREATE INDEX name_of_index ON tbl USING gist (loc);
   2.216 -
   2.217 -GiST indices also support nearest neighbor searches when using the distance
   2.218 -operator (`<->`) in the ORDER BY clause.
   2.219 -
   2.220 -#### Indices on other data types (e.g. GeoJSON)
   2.221 -
   2.222 -Note that further types can be indexed by using an index on an expression with
   2.223 -a conversion function. One conversion function provided by pgLatLon is the
   2.224 -`GeoJSON_to_ecluster(jsonb, text)` function:
   2.225 -
   2.226 -    CREATE TABLE tbl (
   2.227 -            id              serial4         PRIMARY KEY,
   2.228 -            loc             jsonb           NOT NULL );
   2.229 -
   2.230 -    CREATE INDEX name_of_index ON tbl USING gist ((GeoJSON_to_ecluster("loc")));
   2.231 -
   2.232 -When using the conversion function in an expression, the index will be used
   2.233 -automatically:
   2.234 -
   2.235 -    SELECT * FROM tbl WHERE GeoJSON_to_ecluster("loc") && 'N50 E10 10000'::ecircle;
   2.236 -
   2.237 -### 3. Operators
   2.238 -
   2.239 -#### Equality operator `=`
   2.240 -
   2.241 -Tests if two geographic objects are equal.
   2.242 -
   2.243 -The longitude is ignored for the poles, and 180 degrees west is considered to
   2.244 -be equal to 180 degrees east.
   2.245 -
   2.246 -For boxes and circles, two empty objects are considered equal. (Note that a
   2.247 -circle is not empty if the radius is zero but only if it is negative infinity,
   2.248 -i.e. smaller than zero.) Two circles with a positive infinite radius are also
   2.249 -considered equal.
   2.250 -
   2.251 -Implemented for:
   2.252 -
   2.253 -* `epoint = epoint`
   2.254 -* `ebox = ebox`
   2.255 -* `ecircle = ecircle`
   2.256 -
   2.257 -The negation is the inequality operator (`<>` or `!=`).
   2.258 -
   2.259 -#### Linear ordering operators `<<<`, `<<<=`, `>>>=`, `>>>`
   2.260 -
   2.261 -These operators create an arbitrary (but well-defined) linear ordering of
   2.262 -geographic objects, which is used internally for B-tree indexing and merge
   2.263 -joins. These operators will usually not be used by an application programmer.
   2.264 -
   2.265 -#### Overlap operator `&&`
   2.266 -
   2.267 -Tests if two geographic objects have at least one point in common. Currently
   2.268 -implemented for:
   2.269 -
   2.270 -* `epoint && ebox`
   2.271 -* `epoint && ecircle`
   2.272 -* `epoint && ecluster`
   2.273 -* `ebox && ebox`
   2.274 -* `ebox && ecircle`
   2.275 -* `ebox && ecluster`
   2.276 -* `ecircle && ecircle`
   2.277 -* `ecircle && ecluster`
   2.278 -* `ecluster && ecluster`
   2.279 -
   2.280 -The `&&` operator is commutative, i.e. "`a && b`" is the same as "`b && a`".
   2.281 -Each commutation is supported as well.
   2.282 -
   2.283 -#### Lossy overlap operator `&&+`
   2.284 -
   2.285 -Tests if two geographic objects may have at least one point in common. Opposed
   2.286 -to the `&&` operator, the `&&+` operator may return false positives and is
   2.287 -currently implemented for:
   2.288 -
   2.289 -* `epoint &&+ ecluster`
   2.290 -* `ebox &&+ ecircle`
   2.291 -* `ebox &&+ ecluster`
   2.292 -* `ecircle &&+ ecluster`
   2.293 -* `ecluster &&+ ecluster`
   2.294 -
   2.295 -The `&&+` operator is commutative, i.e. "`a &&+ b`" is the same as "`b &&+ a`".
   2.296 -Each commutation is supported as well.
   2.297 -
   2.298 -Where two data types support both the `&&` and the `&&+` operator, the `&&+`
   2.299 -operator computes faster.
   2.300 -
   2.301 -#### Contains operator `@>`
   2.302 -
   2.303 -Tests if the object right of the operator is contained in the object left of
   2.304 -the operator. Currently implemented for:
   2.305 -
   2.306 -* `ebox @> epoint` (alias for `&&`)
   2.307 -* `ebox @> ebox`
   2.308 -* `ebox @> ecluster`
   2.309 -* `ecluster @> epoint` (alias for `&&`)
   2.310 -* `ecluster @> ebox`
   2.311 -* `ecluster @> ecluster`
   2.312 -
   2.313 -The commutator of `@>` ("contains") is `<@` ("is contained in"), i.e.
   2.314 -"`a @> b`" is the same as "`b <@ a`".
   2.315 -
   2.316 -Whether the perimeter of an object is taken into account is undefined and may
   2.317 -differ between the left and the right hand side of the operator. The current
   2.318 -implementation (where not an alias for `&&`) returns true only if an object is
   2.319 -contained completely within the other object, not touching its perimeter,
   2.320 -paths, outlines, or any singular points.
   2.321 -
   2.322 -#### Distance operator `<->`
   2.323 -
   2.324 -Calculates the shortest distance between two geographic objects in meters (zero
   2.325 -if the objects are overlapping). Currently implemented for:
   2.326 -
   2.327 -* `epoint <-> epoint`
   2.328 -* `epoint <-> ebox`
   2.329 -* `epoint <-> ecircle`
   2.330 -* `epoint <-> ecluster`
   2.331 -* `ebox <-> ebox`
   2.332 -* `ebox <-> ecircle`
   2.333 -* `ebox <-> ecluster`
   2.334 -* `ecircle <-> ecircle`
   2.335 -* `ecircle <-> ecluster`
   2.336 -* `ecluster <-> ecluster`
   2.337 -
   2.338 -The `<->` operator is commutative, i.e. "`a <-> b`" is the same as "`b <-> a`".
   2.339 -Each commutation is supported as well.
   2.340 -
   2.341 -For short distances, the result is very accurate (i.e. respects the dimensions
   2.342 -of the WGS-84 spheroid). For longer distances in the order of magnitude of
   2.343 -Earth's radius or greater, the value is only approximate (but the error is
   2.344 -still less than 0.2% as long as no polygons with very long edges are involved).
   2.345 -
   2.346 -The functions `distance(epoint, epoint)` and `distance(ecluster, epoint)` can
   2.347 -be used as an alias for this operator.
   2.348 -
   2.349 -Note: In case of radial searches with a fixed radius, this operator should
   2.350 -not be used. Instead, an `ecircle` should be created and used in combination
   2.351 -with the overlap operator (`&&`). Alternatively, the functions
   2.352 -`distance_within(epoint, epoint, float8)` or `distance_within(ecluster, epoint,
   2.353 -float8)` can be used for fixed-radius searches.
   2.354 -
   2.355 -### 4. Functions
   2.356 -
   2.357 -#### `center(circle)`
   2.358 -
   2.359 -Returns the center of an `ecircle` as an `epoint`.
   2.360 -
   2.361 -#### `distance(epoint, epoint)`
   2.362 -
   2.363 -Calculates the distance between two `epoint` datums in meters. This function is
   2.364 -an alias for the distance operator `<->`.
   2.365 -
   2.366 -Note: In case of radial searches with a fixed radius, this function should not be
   2.367 -used. Use `distance_within(epoint, epoint, float8)` instead.
   2.368 -
   2.369 -#### `distance(ecluster, epoint)`
   2.370 -
   2.371 -Calculates the distance from an `ecluster` to an `epoint` in meters. This
   2.372 -function is an alias for the distance operator `<->`.
   2.373 -
   2.374 -Note: In case of radial searches with a fixed radius, this function should not be
   2.375 -used. Use `distance_within(epoint, epoint, float8)` instead.
   2.376 -
   2.377 -#### `distance_within(`variable `epoint,` fixed `epoint,` radius `float8)`
   2.378 -
   2.379 -Checks if the distance between two `epoint` datums is not greater than a given
   2.380 -value (search radius).
   2.381 -
   2.382 -Note: In case of radial searches with a fixed radius, the first argument must
   2.383 -be used for the table column, while the second argument must be used for the
   2.384 -search center. Otherwise an existing index cannot be used.
   2.385 -
   2.386 -#### `distance_within(`variable `ecluster,` fixed `epoint,` radius `float8)`
   2.387 -
   2.388 -Checks if the distance from an `ecluster` to an `epoint` is not greater than a
   2.389 -given value (search radius).
   2.390 -
   2.391 -#### `ebox(`latmin `float8,` latmax `float8,` lonmin `float8,` lonmax `float8)`
   2.392 -
   2.393 -Creates a new `ebox` with the given boundaries.
   2.394 -See "1. Types", subsection `ebox` for details.
   2.395 -
   2.396 -#### `ebox(epoint, epoint)`
   2.397 -
   2.398 -Creates a new `ebox`. This function may only be used if the longitude
   2.399 -difference is less than or equal to 120 degrees.
   2.400 -See "1. Types", subsection `ebox` for details.
   2.401 -
   2.402 -#### `ecircle(epoint, float8)`
   2.403 -
   2.404 -Creates an `ecircle` with the given center point and radius.
   2.405 -
   2.406 -#### `ecircle(`latitude `float8,` longitude `float8,` radius `float8)`
   2.407 -
   2.408 -Creates an `ecircle` with the given center point and radius.
   2.409 -
   2.410 -#### `ecluster_concat(ecluster, ecluster)`
   2.411 -
   2.412 -Combines two clusters to form a new `ecluster` by uniting all entries of both
   2.413 -clusters. Note that two overlapping areas of polygons annihilate each other
   2.414 -(which may be used to create polygons with holes).
   2.415 -
   2.416 -#### `ecluster_concat(ecluster[])`
   2.417 -
   2.418 -Creates a new `ecluster` that unites all entries of all clusters in the passed
   2.419 -array. Note that two overlapping areas of polygons annihilate each other (which
   2.420 -may be used to create polygons with holes).
   2.421 -
   2.422 -#### `ecluster_create_multipoint(epoint[])`
   2.423 -
   2.424 -Creates a new `ecluster` which contains multiple points.
   2.425 -
   2.426 -#### `ecluster_create_outline(epoint[])`
   2.427 -
   2.428 -Creates a new `ecluster` that is an outline given by the passed points.
   2.429 -
   2.430 -#### `ecluster_create_path(epoint[])`
   2.431 -
   2.432 -Creates a new `ecluster` that is a path given by the passed points.
   2.433 -
   2.434 -#### `ecluster_create_polygon(epoint[])`
   2.435 -
   2.436 -Creates a new `ecluster` that is a polygon given by the passed points.
   2.437 -
   2.438 -#### `ecluster_extract_outlines(ecluster)`
   2.439 -
   2.440 -Set-returning function that returns the outlines of an `ecluster` as `epoint[]`
   2.441 -rows.
   2.442 -
   2.443 -#### `ecluster_extract_paths(ecluster)`
   2.444 -
   2.445 -Set-returning function that returns the paths of an `ecluster` as `epoint[]`
   2.446 -rows.
   2.447 -
   2.448 -#### `ecluster_extract_points(ecluster)`
   2.449 -
   2.450 -Set-returning function that returns the points of an `ecluster` as `epoint`
   2.451 -rows.
   2.452 -
   2.453 -#### `ecluster_extract_polygons(ecluster)`
   2.454 -
   2.455 -Set-returning function that returns the polygons of an `ecluster` as `epoint[]`
   2.456 -rows.
   2.457 -
   2.458 -#### `empty_ebox`()
   2.459 -
   2.460 -Returns the empty `ebox`.
   2.461 -See "1. Types", subsection `ebox` for details.
   2.462 -
   2.463 -#### `epoint(`latitude `float8,` longitude `float8)`
   2.464 -
   2.465 -Returns an `epoint` with the given latitude and longitude.
   2.466 -
   2.467 -#### `epoint_latlon(`latitude `float8,` longitude `float8)`
   2.468 -
   2.469 -Alias for `epoint(float8, float8)`.
   2.470 -
   2.471 -#### `epoint_lonlat(`longitude `float8,` latitude `float8)`
   2.472 -
   2.473 -Same as `epoint(float8, float8)` but with arguments reversed.
   2.474 -
   2.475 -#### `fair_distance(ecluster, epoint,` samples `int4 = 10000)`
   2.476 -
   2.477 -When working with user-generated content, users may be tempted to create
   2.478 -intentionally oversized objects in order to optimize search results in an
   2.479 -unfair manner. The `fair_distance` function aims to handle this by returning an
   2.480 -adjusted distance (i.e. distance increased by a penalty) if a geographic object
   2.481 -(the `ecluster`) consists of more than one point.
   2.482 -
   2.483 -The first argument to this function is an `ecluster`, the second argument is a
   2.484 -search point (`epoint`), and the third argument is an interger related to the
   2.485 -precision (higher precision will require more computation time).
   2.486 -
   2.487 -The penalty by which the returned distance is increased fulfills (at least) the
   2.488 -following properties:
   2.489 -
   2.490 -* The penalty function is continuous (except noise created by numerical
   2.491 -  integration, see paragraph after this list) as long as no objects are added
   2.492 -  to or removed from the `ecluster`. That particularly means: small changes in
   2.493 -  the search point (second argument) cause only small changes in the result.
   2.494 -* For search points far away from the `ecluster` (i.e. large distances compared
   2.495 -  to the dimensions of the `ecluster`), the penalty approaches zero, i.e. the
   2.496 -  behavior of the `fair_distance` function approaches the behavior of the
   2.497 -  `distance` function.
   2.498 -* If the `ecluster` consists of a set of points, the penalty for a search point
   2.499 -  close to one of those points (closer than half of the minimum distance
   2.500 -  between each pair of points in the `ecluster`) is chosen in such a way that
   2.501 -  the adjusted distance is equal to the distance from the search point to the
   2.502 -  closest point in the `ecluster` multiplied by the square root of the count of
   2.503 -  points in the `ecluster`.
   2.504 -* If the `ecluster` does not cover any area (i.e. only consists of points,
   2.505 -  paths, and/or outlines), and if the search point (second argument) overlaps
   2.506 -  with the `ecluster`, then the penalty (and thus the result) is zero.
   2.507 -* The integral (or average) of the square of the fair distance value (result of
   2.508 -  this function) over all possible search points is independent of the
   2.509 -  `ecluster` as long as the `ecluster` does not cover more than a half of
   2.510 -  earth's surface.
   2.511 -
   2.512 -The function uses numerical integration to compute the result. The third
   2.513 -parameter (which defaults to 10000) can be used to adjust the number of samples
   2.514 -taken. A higher sample count increases precision as well as execution time of
   2.515 -the function. Because this function internally uses a spherical model of earth
   2.516 -for certain steps of the calculation, the precision cannot be increased
   2.517 -unboundedly.
   2.518 -
   2.519 -Despite the limitations explained above, it is ensured that the penalty is
   2.520 -always positive, i.e. results returned by the `fair_distance` function are
   2.521 -always equal to or greater than the results returned by the `distance`
   2.522 -function regardless of stochastic effects.  Furthermore, all results are
   2.523 -deterministic and reproducible with the same version of pgLatLon.
   2.524 -
   2.525 -#### `GeoJSON_to_epoint(jsonb, text)`
   2.526 -
   2.527 -Maps a GeoJSON object of type "Point" or "Feature" (which contains a
   2.528 -"Point") to an `epoint` datum. For any other JSON objects, NULL is returned.
   2.529 -
   2.530 -The second parameter (which defaults to `epoint_lonlat`) may be set to a name
   2.531 -of a conversion function that transforms two coordinates (two `float8`
   2.532 -parameters) to an `epoint`.
   2.533 -
   2.534 -#### `GeoJSON_to_ecluster(jsonb, text)`
   2.535 -
   2.536 -Maps a (valid) GeoJSON object to an `ecluster`. Note that this function
   2.537 -does not check whether the JSONB object is a valid GeoJSON object.
   2.538 -
   2.539 -The second parameter (which defaults to `epoint_lonlat`) may be set to a name
   2.540 -of a conversion function that transforms two coordinates (two `float8`
   2.541 -parameters) to an `epoint`.
   2.542 -
   2.543 -#### `max_latitude(ebox)`
   2.544 -
   2.545 -Returns the northern boundary of a given `ebox` in degrees between -90 and +90.
   2.546 -
   2.547 -#### `max_longitude(ebox)`
   2.548 -
   2.549 -Returns the eastern boundary of a given `ebox` in degrees between -180 and +180
   2.550 -(both inclusive).
   2.551 -
   2.552 -#### `min_latitude(ebox)`
   2.553 -
   2.554 -Returns the southern boundary of a given `ebox` in degrees between -90 and +90.
   2.555 -
   2.556 -#### `min_longitude(ebox)`
   2.557 -
   2.558 -Returns the western boundary of a given `ebox` in degrees between -180 and +180
   2.559 -(both inclusive).
   2.560 -
   2.561 -#### `latitude(epoint)`
   2.562 -
   2.563 -Returns the latitude value of an `epoint` in degrees between -90 and +90.
   2.564 -
   2.565 -#### `longitude(epoint)`
   2.566 -
   2.567 -Returns the longitude value of an `epoint` in degrees between -180 and +180
   2.568 -(both inclusive).
   2.569 -
   2.570 -#### `radius(ecircle)`
   2.571 -
   2.572 -Returns the radius of an `ecircle` in meters.
   2.573 -
     3.1 --- a/make-doc.sh	Thu Oct 23 10:39:05 2025 +0200
     3.2 +++ b/make-doc.sh	Thu Oct 23 15:15:56 2025 +0200
     3.3 @@ -1,8 +1,8 @@
     3.4  #!/bin/sh
     3.5  #
     3.6  # This command can be used to update the README.html file after changing the
     3.7 -# README.mkd file.
     3.8 +# README.md file.
     3.9  
    3.10 -echo "<html><head><title>"`grep '[^ \t\r\n][^ \t\r\n]*' README.mkd | head -n 1`"</title></head><body>" > README.html
    3.11 -markdown2 README.mkd >> README.html
    3.12 +echo "<html><head><title>"`grep '[^ \t\r\n][^ \t\r\n]*' README.md | head -n 1`"</title></head><body>" > README.html
    3.13 +markdown2 README.md >> README.html
    3.14  echo "</body></html>" >> README.html

Impressum / About Us