Here is my first attempt:
http://www.jasondavies.com/maps/simplify/
Relevant commit to d3-plugins:
https://github.com/d3/d3-plugins/commit/806c760d9164ff22a05ace29d7c62881e61031a1
I'm sure some things can be improved e.g. it inserts effective areas of
infinity at the points where shared borders "change hands", but I'm
pretty happy with the results.
Internally, it's a two-pass algorithm. The first pass builds a hash
table mapping each point to a different numerical ID (for speed) for
every new combination of lines that share that point.
The second pass simply splits lines into chains every time this ID
changes, and performs Visvalingam on each chain separately. Then, an
effective area of infinity is set for the first and last points so they
don't get dropped. Note that we need to do this for both the first and
last points, so that there are two "infinite" area points at the
changeover positions, since chains may be traversed in different orders.
The rest of the code is really just scaffolding required to navigate the
GeoJSON format.
The other potential improvement is to use a more dedicated data
structure for the hash table instead of JavaScript's built-in object.
This could avoid excessive creation of string keys. On the other hand,
this simplify.project(…) step only needs to occur once, so it may not be
worth bundling additional code just for this step.
--
Jason Davies,
http://www.jasondavies.com/