diff --git a/README.md b/README.md
index 1a31b99..65ebd55 100644
--- a/README.md
+++ b/README.md
@@ -43,8 +43,8 @@ For some examples, check out the `output` folder. For more information, go to [j
## Credits
While I wrote all of the code in this repository myself, and I created several of the simpler images from scratch, other people did help. Here's a comprehensive list.
* **The NASA** for [Basic.png](https://visibleearth.nasa.gov/view.php?id=57730), [Satellite.jpg](https://visibleearth.nasa.gov/view.php?id=57752), and [Altitude.png](https://asterweb.jpl.nasa.gov/gdem.asp),
-* **Tom Patterson** for [Clouds.jpg](http://www.shadedrelief.com/natural3/pages/textures.html), [Rivers.png](http://www.shadedrelief.com/natural3/pages/extra.html), and [Political.svg](https://commons.wikimedia.org/wiki/File:BlankMap-Equirectangular.svg),
-* **Natural Earth** for [Pastel.png](http://www.naturalearthdata.com/downloads/50m-raster-data/50m-natural-earth-2/) and their [vector coastline data](http://www.naturalearthdata.com/downloads/50m-physical-vectors/),
+* **Tom Patterson** for [Clouds.jpg](http://www.shadedrelief.com/natural3/pages/textures.html), [Rivers.png](http://www.shadedrelief.com/natural3/pages/extra.html),
+* **Natural Earth** for [Pastel.png](http://www.naturalearthdata.com/downloads/50m-raster-data/50m-natural-earth-2/) and their [detailed vector data](http://www.naturalearthdata.com/downloads/),
* **The Apache Commons** for their [complex mathematics code](https://commons.apache.org/proper/commons-math/),
* **Technische Universität Berlin** for their [complex mathematics code](http://www3.math.tu-berlin.de/jtem/ellipticFunctions/),
* **Gene Keyes** for his [impressively in-depth documentation of his map projection](http://www.genekeyes.com/CKOG-OOo/7-CKOG-illus-&-coastline.html),
diff --git a/input/Advanced/Supermap.svg b/input/Advanced/Supermap.svg
new file mode 100644
index 0000000..8f0ef66
--- /dev/null
+++ b/input/Advanced/Supermap.svg
@@ -0,0 +1,6319 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Equirectangular map of the world – political borders and topographical features
+
+ A map of the world, showing all countries recognised by the UN as SVG paths, with rivers and lakes overlaid. Borders precise to 50 km.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Niagara Falls
+
+ Salto Angel
+
+ Iguazu Falls
+
+ MELANESIA
+ MICRONESIA
+ POLYNESIA
+ SOUTH AMERICA
+ AUSTRALIA
+ AFRICA
+ ANTARCTICA
+ ASIA
+ MALAY ARCHIPELAGO
+ EUROPE
+ NORTH AMERICA
+ ICELAND
+ WEST INDIES
+ GREENLAND
+ MADAGASCAR
+ CANADIAN SHIELD
+ CANADIAN SHIELD
+ KIRIBATI
+ HAWAIIAN ISLANDS
+ LINE ISLANDS
+ CAROLINE ISLANDS
+ HAWAI‘I
+ GREATER SUNDA ISLANDS
+ PHILIPPINES
+ JAPAN
+ ARCTIC ARCHIPELAGO
+ GREAT DIVIDING RANGE
+ ALPS
+ TIAN SHAN
+ URAL MOUNTAINS
+ CAUCASUS MTS.
+ HIMALAYAS
+ ANDES
+ ROCKY MOUNTAINS
+ NORTH CHINA PLAIN
+ KAZAKH STEPPE
+ NORTHERN EUROPEAN PLAIN
+ GREAT PLAINS
+ CONGO BASIN
+ AMAZON BASIN
+ INDIA
+ SCANDINAVIA
+ INDOCHINA PENINSULA
+ ARABIAN PENINSULA
+ GOBI DESERT
+ SAHARA
+ WESTERN PLATEAU
+ PENÍNSULA IBÉRICA
+ PLATEAU OF TIBET
+ CENTRAL AMERICA
+ ALASKA
+ SIBERIA
+ EAST ANTARCTICA
+ WEST ANTARCTICA
+ TRANSANTARCTIC MOUNTAINS
+ ANTARCTIC PENINSULA
+ TRANSANTARCTIC MOUNTAINS
+ POLAR PLATEAU
+ BRITISH ISLES
+ NEW ZEALAND
+ SRI LANKA
+ TASMANIA
+ NEW GUINEA
+ BORNEO
+ SUMATRA
+ HONSHÜ
+ IRELAND
+ GREAT BRITAIN
+ ANDAMAN ISLANDS
+ NICOBAR ISLANDS
+ MOLUCCAS
+ ALEUTIAN ISLANDS
+ QUEEN ELIZABETH ISLANDS
+ TAYMYR PENINSULA
+ YAMAL PENINSULA
+ KAMCHATKA PENINSULA
+ MALAY PENINSULA
+ GREAT BASIN
+ GREAT ARTESIAN BASIN
+ ETHIOPIAN HIGHLANDS
+ ZAGROS MOUNTAINS
+ ALTAY MOUNTAINS
+ GREATER KHINGAN RANGE
+ STANOVOY RANGE
+ CHAÎNE ANNAMITIQUE
+ SIWALIK HILLS
+ PAMIRS
+ HINDU KUSH
+ KARAKORAM RA.
+ KUNLUN MOUNTAINS
+ ATLAS MOUNTAINS
+ APPALACHIAN MTS.
+ BROOKS RANGE
+ COAST MOUNTAINS
+ CASCADE RANGE
+ ALASKA RANGE
+ MANCHURIAN PLAIN
+ TURAN LOWLAND
+ SAHEL
+ PONTIC STEPPE
+ COASTAL PLAIN
+ CENTRAL LOWLAND
+ GRAN CHACO
+ LLANOS
+ PAMPAS
+ GANGES PLAIN
+ BRAZILIAN HIGHLANDS
+ CENTRAL SIBERIAN PLATEAU
+ MONGOLIAN PLATEAU
+ DECCAN PLATEAU
+ PLANALTO DO MATO GROSSO
+ FERGANA VALLEY
+ SOMALI PENINSULA
+ BALKAN PEN.
+ BETPAQDALA DESERT
+ PUNJAB
+ RUB’ AL KHALI
+ CAATINGAS
+ KALAHARI DESERT
+ BOL’SHEZEMEL’SKAYA TUNDRA
+ SELVAS
+ ANATOLIA
+ PATAGONIA
+ TALOS DOME
+ WILKES LAND
+ AMERICAN HIGHLAND
+ QUEEN MAUD LAND
+ PENSACOLA MOUNTAINS
+ ELLSWORTH MOUNTAINS
+ HOLLICK-KENYON PLATEAU
+ QUEEN MAUDE MOUNTAINS
+ MARIE BYRD LAND
+ ROCKEFELLER PLATEAU
+ DOME C (CHARLIE)
+ DOME A (ARGUS)
+ DOME F (FUJI)
+ SOUTH ISLAND
+ NORTH ISLAND
+ Mt. Everest
+
+ Mt. Kilimanjaro
+
+ Vinson Massif
+
+ Turpan Depression
+
+ Khyber Pass
+ K2
+
+ Muztag Feng
+
+ Kailash
+
+ Gora Elbrus
+
+ Death Valley
+
+ Denali
+
+ Mt. Whitney
+
+ Mt. Kosciuszko
+
+ Cerro Aconcagua
+
+ Cero Raya
+
+ ARCTIC OCEAN
+ SOUTHERN OCEAN
+ NORTH ATLANTIC OCEAN
+ NORTH PACIFIC OCEAN
+ SOUTH PACIFIC OCEAN
+ INDIAN OCEAN
+ SOUTH ATLANTIC OCEAN
+ Black Sea
+ Philippine Sea
+ Coral Sea
+ Tasman Sea
+ Bay of Bengal
+ South China Sea
+ Sea of Japan
+ Mediterranean Sea
+ Arabian Sea
+ Beaufort Sea
+ Caribbean Sea
+ Gulf of Mexico
+ Labrador Sea
+ Hudson Bay
+ Caspian Sea
+ Baffin Bay
+ Gulf of Alaska
+ Red Sea
+ Sea of Okhotsk
+ Ross Sea
+ Weddell Sea
+ Persian Gulf
+ Ross Sea
+ Mediterranean Sea
+ Celebes Sea
+ Sulu Sea
+ Norwegian Sea
+ Greenland Sea
+ Banda Sea
+ Luzon Strait
+ Bay of Biscay
+ Mozambique Channel
+ Gulf of Guinea
+ Scotia Sea
+ Baltic Sea
+ Barents Sea
+ North Sea
+ Irish Sea
+ Java Sea
+ Andaman Sea
+ Yellow Sea
+ East China Sea
+ Chukchi Sea
+ Bahía de Campeche
+ Arafura Sea
+ Timor Sea
+ Gulf of Thailand
+ Laccadive Sea
+ Bellingshausen Sea
+ Amundsen Sea
+ Davis Strait
+ Kara Sea
+ Laptev Sea
+ Drake Passage
+ Bering Sea
+ Sargasso Sea
+ Afghanistan
+ Angola
+ United Arab Emirates
+ Argentina
+ American Samoa (U.S.A.)
+ Antarctica
+ Australia
+ Austria
+ Belgium
+ Burkina Faso
+ Bangladesh
+ Bulgaria
+ Bahrain
+ Bahamas
+ Belarus
+ Bolivia
+ Brazil
+ Botswana
+ Central African Rep.
+ Canada
+ Switzerland
+ Chile
+ China
+ Côte d'Ivoire
+ Cameroon
+ Dem. Rep. Congo
+ Congo
+ Cook Is. (Assoc. with N.Z.)
+ Colombia
+ Cabo Verde
+ Cuba
+ Germany
+ Denmark
+ Algeria
+ Ecuador
+ Egypt
+ Eritrea
+ Spain
+ Ethiopia
+ Finland
+ France
+ Gabon
+ United Kingdom
+ Ghana
+ Guinea
+ Eq. Guinea
+ Greece
+ Greenland
+ Guatemala
+ Guyana
+ Hong Kong
+ Indonesia
+ India
+ Ireland
+ Iran
+ Iraq
+ Iceland
+ Israel
+ Italy
+ Jamaica
+ Jordan
+ Japan
+ Kazakhstan
+ Kenya
+ Kyrgyzstan
+ Cambodia
+ South Korea
+ Laos
+ Liberia
+ Libya
+ Sri Lanka
+ Macao
+ Morocco
+ Madagascar
+ Mexico
+ Mali
+ Myanmar
+ Mongolia
+ Mozambique
+ Mauritania
+ Malaysia
+ Namibia
+ New Caledonia (Fr.)
+ Niger
+ Nigeria
+ Niue (Assoc. with N.Z.)
+ Norway
+ Nepal
+ New Zealand
+ Oman
+ Pakistan
+ Panama
+ Pitcairn Is. (U.K.)
+ Peru
+ Philippines
+ Papua New Guinea
+ Poland
+ North Korea
+ Portugal
+ Paraguay
+ Fr. Polynesia (Fr.)
+ Romania
+ Russia
+ Rwanda
+ Saudi Arabia
+ Sudan
+ S. Sudan
+ Senegal
+ S. Geo. and the Is. (U.K.)
+ Solomon Is.
+ Sierra Leone
+ St. Pierre and Miquelon (Fr.)
+ Suriname
+ Sweden
+ Swaziland
+ Syria
+ Chad
+ Thailand
+ Tajikistan
+ Turkmenistan
+ Tonga
+ Tunisia
+ Turkey
+ Taiwan
+ Tanzania
+ Uganda
+ Ukraine
+ Uruguay
+ United States of America
+ Uzbekistan
+ Venezuela
+ Vietnam
+ Vanuatu
+ Wallis and Futuna Is. (Fr.)
+ Samoa
+ Yemen
+ South Africa
+ Zambia
+ Zimbabwe
+ Ramallah
+
+ Artigas Base
+
+ George Town
+
+ Grand Turk
+
+ Douglas
+
+ San Marino
+
+ Willemstad
+
+ Oranjestad
+
+ Vaduz
+
+ Capitan Arturo Prat Station
+
+ Marambio Base
+
+ Zucchelli Station
+
+ Rothera Station
+
+ Palmer Station
+
+ Base Presidente Montalva
+
+ Carlini Base
+
+ King Sejong Station
+
+ Great Wall Station
+
+ Escudero Base
+
+ Elephant Island
+
+ Scott Base
+
+ McMurdo Station
+
+ Zhongshan Station
+
+ Vostok
+
+ Peter I Island
+
+ Mirny Station
+
+ Mawson Station
+
+ Davis Station
+
+ Concordia Research Station
+
+ Casey Station
+
+ AmundseniScott South Pole Station
+
+ Wasa Station
+
+ Troll Station
+
+ Svea Station
+
+ Novolazarevskaya Station
+
+ Neumayer Station III
+
+ Maitri Station
+
+ Halley Station
+
+ Belgrano II Base
+
+ Sobral Base
+
+ Aboa Station
+
+ San Martín Base
+
+ Gen. O'Higgins Base
+
+ Esperanza Station
+
+ Orcadas Station
+
+ Signy Research Station
+
+ Dumont d'Urville Station
+
+ Showa Station
+
+ Palikir
+
+ Majuro
+
+ Agana
+
+ Funafuti
+
+ Melekeok
+
+ Bir Lehlou
+
+ Monaco
+
+ Tarawa
+
+ Moroni
+
+ Macau
+
+ Andorra
+
+ San Bernardino
+
+ Bridgeport
+
+ Rochester
+
+ Xiamen
+
+ Nanchong
+
+ Neijiang
+
+ Nanyang
+
+ Jinxi
+
+ Yantai
+
+ Zaozhuang
+
+ Suzhou
+
+ Xuzhou
+
+ Wuxi
+
+ Jilin
+
+ Chandigarh
+
+ Jammu
+
+ Sholapur
+
+ Aurangabad
+
+ Nasik
+
+ Dispur
+
+ Jullundur
+
+ Allahabad
+
+ Moradabad
+
+ Ghaziabad
+
+ Agra
+
+ Aligarh
+
+ Meerut
+
+ Dhanbad
+
+ Gwalior
+
+ Vadodara
+
+ Rajkot
+
+ International Falls
+
+ St. Paul
+
+ Billings
+
+ Great Falls
+
+ Missoula
+
+ Minot
+
+ Fargo
+
+ Hilo
+
+ Olympia
+
+ Spokane
+
+ Vancouver
+
+ Flagstaff
+
+ Tucson
+
+ Santa Barbara
+
+ Fresno
+
+ Eureka
+
+ Colorado Springs
+
+ Reno
+
+ Elko
+
+ Albuquerque
+
+ Salem
+
+ Casper
+
+ Topeka
+
+ Kansas City
+
+ Tulsa
+
+ Sioux Falls
+
+ Shreveport
+
+ Baton Rouge
+
+ Ft. Worth
+
+ Corpus Christi
+
+ Austin
+
+ Amarillo
+
+ El Paso
+
+ Laredo
+
+ Burlington
+
+ Montgomery
+
+ Tallahassee
+
+ Orlando
+
+ Jacksonville
+
+ Savannah
+
+ Columbia
+
+ Indianapolis
+
+ Wilmington
+
+ Knoxville
+
+ Richmond
+
+ Charleston
+
+ Baltimore
+
+ Syracuse
+
+ Augusta
+
+ Sault Ste. Marie
+
+ Sitka
+
+ Kigali
+
+ Ternate
+
+ Ambon
+
+ Raba
+
+ Jayapura
+
+ Banda Aceh
+
+ Zhangye
+
+ Wuwei
+
+ Dunhuang
+
+ Tianshui
+
+ Dulan
+
+ Golmud
+
+ Yulin
+
+ Bose
+
+ Wuzhou
+
+ Lupanshui
+
+ Quanzhou
+
+ Hefei
+
+ Suzhou
+
+ Zhanjiang
+
+ Shaoguan
+
+ Balikpapan
+
+ Surakarta
+
+ Bandar Lampung
+
+ Tanjungpandan
+
+ Malang
+
+ Kupang
+
+ Parepare
+
+ Xigaze
+
+ Shache
+
+ Yining
+
+ Altay
+
+ Shizuishan
+
+ Yulin
+
+ Ankang
+
+ Houma
+
+ Yueyang
+
+ Hengyang
+
+ Mianyang
+
+ Xichang
+
+ Baoshan
+
+ Gejiu
+
+ Shijianzhuang
+
+ Handan
+
+ Anshan
+
+ Dalian
+
+ Qingdao
+
+ Linyi
+
+ Huaiyin
+
+ Wenzhou
+
+ Ningbo
+
+ Gorontalo
+
+ Tongliao
+
+ Hohhot
+
+ Chifeng
+
+ Ulanhot
+
+ Hailar
+
+ Jiamusi
+
+ Beian
+
+ Daqing
+
+ Jixi
+
+ Faridabad
+
+ Srinagar
+
+ Vijayawada
+
+ Thiruvananthapuram
+
+ Kochi
+
+ Cuttack
+
+ Hubli
+
+ Mangalore
+
+ Mysore
+
+ Gulbarga
+
+ Kolhapur
+
+ Nanded
+
+ Akola
+
+ Guwahati
+
+ Ludhiana
+
+ Kota
+
+ Jodhpur
+
+ Lucknow
+
+ Saharanpur
+
+ Ranchi
+
+ Bhagalpur
+
+ Raipur
+
+ Jabalpur
+
+ Indore
+
+ Pondicherry
+
+ Salem
+
+ Tiruchirappalli
+
+ Rio Branco
+
+ São Luís
+
+ Porto Velho
+
+ Alvorada
+
+ Corumbá
+
+ Belo Horizonte
+
+ Montes Claros
+
+ Uberlândia
+
+ Colíder
+
+ Alta Floresta
+
+ Cuiabá
+
+ Pelotas
+
+ Caxias do Sul
+
+ Ponta Grossa
+
+ Teresina
+
+ Maceió
+
+ Vitória da Conquista
+
+ Barreiras
+
+ Vila Velha
+
+ Natal
+
+ Campinas
+
+ Sorocaba
+
+ Ribeirão Preto
+
+ Petrolina
+
+ Pago Pago
+
+ Kingstown
+
+ Castries
+
+ Basseterre
+
+ Las Palmas
+
+ Berbera
+
+ Port Louis
+
+ Gaza
+
+ Saint George's
+
+ Papeete
+
+ Manama
+
+ Freeport
+
+ Saint John's
+
+ Kozhikode
+
+ Bhubaneshwar
+
+ Jamshedpur
+
+ Helena
+
+ Bismarck
+
+ Boise
+
+ San Jose
+
+ Sacramento
+
+ Las Vegas
+
+ Santa Fe
+
+ Portland
+
+ Salt Lake City
+
+ Cheyenne
+
+ Des Moines
+
+ Omaha
+
+ Oklahoma City
+
+ Pierre
+
+ San Antonio
+
+ Jackson
+
+ Raleigh
+
+ Cleveland
+
+ Cincinnati
+
+ Nashville
+
+ Memphis
+
+ Norfolk
+
+ Milwaukee
+
+ Buffalo
+
+ Pittsburgh
+
+ Kodiak
+
+ Cold Bay
+
+ Bethel
+
+ Point Hope
+
+ Utqiaġvik
+
+ Nome
+
+ Valdez
+
+ Juneau
+
+ Fairbanks
+
+ Prudhoe Bay
+
+ Padang
+
+ Jiayuguan
+
+ Xining
+
+ Guilin
+
+ Huainan
+
+ Shantou
+
+ Tarakan
+
+ Semarang
+
+ Palembang
+
+ Bandjarmasin
+
+ Ujungpandang
+
+ Lhasa
+
+ Hami
+
+ Hotan
+
+ Kashgar
+
+ Yinchuan
+
+ Pingxiang
+
+ Qiqihar
+
+ Vishakhapatnam
+
+ Amritsar
+
+ Varanasi
+
+ Asansol
+
+ Bhilai
+
+ Bhopal
+
+ Madurai
+
+ Coimbatore
+
+ Cruzeiro do Sul
+
+ Leticia
+
+ Manaus
+
+ Caxias
+
+ Santarém
+
+ Marabá
+
+ Vilhena
+
+ Ji-Paraná
+
+ Campo Grande
+
+ Florianópolis
+
+ Feira de Santana
+
+ Boa Vista
+
+ Macapá
+
+ San Juan
+
+ Stanley
+
+ Hamilton
+
+ Nukualofa
+
+ Hargeysa
+
+ Victoria
+
+ São Tomé
+
+ Apia
+
+ Valletta
+
+ Malé
+
+ Jerusalem
+
+ Praia
+
+ Nassau
+
+ Nicosia
+
+ Shenzhen
+
+ Zibo
+
+ Minneapolis
+
+ Honolulu
+
+ Seattle
+
+ Phoenix
+
+ San Diego
+
+ St. Louis
+
+ New Orleans
+
+ Dallas
+
+ Boston
+
+ Tampa
+
+ Philadelphia
+
+ Detroit
+
+ Anchorage
+
+ Medan
+
+ Lanzhou
+
+ Nanning
+
+ Guiyang
+
+ Chongqing
+
+ Fuzhou
+
+ Guangzhou
+
+ Dongguan
+
+ Bandung
+
+ Surabaya
+
+ Xian
+
+ Taiyuan
+
+ Wuhan
+
+ Changsha
+
+ Kunming
+
+ Zhengzhou
+
+ Shenyeng
+
+ Jinan
+
+ Tianjin
+
+ Nanchang
+
+ Nanjing
+
+ Hangzhou
+
+ Changchun
+
+ Baotou
+
+ Harbin
+
+ Delhi
+
+ Hyderabad
+
+ Pune
+
+ Nagpur
+
+ Jaipur
+
+ Kanpur
+
+ Patna
+
+ Chennai
+
+ Ahmedabad
+
+ Surat
+
+ Belém
+
+ Brasília
+
+ Porto Alegre
+
+ Curitiba
+
+ Fortaleza
+
+ Salvador
+
+ Goiânia
+
+ Recife
+
+ San Francisco
+
+ Denver
+
+ Houston
+
+ Miami
+
+ Atlanta
+
+ Chicago
+
+ Ürümqi
+
+ Chengdu
+
+ New Delhi
+
+ Bangalore
+
+ Los Angeles
+
+ Washington, D.C.
+
+ New York
+
+ Beijing
+
+ Jakarta
+
+ Shanghai
+
+ Mumbai
+
+ Kolkata
+
+ Rio de Janeiro
+
+ São Paulo
+
+ Singapore
+
+ Hong Kong
+
+
diff --git a/input/Tissot-alt2.jpg b/input/Advanced/Tissot Oblique.jpg
similarity index 100%
rename from input/Tissot-alt2.jpg
rename to input/Advanced/Tissot Oblique.jpg
diff --git a/input/Tissot-alt3.jpg b/input/Advanced/Tissot Small.jpg
similarity index 100%
rename from input/Tissot-alt3.jpg
rename to input/Advanced/Tissot Small.jpg
diff --git a/input/Tissot-alt1.jpg b/input/Advanced/Tissot Standard.jpg
similarity index 100%
rename from input/Tissot-alt1.jpg
rename to input/Advanced/Tissot Standard.jpg
diff --git a/input/Advanced/Tissot Wikipedia +0.svg b/input/Advanced/Tissot Wikipedia +0.svg
new file mode 100644
index 0000000..a8141b4
--- /dev/null
+++ b/input/Advanced/Tissot Wikipedia +0.svg
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Equirectangular map of the world – coastlines, graticule, and indicatrices
+
+ A map of the world, showing all landmasses with 10° graticule and Tissot's indicatrices of radius 750 km and spacing 30°. Coastlines precise to 110 km.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/input/Advanced/Tissot Wikipedia -20.svg b/input/Advanced/Tissot Wikipedia -20.svg
new file mode 100644
index 0000000..5d4ab36
--- /dev/null
+++ b/input/Advanced/Tissot Wikipedia -20.svg
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Equirectangular map of the world – coastlines, graticule, and indicatrices
+
+ A map of the world, showing all landmasses with 10° graticule and Tissot's indicatrices of radius 750 km and spacing 30°. Coastlines precise to 110 km.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/input/Basic.svg b/input/Basic.svg
index 900d840..38d9dc2 100644
--- a/input/Basic.svg
+++ b/input/Basic.svg
@@ -15,10 +15,10 @@
@@ -35,7 +35,7 @@
Equirectangular map of the world – coastlines and lakes
- A map of the world, showing all landmasses as SVG paths. Small lakes and islands are not shown. Coastlines precise to 50 km.
+ A map of the world, showing all landmasses as SVG paths. Coastlines precise to 50 km.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/input/Compound.svg b/input/Compound.svg
index b869309..6404a13 100644
--- a/input/Compound.svg
+++ b/input/Compound.svg
@@ -15,10 +15,10 @@
@@ -35,1459 +35,1817 @@
Equirectangular map of the world – coastlines, graticule, and indicatrices
- A map of the world, showing all landmasses with 15° graticule. Small lakes and islands are not shown. Coastlines precise to 50 km.
+ A map of the world, showing all landmasses with 15° graticule. Coastlines precise to 50 km.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1524,8 +1882,11 @@
-
+
+
+
+
diff --git a/input/Graticule.svg b/input/Graticule.svg
index abf633b..9df0074 100644
--- a/input/Graticule.svg
+++ b/input/Graticule.svg
@@ -15,10 +15,10 @@
@@ -35,7 +35,7 @@
Equirectangular map – 5° graticule
- An Equirectangular graticule, showing all landmasses with 5° graticule, including the Arctic Circle, the Antarctic Circle, and the Tropics.
+ An Equirectangular graticule, showing all landmasses with 5° graticule, including the Polar Circles and the Tropics.
@@ -168,7 +168,6 @@
-
diff --git a/input/Orthodromes.svg b/input/Orthodromes.svg
index 6b3e965..0975d69 100644
--- a/input/Orthodromes.svg
+++ b/input/Orthodromes.svg
@@ -18,7 +18,7 @@
dc:description="A mesh of great circles that intersect with 10-fold symmetry at 12 principal nodes and 6-fold symmetry at 20 minor nodes. Aligns with the edges of an icosohedron and its dual dodecahedron."
dc:creator="Justin Kunimune"
dc:source="http://www.naturalearthdata.com/"
- dc:date="2018-01-15"
+ dc:date="2018-02-04"
dc:format="image/svg+xml"
dc:language="en" >
@@ -33,46 +33,48 @@
- Icosohedral orthodromic mesh - Equirectangular projection
+ Icosohedral orthodromic mesh – Equirectangular projection
A mesh of great circles that intersect with 10-fold symmetry at 12 principal nodes and 6-fold symmetry at 20 minor nodes. Aligns with the edges of an icosohedron and its dual dodecahedron.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/input/Political.svg b/input/Political.svg
index 6107ba6..442aa8c 100644
--- a/input/Political.svg
+++ b/input/Political.svg
@@ -1,780 +1,890 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Equirectangular map of the world – political borders
+
+ A map of the world, showing all countries recognised by the UN as SVG paths, with major lakes overlaid. Borders precise to 50 km.
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/input/Tissot-alt1.svg b/input/Tissot-alt1.svg
deleted file mode 100644
index 3fa8798..0000000
--- a/input/Tissot-alt1.svg
+++ /dev/null
@@ -1,1603 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Equirectangular map of the world – coastlines, graticule, and indicatrices
-
- A map of the world, showing all landmasses with 10° graticule and Tissot's indicatrices of radius 750 km and spacing 30°. Small lakes and islands are not shown. Coastlines precise to 50 km.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/input/Tissot.svg b/input/Tissot.svg
index 80edb50..af87d71 100644
--- a/input/Tissot.svg
+++ b/input/Tissot.svg
@@ -15,10 +15,10 @@
@@ -35,20 +35,19 @@
Equirectangular map of the world – coastlines with Tissot's indicatrices
- A map of the world, showing all landmasses with Tissot's indicatrices of radius 3° 45′ and spacing 15°. Small lakes and islands are not shown. Precise to 50 km.
+ A map of the world, showing all landmasses with Tissot's indicatrices of radius 3° 45′ and spacing 15°. Coastlines precise to 50 km.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/zupplemental/compose_maps.py b/src/zupplemental/compose_maps.py
new file mode 100644
index 0000000..139aaa7
--- /dev/null
+++ b/src/zupplemental/compose_maps.py
@@ -0,0 +1,143 @@
+#compose_maps.py
+#make ALL the maps
+
+import math
+
+from generate_borders import generate_borders
+from generate_graticule import generate_graticule
+from generate_indicatrices import generate_indicatrices
+from generate_orthodromes import generate_orthodromes
+from generate_shape import generate_administrivia, generate_disputes, generate_fine_borders, generate_land, generate_rivers, generate_lakes
+from generate_labels import generate_topographical_labels, generate_political_labels, generate_urban_labels
+
+
+def compose_landmasses():
+ print('\t')
+ print('\t\t')
+ generate_land('ne_50m', trim_antarctica=True)
+ print('\t\t ')
+ print('\t\t')
+ generate_lakes('ne_50m', max_rank=4)
+ print('\t\t ')
+ print('\t ')
+
+def compose_graticule():
+ print('\t')
+ print('\t\t')
+ generate_graticule(5, 1, include_tropics=True, adjust_poles=True)
+ print('\t\t ')
+ print('\t ')
+
+def compose_graticule2():
+ print('\t')
+ print('\t\t')
+ generate_graticule(15, .25, include_tropics=True, adjust_poles=True, double_dateline=True)
+ print('\t\t ')
+ print('\t ')
+
+def compose_compound():
+ print('\t')
+ print('\t\t')
+ generate_land('ne_50m', trim_antarctica=True)
+ print('\t\t ')
+ print('\t\t')
+ generate_rivers('ne_50m', max_rank=4)
+ print('\t\t ')
+ print('\t\t')
+ generate_lakes('ne_50m', max_rank=4)
+ print('\t\t ')
+ print('\t\t')
+ generate_graticule(15, 1, include_tropics=True, adjust_poles=True)
+ print('\t\t ')
+ print('\t ')
+
+def compose_indicatrices():
+ print('\t')
+ print('\t\t')
+ generate_land('ne_50m', trim_antarctica=True)
+ print('\t\t ')
+ print('\t\t')
+ generate_lakes('ne_50m', max_rank=4)
+ print('\t\t ')
+ print('\t\t')
+ generate_indicatrices(15, math.radians(3.75), adjust_poles=True)
+ print('\t\t ')
+ print('\t ')
+
+def compose_indicatrices2(ctr_meridian):
+ print('\t')
+ print('\t\t')
+ generate_land('ne_110m')
+ print('\t\t ')
+ print('\t\t')
+ generate_lakes('ne_110m')
+ print('\t\t ')
+ print('\t\t')
+ generate_graticule(10, 1, double_dateline=True)
+ print('\t\t ')
+ print('\t\t')
+ generate_indicatrices(30, 600/6371, ctr_meridian=ctr_meridian, adjust_poles=True)
+ print('\t\t ')
+ print('\t ')
+
+def compose_political():
+ print('\t')
+ print('\t\t')
+ generate_borders('ne_50m', trim_antarctica=True)
+ print('\t\t ')
+ print('\t\t')
+ generate_lakes('ne_50m', max_rank=4)
+ print('\t\t ')
+ print('\t ')
+
+def compose_orthodromes():
+ print('\t')
+ print('\t\t')
+ generate_orthodromes()
+ print('\t\t ')
+ print('\t ')
+
+def compose_everything():
+ print('\t')
+ print('\t\t')
+ generate_borders('ne_50m', trim_antarctica=True, borders_only=False)
+ print('\t\t ')
+ print('\t\t')
+ generate_fine_borders('ne_50m')
+ print('\t\t ')
+ print('\t\t')
+ generate_disputes('ne_50m')
+ print('\t\t ')
+ print('\t\t')
+ generate_administrivia('ne_50m')
+ print('\t\t ')
+ print('\t\t')
+ generate_land('ne_50m', trim_antarctica=True)
+ print('\t\t ')
+ print('\t\t')
+ generate_rivers('ne_50m')
+ print('\t\t ')
+ print('\t\t')
+ generate_lakes('ne_50m')
+ print('\t\t ')
+ print('\t\t')
+ generate_borders('ne_50m', trim_antarctica=True, borders_only=True)
+ print('\t\t ')
+ print('\t\t')
+ generate_graticule(5, 1, include_tropics=True, adjust_poles=True)
+ print('\t\t ')
+ print('\t ')
+ generate_topographical_labels('ne_50m')
+ generate_political_labels('ne_50m')
+ generate_urban_labels('ne_50m')
+
+
+if __name__ == '__main__':
+ # compose_landmasses()
+ # compose_graticule()
+ # compose_compound()
+ # compose_indicatrices()
+ # compose_indicatrices2(-20)
+ # compose_political()
+ # compose_orthodromes()
+ compose_everything()
diff --git a/src/zupplemental/generate_borders.py b/src/zupplemental/generate_borders.py
new file mode 100644
index 0000000..ed9afd2
--- /dev/null
+++ b/src/zupplemental/generate_borders.py
@@ -0,0 +1,50 @@
+import shapefile
+
+from helpers import plot, trim_edges
+
+
+SIZE_CLASSES = ['lg', 'md', 'sm', None, None, None]
+
+
+def generate_borders(source, borders_only=False, labels=False, self_clip=False, trim_antarctica=False):
+ """data from http://www.naturalearthdata.com/"""
+ sf = shapefile.Reader("data/{}_admin_0_countries".format(source))
+ sovereigns = {} #key is 3-char code, value is list of (record,shape)
+ for record, shape in zip(sf.records(), sf.shapes()):
+ if trim_antarctica:
+ if record[4] == 'ATA': #if it is Antarctica
+ shape.points = trim_edges(shape.points)
+
+ sovereigns[record[4]] = sovereigns.get(record[4], []) + [(record, shape)]
+
+ for code in sorted(sovereigns.keys()):
+ for record, shape in sovereigns[code]:
+ if record[3] == record[8]:
+ country_code = record[12]
+ # metropole = (record, shape)
+ # sovereigns[code].remove(metropole) #move the metropole to the front
+ # sovereigns[code] = [metropole] + sovereigns[code]
+ # break
+ print('\t\t\t'.format(country_code))
+ for record, shape in sovereigns[code]:
+ x1, y1, x2, y2 = shape.bbox
+ x = (x1+x2)/2
+ y = (y1+y2)/2
+ region_code = record[12]
+ if country_code == region_code: #metropole
+ # name = record[3]
+ text_size = SIZE_CLASSES[int(record[2]-2)]
+ else: #dependency
+ # name = '{} ({})'.format(record[8], record[3])
+ text_size = SIZE_CLASSES[int(record[2]-1)]
+ # if labels:
+ # if text_size is not None:
+ # print('\t\t\t\t{} '.format(text_size, x, y, name))
+ if borders_only:
+ print('\t\t\t\t'.format(region_code))
+ print('\t\t\t\t\t '.format(region_code))
+ print('\t\t\t\t ')
+ print('\t\t\t\t '.format(region_code))
+ else:
+ plot(shape.points, midx=shape.parts, close=False, fourmat='xd', tabs=4, ident="{0}-shape".format(region_code))
+ print('\t\t\t ')
diff --git a/src/zupplemental/generate_coastlines.py b/src/zupplemental/generate_coastlines.py
index beef8e0..22c7da0 100644
--- a/src/zupplemental/generate_coastlines.py
+++ b/src/zupplemental/generate_coastlines.py
@@ -6,72 +6,17 @@ from helpers import plot, is_widdershins
SOURCE = 'ne_50m'
-SKIP = 1
-EXPAND_ANTARCTICA = True
-MAX_RANK = 2
+TRIM_ANTARCTICA = False
+MAX_RANK = float('inf')
"""data from http://www.naturalearthdata.com/"""
-sf = shapefile.Reader("data/{}_coastline".format(SOURCE))
-pending_coasts = {} #key is last endpoint, value is list of points; every point should appear exactly twice, in each direction
-split_points = {} #key is first endpoint of master curve, value is list of indices where the curve must be split
-final_coasts = []
+sf = shapefile.Reader("data/{}_land".format(SOURCE))
for record, shape in zip(sf.records(), sf.shapes()):
- curve = shape.points[0:len(shape.points):SKIP]
- if curve[-1] != shape.points[-1]: curve.append(shape.points[-1])
- if len(curve) < 4: continue
+ if float(record[2]) > MAX_RANK: continue
- if curve[0] == curve[-1]: #this curve is complete; we're done here
- final_coasts.append(curve)
- else:
- if curve[0] in pending_coasts: #if this is an extension of another path
- curve = pending_coasts.pop(curve[0]) + curve[1:] #replace that
- elif curve[-1] in pending_coasts: #if this reversed is an extension of another path
- curve = pending_coasts.pop(curve[-1]) + list(reversed(curve[:-1])) #replace that
- pending_coasts[curve[-1]] = curve
- pending_coasts[curve[0]] = list(reversed(curve))
-
- # for key in pending_coasts:
- # assert pending_coasts[key][-1] == key, "The curve from {} to {} is keyed by {}".format(val[0], val[-1], key)
- # assert pending_coasts[key][0] in pending_coasts, "{} keys to a curve from {} to {}, but there is no key {}".format(key, val[0], val[-1], val[0])
-
-for key, coast in pending_coasts.items():
- if pending_coasts[coast[0]] is not None: #if the mirror is not checked
- final_coasts.append(coast if is_widdershins(coast) else pending_coasts[coast[0]])
- pending_coasts[key] = None #mark this as checked
-
-final_coasts = sorted(sorted(sorted(final_coasts, key=lambda c:c[0][0]), key=lambda c:c[0][1]), key=len, reverse=True)
-if SOURCE == 'ne_10m':
- afroeurasia = final_coasts[1]
- split_points[afroeurasia[0]] = [len(afroeurasia)]
- final_coasts[1] += final_coasts.pop(12) #manually attach the Caspian to Afroeurasia
-else:
- afroeurasia = final_coasts[0]
- for i in range(1,len(afroeurasia)):
- if math.hypot(afroeurasia[i][0]-afroeurasia[i-1][0], afroeurasia[i][1]-afroeurasia[i-1][1]) > 10:
- split_points[afroeurasia[0]] = [i] #manually detach the Caspian from Afroeurasia
- break
-if EXPAND_ANTARCTICA:
- antarctica = final_coasts[2]
- final_coasts[2] = [(antarctica[0][0], y) for y in range(-90, math.ceil(antarctica[0][1]))] +\
- antarctica + [(antarctica[-1][0], y) for y in range(math.floor(antarctica[-1][1]), -91, -1)]
-
-sf = shapefile.Reader("data/{}_lakes".format(SOURCE))
-for record, lake in zip(sf.records(), sf.shapes()):
- if float(record[-2]) > MAX_RANK: #if this lake isn't important enough
- continue #skip it
-
- x1l, y1l, x2l, y2l = lake.bbox
- for i, continent in enumerate(final_coasts):
- xc, yc = zip(*continent)
- x1c, y1c, x2c, y2c = min(xc), min(yc), max(xc), max(yc)
- if x1c < x1l and y1c < y1l and x2c > x2l and y2c > y2l: #if this continent contains this lake
- curve = lake.points[0:len(lake.points):SKIP]
- if curve[-1] != lake.points[-1]: curve.append(lake.points[-1])
- split_points[continent[0]] = split_points.get(continent[0], []) + [len(continent)+p for p in lake.parts] #mark the movetos
- final_coasts[i] = continent + curve #add it
- break
-
-for coast in final_coasts:
- midx = [0] + split_points.get(coast[0], [])
- plot(coast, midx=midx, fourmat='xd', close=False)
+ if TRIM_ANTARCTICA:
+ if shape.points[0][0] == -180 and shape.points[0][1] < -80: #if it is Antarctica
+ coast = shape.points
+ shape.points = [(coast[0][0],y) for y in range(-90,int(coast[0][1]))] + coast + [(coast[-1][0],y) for y in range(int(coast[-1][1]),-91,-1)]
+ plot(shape.points, midx=shape.parts, close=False, fourmat='xd')
diff --git a/src/zupplemental/generate_graticule.py b/src/zupplemental/generate_graticule.py
index 4beb8ab..4aaf65f 100644
--- a/src/zupplemental/generate_graticule.py
+++ b/src/zupplemental/generate_graticule.py
@@ -1,34 +1,30 @@
import math
-GRATICULE = 15
-INCLUDE_TROPICS = True
-ADJUST_POLES = True #set to True to reduce the number of meridians as you approach the pole
-GRANULARITY = .25
-
AXIAL_TILT = 23.43694
-ANTI_TILT = 66.56306
+ANTI_TILT = 66.56306 #I have both of these because it's the easiest way to deal with roundoff
-def plot_meridian(lamd, cut=0, clazz=None):
+def plot_meridian(lamd, granularity, cut=0, clazz=None):
class_attr = 'class="{}" '.format(clazz) if clazz is not None else ''
- tag = '\t\t\t '
+ tag = '\t\t\t '
print(tag)
-def plot_parallel(phid, cut=0, clazz=None):
+def plot_parallel(phid, granularity, cut=0, clazz=None):
class_attr = 'class="{}" '.format(clazz) if clazz is not None else ''
- tag = '\t\t\t '
+ tag = '\t\t\t '
print(tag)
-if __name__ == '__main__':
- NUM_BASE = 90//GRATICULE
+def generate_graticule(spacing, granularity, include_tropics=False, adjust_poles=False, double_dateline=False):
+ """Generate a mesh of latitude and longitude lines"""
+ NUM_BASE = 90//spacing
cuts = [0]*(4*NUM_BASE)
- if ADJUST_POLES:
+ if adjust_poles: #if this is True, reduce the number of meridians as you approach the pole
old_num = 1
- for p in range(0, 90, GRATICULE):
- new_num = old_num*int(1/math.cos(math.radians(p+GRATICULE/2))/old_num)
+ for p in range(0, 90, spacing):
+ new_num = old_num*int(1/math.cos(math.radians(p+spacing/2))/old_num)
while NUM_BASE%new_num != 0: new_num -= 1
if new_num >= 2*old_num:
for i in range(len(cuts)):
@@ -36,17 +32,17 @@ if __name__ == '__main__':
cuts[i] = 90-p
old_num = new_num
- for x in range(GRATICULE, 180, GRATICULE):
- plot_meridian(-x, cut=cuts[x//GRATICULE%len(cuts)])
- plot_meridian(x, cut=cuts[x//GRATICULE%len(cuts)])
- for y in range(GRATICULE, 90, GRATICULE):
- plot_parallel(-y)
- plot_parallel(y)
- for x in [-180, 0, 180]:
- plot_meridian(x, clazz="prime-m")
- plot_parallel(0, clazz="equator")
- if INCLUDE_TROPICS:
- plot_parallel(-AXIAL_TILT, clazz="tropics")
- plot_parallel(AXIAL_TILT, clazz="tropics")
- plot_parallel(-ANTI_TILT, clazz="circles")
- plot_parallel(ANTI_TILT, clazz="circles")
+ for x in range(spacing, 180, spacing):
+ plot_meridian(-x, granularity, cut=cuts[x//spacing%len(cuts)])
+ plot_meridian(x, granularity, cut=cuts[x//spacing%len(cuts)])
+ for y in range(spacing, 90, spacing):
+ plot_parallel(-y, granularity)
+ plot_parallel(y, granularity)
+ for x in [-180, 0, 180] if double_dateline else [-180, 0]:
+ plot_meridian(x, granularity, clazz="prime-m")
+ plot_parallel(0, granularity, clazz="equator")
+ if include_tropics:
+ plot_parallel(-AXIAL_TILT, granularity, clazz="tropics")
+ plot_parallel(AXIAL_TILT, granularity, clazz="tropics")
+ plot_parallel(-ANTI_TILT, granularity, clazz="circles")
+ plot_parallel(ANTI_TILT, granularity, clazz="circles")
diff --git a/src/zupplemental/generate_indicatrices.py b/src/zupplemental/generate_indicatrices.py
index 379c84c..f748478 100644
--- a/src/zupplemental/generate_indicatrices.py
+++ b/src/zupplemental/generate_indicatrices.py
@@ -3,55 +3,53 @@ import math
from helpers import obliquify, plot
-IND_NUM = 360
# IND_RAD = math.radians(3.75)
-IND_RAD = 750/6371
-SPACING = 30
-ADJUST_SPACING = True
+# IND_RAD = 750/6371
-def plot_indicatrix(phi0, lam0, r):
+def plot_indicatrix(phi0, lam0, r, res):
points = []
- for l in range(0, 360, 360//IND_NUM):
+ for l in range(0, 360, 360//res):
points.append(obliquify(math.pi/2-r, math.radians(l), phi0, lam0))
plot(points)
-def plot_side_indicatrix(phi0, r):
+def plot_side_indicatrix(phi0, r, res):
points = []
midx = [0]
- for l in range(0, 181, 360//IND_NUM):
- points.append(obliquify(math.pi/2-r, math.radians(l), phi0, -math.pi))
+ for l in range(0, 181, 360//res):
+ pr, lr = obliquify(math.pi/2-r, math.radians(l), phi0, 0)
+ points.append((pr, lr - math.pi))
midx.append(len(points))
- for l in range(180, 361, 360//IND_NUM):
- pr, lr = obliquify(math.pi/2-r, math.radians(l), phi0, -math.pi)
- points.append((pr, lr+2*math.pi))
+ for l in range(180, 361, 360//res):
+ pr, lr = obliquify(math.pi/2-r, math.radians(l), phi0, 0)
+ points.append((pr, lr + math.pi))
plot(points, midx=midx, close=False)
-def plot_pole_indicatrix(north, r):
+def plot_pole_indicatrix(north, r, res):
if north:
pp, pr = math.pi/2, math.pi/2-r
else:
pp, pr = -math.pi/2, -math.pi/2+r
points = [(pp, -math.pi)]
- for x in range(-180, 181, 360//IND_NUM):
+ for x in range(-180, 181, 360//res):
points.append((pr, math.radians(x)))
points.append((pp, math.pi))
plot(points)
-if __name__ == '__main__':
- plot_pole_indicatrix(True, IND_RAD)
- for y in range(-90+SPACING, 90, SPACING):
- if ADJUST_SPACING:
- step = SPACING * round(1/math.cos(math.radians(y)))
+def generate_indicatrices(spacing, radius, adjust_poles=False, resolution=60, ctr_meridian=0):
+ plot_pole_indicatrix(True, radius, resolution)
+ for y in range(-90+spacing, 90, spacing):
+ if adjust_poles:
+ step = spacing * round(1/math.cos(math.radians(y)))
else:
- step = SPACING
+ step = spacing
for x in range(-180, 180, step):
- if abs(x) == 180:
- plot_side_indicatrix(math.radians(y), math.pi/36)
+ if abs(x+ctr_meridian) == 180:
+ plot_side_indicatrix(math.radians(y), radius, resolution)
else:
- plot_indicatrix(math.radians(y), math.radians(x), IND_RAD)
- plot_pole_indicatrix(False, IND_RAD)
+ plot_indicatrix(math.radians(y), math.radians(x+ctr_meridian), radius, resolution)
+ plot_pole_indicatrix(False, radius, resolution)
diff --git a/src/zupplemental/generate_labels.py b/src/zupplemental/generate_labels.py
new file mode 100644
index 0000000..436c8fe
--- /dev/null
+++ b/src/zupplemental/generate_labels.py
@@ -0,0 +1,58 @@
+#read data from a shapefile into SVG format
+
+import shapefile
+import math
+
+from helpers import line_break, get_centroid
+
+
+def plot_texts(data, label_class, source, max_rank, regulate_case=False, secondary_attr=None, force_points=False):
+ """data from http://www.naturalearthdata.com/"""
+ sf = shapefile.Reader("data/{}_{}".format(source, data))
+ lat_idx = None
+ for i, field in enumerate(sf.fields):
+ if field[0] in ['scalerank', 'LABELRANK']:
+ rank_idx = i-1
+ if field[0] in ['name', 'NAME']:
+ name_idx = i-1
+ if field[0] == 'featurecla':
+ type_idx = i-1
+ if field[0] == secondary_attr:
+ secd_idx = i-1
+ if field[0] == 'lat_y':
+ lat_idx = i-1
+ if field[0] == 'long_x':
+ lon_idx = i-1
+ for record, shape in zip(sf.records(), sf.shapes()):
+ rank = record[rank_idx]
+ if rank <= max_rank:
+ if lat_idx is not None:
+ x, y = record[lon_idx], record[lat_idx]
+ else:
+ x, y = get_centroid(shape.points, shape.parts)
+ label = record[name_idx]
+ if not label:
+ continue #we can't waste our time worrying about features with no names
+ if label == 'EUROPE':
+ rank += 1 #You're not a continent! Get over it!
+ if regulate_case:
+ label = label.upper()
+ if secondary_attr is not None and record[7] == 'Dependency':
+ label = "{} ({})".format(label, record[secd_idx]) #indicate dependencies
+ text_size = ['sm', 'md', 'lg', 'xl'][min(3, int(max_rank-rank))] #lower ranks get bigger text
+ print('\t{} '.format(
+ label_class, text_size, 180+x, 90-y, label))
+ if force_points or record[type_idx] in ['mountain', 'depression', 'pole', 'waterfall']: #add circles to the ones that need markers
+ print('\t '.format(180+x, 90-y, math.sqrt(max_rank-rank+1)*0.15))
+
+def generate_political_labels(source, max_rank=4):
+ plot_texts('admin_0_countries', 'pol', source, max_rank, secondary_attr='NOTE_ADM0')
+
+def generate_topographical_labels(source, max_rank=2):
+ plot_texts('geography_regions_points', 'geo', source, max_rank)
+ plot_texts('geography_regions_polys', 'geo', source, max_rank, regulate_case=True)
+ plot_texts('geography_regions_elevation_points', 'geo', source, max_rank)
+ plot_texts('geography_marine_polys', 'sea', source, max_rank)
+
+def generate_urban_labels(source, max_rank=1):
+ plot_texts('populated_places', 'pol', source, max_rank, force_points=True)
diff --git a/src/zupplemental/generate_lakes.py b/src/zupplemental/generate_lakes.py
new file mode 100644
index 0000000..b4676a1
--- /dev/null
+++ b/src/zupplemental/generate_lakes.py
@@ -0,0 +1,29 @@
+import math
+import numpy as np
+import shapefile
+
+from helpers import plot
+
+
+SOURCE = 'ne_50m'
+SKIP = 1
+MAX_RANK = 2
+INCLUDE_LAKES = False
+
+
+"""data from http://www.naturalearthdata.com/"""
+sf = shapefile.Reader("data/{}_lakes".format(SOURCE))
+for record, lake in zip(sf.records(), sf.shapes()):
+ if float(record[-2]) > MAX_RANK: #if this lake isn't important enough
+ continue #skip it
+
+ x1l, y1l, x2l, y2l = lake.bbox
+ for i, continent in enumerate(final_coasts):
+ xc, yc = zip(*continent)
+ x1c, y1c, x2c, y2c = min(xc), min(yc), max(xc), max(yc)
+ if x1c < x1l and y1c < y1l and x2c > x2l and y2c > y2l: #if this continent contains this lake
+ curve = lake.points[0:len(lake.points):SKIP]
+ if curve[-1] != lake.points[-1]: curve.append(lake.points[-1])
+ split_points[continent[0]] = split_points.get(continent[0], []) + [len(continent)+p for p in lake.parts] #mark the movetos
+ final_coasts[i] = continent + curve #add it
+ break
\ No newline at end of file
diff --git a/src/zupplemental/generate_orthodromes.py b/src/zupplemental/generate_orthodromes.py
index a1b389c..d3e4c7c 100644
--- a/src/zupplemental/generate_orthodromes.py
+++ b/src/zupplemental/generate_orthodromes.py
@@ -14,7 +14,8 @@ def plot_orthodrome(phi0, lam0, tht0):
plot(points, close=False)
-if __name__ == '__main__':
+def generate_orthodromes():
+ """generate an icosohedral orthodromic mesh, like the Brilliant logo (#notsponsored)"""
for l in range(-180, 180, 36):
plot_orthodrome(math.pi/2, 0, math.radians(l))
for l in range(0, 360, 72):
diff --git a/src/zupplemental/generate_shape.py b/src/zupplemental/generate_shape.py
new file mode 100644
index 0000000..bc6760e
--- /dev/null
+++ b/src/zupplemental/generate_shape.py
@@ -0,0 +1,38 @@
+#read data from a shapefile into SVG format
+
+import shapefile
+
+from helpers import plot, trim_edges
+
+
+def plot_shape(data, source, max_rank, trim_antarctica=False):
+ """data from http://www.naturalearthdata.com/"""
+ sf = shapefile.Reader("data/{}_{}".format(source, data))
+ for i, field in enumerate(sf.fields):
+ if 'rank' in field[0]:
+ rank_idx = i-1
+ for record, shape in zip(sf.records(), sf.shapes()):
+ if record[rank_idx] <= max_rank:
+ if trim_antarctica:
+ if shape.points[0][1] < -60: #if it is Antarctica (this will have a few false positives, but that's fine)
+ shape.points = trim_edges(shape.points)
+
+ plot(shape.points, midx=shape.parts, close=False, fourmat='xd')
+
+def generate_fine_borders(source, max_rank=float('inf')):
+ plot_shape('admin_0_map_units', source, max_rank)
+
+def generate_disputes(source, max_rank=float('inf')):
+ plot_shape('admin_0_boundary_lines_disputed_areas', source, max_rank)
+
+def generate_administrivia(source, max_rank=float('inf')):
+ plot_shape('admin_1_states_provinces_lines', source, max_rank)
+
+def generate_land(source, max_rank=float('inf'), trim_antarctica=False):
+ plot_shape('land', source, max_rank, trim_antarctica=trim_antarctica)
+
+def generate_rivers(source, max_rank=float('inf')):
+ plot_shape('rivers_lake_centerlines', source, max_rank)
+
+def generate_lakes(source, max_rank=float('inf')):
+ plot_shape('lakes', source, max_rank)
diff --git a/src/zupplemental/helpers.py b/src/zupplemental/helpers.py
index 14aff2f..ea768ba 100644
--- a/src/zupplemental/helpers.py
+++ b/src/zupplemental/helpers.py
@@ -1,4 +1,5 @@
import math
+import random as rng
def obliquify(lat1, lon1, lat0, lon0):
@@ -21,14 +22,20 @@ def obliquify(lat1, lon1, lat0, lon0):
while lonf > math.pi:
lonf -= 2*math.pi
+ while lonf < -math.pi:
+ lonf += 2*math.pi
return latf, lonf
-def plot(coords, midx=[0], close=True, fourmat='pr'):
- tag = '\t\t\t 0 and coords[i-1] == coords[i]:
+ continue #no point repeating commands, though that sometimes happens
if coord == last_move:
tag += 'Z'
continue #save space by removing unnecessary repetitions
@@ -51,9 +58,76 @@ def plot(coords, midx=[0], close=True, fourmat='pr'):
print(tag.replace('.000',''))
-def is_widdershins(coords): #this method is not exact, but it should work well enough for my purposes.
- x1, y1 = coords[0]
- x2, y2 = coords[len(coords)//4]
- x3, y3 = coords[len(coords)*3//4]
+def trim_edges(coast):
+ """remove the extra points placed along the edges of the Plate Carree map"""
+ for i in range(len(coast)-1, -1, -1):
+ x0, y0 = coast[i-1] if i > 0 else coast[i]
+ x1, y1 = coast[i]
+ x2, y2 = coast[i+1] if i < len(coast)-1 else coast[i]
+ if (abs(x0) > 179.99 or abs(y0) > 89.99) and (abs(x1) > 179.99 or abs(y1) > 89.99) and (abs(x2) > 179.99 or abs(y2) > 89.99):
+ coast.pop(i)
+ return coast
- return (x2-x1)*(y3-y1) - (x3-x1)*(y2-y1) > 0
+
+def line_break(line):
+ """replace some space with a newline; whichever space is closest to the center"""
+ total_length = len(line)
+ words = line.split(' ')
+ best_length = float('inf')
+ left_length = 0
+ for i in range(len(words)-1):
+ left_length += len(words[i])+1
+ if max(left_length, total_length-left_length) < best_length:
+ best_length = max(left_length, total_length-left_length)
+ best_idx = left_length
+ return line[:best_idx-1] + '\n' + line[best_idx:]
+
+
+def get_centroid(points, parts=None):
+ """Compute the centroid of the spherical shape"""
+ minL = min([p[0] for p in points])
+ minP = min([p[1] for p in points])
+ maxL = max([p[0] for p in points])
+ maxP = max([p[1] for p in points])
+
+ if maxL-minL < 90:
+ return ((maxL+minL)/2, (maxP+minP)/2)
+ elif parts: #if there are multiple parts, try guessing the centroid of just one; the biggest one by bounding box
+ parts.append(len(points))
+ max_area = 0
+ for i in range(1, len(parts)):
+ part = points[parts[i-1]:parts[i]]
+ minL = min([p[0] for p in part])
+ minP = min([p[1] for p in part])
+ maxL = max([p[0] for p in part])
+ maxP = max([p[1] for p in part])
+ if (maxL-minL)*(maxP-minP) > max_area:
+ max_area = (maxL-minL)*(maxP-minP)
+ best_part = (parts[i-1], parts[i])
+ return get_centroid(points[best_part[0]:best_part[1]])
+
+ lines = []
+ for i in range(1, len(points)):
+ lines += [(*points[i-1], *points[i])]
+ xc, yc, zc = 0, 0, 0
+ j = 0
+ num_in = 0
+ while j < 4000 or num_in < 10:
+ j += 1
+ latr = math.asin(rng.random()*2-1)
+ lonr = rng.random()*2*math.pi - math.pi
+ latd, lond = math.degrees(latr), math.degrees(lonr)
+ num_crosses = 0
+ for l1, p1, l2, p2 in lines: #count the lines a northward ray crosses
+ if ((l1 <= lond and l2 > lond) or (l2 <= lond and l1 > lond)) and (p1*(l2-lond)/(l2-l1) + p2*(l1-lond)/(l1-l2) > latd):
+ num_crosses += 1
+
+ if num_crosses%2 == 1: #if odd,
+ num_in += 1
+ xc += math.cos(latr)*math.cos(lonr) #this point is in.
+ yc += math.cos(latr)*math.sin(lonr) #update the centroid
+ zc += math.sin(latr)
+
+ loncr = math.atan2(yc, xc)
+ latcr = math.atan2(zc, math.hypot(xc, yc))
+ return (math.degrees(loncr), math.degrees(latcr))