geodesk-py icon indicating copy to clipboard operation
geodesk-py copied to clipboard

Creating feature set from features

Open osmuser63783 opened this issue 1 year ago • 3 comments

Suppose I’ve done some filtering that I couldn’t do in Geodesk and GQOL, so I’ve done some version of [a for a in list(areas) if xyz]. Now I want to do an operation on the resulting set that I would know how to do if I had a feature set.

I can’t figure out how to get my list of nodes back into a Features object so I can use contains and other things I can do with feature sets.

There could be many ways to solve my problem.. if there was, for example,

  • a constructor for Features that takes a list of Feature objects and returns a feature set (then I could turn my list back into a feature set)
  • a way to pass an anonymous function to a feature set and return a new feature set filtered by whether the anonymous function returns true (then I could do a lot more without turning the feature set into a list or Python set)
  • a way to create an empty feature set and add features one by one
  • a way in GQOL to select an object with a specific id, similar to how you can do way(12345) in Overpass

It looks like none of these options exist (yet)? Sorry I may have overlooked something obvious.

osmuser63783 avatar Nov 30 '23 18:11 osmuser63783

You are correct, these capabilities don't currently exist. We've considered adding them, here are some thoughts:

  • Unlike set objects in Python, feature sets aren't "true" collections; they don't contain any features, they are merely lightweight descriptors, telling the query engine what should be retrieved from the GOL. This makes them very efficient, and you can copy/pass them around without having to worry about memory consumption. On the flip side, there is no way to "add" features to a set

  • We've considered allowing arbitrary Python functions (or anonymous lambdas) to be used as filters for a feature set. However, it may be more intuitive to just use a set (or list) comprehension: [ f for f in features if <your condition> ]

  • Feature sets are currently missing support for __contains__ (i.e. the in operator); this is coming (#23) and should address your use case where you have your own collection of features and want to test them against the matchers/filters of a feature set: [ f for f in your_collection if f in feature_set ]

  • We're considering feature lookup by ID (#24) (Main obstacle here is the lack of an ID-based index which would speed these queries significantly, but consumes a relatively large amount of storage)

clarisma avatar Dec 06 '23 16:12 clarisma

Thanks for considering this!

It's true that I can use [ f for f in features if <your condition> ] or (lazy version) filter(<my function>, features). But these return a list and an iterator, respectively. It means I no longer have access to the convenient functions that feature sets have. For example if I want to map the results I can't just do results.map, I have to write a loop; if I want to write to GeoJSON I can't just to results.geojson.save, I have to look up the GeoJSON syntax and write a helper function. This is not the end of the world but it would be more convenient if I was able to do this in one line with something like features.filter(<my function>).map etc.

osmuser63783 avatar Dec 07 '23 17:12 osmuser63783

Yes, you raised some very good points. I've created two individual enhancement items:

  • #25
  • #26

Both have different challenges and limitations, but we should be able to at least implement one of these in the next major release.

clarisma avatar Dec 09 '23 21:12 clarisma