Zero Block
Click "Block Editor" to enter the edit mode. Use layers, shapes and customize adaptability. Everything is in your hands.
Tilda Publishing
create your own block from scratch
Zero Block
Click "Block Editor" to enter the edit mode. Use layers, shapes and customize adaptability. Everything is in your hands.
Tilda Publishing
create your own block from scratch
Скрипт для перевірки зон доставки
Автори скрипта і інструкції - @fibiku та @nastyanastyanastnastya
Що робить цей скрипт:

1. Перевіряє, чи є на карті елементи з кількома тегами
2. Перевіряє, чи є на карті кілька блоків вкладених координат
3. Перевіряє, чи є на карті перетин зон
Як користуватись?
Тут є два варіанти:
Перший - просто використати онлайн компілятор (наприклад Jupiter Notebook). Якщо вибрали цей варіант - переходимо одразу до блоку "Скрипт"

Другий - встановити все потрібне на свій робочий комп'ютер за інструкцією нижче:
1. Переходимо за посиланням на карту
2. Натискаємо на три крапки (меню) → “Експортувати у KML/KMZ”. (вибирати тільки другу галочку)
3. Завантажуємо файл
4. Конвертуємо його у GeoJSON через https://mapshaper.org або інші онлайн-конвертори.
5. Встановлюємо Pyton (можна встановити через дефолтний Microsoft Store, який є по дефолту в Windows 10 та Windows 11)
6. Переходимо в компілятор (для коректності будемо використовувати vs code)
7. В значення path_to_geojson вказуємо повний шлях до файлу карти
Приклад: path_to_geojson = r"C:\Users\Syrve_Lviv\Downloads\КАРТА САЙТ 08.07 (1) (1).kml"
8. Виконуємо скрипт
Скрипт
import geopandas as gpd
from shapely.geometry import MultiPolygon
import xml.etree.ElementTree as ET
import re
import requests
from io import BytesIO
import numpy as np
from shapely.geometry import Polygon

# 🔁 ЗАМІНИ ШЛЯХ ДО СВОГО ФАЙЛУ НИЖЧЕ - використовуй повний шлях до файлу
path_to_geojson = r"C:\Users\Syrve_Lviv\Downloads\КАРТА САЙТ 08.07 (1) (1).kml"
# Або використовуй пряме посилання на KML файл з Google My Maps
# kml_url = "https://your-google-map-url.com/kml"

# Функція для перевірки KML файлу на проблеми з полігонами
def check_kml_polygons(kml_path_or_url):
    # Завантаження KML
    if kml_path_or_url.startswith('http'):
        response = requests.get(kml_path_or_url)
        kml_content = response.content
    else:
        with open(kml_path_or_url, 'rb') as f:
            kml_content = f.read()
    
    # Парсинг KML
    root = ET.fromstring(kml_content)
    
    # Пошук всіх просторів імен у KML
    namespaces = {'kml': 'http://www.opengis.net/kml/2.2'}
    
    # Знаходження всіх Placemarks
    placemarks = root.findall('.//kml:Placemark', namespaces)
    
    multi_polygon_issues = []
    inner_boundary_issues = []
    
    for placemark in placemarks:
        name_elem = placemark.find('./kml:name', namespaces)
        name = name_elem.text if name_elem is not None else "Безіменна зона"
        
        # Перевірка на кілька тегів Polygon
        polygons = placemark.findall('.//kml:Polygon', namespaces)
        if len(polygons) > 1:
            multi_polygon_issues.append(name)
        
        # Перевірка на innerBoundaryIs
        for polygon in polygons:
            inner_boundaries = polygon.findall('.//kml:innerBoundaryIs', namespaces)
            if inner_boundaries:
                inner_boundary_issues.append(name)
                break
    
    return multi_polygon_issues, inner_boundary_issues

# Функція для перевірки реальних перетинів, ігноруючи дотики
def check_real_intersections(gdf):
    intersections = set()
    for i, row1 in gdf.iterrows():
        for j, row2 in gdf.iterrows():
            if i < j:
                # Перевіряємо чи є реальний перетин (а не просто дотик)
                if row1.geometry.intersects(row2.geometry):
                    intersection = row1.geometry.intersection(row2.geometry)
                    # Перевіряємо, чи перетин має площу (не є просто точкою або лінією)
                    if not intersection.is_empty and intersection.area > 1e-10:
                        intersections.add((row1['name'], row2['name']))
    return intersections

# Перевірка KML файлу
try:
    multi_polygon_issues, inner_boundary_issues = check_kml_polygons(path_to_geojson)
    
    if multi_polygon_issues or inner_boundary_issues:
        print("🔴 Виявлено проблеми з структурою KML:")
        
        if multi_polygon_issues:
            print("\nЗони з кількома тегами <Polygon> (потрібно розділити на окремі фігури):")
            for name in multi_polygon_issues:
                print(f" - {name}")
        
        if inner_boundary_issues:
            print("\nЗони з тегами <innerBoundaryIs> (потрібні лише <outerBoundaryIs>):")
            for name in inner_boundary_issues:
                print(f" - {name}")
        
        print("\nРекомендація: Перемалюйте ці зони в Google My Maps.")
    else:
        print("✅ Структура KML коректна - немає проблем з Polygon та innerBoundaryIs.")
        
    # Завантаження файлу як GeoDataFrame
    try:
        # Спробуємо спочатку як KML
        gdf = gpd.read_file(path_to_geojson, driver='KML').to_crs(epsg=4326)
        print("✅ Файл KML успішно завантажено.")
    except Exception as e:
        print(f"Помилка при завантаженні як KML: {e}")
        print("Спробуємо завантажити як GeoJSON...")
        try:
            # Якщо не вдалося як KML, спробуємо як GeoJSON
            gdf = gpd.read_file(path_to_geojson).to_crs(epsg=4326)
            print("✅ Файл GeoJSON успішно завантажено.")
        except Exception as e:
            print(f"Помилка при завантаженні файлу: {e}")
            print("Переконайтеся, що шлях до файлу правильний і файл має коректний формат.")
            exit(1)
    
    # Розпаковка MultiPolygon у Polygon
    records = []
    for idx, row in gdf.iterrows():
        geom = row.geometry
        # Перевірка на наявність колонки 'name'
        name_col = None
        for col in gdf.columns:
            if col.lower() == 'name':
                name_col = col
                break
        
        name = row.get(name_col, f"zone_{idx}") if name_col else f"zone_{idx}"
        
        if isinstance(geom, MultiPolygon):
            for poly in geom.geoms:
                records.append({'name': name, 'geometry': poly})
        else:
            records.append({'name': name, 'geometry': geom})
    
    flat_gdf = gpd.GeoDataFrame(records, crs="EPSG:4326")
    
    # Перевірка реальних перетинів, ігноруючи дотики
    intersections = check_real_intersections(flat_gdf)
    
    # Вивід результатів
    if intersections:
        print("\n🔴 Виявлено перетини між зонами:")
        for a, b in sorted(intersections):
            print(f" - {a} перетинається з {b}")
    else:
        print("\n✅ Перетинів між зонами не виявлено.")
        
    # Додаткова перевірка для виявлення просто дотиків
    touching = set()
    for i, row1 in flat_gdf.iterrows():
        for j, row2 in flat_gdf.iterrows():
            if i < j:
                if row1.geometry.touches(row2.geometry):
                    touching.add((row1['name'], row2['name']))
    
    if touching:
        print("\nℹ️ Виявлено зони, які дотикаються (це нормально):")
        for a, b in sorted(touching):
            print(f" - {a} дотикається до {b}")
        
except Exception as e:
    print(f"Загальна помилка: {e}")
    print("Перевірте шлях до файлу та його формат.")
Можлива проблема
У разі, якщо при запуску скрипту вибиває, що не вистачає якоїсь бібліотеки - додатково встановлюємо їх скриптом
Для цього, в вікні терміналу по черзі виконуємо наступні команди:
pip install geopandas
pip install shapely
pip install requests
pip install numpy