Домашнє завдання 1 - ViriAldi/HomeworkCycle2020 GitHub Wiki

Цикл домашніх завдань буде присвячено створенню універсальної програми для роботи з ландшафтом планети Земля.

Функціонал програми повинен включати вирішення наступніх проблем:

  • Точне визначення висоти над рівнем моря точки, заданої географічними координатами.
  • Побудова та інтерактивна візуалізація ландшафту місцевості, заданої сферичним прямокутником, з можливістю вибору його розмірів, положення на земній кулі, точності розрахунків, стилю візуалізації.
  • Визначення найкоротшого шляху між 2-ма точками земної поверхні з урахуванням ландшафту. * Розрахунок та візуалізація оптичного пейзажу з будь-якої точки земної кулі.
  • Створення інтерактивної тривимірної карти ландшафту, що оновлюється разом із положенням користувача.

Ці проблеми актуальні й не завжди мають розв'язки з достатньою точністю у наш час.

Достойне розв'язання цих проблем принесло б цінні результати в наступні сфери:

  • Будівництво
  • Гірський туризм
  • Навігація
  • Допомога людям з вадами зору
  • Логістика
  • Транспорт
  • Data Sience
  • Топологія, Геодезія
  • Авіація

Визначення висоти точки земної поверхні за географічними координатами - використовується у наш час для топології, навігації, тощо. Багато сучасних систем навігації (і у додатку Google Maps теж) активно використовують цю можливість. Під питанням стоїть точність такого визначення, тому програма має орієнтуватись на це.

Побудова та візуалізація ландшафту місцевості - означає визначення координат множини точок поверхні у тривимірному просторі і створення структури даних, яка б забезпечувала зв'язок між точками поверхні та можливість приблизного відтворення реального земного ландшафту. До того ж ця можливість може допомогти орієнтуватись в просторі людям з вадами зору.

Визначення найкоротшого шляху - актуальна проблема транспорту, логістики, туризму, будівництва. Найкоротший шлях по ландшафту не відповідає прямій лінії, а параметри цього шляху (максимальний нахил, тощо) мають задаватись користувачем.

Реалізація розв'язку поставлених проблем

Задля реалізації точних розвязків цих проблем, я буду використовувати різноманітні датасети з географічними даними. Зокрема основним з них є National Evaluation Data - набір даних про висоту над рівнем моря точок земної поверхні з кроком 30 метрів. Дані представлення у вигляді різних .tiff файлів для різних регіонів світу. Сумарний об'є даних сягатиме декілька сотень Мб.

Для роботи з даними в такому форамті потрібно здійснити наступні кроки:

  1. Отримати доступ до даних на спеціальному ресурсі Earth Explorer (процес подібний до отримання ключа до API)
  2. Завантажити дані на носій інформації (жосткий або твердотільний диск)
  3. Відкрити ці дані у Python програмі за допомогою інструментів модуля pillow
  4. Сконвертувати ці дані у двовимірний масив за допомогою модуля numpy
  5. Отриманий двовимірний масив - матриця висот з рівним ходом географічних координат

Для опрацювання даних їх варто зберегти у спеціальну структуру даних, з якою буде легко працювати в процесі вирішення поставлених проблем.

Приклад використання даних для побудови тривимірної поверхні ландшафту

Імпорт потрібних бібліотек

from PIL import Image
import numpy
from mpl_toolkits import mplot3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

Відкриття і конвертування даних

def read_data(path):

    im = Image.open(path)
    imarray = numpy.array(im)
    imarray = imarray.T

    return imarray

Реалізація функції обчислення висоти

def get_elevation(coord, corner_long, corner_lat, grid):

    lat, long = coord

    ind_lon = int(3 * abs(corner_long - long) // 0.00250)
    ind_lat = int(3 * abs(corner_lat - lat) // 0.00250)

    return grid[ind_lon][ind_lat]

Обчислення даних для візуалізації

def create_plot_data(coord, size, corner_coord, grid):

    # creating arrays with coordinates
    coords_x = np.array([x + 0.00083333 * i 
                for i in range(-size, size + 1)] * (2 * size + 1))
    coords_y = np.array([y + 0.00083333 * i for i in range(-size, size + 1) 
                for j in range(2 * size + 1)])
    coords_z = np.array([2 * get_elevation(t, corner_coord, grid) 
                for t in zip(coords_x, coords_y)])

    # scaling coordinates
    coords_x = coords_x * 120000
    coords_y = coords_y * 100000

    # creating 2D arrays
    coords_x.resize(2 * size + 1, 2 * size + 1)
    coords_y.resize(2 * size + 1, 2 * size + 1)
    coords_z.resize(2 * size + 1, 2 * size + 1)

    return (coords_x, coords_y, coords_z)

Реалізація візуалізації

def vizualize(plot_data):
    X, Y, Z = plot_data

    ax = plt.axes(projection='3d')
    ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, linewidth=0, antialiased=False, rcount = 500, ccount = 500)

    # Create cubic bounding box to simulate equal aspect ratio
    max_range = np.array([X.max()-X.min(), Y.max()-Y.min(), Z.max()-Z.min()]).max()
    Xb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][0].flatten() + 0.5*(X.max()+X.min())
    Yb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][1].flatten() + 0.5*(Y.max()+Y.min())
    Zb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][2].flatten() + 0.5*(Z.max()+Z.min())

    for xb, yb, zb in zip(Xb, Yb, Zb):
        ax.plot([xb], [yb], [zb], 'w')

    plt.grid()
    plt.show()

Робота програми на конкретному прикладі:

if __name__ == "__main__":
    x, y = [47.5, 7.5]
    size = 40
    grid = read_data("srtm_38_03.tif")
    plot_data = create_plot_data((x, y), size, (50, 5), grid)

    vizualize(plot_data)

Результат (гора Mont Blanc)

Вимоги на систему

  • Спонсор проєкту

Я ініціатор проєкту

  • Бізнес потреба

Покращити доступ до інформації

  • Бізнес вимоги

Ресурс для роботи з ландшафтом землі. Зокрема моделювання і візуалізація ландшафту

  • Питання та обмеження

Граничний термін - 25 травня. Програма - самостійний, унікальний та універсальний ресурс