Currently adding an attribute to a geometry object, putting it in a collection, and retrieveing the attribute back will fail:
from shapely.geometry import MultiPoint, Point
a = Point(0, 0)
b = Point(1, 1)
a.name = 'foo'
b.name = 'bar'
points = MultiPoint([a, b])
points[0].name
This gives:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-41-504767fe2fc1> in <module>()
5 b.name = 'bar'
6 points = MultiPoint([a, b])
----> 7 points[0].name
AttributeError: 'Point' object has no attribute 'name'
I have two questions:
1) Can it be fixed so that user attributes are never lost as in the given example?
2) If the first is not possible, how about implementing something similar to attributes of graphs, nodes, and edges in NetworkX?
For example, it could be something like this:
>>> a = Point(0, 0, name='foo')
>>> b = Point(1, 1, name='bar')
>>> points = MultiPoint([a, b])
>>> points[0].data['name']
'foo'
Why do I want this?
I'm working on a polygon area decomposition problem where I have a set of points with each point having an area requirement assigned to it. It would be convenient to create points like point = Point(0, 0, area_requirement=0.75), so that later I can put them in a MultiPoint and use its methods like MultiPoint.difference, which are required by an algorithm. As this is impossible, I currently use NamedTuple:
class Site(NamedTuple):
point: Point
area_requirement: float
site = Site(point=Point(0, 0), area_requirement=0.75)
But this is not a good solution as I can't put them in MultiPoint and use the MultiPoint.difference method, hence I have to write my own function to calculate difference for List[Site] objects which will be less efficient.
Related issue: https://github.com/Toblerity/Shapely/issues/664
Shapely version: 1.6.4.post1, installed from conda.
Shapely can't solve this problem. MultiPoints aren't 100% predictably ordered or indexed, so you'll lose track of your objects as soon as you add them to a collection. I'm also 99% certain that MultiPoint.difference doesn't preserve any user data that we might attach to geometry objects. The GEOS C functions that Shapely calls return new geometry objects that may be geometrically equivalent to ones you pass to it, but aren't the same references.
Don't go that dark road!
Shapely is about geometry and geometry only. It does not even know about coordinate reference systems.
JTS and by extension GEOS and by extension Shapely are all about the geometries defined by https://en.wikipedia.org/wiki/Simple_Features. There you can find this definition of a geometric object:
A geometric object consists of a geometric primitive, a collection of geometric primitives, or a geometric complex treated as a single entity. A geometric object may be the spatial representation of an object such as a feature or a significant part of a feature.
Everything there is one geometry. Even the collection such as Multi* or GeometryCollection. A geometry has no other attributes, it is just geometry. You can not differentiate between the elements of such a collection in any other way than their geometric properties.
Instead of attaching attributes to geometry objects via monkey-patching, you should much rather create proper features (e.g. using Fiona if it's geographic or with your own simple dict structure) as a combination of a set of attributes and their geometry, just like you did.
Topological elements (your question #2) are something quite different, weighting them is common so it makes sense to attach attributes.
PS: Once your MultiPoint geometries would become bigger (more points) you will probably have better performance by utilising spatial indexing anyways.
Most helpful comment
Don't go that dark road!
Shapely is about geometry and geometry only. It does not even know about coordinate reference systems.
JTS and by extension GEOS and by extension Shapely are all about the geometries defined by https://en.wikipedia.org/wiki/Simple_Features. There you can find this definition of a geometric object:
Everything there is one geometry. Even the collection such as Multi* or GeometryCollection. A geometry has no other attributes, it is just geometry. You can not differentiate between the elements of such a collection in any other way than their geometric properties.
Instead of attaching attributes to geometry objects via monkey-patching, you should much rather create proper features (e.g. using Fiona if it's geographic or with your own simple dict structure) as a combination of a set of attributes and their geometry, just like you did.
Topological elements (your question #2) are something quite different, weighting them is common so it makes sense to attach attributes.
PS: Once your MultiPoint geometries would become bigger (more points) you will probably have better performance by utilising spatial indexing anyways.