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

Additional @turf/concave refactoring #907

Merged
merged 15 commits into from
Aug 17, 2017
Merged

Additional @turf/concave refactoring #907

merged 15 commits into from
Aug 17, 2017

Conversation

stebogit
Copy link
Collaborator

@stebogit stebogit commented Aug 17, 2017

Following #899:

  • replaced @turf/union with geojson-dissolve, thus removed jsts dependency 🎊
  • ⬆️ ⬆️ ⬆️ ⬆️ speed 👍
  • Support null geometries

The reason why I preferred geojson-dissolve to concaveman (as previously suggested) is because the latter returns always a single concave Polygon embracing all the input points, while geojson-dissolve allows to return (Multi)Polygons even with holes if appropriate (as the current @turf/concave implementation does).
However, for what I've seen online after some research, I'm not sure that this is the right/expected behaviour of a concave module. This is mainly due to the maxEdge parameter: if it was set to Infinity @turf/concave would always return a single concave hull Polygon (like concaveman).
In the next major release I would set maxEdge to Infinity by default.

Also I noticed this module throws an Error if there is no hull to return ("too few polygons found to compute concave hull"), likely due to a small maxEdge. I would rather return an empty Feature.

- replaced turf-union with geojson-dissolve;
- updated and added tests;
- updated bench and readme;
@rowanwins
Copy link
Member

Hey @stebogit

That geojson-dissolve module looks interesting, a few q's,

  • what is performance of it like compared to our dissolve module
  • whats is it like size wise once it includes its dependencies

Im sure either the geojson-dissolve or concaveman approaches will be a big improvement!

@DenisCarriere
Copy link
Member

DenisCarriere commented Aug 17, 2017

thus removed jsts dependency

🎉 Woot! 👍

while geojson-dissolve allows to return (Multi)Polygons even with holes if appropriate (as the current @turf/concave implementation does).

👍 Better to keep it similar to the same implementation, if one wants to use concaveman then it's pretty straightforward to use as an external library.

In the next major release I would set maxEdge to Infinity by default.

👍 Sounds like a plan!

Also I noticed this module throws an Error if there is no hull to return ("too few polygons found to compute concave hull"), likely due to a small maxEdge. I would rather return an empty Feature.

👍 Sounds good, this shouldn't be an error. An error should be caused when you are misusing the module (which isn't the case).

Question/Proposal (not immediate to this PR)

  • Improve/refactor @turf/dissolve using geojson-dissolve
  • Drop @turf/union in next major release in favor of using @turf/dissolve (both modules serve the same purpose).

If we are replacing @turf/union with geojson-dissolve, couldn't we refactor @turf/dissolve to use that module (currently it's also using @turf/union).

Also, what's the difference between @turf/union & @turf/dissolve, seems like they would serve the same purpose (@turf/dissolve has a bit more features, but it it's essentially the same for the geometry).

Copy link
Member

@DenisCarriere DenisCarriere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I'm really liking geojson-dissolve, pretty neat library!

"Denis Carriere <@DenisCarriere>",
"Stefano Borghi <@stebogit>",
"Rowan Winsemius <@rowanwins>",
"Daniel Pulido <@dpmcmlxxvi>"
],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also include the Authors/Contributors of geojson-dissolve.

@hackergrrl
Copy link

Nice, someone else is using our code. ❤️

It's worth noting that geojson-dissolve is just a thin wrapper around topojson for the Polygon case, and deserve lots of credit for doing the Hard Work.

function removeDuplicates(points) {
var cleaned = [];
var existing = {};
points.features.forEach(function (pt) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 This syntax looked so familiar that I thought I wrote this part :)

https://github.com/Turfjs/turf/blob/master/packages/turf-clean-coords/index.js#L52-L58

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I told you it was sooo smart! 😄

Also include Polygon or MultiPolygon as valid output
@DenisCarriere
Copy link
Member

@noffle You're code is awesome! 👍 You've got a new fan boy for you're many awesome repos in Digital Democracy.

thin wrapper around topojson for the Polygon case, and deserve lots of credit for doing the Hard Work.

We will add Mike Bostock @mbostock to the list of contributors for his great work in topojson.

@DenisCarriere
Copy link
Member

@rowanwins what is performance of it like compared to our dissolve module

Humm.. I personally worked on @turf/dissolve, one of the main differences is the use of rbush to quickly create an index of the geometries that intersects each other and only perform the union/dissolve operation on those geometries.

Looking at the source code of geojson-dissolve there's a few optimizing things that can speed up the performance:

  • flattenEach in @turf/meta (instead of using flatten + geomEach)
  • @turf/clone instead of using JSON.parse + JSON.stringify
  • geojson-rbush to reduce the amount of dissolve operations (GeoJSON => TopoJSON => Dissolve => TopoJSON => GeoJSON).
  • Would it be possible to translate topojson.merge to pure GeoJSON? It would be worth doing for performance, but might take some time to figure out 🤔..

existing[key] = true;
}
});
return featureCollection(cleaned, points.properties);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FeatureCollection doesn't have properties as a param.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah... ok! 👍

@hackergrrl
Copy link

Very happy to accept those PRs. 😁

@DenisCarriere
Copy link
Member

Very happy to accept those PRs.

Me too! 👍 haha

@DenisCarriere
Copy link
Member

+10 commits later, I think this last commit will "pass" lol 😫

@rowanwins
Copy link
Member

Gday @DenisCarriere

I wrote the bulk of the dissolve module so yep I remember using rbush :)

I'd think it's worth keeping both union and dissolve. While geometry-wise they might have similar inputs and outputs their application is a bit different.

In regards to geojson-dissolve it would be good to do some performance testing against our existing dissolve module. It would be good to see how performant it is in all those conversions of format etc.

@DenisCarriere
Copy link
Member

@rowanwins 👍 For sure, we can do that on a separate PR, I'm also interested in seeing how jsts performs compared to topojson.merge.

@DenisCarriere
Copy link
Member

I wrote the bulk of the dissolve module so yep I remember using rbush :)

Yes team work 👍 🥇

@DenisCarriere DenisCarriere merged commit b8f62e6 into master Aug 17, 2017
@DenisCarriere DenisCarriere deleted the concave-fix branch August 17, 2017 22:47
@stebogit
Copy link
Collaborator Author

@rowanwins @DenisCarriere geojson-dissolve merges only contiguous features, i.e. sharing a side or segment -- being it based on TopoJSON it make sense. If the features don't touch or overlap it just returns the original inputs .
Thus it was perfect for @turf/concave, which uses @turf/tin, but I don't see it particularly useful for @turf/union or @turf/dissolve.
I've been searching online for union/merge algorithms and tools to replace jsts, but no luck so far... 😞
But we'll find a way, eventually! 😃

@stebogit
Copy link
Collaborator Author

stebogit commented Aug 18, 2017

Drop @turf/union in next major release in favor of using @turf/dissolve (both modules serve the same purpose).

...and dissolve does not use jsts! 👍
However I'd still call the final module @turf/union, a quite common term for boolean operations on polygons, and I'd define the propertyName (now a @turf/dissolve argument) to optional, merging all the features by default.

@stebogit stebogit mentioned this pull request Aug 20, 2017
2 tasks
@stebogit
Copy link
Collaborator Author

I'd think it's worth keeping both union and dissolve. While geometry-wise they might have similar inputs and outputs their application is a bit different.

@rowanwins what kind of differences do you have in mind? It looks to me they could be integrated in a single module that can handle a "filter/selection" parameter.

@rowanwins
Copy link
Member

My understanding is that traditionally the output of a union operation won't have any overlapping features, whereas with a dissolve you can still have overlapping features.

This is a helpful article, by and large I think it would be good to retain consistent language with what everyone else is doing.

@DenisCarriere
Copy link
Member

👍 Thanks for the reference @rowanwins.

Helpful link, got me thinking of a few new easy modules @turf/merge & @turf/append (we can open up new issues for that - if you feel those are useful).

I understand a bit better now the difference between dissolve/union, the main difference with dissolve is spatial operation based on a common attribute (which it's currently doing 👍 ).

@stebogit
Copy link
Collaborator Author

stebogit commented Aug 25, 2017

the output of a union operation won't have any overlapping features, whereas with a dissolve you can still have overlapping features.

@rowanwins so basically dissolve is a "filtered" union on the collection of features?
We might have one single module that accept an optional filter function/parameter that define which feature should be merged. If well thought the filter could actually give much more flexibility to the module, and so to the user.

@DenisCarriere
Copy link
Member

👍 @turf/filter module, I also did this type of filter behavior in the @turf/cluster module, but it would better if this was extracted out of the clusters module and reside in it's own repo.

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

Successfully merging this pull request may close these issues.

4 participants