Skip to content

Commit 25be04d

Browse files
committed
Apply to 3.10 and 3.11
1 parent b1a9f11 commit 25be04d

File tree

12 files changed

+1021
-897
lines changed

12 files changed

+1021
-897
lines changed

site/content/3.10/aql/functions/date.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ description: >-
77
ISO 8601 date time strings
88
archetype: default
99
---
10+
## Date and time representations
11+
1012
AQL offers functionality to work with dates, but it does not have a special data type
1113
for dates (neither does JSON, which is usually used as format to ship data into and
1214
out of ArangoDB). Instead, dates in AQL are represented by either numbers or strings.

site/content/3.10/aql/functions/geo.md

Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,384 @@ description: >-
77
accelerated by geo-spatial indexes
88
archetype: default
99
---
10+
## Geo-spatial data representations
11+
12+
You can model geo-spatial information in different ways using the data types
13+
available in ArangoDB. The recommended way is to use objects with **GeoJSON**
14+
geometry but you can also use **longitude and latitude coordinate pairs**
15+
for points. Both models are supported by
16+
[Geo-Spatial Indexes](../../index-and-search/indexing/working-with-indexes/geo-spatial-indexes.md).
17+
18+
### Coordinate pairs
19+
20+
Longitude and latitude coordinates are numeric values and can be stored in the
21+
following ways:
22+
23+
- Coordinates using an array with two numbers in `[longitude, latitude]` order,
24+
for example, in a user-chosen attribute called `location`:
25+
26+
```json
27+
{
28+
"location": [ -73.983, 40.764 ]
29+
}
30+
```
31+
32+
- Coordinates using an array with two numbers in `[latitude, longitude]` order,
33+
for example, in a user-chosen attribute called `location`:
34+
35+
```json
36+
{
37+
"location": [ 40.764, -73.983 ]
38+
}
39+
```
40+
41+
- Coordinates using two separate numeric attributes, for example, in two
42+
user-chosen attributes called `lat` and `lng` as sub-attributes of a `location`
43+
attribute:
44+
45+
```json
46+
{
47+
"location": {
48+
"lat": 40.764,
49+
"lng": -73.983
50+
}
51+
}
52+
```
53+
54+
### GeoJSON
55+
56+
GeoJSON is a geospatial data format based on JSON. It defines several different
57+
types of JSON objects and the way in which they can be combined to represent
58+
data about geographic shapes on the Earth surface.
59+
60+
Example of a document with a GeoJSON Point stored in a user-chosen attribute
61+
called `location` (with coordinates in `[longitude, latitude]` order):
62+
63+
```json
64+
{
65+
"location": {
66+
"type": "Point",
67+
"coordinates": [ -73.983, 40.764 ]
68+
}
69+
}
70+
```
71+
72+
GeoJSON uses a geographic coordinate reference system,
73+
World Geodetic System 1984 (WGS 84), and units of decimal degrees.
74+
75+
Internally ArangoDB maps all coordinate pairs onto a unit sphere. Distances are
76+
projected onto a sphere with the Earth's *Volumetric mean radius* of *6371
77+
km*. ArangoDB implements a useful subset of the GeoJSON format
78+
[(RFC 7946)](https://tools.ietf.org/html/rfc7946).
79+
Feature Objects and the GeometryCollection type are not supported.
80+
Supported geometry object types are:
81+
82+
- Point
83+
- MultiPoint
84+
- LineString
85+
- MultiLineString
86+
- Polygon
87+
- MultiPolygon
88+
89+
#### Point
90+
91+
A [GeoJSON Point](https://tools.ietf.org/html/rfc7946#section-3.1.2) is a
92+
[position](https://tools.ietf.org/html/rfc7946#section-3.1.1) comprised of
93+
a longitude and a latitude:
94+
95+
```json
96+
{
97+
"type": "Point",
98+
"coordinates": [100.0, 0.0]
99+
}
100+
```
101+
102+
#### MultiPoint
103+
104+
A [GeoJSON MultiPoint](https://tools.ietf.org/html/rfc7946#section-3.1.7) is
105+
an array of positions:
106+
107+
```json
108+
{
109+
"type": "MultiPoint",
110+
"coordinates": [
111+
[100.0, 0.0],
112+
[101.0, 1.0]
113+
]
114+
}
115+
```
116+
117+
#### LineString
118+
119+
A [GeoJSON LineString](https://tools.ietf.org/html/rfc7946#section-3.1.4) is
120+
an array of two or more positions:
121+
122+
```json
123+
{
124+
"type": "LineString",
125+
"coordinates": [
126+
[100.0, 0.0],
127+
[101.0, 1.0]
128+
]
129+
}
130+
```
131+
132+
#### MultiLineString
133+
134+
A [GeoJSON MultiLineString](https://tools.ietf.org/html/rfc7946#section-3.1.5) is
135+
an array of LineString coordinate arrays:
136+
137+
```json
138+
{
139+
"type": "MultiLineString",
140+
"coordinates": [
141+
[
142+
[100.0, 0.0],
143+
[101.0, 1.0]
144+
],
145+
[
146+
[102.0, 2.0],
147+
[103.0, 3.0]
148+
]
149+
]
150+
}
151+
```
152+
153+
#### Polygon
154+
155+
A [GeoJSON Polygon](https://tools.ietf.org/html/rfc7946#section-3.1.6) consists
156+
of a series of closed `LineString` objects (ring-like). These *Linear Ring*
157+
objects consist of four or more coordinate pairs with the first and last
158+
coordinate pair being equal. Coordinate pairs of a Polygon are an array of
159+
linear ring coordinate arrays. The first element in the array represents
160+
the exterior ring. Any subsequent elements represent interior rings
161+
(holes within the surface).
162+
163+
The orientation of the first linear ring is crucial: the right-hand-rule
164+
is applied, so that the area to the left of the path of the linear ring
165+
(when walking on the surface of the Earth) is considered to be the
166+
"interior" of the polygon. All other linear rings must be contained
167+
within this interior. According to the GeoJSON standard, the subsequent
168+
linear rings must be oriented following the right-hand-rule, too,
169+
that is, they must run **clockwise** around the hole (viewed from
170+
above). However, ArangoDB is tolerant here (as suggested by the
171+
[GeoJSON standard](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.6)),
172+
all but the first linear ring are inverted if the orientation is wrong.
173+
174+
In the end, a point is considered to be in the interior of the polygon,
175+
if and only if one has to cross an odd number of linear rings to reach the
176+
exterior of the polygon prescribed by the first linear ring.
177+
178+
A number of additional rules apply (and are enforced by the GeoJSON
179+
parser):
180+
181+
- A polygon must contain at least one linear ring, i.e., it must not be
182+
empty.
183+
- A linear ring may not be empty, it needs at least three _distinct_
184+
coordinate pairs, that is, at least 4 coordinate pairs (since the first and
185+
last must be the same).
186+
- No two edges of linear rings in the polygon must intersect, in
187+
particular, no linear ring may be self-intersecting.
188+
- Within the same linear ring, consecutive coordinate pairs may be the same,
189+
otherwise all coordinate pairs need to be distinct (except the first and last one).
190+
- Linear rings of a polygon must not share edges, but they may share coordinate pairs.
191+
- A linear ring defines two regions on the sphere. ArangoDB always
192+
interprets the region that lies to the left of the boundary ring (in
193+
the direction of its travel on the surface of the Earth) as the
194+
interior of the ring. This is in contrast to earlier versions of
195+
ArangoDB before 3.10, which always took the **smaller** of the two
196+
regions as the interior. Therefore, from 3.10 on one can now have
197+
polygons whose outer ring encloses more than half the Earth's surface.
198+
- The interior rings must be contained in the (interior) of the outer ring.
199+
- Interior rings should follow the above rule for orientation
200+
(counterclockwise external rings, clockwise internal rings, interior
201+
always to the left of the line).
202+
203+
Here is an example with no holes:
204+
205+
```json
206+
{
207+
"type": "Polygon",
208+
"coordinates": [
209+
[
210+
[100.0, 0.0],
211+
[101.0, 0.0],
212+
[101.0, 1.0],
213+
[100.0, 1.0],
214+
[100.0, 0.0]
215+
]
216+
]
217+
}
218+
```
219+
220+
Here is an example with a hole:
221+
222+
```json
223+
{
224+
"type": "Polygon",
225+
"coordinates": [
226+
[
227+
[100.0, 0.0],
228+
[101.0, 0.0],
229+
[101.0, 1.0],
230+
[100.0, 1.0],
231+
[100.0, 0.0]
232+
],
233+
[
234+
[100.8, 0.8],
235+
[100.8, 0.2],
236+
[100.2, 0.2],
237+
[100.2, 0.8],
238+
[100.8, 0.8]
239+
]
240+
]
241+
}
242+
```
243+
244+
#### MultiPolygon
245+
246+
A [GeoJSON MultiPolygon](https://tools.ietf.org/html/rfc7946#section-3.1.6) consists
247+
of multiple polygons. The "coordinates" member is an array of
248+
_Polygon_ coordinate arrays. See [above](#polygon) for the rules and
249+
the meaning of polygons.
250+
251+
If the polygons in a MultiPolygon are disjoint, then a point is in the
252+
interior of the MultiPolygon if and only if it is
253+
contained in one of the polygons. If some polygon P2 in a MultiPolygon
254+
is contained in another polygon P1, then P2 is treated like a hole
255+
in P1 and containment of points is defined with the even-odd-crossings rule
256+
(see [Polygon](#polygon)).
257+
258+
Additionally, the following rules apply and are enforced for
259+
MultiPolygons:
260+
261+
- No two edges in the linear rings of the polygons of a MultiPolygon
262+
may intersect.
263+
- Polygons in the same MultiPolygon may not share edges, but they may share
264+
coordinate pairs.
265+
266+
Example with two polygons, the second one with a hole:
267+
268+
```json
269+
{
270+
"type": "MultiPolygon",
271+
"coordinates": [
272+
[
273+
[
274+
[102.0, 2.0],
275+
[103.0, 2.0],
276+
[103.0, 3.0],
277+
[102.0, 3.0],
278+
[102.0, 2.0]
279+
]
280+
],
281+
[
282+
[
283+
[100.0, 0.0],
284+
[101.0, 0.0],
285+
[101.0, 1.0],
286+
[100.0, 1.0],
287+
[100.0, 0.0]
288+
],
289+
[
290+
[100.2, 0.2],
291+
[100.2, 0.8],
292+
[100.8, 0.8],
293+
[100.8, 0.2],
294+
[100.2, 0.2]
295+
]
296+
]
297+
]
298+
}
299+
```
300+
301+
## GeoJSON interpretation
302+
303+
Note the following technical detail about GeoJSON: The
304+
[GeoJSON standard, Section 3.1.1 Position](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.1)
305+
prescribes that lines are **cartesian lines in cylindrical coordinates**
306+
(longitude/latitude). However, this definition is inconvenient in practice,
307+
since such lines are not geodesic on the surface of the Earth.
308+
Furthermore, the best available algorithms for geospatial computations on Earth
309+
typically use geodesic lines as the boundaries of polygons on Earth.
310+
311+
Therefore, ArangoDB uses the **syntax of the GeoJSON** standard,
312+
but then interprets lines (and boundaries of polygons) as
313+
**geodesic lines (pieces of great circles) on Earth**. This is a
314+
violation of the GeoJSON standard, but serving a practical purpose.
315+
316+
Note in particular that this can sometimes lead to unexpected results.
317+
Consider the following polygon (remember that GeoJSON has
318+
**longitude before latitude** in coordinate pairs):
319+
320+
```json
321+
{ "type": "Polygon", "coordinates": [[
322+
[4, 54], [4, 47], [16, 47], [16, 54], [4, 54]
323+
]] }
324+
```
325+
326+
![GeoJSON Polygon Geodesic](../../../images/geojson-polygon-geodesic.webp)
327+
328+
It does not contain the point `[10, 47]` since the shortest path (geodesic)
329+
from `[4, 47]` to `[16, 47]` lies North relative to the parallel of latitude at
330+
47 degrees. On the contrary, the polygon does contain the point `[10, 54]` as it
331+
lies South of the parallel of latitude at 54 degrees.
332+
333+
{{< info >}}
334+
ArangoDB version before 3.10 did an inconsistent special detection of "rectangle"
335+
polygons that later versions from 3.10 onward no longer do, see
336+
[Legacy Polygons](../../index-and-search/indexing/working-with-indexes/geo-spatial-indexes.md#legacy-polygons).
337+
{{< /info >}}
338+
339+
Furthermore, there is an issue with the interpretation of linear rings
340+
(boundaries of polygons) according to
341+
[GeoJSON standard, Section 3.1.6 Polygon](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.6).
342+
This section states explicitly:
343+
344+
> A linear ring MUST follow the right-hand rule with respect to the
345+
> area it bounds, i.e., exterior rings are counter-clockwise, and
346+
> holes are clockwise.
347+
348+
This rather misleading phrase means that when a linear ring is used as
349+
the boundary of a polygon, the "interior" of the polygon lies **to the left**
350+
of the boundary when one travels on the surface of the Earth and
351+
along the linear ring. For
352+
example, the polygon below travels **counter-clockwise** around the point
353+
`[10, 50]`, and thus the interior of the polygon contains this point and
354+
its surroundings, but not, for example, the North Pole and the South
355+
Pole.
356+
357+
```json
358+
{ "type": "Polygon", "coordinates": [[
359+
[4, 54], [4, 47], [16, 47], [16, 54], [4, 54]
360+
]] }
361+
```
362+
363+
![GeoJSON Polygon Counter-clockwise](../../../images/geojson-polygon-ccw.webp)
364+
365+
On the other hand, the following polygon travels **clockwise** around the point
366+
`[10, 50]`, and thus its "interior" does not contain `[10, 50]`, but does
367+
contain the North Pole and the South Pole:
368+
369+
```json
370+
{ "type": "Polygon", "coordinates": [[
371+
[4, 54], [16, 54], [16, 47], [4, 47], [4, 54]
372+
]] }
373+
```
374+
375+
![GeoJSON Polygon Clockwise](../../../images/geojson-polygon-cw.webp)
376+
377+
Remember that the "interior" is to the left of the given
378+
linear ring, so this second polygon is basically the complement on Earth
379+
of the previous polygon!
380+
381+
ArangoDB versions before 3.10 did not follow this rule and always took the
382+
"smaller" connected component of the surface as the "interior" of the polygon.
383+
This made it impossible to specify polygons which covered more than half of the
384+
sphere. From version 3.10 onward, ArangoDB recognizes this correctly.
385+
See [Legacy Polygons](../../index-and-search/indexing/working-with-indexes/geo-spatial-indexes.md#legacy-polygons)
386+
for how to deal with this issue.
387+
10388
## Geo utility functions
11389

12390
The following helper functions **can** use geo indexes, but do not have to in

0 commit comments

Comments
 (0)