-
-
Notifications
You must be signed in to change notification settings - Fork 781
[Spec] Spatial Filters #1747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
From Slack Channel:
{
foos {
shape
{
... on GeoJSON {
centroid
area
length
}
... on Point {
lat
long
}
}
}
} |
I also think this would limit us:
basically the input type must be smth like a input union Also, what is implied by this: query geom_table($point: geometry){
geom_table(
where: {geom_col: {_st_d_within: {distance: 3, from: $point}}}
){
id
geom_col
}
} |
@steveoh @John0x Can you guys type out a few example SQL queries?
I think it would make sense to then translate them into the graphql and see what we want to support. |
It should be pointed out that format would be a singular choice and not an array. This would be similar to arguments from https://graphql.org/learn/queries/#arguments {
human(id: "1000") {
name
height(unit: FOOT)
}
} or from a hasura schema, type Starship {
id: ID!
name: String!
length(unit: LengthUnit = METER): Float
} or from this dgraph discussion query restaurantsNearby {
me(_uid_:x) {
restaurants @filter(near("home.location", "r.location", "50km")) {
name, rating, type
}
}
} |
This implies that given a
It is the same as location_distance_lt: {
point: { latitude: 46.859924, longitude: -113.985402 }
distance: 1500 but the unit is implied and documented as meters and buffer is a more technical term than distance. |
SQLselect name from society.cemeteries c
where ST_Distance(c.shape, ST_SetSRID(ST_Point(430178,4506818), 26912)) >= 3 Possible Implementation 1{
cemeteries (where: { distance_gte: { location: {
"type": "Point",
"coordinates": [430178, 4506818],
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:EPSG::26912"
}
}
}, distance: 3 }) {
name
}
cemeteries (where: { distance_gt: { location: { this could be anything that can resolve to a geometry; an address, milepost, place name, etc }, distance: 3}) {
name
}
} This would necessitate creating all of the number type filters.
SQLcaveat: need hook to convert input between units. select name from society.cemeteries c
where ST_Distance(c.shape, ST_SetSRID(ST_Point(430178,4506818), 26912)) < (7 * 1609.344) Possible Implementation 1{
cemeteries(where: { distance_lt: { location: {}, distance: 7, unit: MILES }}) {
name
}
}
SQLselect count(*) from location.address_points ap
where ST_Intersects(ap.shape, ST_Buffer(ST_SetSRID(ST_Point(430178,4506818), 26912), 3))
select count(*) from location.address_points ap
where ST_Within(ap.shape, ST_Buffer(ST_SetSRID(ST_Point(430178,4506818), 26912), 3))
select count(*) from location.address_points ap
where ST_Contains(ap.shape, ST_Buffer(ST_SetSRID(ST_Point(430178,4506818), 26912), 3)) Possible Implementation 1{
address_points(where: { intersects: { location: {}, distance: 3, unit: METERS }}) {
name
}
address_points(where: { within: { location: {} }) {
name
}
address_points(where: { contains: { location: {} }) {
name
}
}
point in polygon query: What city am I inSQLselect name from boundaries.municipal_boundaries city
where ST_Intersects(city.shape, ST_SetSRID(ST_Point(430178,4506818), 26912)) Possible Implementation 1{
cities(where: { intersects: { location: {} }) {
name
}
} area query: find all cities less than 1 sq mile in sizeSQLselect name from boundaries.municipal_boundaries city
where ST_Area(city.shape) < 2589988 Possible Implementation 1{
cities(where: { area_gt: { value: 1, unit: MILE) {
name
}
} length query: what earthquake faults are longer than a mileSQLselect * from geoscience.quaternary_faults faults
where ST_Length(faults.shape) > 1610 Possible Implementation 1{
faults(where: { length_gt: { value: 1, unit: MILE ) {
name
}
} closest to me: fire stationsSQLselect * from society.fire_stations fs2
order by ST_Distance(shape, ST_SetSRID(ST_Point(430178,4506818), 26912))
limit 1 Possible Implementation 1{
fire_stations(first: 1, order_by: resulting distance, this seems to currently only allow field names?, where: { distance: { location: {} ) {
nodes {
name
}
}
}
|
It starts to look good @steveoh. I will go through all of this on the weekend. Are at the moment busy with the ndc conference. |
I look forward to your comments @michaelstaib |
so here are my 5 cents. I played around a little. I think the way spatial filters work can be divided into four subcategories.
1. Array, Scalar, Object FiltersThese filters are pretty straight forward. Many of them should already work today. They might need a method call, this would not be possible today. It is not complicated to build the expression for it. Array filters and some string filters already do method calls. Not a big deal. Example // Scalar
public virtual double Area { get; }
// Object
public abstract Geometry Boundary { get; }
// Array
public abstract Coordinate[] Coordinates { get; }
// Method call
public Geometry Normalized() 2. Filters that need GeoJsonInputThese filters require GeoJsonInput. They are slightly more complex. Where it is probably not gonna be too much of a challenge to find a good way to return these values, it is hard to use them as input types. We will also add the buffer on the GeoJsonInput input type. This way every input that accepts a geometry can be buffered. public Geometry Buffer(double distance, int quadrantSegments, EndCapStyle endCapStyle) Example public bool Disjoint(Geometry g);
public bool Covers(Geometry g);
public bool CoveredBy(Geometry g); 3. Complex Filters with Custom TypesThese filter require dedicated input types. They usually need a Example public Geometry Difference(Geometry other);
public Geometry Intersection(Geometry other);
public Geometry SymmetricDifference(Geometry other); 4. (Out of scoped)There are a few methods that return types that are just to complex to implement for now. The scope of the "basic" features is already massive. Database Support Overview
Filter TypesGeometry
1. Array, Scalar, Object FiltersArea
Declaration public virtual double Area { get; } Property Value
Proposed SDL extend input GeometryFilter {
area: Float
area_gt: Float
area_gte: Float
area_lt: Float
area_lte: Float
area_in: [Float]
area_not: Float
area_not_gt: Float
area_not_gte: Float
area_not_lt: Float
area_not_lte: Float
area_not_in: [Float]
} Example {
cities(where: { shape: { area_gt: 5 } }) {
name
}
} Boundary
Declaration public abstract Geometry Boundary { get; } Property Value
Proposed SDL extend input GeometryFilter {
boundary: GeometryFilter
} Example {
cities(
where: {
shape: {
boundary: {
contains {
type: "Point",
coordinates: [430178, 4506818] }
}}}) {
name
}
} BoundaryDimension
Declaration public abstract Dimension BoundaryDimension { get; } Property Value
Proposed SDL extend input GeometryFilter {
boundaryDimension: Dimension
boundaryDimension_gt: Dimension
boundaryDimension_gte: Dimension
boundaryDimension_lt: Dimension
boundaryDimension_lte: Dimension
boundaryDimension_in: [Dimension]
boundaryDimension_not: Dimension
boundaryDimension_not_gt: Dimension
boundaryDimension_not_gte: Dimension
boundaryDimension_not_lt: Dimension
boundaryDimension_not_lte: Dimension
boundaryDimension_not_in: [Dimension]
} Example {
cities(where: { shape: { boundaryDimension_in: [CURVE, POINT] } }) {
name
}
} Centroid
Declaration public virtual Point Centroid { get; } Property Value
Proposed SDL extend input GeometryFilter {
centroid: PointFilter
} Example {
cities(where: { shape: { centroid: { x: 430178, y: 4506818 } } }) {
name
}
} Coordinate
Declaration public abstract Coordinate Coordinate { get; } Property Value
Proposed SDL extend input GeometryFilter {
coordinate: CoordinateFilter
} Example {
cities(where: { shape: { coordinate: { x: 430178, y: 4506818, z: 0 } } }) {
name
}
} Coordinates
Declaration public abstract Coordinate[] Coordinates { get; } Property Value
Proposed SDL extend input GeometryFilter {
coordinates_any: Boolean
coordinates_some: CoordinateFilter
coordinates_all: CoordinateFilter
coordinates_none: CoordinateFilter
} Example {
cities(
where: { shape: { coordinates_some: { x: 430178, y: 4506818, z: 0 } } }
) {
name
}
} Dimension
Declaration public abstract Dimension Dimension { get; } Property Value
Proposed SDL extend input GeometryFilter {
dimension: Dimension
dimension_gt: Dimension
dimension_gte: Dimension
dimension_lt: Dimension
dimension_lte: Dimension
dimension_in: [Dimension!]
dimension_not: Dimension
dimension_not_gt: Dimension
dimension_not_gte: Dimension
dimension_not_lt: Dimension
dimension_not_lte: Dimension
dimension_not_in: [Dimension!]
} Proposed SDL {
cities(where: { shape: { dimension_in: [CURVE, POINT] } }) {
name
}
} Envelope
Declaration public Geometry Envelope { get; } Property Value
Proposed SDL extend input GeometryFilter {
envelope: GeometryFilter
} Example {
cities(
where: {
shape: {
envelope: {
contains {
type: "Point",
coordinates: [430178, 4506818] }
}}}) {
name
}
} GeometryType
Declaration public abstract string GeometryType { get; } Property Value
Proposed SDL extend input GeometryFilter {
geometryType: String
geometryType_startWith: String
geometryType_endsWith: String
geometryType_contains: String
geometryType_in: [String!]
geometryType_not: String
geometryType_not_startWith: String
geometryType_not_endsWith: String
geometryType_not_contains: String
geometryType_not_in: [String!]
} InteriorPoint
Declaration public virtual Point InteriorPoint { get; } Property Value
Proposed SDL extend input GeometryFilter {
interiorPoint: PointFilter
} Example {
cities(where: { shape: { interiorPoint: { x: 430178, y: 4506818 } } }) {
name
}
} IsEmpty
Declaration public abstract bool IsEmpty { get; } Property Value
Proposed SDL extend input GeometryFilter {
isEmpty: bool
isEmpty_not: bool
} Example {
cities(where: { shape: { isEmpty: true } }) {
name
}
} IsGeometryCollection
Declaration protected bool IsGeometryCollection { get; } Property Value
Proposed SDL extend input GeometryFilter {
isGeometryCollection: bool
isGeometryCollection_not: bool
} Example {
cities(where: { shape: { isGeometryCollection: true } }) {
name
}
} IsRectangle
Declaration public virtual bool IsRectangle { get; } Property Value
Proposed SDL extend input GeometryFilter {
isRectangle: bool
isRectangle_not: bool
} Example {
cities(where: { shape: { isRectangle: true } }) {
name
}
} IsSimple
Declaration public virtual bool IsSimple { get; } Proposed SDL extend input GeometryFilter {
isSimple: bool
isSimple_not: bool
} Example {
cities(where: { shape: { isSimple: true } }) {
name
}
} IsValid
Declaration public virtual bool IsValid { get; } Proposed SDL extend input GeometryFilter {
isValid: bool
isValid_not: bool
} Example {
cities(where: { shape: { isValid: true } }) {
name
}
} Length
Declaration public virtual double Length { get; } Property Value
Proposed SDL extend input GeometryFilter {
length: Float
length_gt: Float
length_gte: Float
length_lt: Float
length_lte: Float
length_in: [Float!]
length_not: Float
length_not_gt: Float
length_not_gte: Float
length_not_lt: Float
length_not_lte: Float
length_not_in: [Float!]
} Example {
cities(where: { shape: { length: 2 } }) {
name
}
} NumGeometries
Declaration public virtual int NumGeometries { get; } Property Value
Proposed SDL extend input GeometryFilter {
numGeometries: Int
numGeometries_gt: Int
numGeometries_gte: Int
numGeometries_lt: Int
numGeometries_lte: Int
numGeometries_in: [Int!]
numGeometries_not: Int
numGeometries_not_gt: Int
numGeometries_not_gte: Int
numGeometries_not_lt: Int
numGeometries_not_lte: Int
numGeometries_not_in: [Int!]
} Example {
cities(where: { shape: { numGeometries: 2 } }) {
name
}
} NumPoints
Declaration public abstract int NumPoints { get; } Property Value
Proposed SDL extend input GeometryFilter {
numPoints: Int
numPoints_gt: Int
numPoints_gte: Int
numPoints_lt: Int
numPoints_lte: Int
numPoints_in: [Int!]
numPoints_not: Int
numPoints_not_gt: Int
numPoints_not_gte: Int
numPoints_not_lt: Int
numPoints_not_lte: Int
numPoints_not_in: [Int!]
} Example {
cities(where: { shape: { numPoints: 2 } }) {
name
}
} SRID
Declaration public int SRID { get; set; } Property Value
Proposed SDL extend input GeometryFilter {
srid: Int
srid_gt: Int
srid_gte: Int
srid_lt: Int
srid_lte: Int
srid_in: [Int!]
srid_not: Int
srid_not_gt: Int
srid_not_gte: Int
srid_not_lt: Int
srid_not_lte: Int
srid_not_in: [Int!]
} Example {
cities(where: { shape: { srid: 2 } }) {
name
}
} ConvexHull
Declaration public virtual Geometry ConvexHull() Returns
databaseEntry.ConvexHull() Proposed SDL extend input GeometryFilter {
convexHull: GeometryFilter
} Example query Example($other: GeometryFilter) {
cities(where: { shape: { convexHull: $other } }) {
name
}
} Normalized
Declaration public Geometry Normalized() Returns
databaseEntry.Normalized() // Geometry Proposed SDL extend input GeometryFilter {
normalized: GeometryFilter
} Example query Example($other: GeoJsonFitlerInput) {
cities(where: { normalized: { shape: { area: 5 } } }) {
name
}
} Reverse
Declaration public abstract Geometry Reverse() Returns
databaseEntry.Reverse() // Geometry Proposed SDL extend input GeometryFilter {
reverse: GeometryFilter
} Example query Example($other: GeoJsonFitlerInput) {
cities(where: { reverse: { shape: { area: 5 } } }) {
name
}
} 2. Filters that need GeoJsonInputContains
Declaration public virtual bool Contains(Geometry g) Parameters
Returns
databaseEntry.Contains(inputType)
!databaseEntry.Contains(inputType) Proposed SDL extend input GeometryFilter {
contains: GeoJsonFitlerInput
contains_not: GeoJsonFitlerInput
} Example query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { contains: $other } }) {
name
}
}
|
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Within(Geometry) | ✔ | ✔ | ✔ | ✔ |
```csharp
databaseEntry.Within(inputType)
!databaseEntry.Within(inputType)
Proposed SDL
extend input GeometryFilter {
within: GeoJsonFitlerInput
within_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { within: $other } }) {
name
}
}
Covers
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Covers(Geometry) | ✔ | ✔ |
Tests whether this geometry covers the argument geometry
Declaration
public virtual bool Covers(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry with which to compare this Geometry |
Returns
Type | Description |
---|---|
Boolean | true if this Geometry covers g |
databaseEntry.Covers(inputType)
!databaseEntry.Covers(inputType)
Proposed SDL
extend input GeometryFilter {
covers: GeoJsonFitlerInput
covers_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { covers: $other } }) {
name
}
}
CoveredBy
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.CoveredBy(Geometry) | ✔ | ✔ |
Tests whether this geometry is covered by the specified geometry.
Declaration
public bool CoveredBy(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | the Geometry with which to compare this Geometry |
Returns
Type | Description |
---|---|
Boolean | true if this Geometry is covered by g |
databaseEntry.CoveredBy(inputType)
!databaseEntry.CoveredBy(inputType)
Proposed SDL
extend input GeometryFilter {
coveredBy: GeoJsonFitlerInput
coveredBy_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { coveredBy: $other } }) {
name
}
}
Crosses
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Crosses(Geometry) | ✔ | ✔ | ✔ |
Tests whether this geometry crosses the specified geometry.
Declaration
public virtual bool Crosses(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry with which to compare this Geometry |
Returns
Type | Description |
---|---|
Boolean | true if the two Geometrys cross. |
databaseEntry.Crosses(inputType)
!databaseEntry.Crosses(inputType)
Proposed SDL
extend input GeometryFilter {
crosses: GeoJsonFitlerInput
crosses_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { crosses: $other } }) {
name
}
}
Disjoint
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Disjoint(Geometry) | ✔ | ✔ | ✔ | ✔ |
Tests whether this geometry is disjoint from the argument geometry.
Declaration
public bool Disjoint(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry with which to compare this Geometry. |
Returns
Type | Description |
---|---|
Boolean | true if the two Geometrys are disjoint. |
databaseEntry.Disjoint(inputType)
Proposed SDL
extend input GeometryFilter {
disjoint: GeoJsonFitlerInput
disjoint_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { disjoint: $other } }) {
name
}
}
Equals
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
? | ? | ? | ? | ? |
> Probleme here is, we never really had `equals` like this on an object type
Tests whether this geometry is structurally and numerically equal to a given Object.
Declaration
public override bool Equals(object o)
Parameters
Type | Name | Description |
---|---|---|
Object | o | The object to compare |
Returns
Type | Description |
---|---|
Boolean | true if this geometry is exactly equal to the argument |
databaseEntry.Equals(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
equals: GeoJsonFitlerInput
equals_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { equals: $other } }) {
name
}
}
EqualsExact
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.EqualsExact(Geometry) | ✔ |
Returns true if the two Geometrys are exactly equal. Two Geometries are exactly equal if:
This provides a stricter test of equality than EqualsTopologically(Geometry), which is more useful in certain situations (such as using geometries as keys in collections).
This method does not test the values of the GeometryFactory, the SRID, or the UserData fields.
To properly test equality between different geometries, it is usually necessary to Normalize() them first.
Declaration
public bool EqualsExact(Geometry other)
Parameters
Type | Name | Description |
---|---|---|
Geometry | other | The Geometry with which to compare this Geometry. |
databaseEntry.Equals(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
equalsExact: GeoJsonFitlerInput
equalsExact_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { equalsExact: $other } }) {
name
}
}
EqualsTopologically
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.EqualsTopologically(Geometry) | ✔ | ✔ | ✔ | ✔ |
Tests whether this geometry is topologically equal to the argument geometry as defined by the SFS Equals predicate.
Declaration
public virtual bool EqualsTopologically(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | the Geometry with which to compare this Geometry |
Returns
Type | Description |
---|---|
Boolean | true if the two |
Geometry
s are topologically equal
databaseEntry.Equals(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
equalsTopologically: GeoJsonFitlerInput
equalsTopologically_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { equalsTopologically: $other } }) {
name
}
}
Distance
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Distance(Geometry) | ✔ | ✔ | ✔ | ✔ |
Returns the minimum distance between this Geometry and another Geometry g.
Declaration
public virtual double Distance(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry from which to compute the distance. |
Returns
Type | Description |
---|---|
Double | The distance between the geometries |
databaseEntry.Distance(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
distance: DistanceInput
}
input DistanceInput {
from: GeoJsonFitlerInput!
is: Float
is_gt: Float
is_gte: Float
is_lt: Float
is_lte: Float
is_in: Float
is_not: Float
is_not_gt: Float
is_not_gte: Float
is_not_lt: Float
is_not_lte: Float
is_not_in: Float
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { distance: { of: $other, is: 5 } } }) {
name
}
}
Intersection
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Intersection(Geometry) | ✔ | ✔ | ✔ | ✔ |
Computes a Geometry representing the point-set which is common to both this Geometry and the other Geometry.
The intersection of two geometries of different dimension produces a result geometry of dimension less than or equal to the minimum dimension of the input geometries. The result geometry may be a heterogeneous GeometryCollection. If the result is empty, it is an atomic geometry with the dimension of the lowest input dimension.
Intersection of GeometryCollections is supported only for homogeneous collection types.
Non-empty heterogeneous GeometryCollection arguments are not supported.
Declaration
public Geometry Intersection(Geometry other)
Parameters
Type | Name | Description |
---|---|---|
Geometry | other | The Geometry with which to compute the intersection. |
Returns
Type | Description |
---|---|
Geometry | A geometry representing the point-set common to the two Geometrys. |
databaseEntry.Intersection(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
intersection: IntersectionInput
}
input IntersectionInput {
of: GeoJsonFitlerInput
is: GeometryFilter
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(
where: { shape: { intersection: { of: $other, is: { area_gt: 5 } } } }
) {
name
}
}
Intersects
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Intersects(Geometry) | ✔ | ✔ | ✔ | ✔ |
Tests whether this geometry intersects the argument geometry.
Declaration
public virtual bool Intersects(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry with which to compare this Geometry. |
Returns
Type | Description |
---|---|
Boolean | true if the two Geometrys intersect. |
databaseEntry.Intersects(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
intersects: GeoJsonFitlerInput
intersects_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { intersects: $other } }) {
name
}
}
Overlaps
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Overlaps(Geometry) | ✔ | ✔ | ✔ | ✔ |
Tests whether this geometry overlaps the specified geometry.
Declaration
public virtual bool Overlaps(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry with which to compare this Geometry. |
Returns
Type | Description |
---|---|
Boolean | true if the two Geometrys overlap. For this function to return true, the Geometry s must be two points, two curves or two surfaces. |
databaseEntry.Overlaps(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
overlaps: GeoJsonFitlerInput
overlaps_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { overlaps: $other } }) {
name
}
}
Touches
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Touches(Geometry) | ✔ | ✔ | ✔ |
Tests whether this geometry touches the argument geometry
Declaration
public virtual bool Touches(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry with which to compare this Geometry. |
Returns
Type | Description |
---|---|
Boolean | true if the two Geometrys touch; Returns false if both Geometrys are points. |
databaseEntry.Touches(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
touches: GeoJsonFitlerInput
touches_not: GeoJsonFitlerInput
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { touches: $other } }) {
name
}
}
Complex Filters with Custom Types
Union
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Union(Geometry) | ✔ | ✔ | ✔ | ✔ |
> Collision.. this method exists with and without parameter.
Computes a Geometry representing the point-set which is contained in both this Geometry and the other Geometry.
Declaration
public Geometry Union(Geometry other)
Parameters
Type | Name | Description |
---|---|---|
Geometry | other | the Geometry with which to compute the union |
Returns
Type | Description |
---|---|
Geometry | A point-set combining the points of this Geometry and the points of other |
databaseEntry.Union(inputType) // Geometry
Proposed SDL
extend input GeometryFilter {
intersection: UnionInput
}
input UnionInput {
of: GeoJsonFitlerInput
is: GeometryFilter
}
Example
query Example($other: GeoJsonFitlerInput, $other2: GeoJsonFitlerInput) {
cities(
where: {
shape: {
union: {
of: $other
is: { union: { of: $other2, is: { area_gt: 5 } } }
}
}
}
) {
name
}
}
Difference
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Difference(Geometry) | ✔ | ✔ | ✔ | ✔ |
Computes a Geometry representing the closure of the point-set of the points contained in this Geometry that are not contained in the other Geometry.
If the result is empty, it is an atomic geometry with the dimension of the left-hand input.
Non-empty GeometryCollection arguments are not supported.
Declaration
public Geometry Difference(Geometry other)
Parameters
Type | Name | Description |
---|---|---|
Geometry | other | The Geometry with which to compute the difference. |
Returns
Type | Description |
---|---|
Geometry | A Geometry representing the point-set difference of this Geometry with other. |
databaseEntry.Difference(inputType) // Geometry
Proposed SDL
# We would need smht like
extend input GeometryFilter {
difference: DifferenceInput
}
input DifferenceInput {
of: GeoJsonFitlerInput
is: GeometryFilter
}
Example
query Example($other: GeoJsonFitlerInput) {
cities(where: { shape: { difference: { of: $other, is: { area_gt: 5 } } } }) {
name
}
}
Out of scoped
EnvelopeInternal
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
? | ? | ? | ? | ? |
Gets an Envelope containing the minimum and maximum x and y values in this Geometry. If the geometry is empty, an empty Envelope is returned.
Declaration
public Envelope EnvelopeInternal { get; }
Property Value
Type | Description |
---|---|
Envelope | the envelope of this Geometry. |
OgcGeometryType
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.OgcGeometryType | ✔ | ✔ | ✔ | ✔ |
Gets the OGC geometry type
Declaration
public abstract OgcGeometryType OgcGeometryType { get; }
PointOnSurface
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.PointOnSurface | ✔ | ✔ | ✔ |
> out of scope bc equal to InteriorPoint
InteriorPoint
Declaration
public Point PointOnSurface { get; }
Property Value
Type | Description |
---|---|
Point |
PrecisionModel
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
? | ? | ? | ? | ? |
Returns the PrecisionModel used by the Geometry.
Declaration
public PrecisionModel PrecisionModel { get; }
Property Value
Type | Description |
---|---|
PrecisionModel | the specification of the grid of allowable points, for this Geometry and all other Geometrys. |
SortIndex
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
? | ? | ? | ? | ? |
Gets a value to sort the geometry
Declaration
protected abstract Geometry.SortIndexValue SortIndex { get; }
IsWithinDistance
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.IsWithinDistance(Geometry, double) | ✔ | ✔ | ✔ |
> I think is already covered by `distance_lt`?
Tests whether the distance from this Geometry to another is less than or equal to a specified value.
Declaration
public virtual bool IsWithinDistance(Geometry geom, double distance)
Parameters
Type | Name | Description |
---|---|---|
Geometry | geom | the Geometry to check the distance to. |
Double | distance | the distance value to compare. |
Returns
Type | Description |
---|---|
Boolean | true if the geometries are less than distance apart. |
Relate
NetTopologySuite | SQL Server (geometry) | SQL Server (geography) | SQLite | Npgsql |
---|---|---|---|---|
Geometry.Relate(Geometry, string) | ✔ | ✔ | ✔ |
Returns the DE-9IM intersection matrix for the two Geometrys.
Declaration
public virtual IntersectionMatrix Relate(Geometry g)
Parameters
Type | Name | Description |
---|---|---|
Geometry | g | The Geometry with which to compare this Geometry |
Returns
Type | Description |
---|---|
IntersectionMatrix | A matrix describing the intersections of the interiors, boundaries and exteriors of the two Geometrys. |
Nice work @PascalSenn :) The biggest problem, that I can see right now, is to get input and output of spatial data to be consistent. I tried using the GeoJSON format with a custom Scalar (see repo). Taking a structured object without typings as the input and returning a stringified json object as the output. It works using the online playground but causes a lot of weird problems with the apollo react client (for input). http://docs.opengeospatial.org/per/18-021.pdf |
Slack cliff notes
SDL shape and supportCreate types for
e.g. point: { "x": 1, "y": 1, "srid": 123123 }
e.g. .AddEntityFrameworkSpatial(opt => opt.DefaultSRID = 26912) Filtering support
where: {
location:{
distance: {
from: {"x": 1,"y": 2} ,
is_lt:5,
unit: MILES
}}} |
This one is now merged. |
Spatial Filters
Introduction
Create a set of spatial filters based on a subset of OGC spatial functions.
Proposal
Example Objects
All examples will take place in the following domain:
Proposal
Words
Suggested words in the following examples like
shape_contains
,shape_crosses
,shape_equals
,shape_intersects
,shape_overlaps
,shape_touches
,shape_within
will be a part of the NamingConvention and can be customized by the user.For line and polygon geometries,
shape_length
andshape_area
will generate the same filters as the scalar int type.Spatial filters in HotChocolate will look like the following example:
Since points and lines have a hard time intersecting with other points, a method to buffer them into polygons would be very useful for filtering points or lines that are near other points. e.g. an address point in relation to covid testing centers (points) or address points along a road (line).
The input geometry should allow for the GeoJSON spec and optionally allow for other geometry types like the esri spec to be extended into the system. With custom middleware users could use an address or a route and mile post or a place name to resolve a geometry from an external system. These results will need to be cached or persisted since they can be used multiple times in a single query.
Prior GeoJSON art
Data is stored in different projections to have the least amount of distortion when making a round world flat. If the input geometry coordinates are stored in a different projection than the underlying data, a hook to reproject the data will be required. This could be resolved via a web service, code, or via a database function if supported.
How others did it
hasura
sample output.
The output location serialized as geojson
The landmark location appears to be well known binary.
graphqljs neo4j
with a buffer
Displaying Spatial Data
Introduction
Create a way to display a geometry when requested as a scalar type.
Proposal
Create a a scalar type that can represent the geometry as a javascript serialized object e.g. GeoJSON, string, or binary.
Words
Suggested words in the following examples like
area
,length
,centroid
,envelope
,wkt
,wkb
, andall
will be a part of the NamingConvention and can be customized by the user.A centroid will return the center of the geometry. The envelope will return the minimum bounding box around the geometry. wkt will return the well known text representation, wkb will return the well known binary as a byte[], and all will return the full shape as geojson. Area returns the ST_Area. Length returns the ST_Length. Every word used here will return the representation as geojson unless otherwise specified or where not applicable e.g. wkt, wkb.
The output serialization can be modified by using arguments.
The output coordinate system can also be supplied as an argument using the well known id.
The text was updated successfully, but these errors were encountered: