Shapely: not possible to create shapely object from wkt

Created on 6 Feb 2017  路  7Comments  路  Source: Toblerity/Shapely

Environment: Win10 64 bit
Version:

>>> shapely.__version__
'1.6a1'

Creating shapely object from wkt is working in case of point and linestring
from shapely.geometry import asShape

>>> asShape({'type': 'Point', 'coordinates': (0.0, 0.0)}).buffer(1.0).area
3.1365484905459384
>>> asShape({'type': "LineString", "coordinates": [(-1,0),(0,0)]}).buffer(1.0).area
5.13654849054594

but in case of polygon it fails. The object is seemingly created,

>>> asShape({'type': "Polygon", "coordinates": [(0,0), (0,1), (1,1),(1,0),(0,0)]})
<shapely.geometry.polygon.PolygonAdapter object at 0x00000251C2CA7710>

however calling any methods throwing exceptions

>>> asShape({'type': "Polygon", "coordinates": [(0,0), (0,1), (1,1),(1,0),(0,0)]}).area
Traceback (most recent call last):
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 407, in geos_linearring_from_py
    array = ob.__array_interface__
AttributeError: 'tuple' object has no attribute '__array_interface__'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    asShape({'type': "Polygon", "coordinates": [(0,0), (0,1), (1,1),(1,0),(0,0)]}).area()
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\base.py", line 431, in area
    return self.impl['area'](self)
  File "C:\Anaconda3\lib\site-packages\shapely\topology.py", line 55, in __call__
    self._validate(this)
  File "C:\Anaconda3\lib\site-packages\shapely\topology.py", line 17, in _validate
    if ob is None or ob._geom is None:
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\proxy.py", line 49, in _geom
    self.__geom__, n = self.factory(self.context[0], self.context[1])
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 526, in geos_polygon_from_py
    ret = geos_linearring_from_py(shell)
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 468, in geos_linearring_from_py
    n = len(ob[0])
TypeError: object of type 'int' has no len()

Most helpful comment

These examples are not using WKT. http://toblerity.org/shapely/manual.html#well-known-formats

They are using the __geo_interface__ representation of the geometry, which is fine.

The reason your polygon is failing is because it's not valid. Polygon coordinate sequences should be a list of lists of coordinates, not a list of coordinates as you have. This is because a polygon is composed of multiple linear rings - an exterior ring, and optional multiple interior rings.

The following code works. Note the additional brackets in the coordinates.

>>> polygon = asShape({'type': "Polygon", "coordinates": [[(0,0), (0,1), (1,1),(1,0),(0,0)]]})
>>> polygon.is_valid

Also note that if you're not using numpy arrays for the coordinates you could just as well use shape() instead of asShape(). In this case the error is raised immediately, rather than when you try to access the data. http://toblerity.org/shapely/shapely.geometry.html#shapely.geometry.asShape

All 7 comments

These examples are not using WKT. http://toblerity.org/shapely/manual.html#well-known-formats

They are using the __geo_interface__ representation of the geometry, which is fine.

The reason your polygon is failing is because it's not valid. Polygon coordinate sequences should be a list of lists of coordinates, not a list of coordinates as you have. This is because a polygon is composed of multiple linear rings - an exterior ring, and optional multiple interior rings.

The following code works. Note the additional brackets in the coordinates.

>>> polygon = asShape({'type': "Polygon", "coordinates": [[(0,0), (0,1), (1,1),(1,0),(0,0)]]})
>>> polygon.is_valid

Also note that if you're not using numpy arrays for the coordinates you could just as well use shape() instead of asShape(). In this case the error is raised immediately, rather than when you try to access the data. http://toblerity.org/shapely/shapely.geometry.html#shapely.geometry.asShape

Okey, I misspelled the list, but either the correct form does not work:
polygon = asShape({'type': "Polygon", "coordinates": [(0,0), (0,1), (1,1),(1,0),(0,0)]})

>>> polygon.area
Traceback (most recent call last):
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 407, in geos_linearring_from_py
    array = ob.__array_interface__
AttributeError: 'tuple' object has no attribute '__array_interface__'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    polygon.area
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\base.py", line 431, in area
    return self.impl['area'](self)
  File "C:\Anaconda3\lib\site-packages\shapely\topology.py", line 55, in __call__
    self._validate(this)
  File "C:\Anaconda3\lib\site-packages\shapely\topology.py", line 17, in _validate
    if ob is None or ob._geom is None:
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\proxy.py", line 49, in _geom
    self.__geom__, n = self.factory(self.context[0], self.context[1])
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 526, in geos_polygon_from_py
    ret = geos_linearring_from_py(shell)
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 468, in geos_linearring_from_py
    n = len(ob[0])
TypeError: object of type 'int' has no len()

even if I use numpy array:
arr = numpy.array([(0,0), (0,1), (1,1),(1,0),(0,0)])

ss = asShape({'type': "Polygon", "coordinates": arr})
>>> ss.area
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    ss.area
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\base.py", line 431, in area
    return self.impl['area'](self)
  File "C:\Anaconda3\lib\site-packages\shapely\topology.py", line 55, in __call__
    self._validate(this)
  File "C:\Anaconda3\lib\site-packages\shapely\topology.py", line 17, in _validate
    if ob is None or ob._geom is None:
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\proxy.py", line 49, in _geom
    self.__geom__, n = self.factory(self.context[0], self.context[1])
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 526, in geos_polygon_from_py
    ret = geos_linearring_from_py(shell)
  File "C:\Anaconda3\lib\site-packages\shapely\geometry\polygon.py", line 408, in geos_linearring_from_py
    assert len(array['shape']) == 2
AssertionError

@pythonfun0 Your polygon definition is not quite right. Try this:

polygon = shape({'type': "Polygon", "coordinates": [[(0,0), (0,1), (1,1),(1,0),(0,0)]]})

Note the additional set of brackets around the coordinates. The structure for a GeoJSON Polygon is:

For type "Polygon", the "coordinates" member must be an array of LinearRing coordinate arrays. For Polygons with multiple rings, the first must be the exterior ring and any others must be interior rings or holes.

In other words:

{
    "type": "Polygon",
    "coordinates": [
        [<outer ring: (x, y), (x, y), ...>],
        [<hole 1 ring: (x, y), (x, y), ...>],
        [<hole 2 ring: (x, y), (x, y), ...>],
    ]
}

but you don't have any holes, so you need:

{
    "type": "Polygon",
    "coordinates": [
        [<outer ring: (x, y), (x, y), ...>],
    ]
}

Your LineString example works because the outer ring alone _is_ a valid LineString, but it is not a valid Polygon on its own unless it is nested properly.

If you read carefully my later comment, I wrote that it is not a nested list, I misspelled it!
So, once again I tried to crate polygon from wkt this way:
polygon = asShape({'type': "Polygon", "coordinates": [(0,0), (0,1), (1,1),(1,0),(0,0)]})

I don't want to create any nested polygon object!

Please, paste a real working code example, if you can have it!

Thanks!

If you read carefully my later comment, I wrote that it is not a nested list, I misspelled it!
So, once again I tried to crate polygon from wkt this way:
polygon = asShape({'type': "Polygon", "coordinates": [(0,0), (0,1), (1,1),(1,0),(0,0)]})

it does not work with square brackets
polygon = asShape({'type':'Polygon', 'coordinates':[[0,0],[0,1],[1,1],[1,0]]})

I don't want to create any nested polygon object!

Please, paste a real working code example, if you can have it!

Thanks!

@pythonfun0 You're not seeing what we're trying to point out.

You're typing this:

polygon = asShape({'type': "Polygon", "coordinates": [(0,0), (0,1), (1,1), (1,0), (0,0)]})

You should be typing this:

polygon = asShape({'type': "Polygon", "coordinates": [[(0,0), (0,1), (1,1), (1,0), (0,0)]]})

Even if your polygon only has an exterior ring and no interior rings, you still need to pass a nested list.

I've already get it, sorry I read absently your answers. A list of list of coordinates works perfectly.
Thank you!

Was this page helpful?
0 / 5 - 0 ratings