hub/venv/lib/python3.7/site-packages/shapely/geometry/multilinestring.py

147 lines
3.9 KiB
Python

"""Collections of linestrings and related utilities
"""
import sys
if sys.version_info[0] < 3:
range = xrange
from ctypes import c_void_p, cast
from shapely.geos import lgeos
from shapely.geometry.base import BaseMultipartGeometry, geos_geom_from_py
from shapely.geometry import linestring
from shapely.geometry.proxy import CachingGeometryProxy
__all__ = ['MultiLineString', 'asMultiLineString']
class MultiLineString(BaseMultipartGeometry):
"""
A collection of one or more line strings
A MultiLineString has non-zero length and zero area.
Attributes
----------
geoms : sequence
A sequence of LineStrings
"""
def __init__(self, lines=None):
"""
Parameters
----------
lines : sequence
A sequence of line-like coordinate sequences or objects that
provide the numpy array interface, including instances of
LineString.
Example
-------
Construct a collection containing one line string.
>>> lines = MultiLineString( [[[0.0, 0.0], [1.0, 2.0]]] )
"""
super(MultiLineString, self).__init__()
if not lines:
# allow creation of empty multilinestrings, to support unpickling
pass
else:
self._geom, self._ndim = geos_multilinestring_from_py(lines)
def shape_factory(self, *args):
return linestring.LineString(*args)
@property
def __geo_interface__(self):
return {
'type': 'MultiLineString',
'coordinates': tuple(tuple(c for c in g.coords) for g in self.geoms)
}
def svg(self, scale_factor=1., stroke_color=None):
"""Returns a group of SVG polyline elements for the LineString geometry.
Parameters
==========
scale_factor : float
Multiplication factor for the SVG stroke-width. Default is 1.
stroke_color : str, optional
Hex string for stroke color. Default is to use "#66cc99" if
geometry is valid, and "#ff3333" if invalid.
"""
if self.is_empty:
return '<g />'
if stroke_color is None:
stroke_color = "#66cc99" if self.is_valid else "#ff3333"
return '<g>' + \
''.join(p.svg(scale_factor, stroke_color) for p in self) + \
'</g>'
class MultiLineStringAdapter(CachingGeometryProxy, MultiLineString):
context = None
_other_owned = False
def __init__(self, context):
self.context = context
self.factory = geos_multilinestring_from_py
@property
def _ndim(self):
try:
# From array protocol
array = self.context[0].__array_interface__
n = array['shape'][1]
assert n == 2 or n == 3
return n
except AttributeError:
# Fall back on list
return len(self.context[0][0])
def asMultiLineString(context):
"""Adapts a sequence of objects to the MultiLineString interface"""
return MultiLineStringAdapter(context)
def geos_multilinestring_from_py(ob):
# ob must be either a MultiLineString, a sequence, or
# array of sequences or arrays
if isinstance(ob, MultiLineString):
return geos_geom_from_py(ob)
obs = getattr(ob, 'geoms', ob)
L = len(obs)
assert L >= 1
exemplar = obs[0]
try:
N = len(exemplar[0])
except TypeError:
N = exemplar._ndim
if N not in (2, 3):
raise ValueError("Invalid coordinate dimensionality")
# Array of pointers to point geometries
subs = (c_void_p * L)()
# add to coordinate sequence
for l in range(L):
geom, ndims = linestring.geos_linestring_from_py(obs[l])
subs[l] = cast(geom, c_void_p)
return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
# Test runner
def _test():
import doctest
doctest.testmod()
if __name__ == "__main__":
_test()