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("Перевірте шлях до файлу та його формат.")