Geometry subclasses

Creating a new plpygis geometry from a WKB, GeoJSON or Shapely instance, will produce a new subclass of the base Geometry class:

Creation

New instances of the three base shapes (points, lines and polygons) may be created by passing in coordinates:

>>> point = Point((0, 0))
>>> line = LineString([(0, 0), (0, 1)])
>>> poly = Polygon([[(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)], [(4, 4), (4, 6), (6, 6), (6, 4), (4, 4)]])

Editing

Coordinates may be accessed and modified after creation.

>>> point = Point((0, 0))
>>> print(point.x)
0
>>> point.x = 10
>>> print(point.x)
10

Composition

Individual LineString instances are composed of a list of Point instances that each represent a vertex in the line. Similarly, Polygon instances are composed of a list of LineString instances that each represent linear rings.

The lists of vertices or linear rings can be modified, for example by adding a new Point to the end of a LineString.

Note

The first linear ring in a polygon should represent the exterior ring, while subsequent linear rings are internal boundaries. plpygis will not validate geometries when they are created.

The four collection types, MultiPoint, LineString, MultiPolygon and GeometryCollection, are each composed of a list of other geometries of the appropriate type. At creation time, the collection types are created by passing in a list of existing instances:

>>> p1 = Point((0, 0))
>>> p2 = Point((1, 1))
>>> mp = MultiPoint([p1, p2])

plpygis will not create copies of any Geometry <plpygis.geometry.Geometry objects used to create a collection. However, changes to the SRID or dimensionality of any component geometries will not be reflected unless the collection’s SRID or dimensionality also changes.

>>> p = Point((0, 0))
>>> mp = MultiPoint([p1])
>>> mp.points[0].x
0
>>> p.x = 100
>>> mp.points[0].x
100

SRIDs

An SRID may be added at creation time with an optional SRID parameter:

>>> point = Point((0, 0), srid=4326)

When creating a multigeometry with an SRID, each geometry must have the same SRID or no SRID.

>>> p1 = Point((0, 0), srid=4326)
>>> p2 = Point((1, 1), srid=4326)
>>> mp = MultiPoint([p1, p2], srid=4326)

>>> p3 = Point((0, 0))
>>> p4 = Point((1, 1))
>>> mp = MultiPoint([p3, p4], srid=4326)

plpygis will not allow the creation of a multigeometry with no SRID if any of the geometries have one.

Warning

Changing the SRID of an instance that is part of another geometry (such as a Point that is a vertex in a LineString or a vertex in the linear ring of a Polygon) will not be detected. When converted to a WKB or Shapely instance, only the SRID of the “parent” geometry will be used.

Dimensionality

The dimz and dimm boolean parameters will indicate whether the geometry will have Z and M dimensions. plpygis will attempt to match provided coordinates with the requested dimensions or will set them to an initial value of 0 if they have not been provided:

>>> p1 = Point((0, 0, 1), dimz=True, dimm=True)
>>> print("p1", p1.x, p1.y, p1.z, p1.m)
p1 0 0 1 0
>>> p2 = Point((0, 0, 1), dimm=True)
>>> print("p2", p2.x, p2.y, p2.z, p2.m)
p2 0 0 None 1
>>> p3 = Point((0, 0, 1, 2))
>>> print("p3", p3.x, p3.y, p3.z, p3.m)
p3 0 0 1 2

The dimensionality of an existing instance may be altered after creation, by setting dimz or dimm. Adding a dimension will add a Z or M coordinate with an initial value of 0 to the geometry and all geometries encompassed within it (e.g., each vertex in a LineString or each Point in a MultiPoint will gain the new dimension).

A new dimension may also be added to a single Point by assigning to the z or m properties.

Adding a new dimension to a Point that is a vertex in a LineString or a vertex in the linear ring of a Polygon will not change the dimensionality of the LineString or the Polygon. The dimensionality of “parent” instance must also be changed for the new coordinates to be reflected when converting to other representations.

>>> p1 = Point((0, 0))
>>> p2 = Point((1, 1))
>>> mp = MultiPoint([p1, p2])
>>> print(mp.dimz)
False
>>> p1.z = 2
>>> print(p1.miz)
True
>>> print(mp.dimz)
False
>>> mp.dimz = True
>>> print(mp.dimz)
True
>>> print("p1.z", p1.z, "p2.z", p2.z)
p1.z 2 p2.z 0

Performance considerations

Lazy evaluation

plpygis uses native WKB parsing to extract header information that indicates the geometry type, SRID and the presence of a Z or M dimension. Full parsing of the entire geometry only occurs when needed. It is therefore possible to test the type and dimensionality of a Geometry with only the first few bytes of data having been read. Perform these checks before performing any action that will require reading the remainder of the WKB.

Caching

plpygis will cache the initial WKB it was created from. As soon as any coordinates or composite geometries are referenced, the cached WKB is lost and a subsequent request that requires the WKB will necessitate it being generated from scratch. For sets of large geometries, this can have a noticeable affect on performance. Therefore, if doing a conversion to a Shapely geometry - an action which relies on the availability of the WKB - it is recommended that this conversion be done before any other operations on the plpygis geometry.

Note

Getting type, srid, dimz and dimm are considered “safe” operations. However writing a new SRID or changing the dimensionality will also result in the cached WKB being lost. A geometry’s type may never be changed.

As a summary, getting the following properties will not affect performance:

Setting the following properties will cause any cached WKB to be cleared:

Getting the following property relies on the presence of the WKB (cached or generated):

If the Geometry was created from a WKB, the follwing actions will trigger a full parse and will clear the cached copy of the WKB: