Map Simplification with Visvalingam's Algorithm
bost.ocks.org
bost.ocks.org
It's MUCH harder if you want adjacent borders to line up w/o gaps. You have to find all shared verts, run the smoothing algo on them, do the same for the coastlines / islands and then put all the pieces back together. I think 10% of my code was cleaning dirty data (removing duplicate points, detecting and fixing self intersection) 80% of my code was breaking everything up and putting it back together and 10% was the Visvalingam / Whyatt algo.
The biggest time sink was dealing w/ messy data. Between countries, states, counties, zip codes, neighborhoods etc, we hit A LOT of crappy corner cases. If anyone else is endeavoring to do the same, contact me and I can probably save you a week of work.
The message I sent was:
"I'd be very interested in any data you might have of this type (to overlay on a 3D model of Earth I'm building for a flight tracking project).
What data do you have?"
If you could respond via the address in my profile I'd be most grateful!
I'll probably package it up as a Node module so that it's easy to enable dynamic simplification of GeoJSON files. (A more efficient representation of shapes would also be helpful, though I like the convenience of plain text.) Or possibly a D3 plugin; it might be useful to extend the d3.geo.path shape generator to support more efficient dynamic filtering of points.
The problem is that the area always shrinks (for a convex curve). This is simply because all those polygon simplifiers work by selecting a subset of the points, and removing points (from a convex curve) means that you always "cut corners".
For my application, this is totally undesirable. I'm starting with a convex polygon, and the simplified polygon should fully enclose the original polygon. Thus, the simplified polygon has to consist of points outside the original polygon.
Is there any existing algorithm which accomplishes that? That is, which adds to the (convex) polygon rather than removing from it?
Once you reach a rectangle or a triangle there will be no more candidates.
So my current approach is to take ABCDE and replace BC and CD with that of the (infinitely many) tangents on C where the resulting area is minimal. Then B' is the intersection of the ray AB with that tangent. D' is corresponding intersection with ray ED. ABCDE is then replaced with AB'D'E (i.e. B->B', C removed, D->D').
Although I didn't yet do the math to find the optimal tangent on each point, it shouldn't be too hard to find that one.
Note that the simple ABCD approach is a degenerate case from this new approach: You just always choose the tangent to be BC. So I expect the new approach to produce strictly better results.
However, is there anything more elaborate than that? I don't belive I'm the first one who formulates that problem...
http://archive.org/details/minimumareacircu00agga "We show that the smallest k-gon circumscribing a convex n-gon can be computed in O(n^2 log n log k) time" This is elaborate enough... the paper isn't written in anything like pseudocode.
I'm presuming that that's not the result referred to below though (it's different authors, but this was the same year as the paper above): http://www.sciencedirect.com/science/article/pii/0734189X859... "A recent paper by Dori and Ben-Bassat presented an algorithm for finding a minimal area k-gon circumscribing a given convex n-gon, where k < n. An infinite class of polygons for which their algorithm fails to find the minimal area circumscribing k-gon is presented."
http://www.springerlink.com/content/11373157378222m3/ "Given any plane strictly convex region K and any positive integer n >= 3, there exists an inscribed 2n-gon Q_2n and a circumscribed n-gon P_n such that Area(P_n)/Area(Q_2n) <= secant(pi/n)." (ie this is how much you expand the area when you halve the number of edges)
If nothing else, knowing that the words "minimum circumscribing polygons" is the right thing to google for is useful (not just minimum-area - I presume minimum-perimiter solutions are useful to you too)
it's clearly there in the source, but i don't understand the comment there, either. what am i missing?! (i understand the lack of a guarantee of increasing area - what i don't understand why the algorithm should "care"; once the point is gone, it is gone...).
However, one thing it doesn't do (and Visvalingam’s algorithm doesn't either) is remove loops. In many cases you wouldn't want that, but sometimes you just want to draw a line that looks right, and being able to remove redundant parts of the polyline would be very helpful. For example, in the case where you have a GPS track of a run where you run to a nearby oval, do ten laps, and then run home, and you want the simplest polyline that looks right.
1: https://github.com/mourner/simplify-js 2: https://github.com/omarestrella/simplify.py/
I'm really curious, too, how Visvalingam performs when the variance of the heights of the triangles is large. Intuitively, it seems like it'd be much more aggressive than Peucker about removing spikes in data, which, depending on what you were aiming at, could be good or bad. Imagine processing a polyline whose coordinates are:
[0,0],[4,2],[8,0],[9,-9],[10,0],[14,1],[18,0]
Peucker would preserve [9,-9] until very last. It seems like Visvalingam would remove that relatively early.
edit: Either way, it's a nice algorithm to add to the quiver.
Alchemy in general is a jaw dropping piece of kit. It would give the UX types here a seizure though...