Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use GeometryCollection when shapely is installed #100

Closed
liskin opened this issue Apr 12, 2021 · 20 comments
Closed

Cannot use GeometryCollection when shapely is installed #100

liskin opened this issue Apr 12, 2021 · 20 comments

Comments

@liskin
Copy link
Contributor

liskin commented Apr 12, 2021

Similar to #68.

When shapely is installed, GeometryCollection can't be used:

from fastkml import kml
p = kml.Placemark(styleUrl="#normal")
p.geometry = {'type': "GeometryCollection", 'geometries': []}
p.to_string()

This fails with ValueError("Illegal geometry type."), but it works just fine when fastkml uses pygeoif.

I'm guessing it's because

from pygeoif.geometry import GeometryCollection

and then
elif isinstance(self.geometry, GeometryCollection):

fails because
self.geometry = asShape(geometry)

creates a shapely GeometryCollection, not pygeoif one.

@cleder
Copy link
Owner

cleder commented Oct 14, 2021

#137 drops shapely support

@cleder cleder closed this as completed Oct 14, 2021
@liskin
Copy link
Contributor Author

liskin commented Oct 14, 2021

Oh, but why? It was really practical being able to use shapely objects directly. 😿

@cleder
Copy link
Owner

cleder commented Oct 14, 2021

Mainly to support pygeoif 1.0, type annotations, and to get rid of some edge case bugs.
You can use shapely.geometry.shape to convert between pygeoif and shapely geometries.

@liskin
Copy link
Contributor Author

liskin commented Oct 14, 2021

Okay, fair enough, I'll give shapely.geometry.shape (or in my case the reverse, shapely.geometry.mapping) a try. Thanks for the answer.

@cleder
Copy link
Owner

cleder commented Oct 15, 2021

Maybe we could inject a geometry transformer function when constructing the KML, (e.g shapely.geometry.shape) so the geometry can be returned in the preferred format.

@liskin
Copy link
Contributor Author

liskin commented Nov 5, 2021

I finally got around to testing my code with fastkml 1.0a1 and it turns out it just works. shapely geometry is automatically converted to pygeoif geometry via __geo_interface__ and everything just works. So… nevermind and sorry for the noise. :-)

@cleder
Copy link
Owner

cleder commented Nov 5, 2021

Thanks for testing and letting me know, :-) Much appreciated!

@liskin
Copy link
Contributor Author

liskin commented Nov 1, 2023

Seems like __geo_interface__ stuff doesn't work any more in 1.0.alpha.6. Looks like it's now necessary to manually convert even pygeoif objects to fastkml.geometry objects otherwise one gets errors like these:
AttributeError: 'GeometryCollection' object has no attribute 'etree_element'

I wonder if that's intentional?

@cleder
Copy link
Owner

cleder commented Nov 1, 2023

No it is not intentional.
Can you supply an example to reproduce this?

@liskin
Copy link
Contributor Author

liskin commented Nov 1, 2023

Sure:

#!/usr/bin/env python3

import fastkml
import pygeoif.geometry

g = pygeoif.geometry.Point(1, 1)
if fastkml.__version__ == "1.0a4":
    p = fastkml.kml.Placemark()
    p.geometry = g
else:
    p = fastkml.kml.Placemark(geometry=g)
print(p.to_string())
$ python3 -m venv venv-fastkml-a4
$ python3 -m venv venv-fastkml-a6
$ ./venv-fastkml-a4/bin/pip install 'fastkml == 1.0a4'
$ ./venv-fastkml-a6/bin/pip install 'fastkml == 1.0a6'
$ ./venv-fastkml-a4/bin/python fastkml-interface.py
/tmp/venv-fastkml-a4/lib/python3.11/site-packages/fastkml/config.py:37: UserWarning: Package `lxml` missing. Pretty print will be disabled
  warnings.warn("Package `lxml` missing. Pretty print will be disabled")
<kml:Placemark xmlns:kml="http://www.opengis.net/kml/2.2"><kml:visibility>1</kml:visibility><kml:Point><kml:coordinates>1.000000,1.000000</kml:coordinates></kml:Point></kml:Placemark>
$ ./venv-fastkml-a6/bin/python fastkml-interface.py 
/tmp/venv-fastkml-a6/lib/python3.11/site-packages/fastkml/config.py:37: UserWarning: Package `lxml` missing. Pretty print will be disabled
  warnings.warn("Package `lxml` missing. Pretty print will be disabled")
Traceback (most recent call last):
  File "/tmp/fastkml-interface.py", line 13, in <module>
    print(p.to_string())
          ^^^^^^^^^^^^^
  File "/tmp/venv-fastkml-a6/lib/python3.11/site-packages/fastkml/base.py", line 116, in to_string
    self.etree_element(
  File "/tmp/venv-fastkml-a6/lib/python3.11/site-packages/fastkml/kml.py", line 1757, in etree_element
    element.append(self._geometry.etree_element())
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Point' object has no attribute 'etree_element'

So yeah I can pretty confidently say the examples from https://fastkml.readthedocs.io/en/latest/usage_guide.html no longer work :-)

@cleder
Copy link
Owner

cleder commented Nov 1, 2023

There was a lot of refactoring in fastkml.geometry (it has developed into a mess, what was the developer thinking 🤯 ) Check what you pass against the type annotations, this probably changed during this refactor.
Thanks for your support, I will take a look, writing a guide migrating from 0 to 1 is on my radar, just not a priority right now

@cleder cleder reopened this Nov 1, 2023
@cleder
Copy link
Owner

cleder commented Nov 1, 2023

#239 is probably the place to look

@cleder
Copy link
Owner

cleder commented Nov 2, 2023

closing this in favour of #264

@cleder cleder closed this as completed Nov 2, 2023
@cleder
Copy link
Owner

cleder commented Dec 9, 2023

@liskin the commit brings back the option to create a feature with just a geometry to support backwards compatibility

@liskin
Copy link
Contributor Author

liskin commented Dec 11, 2023

@liskin the commit brings back the option to create a feature with just a geometry to support backwards compatibility

Right, it does indeed. ♥
Unfortunately now one can't use fastkml.geometry objects for the Placemark geometry any more. Not sure if that's intended… 🙂
(I mean I don't want that, I want to be passing shapely/pygeoif data, but I think you perhaps wanted to support both?)

And then there are some vaguely related issues:

  • geometry needs to be passed to the Placemark constructor because it's a read-only property without a setter
  • style_url, on the other hand, can now only be set using the property setter, as the constructor argument assumes it's a StyleUrl class, whereas the property setter converts it from a string

And then I commented on 2 commits of yours pointing out other random breakages (XML namespaces, NetworkLink having no Link).

@liskin
Copy link
Contributor Author

liskin commented Dec 11, 2023

These are the changes I had to make to make my project's tests pass locally:

Shall I open a PR from develop...liskin:fastkml:fixes?

@cleder
Copy link
Owner

cleder commented Dec 12, 2023

PRs are always welcome ;-)

@cleder
Copy link
Owner

cleder commented Dec 12, 2023

The current develop (I have not cut a release for this yet) reintroduces the ability to pass a shapely or pygeoif (or anything else that supports the __geo_interface__ protocol) as the geometry to placemark, or a fastkml.geometry kml object as kml_geometry.

I can reintroduce a geometry property getter and setter on feature if this is needed (although probably under another name to avoid confusion, like geo_geometry)

@liskin
Copy link
Contributor Author

liskin commented Dec 12, 2023

The current develop (I have not cut a release for this yet) reintroduces the ability to pass a shapely or pygeoif (or anything else that supports the __geo_interface__ protocol) as the geometry to placemark, or a fastkml.geometry kml object as kml_geometry.

Oh, I see, I somehow missed the kml_geometry bit. That's all right then.

I can reintroduce a geometry property getter and setter on feature if this is needed (although probably under another name to avoid confusion, like geo_geometry)

Not really needed, I just found it a bit confusing that old versions of fastkml accepted style_url (or even styleUrl back then I think) as constructor argument and geometry was passed via a property setter, and now in 1.0a9 it's the other way round. So… just make sure it's documented when you eventually make a release 🙂

@liskin liskin mentioned this issue Dec 12, 2023
@cleder
Copy link
Owner

cleder commented Dec 12, 2023

I made some 'questionable' decisions for shortcuts 10 years ago, based on a use case I had back then. I never imagined it would have north of 100K downloads a month, in the first few years I was proud when it had 75 per month (IIRC) 😃

Version 1.0 should be more consistent, easier to work with and to contribute to.

I appreciate your continuing contributions, your comments are very valuable to give me insights what users want to get out of this package 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants