Create NIL (zero vertex) geometry

829
7
10-30-2023 09:27 AM
Bud
by
Notable Contributor

In a separate post (ST_Geometry — Don't allow empty geometry), @VinceAngelo mentioned:

A NIL (zero vertex) geometry is a valid shape type. It is required for some operations (e.g., the result of the intersection of two disjoint features). The shapefile specification permits Nil paired with any other one geometry type as the supported types in shapefiles.

Are there any other ways to create NIL (zero vertex) geometry -- other than "intersecting two disjoint features"?

For example, create NIL (zero vertex) geometry using editing tools in ArcGIS Pro. Use case: SQL query testing (Oracle 18c; 10.7.1 EGDB; SDE.ST_GEOMETRY).

Thanks.


Edit - Related: WKT: What is the reasoning behind the concept of a POINT EMPTY?

Tags (1)
0 Kudos
7 Replies
DanPatterson
MVP Esteemed Contributor
pline = arcpy.Polyline(arcpy.Array(None))  # -- create a polyline with an empty array

# -- some properties
pline.length  # -- no length
0.0

pline.pointCount  # -- no points
0

pline.JSON  # -- no path to make
'{"paths":[],"spatialReference":{"wkid":null}}'

print(pline.centroid)  # -- it has no centroid
None

... sort of retired...
VinceAngelo
Esri Esteemed Contributor

For reference, the empty array trick works for Polygon, Polyline, and Multipoint classes, but PointGeometry won't accept a None point parameter.

- V

Bud
by
Notable Contributor

I'm struggling with Python since I don't write Python scripts very often. Is there any chance you could provide a full script for inserting a nil geometry row into an existing polygon feature class?

0 Kudos
VinceAngelo
Esri Esteemed Contributor

You can use the Well-Known Text keyword "EMPTY" to generate a NIL geometry:

 

 

import arcpy

sr = arcpy.SpatialReference(4326)

np = arcpy.FromWKT("POLYGON EMPTY",sr)
print("np - pointCount: {:d} JSON: {:s}".format(np.pointCount,np.JSON))

nl = arcpy.FromWKT("LINESTRING EMPTY",sr)
print("nl - pointCount: {:d} JSON: {:s}".format(nl.pointCount,nl.JSON))

nm = arcpy.FromWKT("MULTIPOINT EMPTY",sr)
print("nm - pointCount: {:d} JSON: {:s}".format(nm.pointCount,nm.JSON))

nx = arcpy.FromWKT("POINT EMPTY",sr)
print("nx - pointCount: {:d} JSON: {:s}".format(nx.pointCount,nx.JSON))
print("nx - firstPoint: {:s}".format(str(nx.firstPoint)))

 

 

which results in:

 

 

np - pointCount: 0 JSON: {"rings":[],"spatialReference":{"wkid":4326,"latestWkid":4326}}
nl - pointCount: 0 JSON: {"paths":[],"spatialReference":{"wkid":4326,"latestWkid":4326}}
nm - pointCount: 0 JSON: {"points":[],"spatialReference":{"wkid":4326,"latestWkid":4326}}
nx - pointCount: 1 JSON: {"x":"NaN","y":"NaN","spatialReference":{"wkid":4326,"latestWkid":4326}}
nx - firstPoint: None

 

 

Curiously, the PointGeometry type always returns a pointCount of one, but the firstPoint is None.

 

WKT can also be used at the SQL prompt in Oracle:

 

SQL> SELECT 'POLYGON' as type,SDE.ST_ASTEXT(SDE.ST_PolyFromText('POLYGON EMPTY',4326)) as geom FROM DUAL;

TYPE
-------
GEOM
--------------------------------------------------------------------------------
POLYGON
POLYGON EMPTY

SQL> SELECT 'LINE   ' as type,SDE.ST_ASTEXT(SDE.ST_LineFromText('LINESTRING EMPTY',4326)) as geom FROM DUAL;

TYPE
-------
GEOM
--------------------------------------------------------------------------------
LINE
LINESTRING EMPTY

SQL> SELECT 'MPOINT ' as type,SDE.ST_ASTEXT(SDE.ST_MPointFromText('MULTIPOINT EMPTY',4326)) as geom FROM DUAL;

TYPE
--------
GEOM
--------------------------------------------------------------------------------
MPOINT
MULTIPOINT EMPTY

SQL> SELECT 'POINT  ' as type,SDE.ST_ASTEXT(SDE.ST_PointFromText('POINT EMPTY',4326)) as geom FROM DUAL;

TYPE
-------
GEOM
--------------------------------------------------------------------------------
POINT
POINT EMPTY

SQL>

 

- V

Bud
by
Notable Contributor

For my notes, regarding, "WKT can also be used at the SQL prompt in Oracle:"

In Oracle, functions like SDE.ST_PolyFromText() return the subtype [SDE.ST_POLYFROMTEXT] , not the supertype [SDE.ST_GEOMETRY] .

See: Is it ok to store ST_POLYFROMTEXT in ST_GEOMETRY shape column?

Bud_0-1700596482296.png

I suspect that might be a problem: Esri Canada Case #03491474 - Is it ok to store ST_POLYFROMTEXT in ST_GEOMETRY shape column?


This bug report suggests to "...convert any geometry values which were created with a subtype to st_geometry, by using the st_geometry constructor."

Bug: Unable to define a query layer in ArcGIS where the data source uses an st_geometry subtype in Oracle


That seems to work:

Bud_1-1700596687313.png


For what it's worth, I think "by using the st_geometry constructor." is a recent addition to that bug report. That part wasn't included in the bug report previously; Esri must have added it to clarify how to convert from the subtype to the supertype.

GIS Stack Exchange: Get ArcGIS to recognize ST_POINT

Bud_2-1700596972438.png

Ideas:

 

0 Kudos
DanPatterson
MVP Esteemed Contributor

Which brings us back to the old question about arcpy.Point having a value for x and y which is a valid number. 

You can assign math.nan or numpy.nan to the x and y values but you have to test whether they are nan (not a number)

I can only wish points could just be defined from arrays

np.full(shape=(4,), fill_value=np.nan, order='C')
array([nan, nan, nan, nan])
# -- or
np.empty((0,))
array([], dtype=float64)

 

import math
import arcpy

p0 = arcpy.Point()  # -- sadly given default values
p0
<Point (0.0, 0.0, #, #)>

# -- define invalid x, y values 
p1 = arcpy.Point(math.nan, math.nan)
p1
<Point (nan, nan, #, #)>
#
# -- then check in code
math.isnan(p1.X)

pg0 = arcpy.PointGeometry(p0, None, None, None)
pg0[0]  # must contain a point
<Point (nan, nan, #, #)>

 


... sort of retired...
0 Kudos
Bud
by
Notable Contributor
0 Kudos