1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
"""Points and related utilities."""
import numpy as np
import shapely
from shapely.errors import DimensionError
from shapely.geometry.base import BaseGeometry
__all__ = ["Point"]
class Point(BaseGeometry):
"""A geometry type that represents a single coordinate.
Each coordinate has x, y and possibly z and/or m values.
A point is a zero-dimensional feature and has zero length and zero area.
Parameters
----------
args : float, or sequence of floats
The coordinates can either be passed as a single parameter, or as
individual float values using multiple parameters:
1) 1 parameter: a sequence or array-like of with 2 or 3 values.
2) 2 or 3 parameters (float): x, y, and possibly z.
Attributes
----------
x, y, z, m : float
Coordinate values
Examples
--------
Constructing the Point using separate parameters for x and y:
>>> from shapely import Point
>>> p = Point(1.0, -1.0)
Constructing the Point using a list of x, y coordinates:
>>> p = Point([1.0, -1.0])
>>> print(p)
POINT (1 -1)
>>> p.y
-1.0
>>> p.x
1.0
"""
__slots__ = []
def __new__(self, *args):
"""Create a new Point geometry."""
if len(args) == 0:
# empty geometry
# TODO better constructor
return shapely.from_wkt("POINT EMPTY")
elif len(args) > 3:
raise TypeError(f"Point() takes at most 3 arguments ({len(args)} given)")
elif len(args) == 1:
coords = args[0]
if isinstance(coords, Point):
return coords
# Accept either (x, y) or [(x, y)]
if not hasattr(coords, "__getitem__"): # generators
coords = list(coords)
coords = np.asarray(coords).squeeze()
else:
# 2 or 3 args
coords = np.array(args).squeeze()
if coords.ndim > 1:
raise ValueError(
f"Point() takes only scalar or 1-size vector arguments, got {args}"
)
if not np.issubdtype(coords.dtype, np.number):
coords = [float(c) for c in coords]
geom = shapely.points(coords)
if not isinstance(geom, Point):
raise ValueError("Invalid values passed to Point constructor")
return geom
# Coordinate getters and setters
@property
def x(self):
"""Return x coordinate."""
return float(shapely.get_x(self))
@property
def y(self):
"""Return y coordinate."""
return float(shapely.get_y(self))
@property
def z(self):
"""Return z coordinate."""
z = shapely.get_z(self)
if np.isnan(z) and not shapely.has_z(self):
raise DimensionError("This point has no z coordinate.")
return float(z)
@property
def m(self):
"""Return m coordinate.
.. versionadded:: 2.1.0
Also requires GEOS 3.12.0 or later.
"""
if not shapely.has_m(self):
raise DimensionError("This point has no m coordinate.")
return float(shapely.get_m(self))
@property
def __geo_interface__(self):
"""Return a GeoJSON-like mapping of the Point geometry."""
coords = self.coords
return {"type": "Point", "coordinates": coords[0] if len(coords) > 0 else ()}
def svg(self, scale_factor=1.0, fill_color=None, opacity=None):
"""Return SVG circle element for the Point geometry.
Parameters
----------
scale_factor : float
Multiplication factor for the SVG circle diameter. Default is 1.
fill_color : str, optional
Hex string for fill color. Default is to use "#66cc99" if
geometry is valid, and "#ff3333" if invalid.
opacity : float
Float number between 0 and 1 for color opacity. Default value is 0.6
"""
if self.is_empty:
return "<g />"
if fill_color is None:
fill_color = "#66cc99" if self.is_valid else "#ff3333"
if opacity is None:
opacity = 0.6
return (
f'<circle cx="{self.x}" cy="{self.y}" r="{3.0 * scale_factor}" '
f'stroke="#555555" stroke-width="{1.0 * scale_factor}" fill="{fill_color}" '
f'opacity="{opacity}" />'
)
@property
def xy(self):
"""Separate arrays of X and Y coordinate values.
Examples
--------
>>> from shapely import Point
>>> x, y = Point(0, 0).xy
>>> list(x)
[0.0]
>>> list(y)
[0.0]
"""
return self.coords.xy
shapely.lib.registry[0] = Point
|