Crispy edges with topojson?

2019-05-22 18:52发布

问题:

Mike Bostock shared a range of world wide topojson files.

As I wanted more data and higher quality, I now generate my own high quality topojson files from Natural Earth. To make it simple, my makefile / command is such:

admin_0: crop
    ../node_modules/topojson/bin/topojson \
        --id-property name \
        -p name=name \
        -q 1e4 \
        --filter=small \
        -o admin_0.topo.json \
        -- admin_0=./natural_earth_vector/10m_cultural/ne_10m_admin_0_countries.shp

But my 3MB .topojson is crispy, nasty, graphically messy. Take a look at the coastline, you will see the most annoying thing : lines looking like "stairs" : horizontal, vertical, horizontal, vertical,...

On his side, M. Bostock's 90kb .topojson does surprisingly fine in term of elegance. Not perfect, but nice, and he does have diagonals (!) and various angles used by his lines.

I tried reducing the quantization to -q 1e3, but it keeps crispy, and it's even more ugly: the stair's steps are even bigger.

From the command line API, I noticed and read as much as I could on :

  • -q, --quantization, --no-quantization maximum number of differentiable points along either dimension
  • -s, --simplify precision threshold for Visvalingam simplification
  • --simplify-proportion proportion of points to retain for Visvalingam simplification
  • --width scale and translate to fit a viewport of the specified width
  • --height scale and translate to fit a viewport of the specified height

which may all help me. I made some test to mainly learn that balancing simplification is tricky. I would like to ask for experienced users how then handle and balance their topojson simplification.

What approach do you take yourself ? and so... What topojson parameters should I use to make my topojson nicer ? (no crispy stairs-steps edge, correct loyalty the the shape)

回答1:

-q VS -s

More details on Topojson: quantization VS simplification .

The total size of your geometry is controlled by two factors: the number of digits (the precision) of each coordinate and the number of points.

The quantization -q reduce the number of digits for each coordinate. Initially, geopoints have very high precision such

…,[-90.07231180399987,29.501753271000098],[-90.06635619599979,29.499494248000133],…

Quantization -q 1e4 where 1e4=10000 creates a 10,000×10,000 grid with integer values between 0 and 9999 such [-6700,1030]. Characters by coordinate is reduced from ~40 to 12, a ~75% reduction, with a maximum of 4 digits by value. Secondly, quatization makes geopoints which where distinct in the input shapefile to now share the same coordinates, such [24,62],[24,62],[24,62]…. These duplicates are merged. The end result are shapes defined by points on the grids. If you ONLY use the quantization your shapes will be made of vertical + horizontal lines from grid-point to grid-point.

In contrast, simplification removes information by removing points. The Visvalingam method used by the TopoJSON removes the least-noticeable points, the principle is wittily illustrated in Line Simplification article. To have many fine triangles to delicately removes, first use a higher quantization, then a simplification :

 #world
 topojson -q 1e6 -s 7e-5 -o world-110m.json -- NaturalEarth-110m.shp

It's the simplification which by removing some corner points create diagonals lines in topojson-based shapes.

-s

Asked on google group, M. Bostock proposed some smart tips.

  1. For the USA, use -s 7e-7. "e" stands for exponent, measured in steradians for spherical coordinates. 7e-8 is ten times smaller, which is a lot more detail! 7e-5 is one hundred times less details.

Lately, I’ve started pre-projecting the TopoJSON. This allows you to specify an intuitive simplification threshold in screen pixels (--cartesian --width 960 -s 1 for one square pixel, e.g.) and makes rendering very fast on the client since the TopoJSON is already projected.

Demos

Two live use and an other are such :

# projected (giving node extra memory since input shapefile is big)
us-albers.json: County_2010Census_DP1.shp
    node --max_old_space_size=8192 node_modules/.bin/topojson \
        -q 1e5 \
        -s 1 \
        --projection 'd3.geo.albersUsa()' \
        --id-property=GEOID10 \
        -p name=NAMELSAD10,pop=+DP0010001 \
        -o $@ \
        -- counties=County_2010Census_DP1.shp

# non-projected (not used by this example, but included for reference)
  topojson --max_old_space_size=8192 \
     -q 1e6 \
     -s 7e-5 \
     -o world-110m.json \
     -- NaturalEarth-110m.shp
#USA
  topojson \
    -q 1e5 \
    -s 7e-7 \
    --id-property=GEOID10 \
    -p name=NAMELSAD10,pop=+DP0010001 \
    -o $@ \
    -- counties=County_2010Census_DP1.shp

With unprojected, as your mapped area's dimensions get 10 times smaller (i.e. Nevada), the 7e-7 should move to smaller values such 7e-8.

Cartesian

http://bost.ocks.org/mike/simplify/