| Version 17 (modified by chodgson, 4 years ago) |
|---|
EMPTY GEOMETRY Handling
The semantics of NULL are well defined for us already in SQL standards. However, in the world of Geometry / Geography we have another entity which is not quite NULL nor quite fully defined: the empty geometry. Empty geometries can be created with things like intersection calls that have have no intersection, e.g. ST_Intersect('POINT(0 0)', 'POINT(1 1)') == POINT EMPTY. So, in the presence of empty, how should functions behave?
Ideally GEOMETRY EMPTY should behave more like 'zero' (0) than NULL - it is an expected, valid result of a successful, valid operation. In other words, dealing with EMPTY should require as little "special case" handling as possible in logical expressions making use of multiple geometry operations and/or comparisons. Maintaining compatibility with other spatial databases is probably valuable in its own right, and also because they have probably already done some thinking around these issues.
- ST_Union(geometry, empty) == geometry
- ST_Union(empty, empty) == empty
- ST_Difference(geometry, empty) == geometry
- ST_Difference(empty, geometry) == empty
- ST_Distance(geometry, empty) == NULL
- ST_DWithin(geometry, empty, tolerance) == FALSE
- ST_Contains(geometry, empty) == FALSE
- ??? ST_Contains(empty, empty) == FALSE
- ST_Intersects(geometry, empty) == FALSE
- ??? ST_Intersects(empty, empty) == FALSE
- ??? ST_Disjoint(empty, empty) == FALSE
- ??? ST_Disjoint(geometry, empty) == FALSE
- ST_IsSimple(empty) == TRUE
- ST_IsValid(empty) == TRUE
Note: It might make sense to try to maintain the geometric truisms when specifying the semantics around empty - ie. things like:
- intersects( A, B ) => !disjoint( A, B )
- A == B => intersects( A, B )
- contains( A, B ) && contains( B, A ) => A == B
If we don't maintain these we will probably need to complicate logical comparisons with special cases for empty - it may be the case that this is necessary, but it would be nice if it just 'came out in the wash'.
This suggests to me that perhaps:
- ST_Intersects( empty, empty ) == TRUE
- ST_Disjoint( empty, empty ) == FALSE
- ST_Distance( empty, empty) == 0
- ST_DWithin( empty, empty, tolerance) == true
Hmmm.. perhaps this isn't even possible generally, as:
- intersects( A, B ) => intersection( A, B ) != empty
but I think that we certainly want:
- intersection( empty, empty) == empty
SQL Server 2008
For reference and comparison, courtesy of Robe:
SELECT Geometry::STGeomFromText('POINT(1 2)',4326).STUnion(Geometry::STGeomFromText('POLYGON EMPTY',4326))
=> POINT (1 2)
SELECT (Geometry::STGeomFromText('POLYGON EMPTY',4326).STUnion(Geometry::STGeomFromText('POLYGON EMPTY',4326))).STAsText()
=> GEOMETRYCOLLECTION EMPTY
SELECT (Geometry::STGeomFromText('POINT(1 3)',4326).STDifference(Geometry::STGeomFromText('POLYGON EMPTY',4326))).STAsText()
=> POINT (1 3)
SELECT (Geometry::STGeomFromText('POLYGON EMPTY',4326).STDifference(Geometry::STGeomFromText('POLYGON EMPTY',4326))).STAsText()
=> GEOMETRY COLLECTION EMPTY
SELECT (Geometry::STGeomFromText('POINT(1 3)',4326).STContains(Geometry::STGeomFromText('POLYGON EMPTY',4326)))
=> 0
SELECT (Geometry::STGeomFromText('POLYGON EMPTY',4326).STContains(Geometry::STGeomFromText('POLYGON EMPTY',4326)))
=> 0
SELECT (Geometry::STGeomFromText('POINT(1 3)',4326).STIntersects(Geometry::STGeomFromText('POLYGON EMPTY',4326)))
=> 0
SELECT (Geometry::STGeomFromText('POLYGON EMPTY',4326).STIntersects(Geometry::STGeomFromText('POLYGON EMPTY',4326)))
=> 0
SELECT (Geometry::STGeomFromText('POLYGON EMPTY',4326).STDisjoint(Geometry::STGeomFromText('POLYGON EMPTY',4326)))
=> 1
SELECT (Geometry::STGeomFromText('POINT(1 3)',4326).STDisjoint(Geometry::STGeomFromText('POLYGON EMPTY',4326)))
=> 1
SELECT Geometry::STGeomFromText('POLYGON EMPTY',4326).STIsSimple()
=> 1
SELECT Geometry::STGeomFromText('POLYGON EMPTY',4326).STIsValid()
=> 1
SELECT (Geometry::STGeomFromText('POLYGON EMPTY',4326).STDistance(Geometry::STGeomFromText('POLYGON EMPTY',4326)))
=> NULL
SELECT (Geometry::STGeomFromText('POLYGON EMPTY',4326).STIntersection(Geometry::STGeomFromText('POLYGON EMPTY',4326))).STAsText()
=> GEOMETRY COLLECTION EMPTY
