Простой Python. Современный стиль программирования (Любанович) - страница 250

>ne_110m_admin_1_states_provinces_shp.README.html

>ne_110m_admin_1_states_provinces_shp.sbn

>ne_110m_admin_1_states_provinces_shp.VERSION.txt

>ne_110m_admin_1_states_provinces_shp.sbx

>ne_110m_admin_1_states_provinces_shp.dbf

>ne_110m_admin_1_states_provinces_shp.shp

>ne_110m_admin_1_states_provinces_shp.prj

>ne_110m_admin_1_states_provinces_shp.shx

Мы будем использовать эти файлы в наших примерах.

Нарисуем карту

Для прочтения шейп-файла вам понадобится эта библиотека:

>$ pip install pyshp

Теперь введите текст программы, map1.py, который я модифицировал из статьи в блоге Geospatial Python (http://bit.ly/raster-shape):

>def display_shapefile(name, iwidth=500, iheight=500):

>····import shapefile

>····from PIL import Image, ImageDraw

>····r = shapefile.Reader(name)

>····mleft, mbottom, mright, mtop = r.bbox

>····# map units

>····mwidth = mright — mleft

>····mheight = mtop — mbottom

>····# scale map units to image units

>····hscale = iwidth/mwidth

>····vscale = iheight/mheight

>····img = Image.new("RGB", (iwidth, iheight), "white")

>····draw = ImageDraw.Draw(img)

>····for shape in r.shapes():

>········pixels = [

>············(int(iwidth — ((mright — x) * hscale)), int((mtop — y) * vscale))

>············for x, y in shape.points]

>········if shape.shapeType == shapefile.POLYGON:

>············draw.polygon(pixels, outline='black')

>········elif shape.shapeType == shapefile.POLYLINE:

>············draw.line(pixels, fill='black')

>····img.show()

>if __name__ == '__main__':

>····import sys

>····display_shapefile(sys.argv[1], 700, 700)

Эта программа считывает шейп-файл и проходит по отдельным фигурам. Я ищу только два типа фигур: многоугольник, который соединяет последнюю точку с начальной, и ломаную линию, которая этого не делает. Я строил свою логику на основе оригинальной статьи и беглого просмотра документации pyshp, поэтому вполне уверен в том, что знаю, как работает программа. Иногда вам просто нужно начать и затем справляться с возникающими проблемами.

Запустим наш код. Аргументом станет базовое имя для шейп-файла, не содержащее расширения:

>$ python map1.py ne_110m_admin_1_states_provinces_shp

Вы должны увидеть что-то похожее на рис. Б.1.


Рис. Б.1. Предварительная карта


Что ж, программа нарисовала карту, которая напоминает Соединенные Штаты, но:

• между Аляской и Гавайями видим что-то вроде растрепанных кошкой ниток — это баг;

• страна сплющена, а мне нужна проекция;

• картинка не очень красивая — мне нужно задать стиль.

По поводу первого пункта: в логике программы есть ошибка, но что мне делать? В главе 12 рассматриваются советы для разработчиков, включая информацию об отладке, но мы можем рассмотреть и другие варианты. Я мог бы написать несколько тестов и работать, пока не исправлю ошибку, или же могу применить какую-нибудь другую библиотеку для создания карты. Возможно, более высокоуровневое решение поможет мне справиться со всеми тремя проблемами (лишние линии, сплющенный вид и примитивный стиль).