Making ocean and land sectors

Here are instruction for making the spherical tiling (tessellation) of planet surface in general and the ocean and land tiling in particular.

We need data of one of the planets (lands and riversz shapefiles). And we need
SQL script that will do all the work.

In the end we will obtain a set of polygons that completely or partially covers the spherical surface of the planet. In the case of land tiles, we will take into account natural features of the land (currently, only the rivers). In addition to polygons, the script main functions produce graphs of possible transitions between sectors (.dbf files, for the ocean and lands separately).

Data preparation

The following commands suggest default PostgreSQL+PostGIS installation. riversz and lands shapefiles should be fetched from this site or they must contain data with similar structure.

Firstly, we prepare the import SQL files (here we use map schema for planet map data):

shp2pgsql -s 3785 -d -D -I -t 2D -N skip riversz.shp /
    map.rivers > rivers.sql
shp2pgsql -s 3785 -d -D -I -N skip lands.shp /
    map.lands > lands.sql

Next we should create a database. Here we use planet for database name.

createdb --host=localhost --port=5432 --username=postgres \
    --echo --template=template0 "planet" "whole planet data"

Script sectors.sql must be evaluated first. After that we import the data.

psql --host=localhost --port=5432 --username=postgres /
    --dbname=planet --echo-errors --file=sectors.sql
psql --host=localhost --port=5432 --username=postgres /
    --dbname=planet --echo-errors --file=rivers.sql
psql --host=localhost --port=5432 --username=postgres /
    --dbname=planet --echo-errors --file=lands.sql

Optional step. Some GISes (mapnik) require explicit integer fields for feature ids.

ALTER TABLE map.lands ALTER COLUMN fid TYPE BigInt;
ALTER TABLE map.lands ALTER COLUMN aid TYPE BigInt;
ALTER TABLE map.rivers ALTER COLUMN fid TYPE BigInt;
ALTER TABLE map.rivers ALTER COLUMN lmid TYPE BigInt;

All preparations done.

PostgreSQL configuration

If you intend to use large geometry data like planet data from this site, then you need to make changes to PostgreSQL database configuration.

Look into PostGIS Performance Tips to understand what to do.

Synopsis

Script sectors.sql has two main functions for creating ocean and land tiles. Let us examine in detail their specifications.

ocean sectors

map.makeOceanSectors(
    world Geometry,
    avg_vp_areaKM Double Precision,
    merging_ratio Double Precision,
    merging_method Int
    ) RETURNS Void

world is any valid polygon which will be the border of the world.
avg_vp_areaKM is average area (km2) of small polygons from which ocean sectors will be constructed. This area can be affected by is_whole_planet.
merging_ratio defines a share of avg_vp_areaKM, such that if the sector is smaller than it, it will be merged with a neighboring sector.

Example. Following will generate ocean tiles in the defined polygon with average
size of 1000000 km2, merge small sectors if their size less then half
of average size, using ‘second’ merging method and taking into account
only the specified world polygon for calculating the number of voronoi polygons.

SELECT * FROM map.makeOceanSectors( ST_GeomFromText(
    'POLYGON((-75 -85, 75 -85, 75 85, -75 85, -75 -85))', 4326 ),
    1000000, 0.5, 2
);

Currently, only two merging methods available: ‘1’ is merging by the longest edge, ‘2’ is merging by the closest center.

land sectors

map.makeLandSectors(
    aid BigInt,
    avg_vp_areaKM Double Precision,
    avg_sector_areaKM Double Precision,
    max_sector_cut_area_ratio Float,
    pref_min_island_area_ratio Float,
    min_streamflow Int
    ) RETURNS Void

aid is area id of a land defined in lands shapefile.
avg_vp_areaKM is average area (km2) of small polygons from which land sectors will be constructed.
avg_sector_areaKM is average area (km2) of result sectors to be constructed.
max_sector_cut_area_ratio defines share of avg_sector_areaKM as maximum area which can be cut by the river.
pref_min_island_area_ratio defines share of avg_sector_areaKM as minimum area which an island must have in order to become a sector right away, regardless of the distance to the mainland.
Only rivers with the streamflow not less then min_streamflow will be used for sectors cutting.

Example. Following will generate land tiles within the specified land (aid=5) with average voronoi polygon size of 5000 km2, with average sector size of 40000 km2, with maximum area of 0.125*40000 km2 which can be cut by rivers, with minimum area of 0.25*40000 km2 intended for independent sector islands, using only rivers with minimum streamflow of 2 for sectors cutting.

SELECT * FROM map.makeLandSectors(5, 5000, 40000, 0.125, 0.25, 2);

Remarks

The exemplary results can be viewed on the sample planets on this site. Shapefiles with these results can be downloaded from the planet data pages.

You should carefully reduce the average area of voronoi polygons, since calculations with small areas can be very long. See also the section on database configuration.

The current version of the script does not make territory around the poles as one sector. Because the desired circle coverage is not a valid geometry in the Mercator projection, which is a working projection for mapnik.

SELECT ST_IsValid(ST_Transform(ST_GeomFromText(
    'POLYGON((-180 75, -90 75, 0 75, 90 75, -180 75))', 4326 ), 3785));
> False

But separate parts of this circle can be made valid with a small offset from the pole

SELECT ST_IsValid(ST_Transform(ST_GeomFromText(
    'POLYGON((-180 75, -90 75, 0 75, -90 89.9999, -180 75))', 4326), 3785));
> True
SELECT ST_IsValid(ST_Transform(ST_GeomFromText(
    'POLYGON((0 75, 90 75, 180 75, 90 89.9999, 0 75))', 4326), 3785));
> True

Perhaps there should be an option for choosing between these variants.

Since some of the PostGIS functions do not work correctly (ST_Split), narrow gaps can be formed between the polygons. To eliminate them, when combining geometries by ST_Union function, we usually make the geometry wider by using ST_Buffer with 1 meter buffer size. This also leads to a lower limit on the area of the base polygons.

We use MULTIPOLYGON geometry type for the resulting sectors, because they can consist of separate parts.