Огромное спасибо кодерам под никами:
evsegn и Armageddonist
Описание:
Эта программа - инструмент для измерения расстояния между множеством координат (широта, долгота) на карте. Пользователь может добавлять координаты в список, а программа будет автоматически рассчитывать расстояния между каждой парой координат и отображать их на графике
Исходный код программы:
И нет, я не буду выкладывать .bat, детишки сразу испугаются и побегут плакать модераторам((
Появиться желание - разберётесь как экспортировать данный код.
P.s. Python 3.11, PyQt5
Но не стоит расстраиваться, так же запустили онлайн карту с тем же функционалом что и в программе.
Работает на любом устройстве с веб-браузером.
Отсутствие необходимости установки: открывается прямо в браузере.
Использование OpenStreetMap: бесплатные и открытые картографические данные.
Широкий функционал: линейка, добавление точек, расчет расстояний и т.д.
Удобный пользовательский интерфейс с контекстным меню.
Функционал:
Линейка (начертит красную линию на карте и тут же обозначит её длинну в метрах)
Добавление по координатам
Кнопка показать моё местоположение на карте работает только после клика и дальнейшего разрешения доступа
Добавление по клику на карте
Массовый импорт точек
(каждая точка в формате "60.002244,30.223344" должна быть с новой строки)
Долгий тап / правый клик покажет контекстное меню с полезностями
Каждая точка имеет порядковый номер, который наглядно виден прямо на карте
Считает расстояние между всеми возможными парами точек на карте
Возможность поделиться ссылкой на ваше состояние карты со всеми точками
evsegn и Armageddonist
Описание:
Эта программа - инструмент для измерения расстояния между множеством координат (широта, долгота) на карте. Пользователь может добавлять координаты в список, а программа будет автоматически рассчитывать расстояния между каждой парой координат и отображать их на графике
Вам нужно зарегистрироваться, чтобы видеть изображения.
Исходный код программы:
Python:
import sys
import math
from geopy.distance import geodesic
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QDoubleSpinBox, QPlainTextEdit, QLabel, QListWidget, QListWidgetItem, QDesktopWidget, QFileDialog
from PyQt5.QtCore import Qt
import datetime
import re
class CoordinateHelper(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("EVSEGN Cord helper")
screen = QDesktopWidget().screenGeometry()
x = (screen.width() - 800) // 2
y = (screen.height() - 800) // 2
self.setGeometry(x, y, 800, 800)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.create_widgets()
def create_widgets(self):
self.main_layout = QVBoxLayout()
self.central_widget.setLayout(self.main_layout)
self.input_layout = QHBoxLayout()
self.main_layout.addLayout(self.input_layout)
self.label = QLabel("Введите координаты (широта, долгота):")
self.input_layout.addWidget(self.label)
self.entry = QLineEdit()
self.input_layout.addWidget(self.entry)
self.distance_threshold_layout = QHBoxLayout()
self.main_layout.addLayout(self.distance_threshold_layout)
self.distance_threshold_label = QLabel("Порог расстояния (м):")
self.distance_threshold_layout.addWidget(self.distance_threshold_label)
self.distance_threshold_spinbox = QDoubleSpinBox()
self.distance_threshold_spinbox.setRange(1, 100)
self.distance_threshold_spinbox.setValue(25)
self.distance_threshold_layout.addWidget(self.distance_threshold_spinbox)
self.add_button = QPushButton("Добавить координаты")
self.add_button.clicked.connect(self.add_coordinate)
self.main_layout.addWidget(self.add_button)
self.import_button = QPushButton("Импорт из файла")
self.import_button.clicked.connect(self.import_coordinates_from_file)
self.main_layout.addWidget(self.import_button)
self.recognize_button = QPushButton("Распознать координаты на фото (В ПРОЦЕССЕ)")
self.main_layout.addWidget(self.recognize_button)
self.coordinates_list_label = QLabel("Добавленные координаты:")
self.main_layout.addWidget(self.coordinates_list_label)
self.coordinates_list = QListWidget()
self.coordinates_list.itemClicked.connect(self.on_item_clicked)
self.main_layout.addWidget(self.coordinates_list)
self.delete_button = QPushButton("Удалить координаты")
self.delete_button.clicked.connect(self.delete_coordinate)
self.main_layout.addWidget(self.delete_button)
self.export_button = QPushButton("Экспортировать в GPX")
self.export_button.clicked.connect(self.export_to_gpx)
self.main_layout.addWidget(self.export_button)
self.fig = Figure(figsize=(10, 6))
self.ax = self.fig.add_subplot(111)
self.canvas = FigureCanvas(self.fig)
self.main_layout.addWidget(self.canvas)
self.coordinates = []
self.distances = {}
def parse_coordinates(self, coord_str):
try:
lat, lon = coord_str.replace(',', ' ').split()
return float(lat), float(lon)
except ValueError:
raise ValueError("Недопустимый формат координат. Используйте 'широта, долгота'")
def calculate_distances(self):
self.distances = {}
for i in range(len(self.coordinates)):
for j in range(i+1, len(self.coordinates)):
start = self.coordinates[i]
end = self.coordinates[j]
distance = geodesic(start, end).m
self.distances[(i, j)] = distance
def draw_map(self):
self.ax.clear()
self.ax.set_xlabel('Долгота')
self.ax.set_ylabel('Широта')
self.ax.set_title('Расстояние между координатами')
for i, (lat, lon) in enumerate(self.coordinates):
self.ax.plot(lon, lat, 'ro', markersize=5)
self.ax.text(lon, lat, f"{i+1}", ha='center', va='center', fontsize=16)
for (i, j), distance in self.distances.items():
start = self.coordinates[i]
end = self.coordinates[j]
line_color = 'r' if distance < self.distance_threshold_spinbox.value() else 'b'
self.ax.plot([start[1], end[1]], [start[0], end[0]], f'{line_color}-')
midx = (start[1] + end[1]) / 2
midy = (start[0] + end[0]) / 2
self.ax.text(midx, midy, f"{distance:.2f} m", ha='center', va='center')
self.canvas.draw()
def add_coordinate(self):
try:
lat, lon = self.parse_coordinates(self.entry.text())
self.coordinates.append((lat, lon))
item = QListWidgetItem(f"{lat}, {lon}")
self.coordinates_list.addItem(item)
self.entry.clear()
self.calculate_distances()
self.draw_map()
except ValueError as e:
print(e)
def delete_coordinate(self):
current_row = self.coordinates_list.currentRow()
if current_row != -1:
self.coordinates_list.takeItem(current_row)
del self.coordinates[current_row]
self.calculate_distances()
self.draw_map()
def on_item_clicked(self, item):
self.coordinates_list.setCurrentItem(item)
def export_to_gpx(self):
if not self.coordinates:
print("Нет координат для экспорта")
return
filename, _ = QFileDialog.getSaveFileName(self, "Экспорт в GPX", "", "GPX files (*.gpx)")
if not filename:
return
with open(filename, "w") as f:
f.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n")
f.write("<gpx xmlns=\"http://www.topografix.com/GPX/1/0\" version=\"1.0\">\n")
f.write(" <trk>\n")
f.write(" <trkseg>\n")
for i, (lat, lon) in enumerate(self.coordinates):
timestamp = datetime.datetime.now() + datetime.timedelta(seconds=i)
timestamp_str = timestamp.strftime("%Y-%m-%dT%H:%M:%SZ")
f.write(f" <trkpt lat=\"{lat}\" lon=\"{lon}\">\n")
f.write(f" <ele>0.0</ele>\n")
f.write(f" <time>{timestamp_str}</time>\n")
f.write(f" </trkpt>\n")
f.write(" </trkseg>\n")
f.write(" </trk>\n")
f.write("</gpx>\n")
print(f"Координаты экспортированы в файл {filename}")
def import_coordinates_from_file(self):
filename, _ = QFileDialog.getOpenFileName(self, "Импорт из файла", "", "Text files (*.txt)")
if not filename:
return
with open(filename, "r", encoding="utf-8") as f:
text = f.read()
coordinates = []
for line in text.splitlines():
matches = re.findall(r"(\d+(?:\.\d+)?)", line)
if len(matches) == 2:
lat, lon = map(float, matches)
coordinates.append((lat, lon))
for coord in coordinates:
item = QListWidgetItem(f"{coord[0]}, {coord[1]}")
self.coordinates_list.addItem(item)
self.coordinates.append(coord)
self.calculate_distances()
self.draw_map()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = CoordinateHelper()
window.show()
sys.exit(app.exec_())
И нет, я не буду выкладывать .bat, детишки сразу испугаются и побегут плакать модераторам((
Появиться желание - разберётесь как экспортировать данный код.
P.s. Python 3.11, PyQt5
Но не стоит расстраиваться, так же запустили онлайн карту с тем же функционалом что и в программе.
Работает на любом устройстве с веб-браузером.
Отсутствие необходимости установки: открывается прямо в браузере.
Использование OpenStreetMap: бесплатные и открытые картографические данные.
Широкий функционал: линейка, добавление точек, расчет расстояний и т.д.
Удобный пользовательский интерфейс с контекстным меню.
Функционал:





(каждая точка в формате "60.002244,30.223344" должна быть с новой строки)




Вам нужно зарегистрироваться, чтобы видеть ссылки.
Вам нужно зарегистрироваться, чтобы видеть ссылки.
Вложения
Вам нужно зарегистрироваться, чтобы просматривать вложения.
Последнее редактирование: