nms-scribe / cosmopoeia

A tool to generate fantasy maps for GIS.
MIT License
3 stars 1 forks source link

Spherical Mapping #1

Closed nms-scribe closed 8 months ago

nms-scribe commented 10 months ago

Cosmopoeia currently treats the world as if it were flat. While a flat world in fantasy is possible, it should also be able to treat the world as if it were a sphere. I've already got it "wrapping" around to the east and west if the extents go far enough. The bigger problem is the classic projection issue: cosmopoeia creates more detailed, smaller tiles closer to the poles than at the equator. While it looks okay on a equirectangular map, if you try to show the world in a more equal-area projection, it starts looking weird at the poles.

I feel that fixing this may be an easier task than it sounds, but still not that easy. Some of it may just fall into place with a few changes, others may require rewriting a few well-known algorithms. Here are the steps:

NOTE: I don't know how to figure out the spacing for sphere mode given an expected tile count. My attempts to solve this problem have devolved into calculus, and would require a bunch more time to figure it out than I should spend on that. It would be better to start at a spacing interval (latitudinal spacing only). At best I could run a guessing game algorithm to find a spacing that provides the right number of tiles.

The rest of the steps describe how things will work if flat mode is off, sometimes referred to as sphere mode.

nms-scribe commented 8 months ago

Okay, I'm putting this here because I think I feel like an idiot regarding that NOTE above about calculating the spacing of tiles. The answer seems simple. I'd like to point out that I'm assuming a spherical world, not a spheroid or geoid shape. This simplifies calculations, but also represents the fact that the worlds are not going to be exactly earth-like.

1) Calculate the area of the map on the sphere. This is not difficult math: there are formulas out there for calculating the area of a "cap" of a sphere above a certain latitude. Use those to subtract the area north and south of the map. Then, get the area of the remaining east-west bounds by finding it as a fraction of the total remaining area. The fraction is basically just the width in degrees divided by 360.

2) Divide that area up by the number of tiles desired.

3) The square root of that number is what I'll call metrical spacing. This can be converted easily into longitude and latitude degrees based on known formula. The number of metrical units in a degree of latitude is static. The number of metrical units in a degree of longitude can be calculated based on available formulas.

Since the area is calculated in meters (or whatever) before dividing by the number of tiles, it's already been projected onto a sphere. The third step "unprojects" this back into the coordinates.

nms-scribe commented 8 months ago

NOTE: Some future programmer might want to consider using an ellipsoidal shape. This is not as easy as you'd think, the distance algorithm for that is complex and requires iterating (http://www.movable-type.co.uk/scripts/latlong-vincenty.html, although it sounds like there are better algorithms). That is another reason I'll choose spherical for this.

I did check, and gdal doesn't support distances and other calculations based on CRS. There is a library called GeographicLib that does this stuff, and a rust wrapper around it (https://docs.rs/geographiclib/latest/geographiclib/), if I ever do want to support elipsoids.

nms-scribe commented 8 months ago

Some algorithms for geometry on spherical surface. This stuff gives me distance and bearing, at least. I still need area for a polygon: http://www.movable-type.co.uk/scripts/latlong.html

nms-scribe commented 8 months ago

This is complete as --world-shape sphere. Although in that mode the precipitation really slows down, and terrain building creates a lot more ocean (the latter might cause the former). But the results look nice. I'm going to create a new issue to deal with spherical delaunay. That may help things out a bit.