Osmose/Combining results externally

From OpenStreetMap Wiki
Jump to navigation Jump to search

Matching different types of issues by distance

Sometimes you want to find issues of one type which are near to any issues of another type. Example. Run this code on your computer to download the issues for a specific area and do this kind of filtering.

#! /usr/bin/env python3

# Usage example:
#
#   Paste into `this_file.py`, then do:
#
#   $ python3 -i this_file.py
#   >>> max_distance = 0.005
#   >>>
#   >>> bbox_italy_NE = '9.664110533640269%2C45.18127164811838%2C13.564257018015269%2C47.09556621577258'
#   >>> # How to get the value to put in this variable:
#   >>> # Look at the area in Osmose, then copy the `&bbox=` from the address.
#   >>>
#   >>> issues_italy_NE_7150 = issues(7150, bbox_italy_NE)
#   >>> issues_italy_NE_8210 = issues(8210, bbox_italy_NE)
#   >>> for issue1, issue2 in issues_near_each_other(issues_italy_NE_7150, issues_italy_NE_8210, max_distance):
#   ...     print(url_to_view_issue(issue1))
#   ... 


import json
import math
from typing import Any
import urllib.request


Issue = dict[str, Any]
"""
To be redefined as typing.TypedDict.
Fields:
    - "lat": float
    - "lon": float
    - "id": str
    - other fields returned by the Osmose API
"""


def url_to_download_issues(item: int, bbox: str) -> str:
    return (
        'https://osmose.openstreetmap.fr/api/0.3/issues'
        f'?zoom=9&item={item}&level=1%2C2%2C3&limit=500'
        f'&bbox={bbox}'
    )


def issues(item: int, bbox: str) -> list[Issue]:
    with urllib.request.urlopen(url_to_download_issues(item, bbox)) as f:
        risposta = f.read()
    issues = json.loads(risposta.decode('utf-8'))['issues']
    print(f"For the item {item}, {len(issues)} issues have been downloaded.")
    return issues


def distance(s1: Issue, s2: Issue) -> float:
    return math.sqrt(
        (s1["lat"] - s2["lat"]) ** 2
        + (s1["lon"] - s2["lon"]) ** 2
    )


def issues_near_each_other(
    list_1: list[Issue],
    list_2: list[Issue],
    max_distance: float,
) -> list[tuple[Issue, Issue]]:
    result = []

    for issue_1 in list_1:
        for issue_2 in list_2:
            if distance(issue_1, issue_2) < max_distance:
                result.append((issue_1, issue_2))

    return result


def url_to_view_issue(s: Issue) -> str:
    return (
        'https://osmose.openstreetmap.fr/en/map/'
        '#item=2100%2C7150%2C8210%2C8211%2C8212'
        '&zoom=17'
        '&level=1%2C2%2C3'
        f'&loc=17/{s["lat"]}/{s["lon"]}'
        f'&issue_uuid={s["id"]}'
    )