added new GIS functions and unit support to geo package

pull/1288/head
Scott Anderson 2020-08-11 09:16:06 -06:00
parent cbeff50523
commit 71f5651516
12 changed files with 555 additions and 35 deletions

View File

@ -80,6 +80,7 @@ Define geographic regions using the following shapes:
- [box](#box)
- [circle](#circle)
- [point](#point)
- [polygon](#polygon)
### box
@ -116,6 +117,20 @@ Define a circular region by specifying an object containing the following proper
}
```
### point
Define a point region by specifying and object containing the following properties:
- **lat**: latitude in decimal degrees (WGS 84) _(Float)_
- **lon**: longitude in decimal degrees (WGS 84) _(Float)_
##### Example point region
```js
{
lat: 40.671659,
lon: -73.936631
}
```
### polygon
Define a custom polygon region using an object containing the following properties:
@ -136,3 +151,38 @@ Define a custom polygon region using an object containing the following properti
]
}
```
## GIS geometry definitions
Many functions in the Geo package manipulate data based on geographic information system (GIS) data.
Define GIS geometry using the following:
- Any [region type](#region-definitions) _(typically [point](#point))_
- [linestring](#linestring)
### linestring
Define a geographic linestring path using an object containing the following properties:
- **linestring**: string containing comma-separatedlongitude and latitude
coordinate pairs (`lon lat,`):
```js
{
linestring: "39.7515 14.01433, 38.3527 13.9228, 36.9978 15.08433"
}
```
## Distance units
The Geo package supports the following units of measurement for distance:
- `m` - meters
- `km` - kilometers _(default)_
- `mile` - miles
### Define distance units
Use the Geo package `units` option to define custom units of measurement:
```js
import "experimental/geo"
option geo.units = {distance: "mile"}
```

View File

@ -196,19 +196,30 @@ filterRows = (
maxSize=-1,
level=-1,
s2cellIDLevel=-1,
correlationKey=["_time"],
strict=true
) => {
_columns =
|> columns(column: "_value")
|> tableFind(fn: (key) => true )
|> getColumn(column: "_value")
_rows =
tables
|> gridFilter(
region,
minSize: minSize,
maxSize: maxSize,
level: level,
s2cellIDLevel: s2cellIDLevel
)
|> toRows(correlationKey)
if contains(value: "lat", set: _columns) then
tables
|> gridFilter(
region: region,
minSize: minSize,
maxSize: maxSize,
level: level,
s2cellIDLevel: s2cellIDLevel)
else
tables
|> gridFilter(
region: region,
minSize: minSize,
maxSize: maxSize,
level: level,
s2cellIDLevel: s2cellIDLevel)
|> toRows()
_result =
if strict then
_rows

View File

@ -0,0 +1,36 @@
---
title: geo.s2CellLatLon() function
description: >
The `geo.s2CellLatLon()` function returns the latitude and longitude of the
center of an S2 cell.
menu:
v2_0_ref:
name: geo.s2CellLatLon
parent: Geo
weight: 401
v2.0/tags: [functions, geo]
related:
- /v2.0/query-data/flux/geo/
---
The `geo.s2CellLatLon()` function returns the latitude and longitude of the
center of an S2 cell.
_**Function type:** Transformation_
```js
import "experimental/geo"
geo.s2CellLatLon(
token: "89c284"
)
// Returns {lat: 40.812535546624574, lon: -73.55941282728273}
```
## Parameters
### token
S2 cell ID token.
_**Data type:** String_

View File

@ -32,8 +32,7 @@ import "experimental/geo"
geo.shapeData(
latField: "latitude",
lonField: "longitude",
level: 10,
correlationKey: ["_time"]
level: 10
)
```
@ -57,12 +56,6 @@ when generating the S2 cell ID token.
_**Data type:** Integer_
### correlationKey
List of columns used to uniquely identify a row for output.
Default is `["_time"]`.
_**Data type:** Array of strings_
## Examples
##### Shape data to meet the requirements of the Geo package

View File

@ -0,0 +1,86 @@
---
title: geo.ST_Contains() function
description: >
The `geo.ST_Contains()` function tests if the specified region contains the specified
GIS geometry and returns `true` or `false`.
menu:
v2_0_ref:
name: geo.ST_Contains
parent: Geo
weight: 401
v2.0/tags: [functions, geo, GIS]
related:
- /v2.0/query-data/flux/geo/
---
The `geo.ST_Contains()` function tests if the specified region contains the specified
geographic information system (GIS) geometry and returns `true` or `false`.
_**Function type:** Test_
```js
import "experimental/geo"
geo.ST_Contains(
region: {lat: 40.7, lon: -73.3, radius: 20.0},
geometry: {lon: 39.7515, lat: 15.08433}
)
// Returns false
```
## Parameters
### region
The region to test.
Specify object properties for the shape.
_See [Region definitions](/v2.0/reference/flux/stdlib/experimental/geo/#region-definitions)._
_**Data type:** Object_
### geometry
The GIS geometry to test.
Can be either point or linestring geometry.
_See [GIS geometry definitions](/v2.0/reference/flux/stdlib/experimental/geo/#gis-geometry-definitions)._
_**Data type:** Object_
## Examples
##### Test if geographic points are inside of a region
```js
import "experimental/geo"
region = {
minLat: 40.51757813,
maxLat: 40.86914063,
minLon: -73.65234375,
maxLon: -72.94921875
}
data
|> geo.toRows()
|> map(fn: (r) => ({
r with st_contains: geo.ST_Contains(region: region, geometry: {lat: r.lat, lon: r.lon})
}))
```
##### Test if tracks are inside of a region
```js
import "experimental/geo"
region = {
minLat: 40.51757813,
maxLat: 40.86914063,
minLon: -73.65234375,
maxLon: -72.94921875
}
data
|> geo.toRows()
|> geo.asTracks()
|> geo.ST_LineString()
|> map(fn: (r) => ({
r with st_contains: geo.ST_Contains(region: region, geometry: {linestring: r.st_linestring})
}))
```

View File

@ -0,0 +1,85 @@
---
title: geo.ST_Distance() function
description: >
The `geo.ST_Distance()` function returns the distance between the specified region
and specified GIS geometry.
menu:
v2_0_ref:
name: geo.ST_Distance
parent: Geo
weight: 401
v2.0/tags: [functions, geo, GIS]
related:
- /v2.0/query-data/flux/geo/
---
The `geo.ST_Distance()` function returns the distance between the specified region
and specified geographic information system (GIS) geometry.
Define distance units with the [`geo.units` option](/v2.0/reference/flux/stdlib/experimental/geo/#define-distance-units).
_**Function type:** Transformation_
```js
import "experimental/geo"
geo.ST_Distance(
region: {lat: 40.7, lon: -73.3, radius: 20.0},
geometry: {lon: 39.7515, lat: 15.08433}
)
// Returns 10734.184618677662 (km)
```
## Parameters
### region
The region to test.
Specify object properties for the shape.
_See [Region definitions](/v2.0/reference/flux/stdlib/experimental/geo/#region-definitions)._
_**Data type:** Object_
### geometry
The GIS geometry to test.
Can be either point or linestring geometry.
_See [GIS geometry definitions](/v2.0/reference/flux/stdlib/experimental/geo/#gis-geometry-definitions)._
_**Data type:** Object_
## Examples
##### Test if geographic points are inside of a region
```js
import "experimental/geo"
region = {
minLat: 40.51757813,
maxLat: 40.86914063,
minLon: -73.65234375,
maxLon: -72.94921875
}
data
|> geo.toRows()
|> map(fn: (r) => ({
r with st_contains: ST_Distance(region: region, geometry: {lat: r.lat, lon: r.lon})
}))
```
##### Calculate the distance between geographic points and a region
```js
import "experimental/geo"
region = {
minLat: 40.51757813,
maxLat: 40.86914063,
minLon: -73.65234375,
maxLon: -72.94921875
}
data
|> geo.toRows()
|> map(fn: (r) => ({
r with st_distance: ST_Distance(region: region, geometry: {lat: r.lat, lon: r.lon})
}))
```

View File

@ -0,0 +1,75 @@
---
title: geo.ST_DWithin() function
description: >
The `geo.ST_DWithin()` function tests if the specified region is within a defined
distance from the specified geographic information system (GIS) geometry and
returns `true` or `false`.
menu:
v2_0_ref:
name: geo.ST_DWithin
parent: Geo
weight: 401
v2.0/tags: [functions, geo, GIS]
related:
- /v2.0/query-data/flux/geo/
---
The `geo.ST_DWithin()` function tests if the specified region is within a defined
distance from the specified geographic information system (GIS) geometry and
returns `true` or `false`.
_**Function type:** Test_
```js
import "experimental/geo"
geo.ST_DWithin(
region: {lat: 40.7, lon: -73.3, radius: 20.0},
geometry: {lon: 39.7515, lat: 15.08433},
distance: 1000.0
)
// Returns false
```
## Parameters
### region
The region to test.
Specify object properties for the shape.
_See [Region definitions](/v2.0/reference/flux/stdlib/experimental/geo/#region-definitions)._
_**Data type:** Object_
### geometry
The GIS geometry to test.
Can be either point or linestring geometry.
_See [GIS geometry definitions](/v2.0/reference/flux/stdlib/experimental/geo/#gis-geometry-definitions)._
_**Data type:** Object_
### distance
Maximum allowed distance between the region and geometry.
_Define distance units with the [`geo.units` option](/v2.0/reference/flux/stdlib/experimental/geo/#define-distance-units)._
_**Data type:** Float_
## Examples
##### Test if geographic points are within a distance from a region
```js
import "experimental/geo"
region = {
minLat: 40.51757813,
maxLat: 40.86914063,
minLon: -73.65234375,
maxLon: -72.94921875
}
data
|> geo.toRows()
|> map(fn: (r) => ({
r with st_within: geo.ST_DWithin(region: box, geometry: {lat: r.lat, lon: r.lon}, distance: 15.0)
}))
```

View File

@ -0,0 +1,66 @@
---
title: geo.ST_Intersects() function
description: >
The `geo.ST_Intersects()` function tests if the specified geographic information
system (GIS) geometry intersects with the specified region and returns `true` or `false`.
menu:
v2_0_ref:
name: geo.ST_Intersects
parent: Geo
weight: 401
v2.0/tags: [functions, geo, GIS]
related:
- /v2.0/query-data/flux/geo/
---
The `geo.ST_Intersects()` function tests if the specified geographic information
system (GIS) geometry intersects with the specified region and returns `true` or `false`.
_**Function type:** Test_
```js
import "experimental/geo"
geo.ST_Intersects(
region: {lat: 40.7, lon: -73.3, radius: 20.0},
geometry: {linestring: "39.7515 14.01433, 38.3527 13.9228, 36.9978 15.08433"}
)
// Returns false
```
## Parameters
### region
The region to test.
Specify object properties for the shape.
_See [Region definitions](/v2.0/reference/flux/stdlib/experimental/geo/#region-definitions)._
_**Data type:** Object_
### geometry
The GIS geometry to test.
Can be either point or linestring geometry.
_See [GIS geometry definitions](/v2.0/reference/flux/stdlib/experimental/geo/#gis-geometry-definitions)._
_**Data type:** Object_
## Examples
##### Test if geographic points intersect with a region
```js
import "experimental/geo"
region = {
minLat: 40.51757813,
maxLat: 40.86914063,
minLon: -73.65234375,
maxLon: -72.94921875
}
data
|> geo.toRows()
|> map(fn: (r) => ({
r with st_within: geo.ST_Intersects(region: box, geometry: {lat: r.lat, lon: r.lon})
}))
```

View File

@ -0,0 +1,62 @@
---
title: geo.ST_Length() function
description: >
The `geo.ST_Length()` function returns the [spherical length or distance](https://mathworld.wolfram.com/SphericalDistance.html)
of the specified geographic information system (GIS) geometry.
menu:
v2_0_ref:
name: geo.ST_Length
parent: Geo
weight: 401
v2.0/tags: [functions, geo, GIS]
related:
- /v2.0/query-data/flux/geo/
---
The `geo.ST_Length()` function returns the [spherical length or distance](https://mathworld.wolfram.com/SphericalDistance.html)
of the specified geographic information system (GIS) geometry.
Define distance units with the [`geo.units` option](/v2.0/reference/flux/stdlib/experimental/geo/#define-distance-units).
_**Function type:** Transformation_
```js
import "experimental/geo"
geo.ST_Length(
geometry: {linestring: "39.7515 14.01433, 38.3527 13.9228, 36.9978 15.08433"}
)
// Returns 346.1023974652474 (km)
```
## Parameters
### geometry
The GIS geometry to measure.
Can be either point or linestring geometry.
Points will always return `0.0`.
_See [GIS geometry definitions](/v2.0/reference/flux/stdlib/experimental/geo/#gis-geometry-definitions)._
_**Data type:** Object_
## Examples
##### Calculate the length of geographic paths
```js
import "experimental/geo"
region = {
minLat: 40.51757813,
maxLat: 40.86914063,
minLon: -73.65234375,
maxLon: -72.94921875
}
data
|> geo.toRows()
|> geo.asTracks()
|> geo.ST_LineString()
|> map(fn: (r) => ({
r with st_length: geo.ST_Length(geometry: {linestring: r.st_linestring})
}))
```

View File

@ -0,0 +1,69 @@
---
title: geo.ST_LineString() function
description: >
The `geo.ST_LineString()` function converts a series of geographic points into
[linestring](/v2.0/reference/flux/stdlib/experimental/geo/#linestring).
menu:
v2_0_ref:
name: geo.ST_LineString
parent: Geo
weight: 401
v2.0/tags: [functions, geo, GIS]
related:
- /v2.0/query-data/flux/geo/
---
The `geo.ST_LineString()` function converts a series of geographic points into
[linestring](/v2.0/reference/flux/stdlib/experimental/geo/#linestring).
Group data into meaningful, ordered paths to before converting to linestring.
Rows in each table must have `lat` and `lon` columns.
Output tables contain a single row with a `st_linestring` column containing the resulting linestring.
_**Function type:** Aggregate_
```js
import "experimental/geo"
geo.ST_LineString()
```
## Examples
### Convert a series of geographic points into linestring
##### Input data
| _time | id | lon | lat |
|:----- |:--: | ---: | ---: |
| 2020-01-01T00:00:00Z | a213b | 39.7515 | 14.01433 |
| 2020-01-02T00:00:00Z | a213b | 38.3527 | 13.9228 |
| 2020-01-03T00:00:00Z | a213b | 36.9978 | 15.08433 |
```js
import "experimental/geo"
data
|> geo.ST_LineString()
```
##### Output data
| id | st_linestring |
|:-- |:------------- |
| a213b | 39.7515 14.01433, 38.3527 13.9228, 36.9978 15.08433 |
## Function definition
```js
ST_LineString = (tables=<-) =>
tables
|> reduce(fn: (r, accumulator) => ({
__linestring: accumulator.__linestring + (if accumulator.__count > 0 then ", " else "") + string(v: r.lat) + " " + string(v: r.lon),
__count: accumulator.__count + 1
}), identity: {
__linestring: "",
__count: 0
}
)
|> rename(columns: {__linestring: "st_linestring"})
```

View File

@ -22,19 +22,9 @@ _**Function type:** Transformation_
```js
import "experimental/geo"
geo.toRows(
correlationKey: ["_time"]
)
geo.toRows()
```
## Parameters
### correlationKey
List of columns used to uniquely identify a row for output.
Default is `["_time"]`.
_**Data type:** Array of strings_
## Examples
```js
import "experimental/geo"
@ -49,9 +39,5 @@ from(bucket: "example-bucket")
```js
toRows = (tables=<-, correlationKey=["_time"]) =>
tables
|> pivot(
rowKey: correlationKey,
columnKey: ["_field"],
valueColumn: "_value"
)
|> v1.fieldsAsCols()
```

View File

@ -22,7 +22,8 @@ InfluxDB until the next InfluxDB v2.0 release._
- Add functions to convert semantic monotype to AST type.
- Add BigQuery support.
- Rust flatbuffer serialization for `MonoType` and `TypeExpression`.
- Extend with Geo package functions and add unit support.
- Extend with Geo package with GIS functions and
[unit support](/v2.0/reference/flux/stdlib/experimental/geo/#distance-units).
### Bug fixes
- String interpolation in arrays.