marceloprates / prettymaps

A small set of Python functions to draw pretty maps from OpenStreetMap data. Based on osmnx, matplotlib and shapely libraries.
GNU Affero General Public License v3.0
11.12k stars 522 forks source link

Rendering coastline #47

Closed G21-Goose closed 3 years ago

G21-Goose commented 3 years ago

I believe this fixes the issue in #7 . It's difficult to get polygons for the coastline as the polygons will be extremely large and may in some cases have errors (as mentioned on the OSM wiki). The smaller closed polygons with repaired coastlines from OSMCoastline is made available here.

The water-polygons-split-4326.zip file is 738MB and the extracted .shp file is about 1GB.

A coastline layer can be used to point to the extracted water_polygons.shp file (using the file_location key) along while using a buffer to ensure the polygons are included (this file needs to be downloaded first). The large buffer does not seem to add that much extra time to the processing as the file is already downloaded.

'coastline':{
    'file_location':'./water-polygons-split-4326/water-polygons-split-4326/water_polygons.shp',
    'buffer':100000,
    'circle':False
},

Before this change the map for Eureka, California would look like: image

and after it looks like: image

In both these examples I also have water layer as the coastline data does not rivers and bays etc:

'water': {
    'tags':{
        'waterway': True,
        'water': True,
        'harbour': True,
        'marina': True,
        'bay': True,
        'river': True
    },
    'dilate':100
},
hanksims commented 3 years ago

Oh, super. I made a couple of halfhearted attempts to plot shapefiles without success -- so happy you've made a solution.

hanksims commented 3 years ago

I'm not sure why I'm not able to get the water to go right up to the border of the map, as you have done. It clips thusly:

eureka2

Here's my full eureka.py:

import vsketch
from prettymaps import *
import matplotlib.font_manager as fm
from matplotlib import pyplot as plt

palette = ['#433633', '#FF5E5B']
background_c = '#F2F4CB'
dilate = 100

# Setup figure
fig, ax = plt.subplots(figsize = (10, 10), constrained_layout = True)

# Plot
layers = plot(
    (40.8045835,-124.1669452), radius = 1500,
    ax = ax,
    layers = {
        'perimeter': {'circle': False, 'dilate': dilate},
        'streets': {
            'width': {
                'primary': 5,
                'secondary': 4,
                'tertiary': 3,
                'residential': 2,
                'footway': 1,
            },
            'circle': False,
            'dilate': dilate
        },
        'building': {
            'tags': {'building': True},
            'union': False,
            'circle': False,
            'dilate': dilate
        },
        'green': {
            'tags': {
                'landuse': ['grass', 'village_green'],
                'leisure': 'park'
            },
            'circle': False,
            'dilate': dilate
        },
       'coastline': {
            'file_location':'../osm-water-polygon/water-polygons-split-4326/water_polygons.shp',
            'buffer': 100000,
            'circle': False
        },
    },

    drawing_kwargs = {
        'background': {'fc': '#F2F4CB', 'ec': '#dadbc1', 'hatch': 'ooo...', 'zorder': -1},
        'perimeter': {'fill': False, 'lw': 3, 'zorder': 0},
        'green': {'fc': '#8BB174', 'ec': '#2F3737', 'hatch_c': '#A7C497', 'hatch': 'ooo...', 'lw': 1, 'zorder': 1},
        'water': {'fc': '#a8e1e6', 'ec': '#2F3737', 'hatch_c': '#9bc3d4', 'hatch': 'ooo...', 'lw': 1, 'zorder': 3},
        'coastline': {'fc': '#a8e1e6', 'ec': '#2F3737', 'hatch_c': '#9bc3d4', 'hatch': 'ooo...', 'lw': 1, 'zorder': 3},
        'streets': {'fc': '#2F3737', 'ec': '#475657', 'alpha': 1, 'lw': 0, 'zorder': 4},
        'building': {'palette': palette, 'ec': '#2F3737', 'lw': .5, 'zorder': 5},
    },
    osm_credit = False,
)

# Set bounds
xmin, ymin, xmax, ymax = layers['perimeter'].bounds
dx, dy = xmax-xmin, ymax-ymin
ax.set_xlim(xmin-.06*dx, xmax+.06*dx)
ax.set_ylim(ymin-.06*dy, ymax+.06*dy)

# Draw left text
ax.text(
    xmin-.06*dx, ymin+.5*dy,
    'Eureka, California',
    color = '#2F3737',
    rotation = 90,
    fontproperties = fm.FontProperties(fname = 'PermanentMarker-Regular.ttf', size = 35),
)

plt.savefig('eureka.png')
plt.savefig('eureka.svg')
G21-Goose commented 3 years ago

If you remove dilate from the perimeter layer you should be able to get it going up to the edge, but it will have sharp edges. I think if you add dilate to the coastline layer it should go to the edges but be more rounded.

dilate removed from the perimeter layer image

dilate set for the coastline layer image

hanksims commented 3 years ago

This was correct. Thank you.