Files
dbstorage/dbapp/fix_objitems_without_source.py

128 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Скрипт для исправления ObjItems без связи с Source.
Для каждого ObjItem без source:
1. Получить координаты из geo_obj
2. Найти ближайший Source (по coords_average)
3. Если расстояние <= 0.5 градуса, связать ObjItem с этим Source
4. Иначе создать новый Source с coords_average = координаты geo_obj
"""
# import os
# import django
# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dbapp.settings")
# django.setup()
# from mainapp.models import ObjItem, Source, CustomUser
# from django.contrib.gis.geos import Point
# from django.contrib.gis.measure import D
# from django.contrib.gis.db.models.functions import Distance
# def calculate_distance_degrees(coord1, coord2):
# """Вычисляет расстояние между двумя координатами в градусах."""
# import math
# lon1, lat1 = coord1
# lon2, lat2 = coord2
# return math.sqrt((lon2 - lon1) ** 2 + (lat2 - lat1) ** 2)
# def fix_objitems_without_source():
# """Исправляет ObjItems без связи с Source."""
# # Получаем пользователя по умолчанию
# default_user = CustomUser.objects.get(id=1)
# # Получаем все ObjItems без source
# objitems_without_source = ObjItem.objects.filter(source__isnull=True)
# total_count = objitems_without_source.count()
# print(f"Найдено {total_count} ObjItems без source")
# if total_count == 0:
# print("Нечего исправлять!")
# return
# fixed_count = 0
# new_sources_count = 0
# for objitem in objitems_without_source:
# # Проверяем, есть ли geo_obj
# if not hasattr(objitem, 'geo_obj') or not objitem.geo_obj or not objitem.geo_obj.coords:
# print(f"ObjItem {objitem.id} не имеет geo_obj или координат, пропускаем")
# continue
# geo_coords = objitem.geo_obj.coords
# coord_tuple = (geo_coords.x, geo_coords.y)
# # Ищем ближайший Source
# sources_with_coords = Source.objects.filter(coords_average__isnull=False)
# closest_source = None
# min_distance = float('inf')
# for source in sources_with_coords:
# source_coord = (source.coords_average.x, source.coords_average.y)
# distance = calculate_distance_degrees(coord_tuple, source_coord)
# if distance < min_distance:
# min_distance = distance
# closest_source = source
# # Если нашли близкий Source (расстояние <= 0.5 градуса)
# if closest_source and min_distance <= 0.5:
# objitem.source = closest_source
# objitem.save()
# print(f"ObjItem {objitem.id} связан с Source {closest_source.id} (расстояние: {min_distance:.4f}°)")
# fixed_count += 1
# else:
# # Создаем новый Source
# new_source = Source.objects.create(
# coords_average=Point(coord_tuple, srid=4326),
# created_by=default_user
# )
# objitem.source = new_source
# objitem.save()
# print(f"ObjItem {objitem.id} связан с новым Source {new_source.id}")
# fixed_count += 1
# new_sources_count += 1
# print(f"\nГотово!")
# print(f"Исправлено ObjItems: {fixed_count}")
# print(f"Создано новых Source: {new_sources_count}")
# if __name__ == "__main__":
# fix_objitems_without_source()
from geographiclib.geodesic import Geodesic
def calculate_mean_coords(coord1: tuple, coord2: tuple) -> tuple[tuple, float]:
"""
Вычисляет среднюю точку между двумя координатами с использованием геодезических вычислений (с учётом эллипсоида).
:param lat1: Широта первой точки в градусах.
:param lon1: Долгота первой точки в градусах.
:param lat2: Широта второй точки в градусах.
:param lon2: Долгота второй точки в градусах.
:return: Словарь с ключами 'lat' и 'lon' для средней точки, и расстояние(dist) в КМ.
"""
lon1, lat1 = coord1
lon2, lat2 = coord2
geod_inv = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
azimuth1 = geod_inv['azi1']
distance = geod_inv['s12']
geod_direct = Geodesic.WGS84.Direct(lat1, lon1, azimuth1, distance / 2)
return (geod_direct['lon2'], geod_direct['lat2']), distance/1000
# Пример использования
lat1, lon1 = 56.15465080269812, 38.140518028837285
lat2, lon2 = 56.0852, 38.0852
midpoint = calculate_mean_coords((lat1, lon1), (lat2, lon2)) #56.15465080269812, 38.140518028837285
print(f"Средняя точка: {midpoint[0]}")
print(f"Расстояние: {midpoint[1]} км")