Files
GIS/OOPT/Преобразование в СК - Поворотные точки (разные варианты) - MAPINFO.ipynb

1743 lines
102 KiB
Plaintext
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.
{
"cells": [
{
"cell_type": "markdown",
"id": "c2af5362",
"metadata": {},
"source": [
"## 0. CSV координаты в шейпфайл"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "6fc7c48c",
"metadata": {},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"import pandas as pd\n",
"import folium\n",
"import os"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e53da044",
"metadata": {},
"outputs": [],
"source": [
"# Считываем проекцию в формате WKT и сохраняем ее в переменной\n",
"from pyproj import CRSa\n",
"from shapely.geometry import LineString\n",
"\n",
"csv = '4_Маршруты_shapefiles (от Волковой)\\\\Исходники\\\\Орнитологический маршрут.csv'\n",
"\n",
"df = pd.read_csv(csv, sep=';', decimal=',')\n",
"\n",
"file_name = os.path.splitext(os.path.basename(csv))[0]\n",
"\n",
"# Создаем геометрию Point из координат\n",
"geometry = gpd.points_from_xy(df['X'], df['Y'])\n",
"\n",
"# Создаем GeoDataFrame Gauss Kruger Zone 7= 20007\n",
"gdf = gpd.GeoDataFrame(df, geometry=geometry, crs=32637)\n",
"gdf.to_file(file_name + '.shp')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "82b264e1",
"metadata": {},
"outputs": [],
"source": [
"gdf.explore(tiles='Esri.WorldImagery')"
]
},
{
"cell_type": "markdown",
"id": "ab249f7b",
"metadata": {},
"source": [
"#### МСК координаты в шейп (далее уже в полигон)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "d7f062ed",
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'pd' is not defined",
"output_type": "error",
"traceback": [
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
"\u001b[31mNameError\u001b[39m Traceback (most recent call last)",
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 7\u001b[39m\n\u001b[32m 3\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mshapely\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mgeometry\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m LineString\n\u001b[32m 5\u001b[39m csv = \u001b[33m'\u001b[39m\u001b[33mКладбище поселка Прикубанский.csv\u001b[39m\u001b[33m'\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m7\u001b[39m df = \u001b[43mpd\u001b[49m.read_csv(csv, sep=\u001b[33m'\u001b[39m\u001b[33m;\u001b[39m\u001b[33m'\u001b[39m, decimal=\u001b[33m'\u001b[39m\u001b[33m,\u001b[39m\u001b[33m'\u001b[39m)\n\u001b[32m 9\u001b[39m file_name = os.path.splitext(os.path.basename(csv))[\u001b[32m0\u001b[39m]\n\u001b[32m 11\u001b[39m \u001b[38;5;66;03m# Создаем геометрию Point из координат\u001b[39;00m\n",
"\u001b[31mNameError\u001b[39m: name 'pd' is not defined"
]
}
],
"source": [
"# Считываем проекцию в формате WKT и сохраняем ее в переменной\n",
"from pyproj import CRS\n",
"from shapely.geometry import LineString\n",
"\n",
"csv = 'Кладбище поселка Прикубанский.csv'\n",
"\n",
"df = pd.read_csv(csv, sep=';', decimal=',')\n",
"\n",
"file_name = os.path.splitext(os.path.basename(csv))[0]\n",
"\n",
"# Создаем геометрию Point из координат\n",
"geometry = gpd.points_from_xy(df['Y'], df['X'])\n",
"\n",
"# Создаем GeoDataFrame Gauss Kruger Zone 7= 20007\n",
"from pyproj import CRS\n",
"with open(r'F:\\PROJECT-Colormap\\Преобразования географических проекций (СК, ГСК-2011, МСК)\\МСК23 проекции Краснодар\\MCK-23_Zone_2N.prj', 'r') as f:\n",
" msk23_2 = f.read()\n",
"\n",
"gdf = gpd.GeoDataFrame(df, geometry=geometry, crs=msk23_2)\n",
"gdf.to_file(file_name + '.shp')"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "77c500dd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Shapefile с полигоном успешно сохранён: polygon.shp\n"
]
}
],
"source": [
"import geopandas as gpd\n",
"import pandas as pd\n",
"from shapely.geometry import Polygon\n",
"\n",
"# Читаем CSV\n",
"df = pd.read_csv('Кладбище поселка Прикубанский.csv', delimiter=';', decimal=',')\n",
"\n",
"# Сортируем по столбцу с порядком точек (N)\n",
"df_sorted = df.sort_values(by='N')\n",
"\n",
"# Создаём список координат (X, Y)\n",
"coords = list(zip(df_sorted['Y'], df_sorted['X']))\n",
"\n",
"# Убедимся, что полигон замкнут (повторяем первую точку в конце)\n",
"if coords[0] != coords[-1]:\n",
" coords.append(coords[0])\n",
"\n",
"# Создаём полигон\n",
"polygon = Polygon(coords)\n",
"\n",
"# Создаём GeoDataFrame с одним объектом\n",
"gdf = gpd.GeoDataFrame(index=[0], geometry=[polygon])\n",
"\n",
"# Создаем GeoDataFrame Gauss Kruger Zone 7= 20007\n",
"from pyproj import CRS\n",
"with open(r'F:\\PROJECT-Colormap\\Преобразования географических проекций (СК, ГСК-2011, МСК)\\МСК23 проекции Краснодар\\MCK-23_Zone_2N.prj', 'r') as f:\n",
" msk23_2 = f.read()\n",
"gdf.set_crs(msk23_2, inplace=True)\n",
"\n",
"# Сохраняем в shapefile\n",
"gdf.to_file('polygon.shp')\n",
"\n",
"print(\"Shapefile с полигоном успешно сохранён: polygon.shp\")\n"
]
},
{
"cell_type": "markdown",
"id": "0971c4df",
"metadata": {},
"source": [
"## 1. Преобразование файлов (shapefile, DXF) в различные координатные системы (в архивы и по папкам) - ОСНОВНОЕ ПО ООПТ"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "7f795d2a-9b80-4097-861c-82525843e4dd",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting folium\n",
" Downloading folium-0.20.0-py2.py3-none-any.whl.metadata (4.2 kB)\n",
"Collecting branca>=0.6.0 (from folium)\n",
" Downloading branca-0.8.2-py3-none-any.whl.metadata (1.7 kB)\n",
"Requirement already satisfied: jinja2>=2.9 in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from folium) (3.1.6)\n",
"Requirement already satisfied: numpy in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from folium) (2.4.2)\n",
"Requirement already satisfied: requests in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from folium) (2.32.5)\n",
"Collecting xyzservices (from folium)\n",
" Downloading xyzservices-2025.11.0-py3-none-any.whl.metadata (4.3 kB)\n",
"Requirement already satisfied: MarkupSafe>=2.0 in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from jinja2>=2.9->folium) (3.0.3)\n",
"Requirement already satisfied: charset_normalizer<4,>=2 in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from requests->folium) (3.4.4)\n",
"Requirement already satisfied: idna<4,>=2.5 in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from requests->folium) (3.11)\n",
"Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from requests->folium) (2.6.3)\n",
"Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from requests->folium) (2026.1.4)\n",
"Downloading folium-0.20.0-py2.py3-none-any.whl (113 kB)\n",
"Downloading branca-0.8.2-py3-none-any.whl (26 kB)\n",
"Downloading xyzservices-2025.11.0-py3-none-any.whl (93 kB)\n",
"Installing collected packages: xyzservices, branca, folium\n",
"\n",
" ---------------------------------------- 3/3 [folium]\n",
"\n",
"Successfully installed branca-0.8.2 folium-0.20.0 xyzservices-2025.11.0\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n",
"[notice] A new release of pip is available: 25.3 -> 26.0.1\n",
"[notice] To update, run: C:\\Users\\Lenovo\\AppData\\Local\\Python\\pythoncore-3.14-64\\python.exe -m pip install --upgrade pip\n"
]
}
],
"source": [
"pip install folium"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "a0c1ced4",
"metadata": {},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"import pandas as pd\n",
"import folium\n",
"import os"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "68144dd6",
"metadata": {},
"outputs": [],
"source": [
"# Функция создания списка шейпфайлов для обработки\n",
"def shp_lst(folder):\n",
" lst = []\n",
" for file in os.listdir(folder):\n",
" if file.endswith(\".shp\"):\n",
" lst.append(os.path.join(folder, file))\n",
" print(lst[:2], '\\n', f'Всего: {len(lst)} файл(-а, -ов)')\n",
" return lst"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "7075b191",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Geographic 2D CRS: EPSG:4326>\n",
"Name: WGS 84\n",
"Axis Info [ellipsoidal]:\n",
"- Lat[north]: Geodetic latitude (degree)\n",
"- Lon[east]: Geodetic longitude (degree)\n",
"Area of Use:\n",
"- name: World.\n",
"- bounds: (-180.0, -90.0, 180.0, 90.0)\n",
"Datum: World Geodetic System 1984 ensemble\n",
"- Ellipsoid: WGS 84\n",
"- Prime Meridian: Greenwich"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Считываем проекцию в формате WKT и сохраняем ее в переменной\n",
"from pyproj import CRS\n",
"with open(r'c:\\ГИС-проекты\\2025 - ООПТ\\ООПТ из Программы\\MSK23_prj\\Russia_Cadastre_23_1.prj', 'r') as f:\n",
" #wkt = f.read()\n",
" msk23_1 = f.read()\n",
"# crs = CRS.from_wkt(wkt)\n",
"\n",
"with open(r'c:\\ГИС-проекты\\2025 - ООПТ\\ООПТ из Программы\\MSK23_prj\\Russia_Cadastre_23_2.prj', 'r') as f:\n",
" msk23_2 = f.read()\n",
"\n",
"# msk23_1 = '+proj=tmerc +lat_0=0 +lon_0=37.98333333333 +k=1 +x_0=1300000 +y_0=-4511057.628 +ellps=krass +towgs84=23.57,-140.95,-78.9,0,0,0,0.22 +units=m +no_defs'\n",
"# msk23_2 = '+proj=tmerc +lat_0=0 +lon_0=40.98333333333 +k=1 +x_0=2300000 +y_0=-4511057.628 +ellps=krass +towgs84=23.57,-140.95,-78.9,0,0,0,0.22 +units=m +no_defs'\n",
"\n",
"# Границы районов края со столбцом зон МСК23\n",
"gdf_boundary = gpd.read_file(r'c:\\ГИС-проекты\\2025 - ООПТ\\ООПТ из Программы\\Слои КК\\Borders-adm-MSK-Zone.shp')\n",
"# Преобразуем в WGS84\n",
"gdf_boundary = gdf_boundary.to_crs(4326)\n",
"gdf_boundary.crs"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "5b2973a2",
"metadata": {},
"outputs": [],
"source": [
"# Создадим два фрейма с зонам МСК23 в проекции 4326 (для простоты)\n",
"msk23_1_boundary = gdf_boundary[gdf_boundary['MSK23_Zone']==1].union_all()\n",
"msk23_1_boundary = gpd.GeoDataFrame({'geometry': [msk23_1_boundary]}, crs=gdf_boundary.crs)\n",
"\n",
"msk23_2_boundary = gdf_boundary[gdf_boundary['MSK23_Zone']==2].union_all()\n",
"msk23_2_boundary = gpd.GeoDataFrame({'geometry': [msk23_2_boundary]}, crs=gdf_boundary.crs)\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "4c032512",
"metadata": {},
"outputs": [],
"source": [
"# Словарь для создания папки для района\n",
"rayon_dic = {\n",
" 'esk': 'Ейский район',\n",
" 'kvk': 'Кавказский район',\n",
" 'kln': 'Калининский район',\n",
" 'knv': 'Каневской район',\n",
" 'krl': 'Крыловский район',\n",
" 'krm': 'Крымский район',\n",
" 'ksh': 'Кущевский район',\n",
" 'mst': 'Мостовской район',\n",
" 'nvk': 'Новокубанский район',\n",
" 'pvl': 'Павловский район',\n",
" 'tbl': 'Тбилисский район',\n",
" 'tps': 'Туапсинский район',\n",
" 'usp': 'Успенский район',\n",
" 'ulb': 'Усть-Лабинский район',\n",
" 'anp': 'Анапский район',\n",
" 'brh': 'Брюховецкий район',\n",
" 'glj': 'Геленджикский район',\n",
" 'nvp': 'Новопокровский район',\n",
" 'nvr': 'Новороссийск',\n",
" 'otr': 'Отрадненский район',\n",
" 'sch': 'Сочи',\n",
" 'svr': 'Северский район',\n",
" 'tmr': 'Темрюкский район',\n",
" 'shr': 'Щербиновский район'\n",
"} "
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "3bea704d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['C:\\\\ГИС-проекты\\\\2025 - ООПТ\\\\ООПТ из Программы\\\\Input_processing\\\\nvr-vasilevskie_osypi_pp_orz-new.shp'] \n",
" Всего: 1 файл(-а, -ов)\n"
]
}
],
"source": [
"folder = r'C:\\ГИС-проекты\\2025 - ООПТ\\ООПТ из Программы\\Input_processing'\n",
"shp_lst = shp_lst(folder)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "11a13016-0a7e-4746-8d1a-b70b2039aade",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting ezdxf\n",
" Downloading ezdxf-1.4.3-py3-none-any.whl.metadata (9.9 kB)\n",
"Collecting pyparsing>=2.0.1 (from ezdxf)\n",
" Downloading pyparsing-3.3.2-py3-none-any.whl.metadata (5.8 kB)\n",
"Requirement already satisfied: typing_extensions>=4.6.0 in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from ezdxf) (4.15.0)\n",
"Requirement already satisfied: numpy in c:\\users\\lenovo\\appdata\\local\\python\\pythoncore-3.14-64\\lib\\site-packages (from ezdxf) (2.4.2)\n",
"Collecting fonttools (from ezdxf)\n",
" Downloading fonttools-4.61.1-cp314-cp314-win_amd64.whl.metadata (116 kB)\n",
"Downloading ezdxf-1.4.3-py3-none-any.whl (1.3 MB)\n",
" ---------------------------------------- 0.0/1.3 MB ? eta -:--:--\n",
" ---------------------------------------- 0.0/1.3 MB ? eta -:--:--\n",
" ---------------------------------------- 0.0/1.3 MB ? eta -:--:--\n",
" ------- -------------------------------- 0.3/1.3 MB ? eta -:--:--\n",
" ------- -------------------------------- 0.3/1.3 MB ? eta -:--:--\n",
" --------------- ------------------------ 0.5/1.3 MB 663.7 kB/s eta 0:00:02\n",
" --------------- ------------------------ 0.5/1.3 MB 663.7 kB/s eta 0:00:02\n",
" ----------------------- ---------------- 0.8/1.3 MB 626.9 kB/s eta 0:00:01\n",
" ----------------------- ---------------- 0.8/1.3 MB 626.9 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ------------------------------- -------- 1.0/1.3 MB 588.7 kB/s eta 0:00:01\n",
" ---------------------------------------- 1.3/1.3 MB 371.6 kB/s 0:00:03\n",
"Downloading pyparsing-3.3.2-py3-none-any.whl (122 kB)\n",
"Downloading fonttools-4.61.1-cp314-cp314-win_amd64.whl (2.3 MB)\n",
" ---------------------------------------- 0.0/2.3 MB ? eta -:--:--\n",
" ---------------------------------------- 0.0/2.3 MB ? eta -:--:--\n",
" ---------------------------------------- 0.0/2.3 MB ? eta -:--:--\n",
" ---- ----------------------------------- 0.3/2.3 MB ? eta -:--:--\n",
" ---- ----------------------------------- 0.3/2.3 MB ? eta -:--:--\n",
" ---- ----------------------------------- 0.3/2.3 MB ? eta -:--:--\n",
" --------- ------------------------------ 0.5/2.3 MB 389.7 kB/s eta 0:00:05\n",
" --------- ------------------------------ 0.5/2.3 MB 389.7 kB/s eta 0:00:05\n",
" --------- ------------------------------ 0.5/2.3 MB 389.7 kB/s eta 0:00:05\n",
" ------------- -------------------------- 0.8/2.3 MB 463.1 kB/s eta 0:00:04\n",
" ------------- -------------------------- 0.8/2.3 MB 463.1 kB/s eta 0:00:04\n",
" ------------- -------------------------- 0.8/2.3 MB 463.1 kB/s eta 0:00:04\n",
" ------------------ --------------------- 1.0/2.3 MB 432.6 kB/s eta 0:00:03\n",
" ------------------ --------------------- 1.0/2.3 MB 432.6 kB/s eta 0:00:03\n",
" ------------------ --------------------- 1.0/2.3 MB 432.6 kB/s eta 0:00:03\n",
" ---------------------- ----------------- 1.3/2.3 MB 436.2 kB/s eta 0:00:03\n",
" ---------------------- ----------------- 1.3/2.3 MB 436.2 kB/s eta 0:00:03\n",
" ---------------------- ----------------- 1.3/2.3 MB 436.2 kB/s eta 0:00:03\n",
" --------------------------- ------------ 1.6/2.3 MB 431.0 kB/s eta 0:00:02\n",
" --------------------------- ------------ 1.6/2.3 MB 431.0 kB/s eta 0:00:02\n",
" ------------------------------- -------- 1.8/2.3 MB 447.5 kB/s eta 0:00:02\n",
" ------------------------------- -------- 1.8/2.3 MB 447.5 kB/s eta 0:00:02\n",
" ------------------------------- -------- 1.8/2.3 MB 447.5 kB/s eta 0:00:02\n",
" ------------------------------- -------- 1.8/2.3 MB 447.5 kB/s eta 0:00:02\n",
" ------------------------------------ --- 2.1/2.3 MB 421.3 kB/s eta 0:00:01\n",
" ------------------------------------ --- 2.1/2.3 MB 421.3 kB/s eta 0:00:01\n",
" ------------------------------------ --- 2.1/2.3 MB 421.3 kB/s eta 0:00:01\n",
" ---------------------------------------- 2.3/2.3 MB 421.1 kB/s 0:00:05\n",
"Installing collected packages: pyparsing, fonttools, ezdxf\n",
"\n",
" ------------- -------------------------- 1/3 [fonttools]\n",
" ------------- -------------------------- 1/3 [fonttools]\n",
" ------------- -------------------------- 1/3 [fonttools]\n",
" ------------- -------------------------- 1/3 [fonttools]\n",
" ------------- -------------------------- 1/3 [fonttools]\n",
" ------------- -------------------------- 1/3 [fonttools]\n",
" -------------------------- ------------- 2/3 [ezdxf]\n",
" -------------------------- ------------- 2/3 [ezdxf]\n",
" -------------------------- ------------- 2/3 [ezdxf]\n",
" -------------------------- ------------- 2/3 [ezdxf]\n",
" -------------------------- ------------- 2/3 [ezdxf]\n",
" -------------------------- ------------- 2/3 [ezdxf]\n",
" -------------------------- ------------- 2/3 [ezdxf]\n",
" ---------------------------------------- 3/3 [ezdxf]\n",
"\n",
"Successfully installed ezdxf-1.4.3 fonttools-4.61.1 pyparsing-3.3.2\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" WARNING: The scripts fonttools.exe, pyftmerge.exe, pyftsubset.exe and ttx.exe are installed in 'C:\\Users\\Lenovo\\AppData\\Local\\Python\\pythoncore-3.14-64\\Scripts' which is not on PATH.\n",
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\n",
" WARNING: The script ezdxf.exe is installed in 'C:\\Users\\Lenovo\\AppData\\Local\\Python\\pythoncore-3.14-64\\Scripts' which is not on PATH.\n",
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\n",
"\n",
"[notice] A new release of pip is available: 25.3 -> 26.0.1\n",
"[notice] To update, run: C:\\Users\\Lenovo\\AppData\\Local\\Python\\pythoncore-3.14-64\\python.exe -m pip install --upgrade pip\n"
]
}
],
"source": [
"pip install ezdxf"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "d84b7e1a",
"metadata": {},
"outputs": [],
"source": [
"### Сохраняет файлы в папку с именем района, которая создается автоматически по трем первым буквам шейп-файла\n",
"import ezdxf\n",
"import os\n",
"import zipfile\n",
"import fiona\n",
"\n",
"# Функция для создания архива шейпа в той же папке\n",
"# filepath - путь к файлу, outfolder - папка для сохранения\n",
"def zip_shp(filepath, outfolder):\n",
" filename = os.path.splitext(os.path.basename(filepath))[0]\n",
" folder = os.path.dirname(filepath)\n",
" with zipfile.ZipFile(outfolder + \"//\" + f'{filename}.zip', 'w') as zip_file:\n",
" # Ищем файлы с одинаковым именем, но с разным расширением\n",
" for file in os.listdir(folder):\n",
" if os.path.splitext(file)[0] == filename:\n",
" # Добавляем файл в архив\n",
" zip_file.write(os.path.join(folder, file), file) \n",
" # Удаляет файл\n",
" os.remove(os.path.join(folder, file))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f8000661-5fda-4f3a-b112-7248b1d2d8e4",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Processing c:\\гис-проекты\\fiona-1.10.1-cp314-cp314-win_amd64.whl\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING: Requirement 'fiona-1.10.1-cp314-cp314-win_amd64.whl' looks like a filename, but the file does not exist\n",
"ERROR: Could not install packages due to an OSError: [Errno 2] No such file or directory: 'C:\\\\ГИС-проекты\\\\fiona-1.10.1-cp314-cp314-win_amd64.whl'\n",
"\n",
"\n",
"[notice] A new release of pip is available: 25.3 -> 26.0.1\n",
"[notice] To update, run: C:\\Users\\Lenovo\\AppData\\Local\\Python\\pythoncore-3.14-64\\python.exe -m pip install --upgrade pip\n"
]
}
],
"source": [
"pip install GDAL-3.9.1-cp314-cp314-win_amd64.whl\n",
"pip install fiona-1.10.1-cp314-cp314-win_amd64.whl"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "b0cbd752",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\Lenovo\\AppData\\Local\\Temp\\ipykernel_14212\\3067829712.py:25: UserWarning: Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" if gdf.geometry.centroid.intersects(msk23_1_boundary).any():\n"
]
}
],
"source": [
"# Временная папка\n",
"temp = 'temp'\n",
"os.makedirs(temp, exist_ok=True)\n",
" \n",
"# Преобразуем все файлы в проекцию WGS84 и сохраняем в формате shape и DVG\n",
"for shp in shp_lst:\n",
" gdf = gpd.read_file(shp)\n",
" # Создать папку для района\n",
" outfolder = rayon_dic[os.path.basename(shp)[:3]] # берет первый три буквы названия файла и достает из словаря полное название района\n",
" os.makedirs(outfolder, exist_ok=True)\n",
" \n",
" ### WGS84\n",
" gdf = gdf.to_crs(4326)\n",
" filepath = os.path.join(temp, os.path.splitext(os.path.basename(shp))[0]) + '_WGS84' + '.shp'\n",
" gdf.to_file(filename=filepath, driver='ESRI Shapefile')\n",
" zip_shp(filepath, outfolder)\n",
" # DXF\n",
" filepath = os.path.join(outfolder, os.path.splitext(os.path.basename(shp))[0]) + '_WGS84' + '.dxf'\n",
" #gdf.geometry.to_file(filepath, driver=\"DXF\")\n",
" gdf.geometry.to_file(filepath, driver=\"DXF\", engine='fiona')\n",
" \n",
" # Раздел с МСК23 (распределение по зонам)\n",
" # Для определения делаем центроид полигона, если он внутри зоны МСК1, то это зона 1, если нет, то зона 2 (предварительно пришлось преобразовать WGS84 в Меркатор - не работало)\n",
" # if gdf.to_crs(3857).geometry.centroid.intersects(msk23_1_boundary).any():\n",
" if gdf.geometry.centroid.intersects(msk23_1_boundary).any():\n",
" gdf = gdf.to_crs(msk23_1)\n",
" filepath = os.path.join(temp, os.path.splitext(os.path.basename(shp))[0]) + '_MSK23_1' + '.shp'\n",
" gdf.to_file(filename=filepath, driver='ESRI Shapefile')\n",
" zip_shp(filepath, outfolder)\n",
" # DXF\n",
" filepath = os.path.join(outfolder, os.path.splitext(os.path.basename(shp))[0]) + '_MSK23_1' + '.dxf'\n",
" gdf.geometry.to_file(filepath, driver=\"DXF\")\n",
" else:\n",
" gdf = gdf.to_crs(msk23_2)\n",
" filepath = os.path.join(temp, os.path.splitext(os.path.basename(shp))[0]) + '_MSK23_2' + '.shp'\n",
" gdf.to_file(filename=filepath, driver='ESRI Shapefile')\n",
" zip_shp(filepath, outfolder)\n",
" # DXF\n",
" filepath = os.path.join(outfolder, os.path.splitext(os.path.basename(shp))[0]) + '_MSK23_2' + '.dxf'\n",
" gdf.geometry.to_file(filepath, driver=\"DXF\")\n",
"\n",
"\n",
" \n",
"# with tempfile.TemporaryDirectory() as temp_dir:\n",
"# temp_dir = Path(temp_dir)\n",
"# localFile = 'myshapefile'\n",
"\n",
"# gdf.to_file(filename=temp_dir, driver='ESRI Shapefile')\n",
"\n",
"# archiveFile = shutil.make_archive(localFile, 'zip', temp_dir)\n",
"# shutil.rmtree(temp_dir)\n",
" \n",
"# # Преобразуем данные в формат DWG-DXF\n",
"# filepath = os.path.join(outfolder, os.path.splitext(os.path.basename(shp))[0]) + '.dxf'\n",
" \n",
"# # Create a new DXF document\n",
"# doc = ezdxf.new(dxfversion='R2010')\n",
"# # Add a new layer to the DXF document\n",
"# msp = doc.modelspace()\n",
"\n",
"# # Iterate through the GeoDataFrame and add geometries to the DXF\n",
"# for _, row in gdf.iterrows():\n",
"# if row.geometry.type == 'Point':\n",
"# msp.add_point((row.geometry.x, row.geometry.y))\n",
"# elif row.geometry.type in ['LineString', 'MultiLineString']:\n",
"# for line in row.geometry:\n",
"# msp.add_lwpolyline(line.coords)\n",
"# elif row.geometry.type in ['Polygon', 'MultiPolygon']:\n",
"# for poly in row.geometry:\n",
"# coords = list(poly.exterior.coords)\n",
"# coords.append(coords[0]) # добавляем последнюю точку координат к началу списка координат\n",
"# msp.add_lwpolyline(coords)\n",
"\n",
"# # Save the DXF file\n",
"# doc.saveas(filepath)"
]
},
{
"cell_type": "markdown",
"id": "0dff4cdd",
"metadata": {},
"source": [
"##### Преобразование файлов в DXF"
]
},
{
"cell_type": "code",
"execution_count": 87,
"id": "a33bf66c",
"metadata": {},
"outputs": [],
"source": [
"for shp in shp_lst:\n",
" gdf = gpd.read_file(shp)\n",
" # Создать папку для района\n",
" outfolder = rayon_dic[os.path.basename(shp)[:3]] # берет первый три буквы названия файла и достает из словаря полное название района\n",
" os.makedirs(outfolder, exist_ok=True)\n",
" \n",
" # DXF\n",
" filepath = os.path.join(outfolder, os.path.splitext(os.path.basename(shp))[0]) + '.dxf'\n",
" gdf.geometry.to_file(filepath, driver=\"DXF\")"
]
},
{
"cell_type": "markdown",
"id": "8f6d5884",
"metadata": {},
"source": [
"!!!!! ДАЛЕЕ НУЖНО РАЗБИРАТЬСЯ\n",
"https://mapscaping.com/shapefile-to-dxf/"
]
},
{
"cell_type": "code",
"execution_count": 90,
"id": "2a16cebd",
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "DataSourceError",
"evalue": "input.shp: No such file or directory",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mDataSourceError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[90], line 5\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mezdxf\u001b[39;00m\n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# Load the Shapefile\u001b[39;00m\n\u001b[1;32m----> 5\u001b[0m gdf \u001b[38;5;241m=\u001b[39m \u001b[43mgpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread_file\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43minput.shp\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;66;03m# Create a new DXF document\u001b[39;00m\n\u001b[0;32m 8\u001b[0m doc \u001b[38;5;241m=\u001b[39m ezdxf\u001b[38;5;241m.\u001b[39mnew(dxfversion\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mR2010\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\geopandas\\io\\file.py:299\u001b[0m, in \u001b[0;36m_read_file\u001b[1;34m(filename, bbox, mask, columns, rows, engine, **kwargs)\u001b[0m\n\u001b[0;32m 296\u001b[0m from_bytes \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m 298\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m engine \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpyogrio\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m--> 299\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _read_file_pyogrio(\n\u001b[0;32m 300\u001b[0m filename, bbox\u001b[38;5;241m=\u001b[39mbbox, mask\u001b[38;5;241m=\u001b[39mmask, columns\u001b[38;5;241m=\u001b[39mcolumns, rows\u001b[38;5;241m=\u001b[39mrows, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs\n\u001b[0;32m 301\u001b[0m )\n\u001b[0;32m 303\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m engine \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfiona\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m 304\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m pd\u001b[38;5;241m.\u001b[39mapi\u001b[38;5;241m.\u001b[39mtypes\u001b[38;5;241m.\u001b[39mis_file_like(filename):\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\geopandas\\io\\file.py:549\u001b[0m, in \u001b[0;36m_read_file_pyogrio\u001b[1;34m(path_or_bytes, bbox, mask, rows, **kwargs)\u001b[0m\n\u001b[0;32m 540\u001b[0m warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[0;32m 541\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThe \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124minclude_fields\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m and \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mignore_fields\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m keywords are deprecated, and \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 542\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwill be removed in a future release. You can use the \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcolumns\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m keyword \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 545\u001b[0m stacklevel\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m3\u001b[39m,\n\u001b[0;32m 546\u001b[0m )\n\u001b[0;32m 547\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcolumns\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m kwargs\u001b[38;5;241m.\u001b[39mpop(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minclude_fields\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m--> 549\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m pyogrio\u001b[38;5;241m.\u001b[39mread_dataframe(path_or_bytes, bbox\u001b[38;5;241m=\u001b[39mbbox, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyogrio\\geopandas.py:265\u001b[0m, in \u001b[0;36mread_dataframe\u001b[1;34m(path_or_buffer, layer, encoding, columns, read_geometry, force_2d, skip_features, max_features, where, bbox, mask, fids, sql, sql_dialect, fid_as_index, use_arrow, on_invalid, arrow_to_pandas_kwargs, **kwargs)\u001b[0m\n\u001b[0;32m 260\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m use_arrow:\n\u001b[0;32m 261\u001b[0m \u001b[38;5;66;03m# For arrow, datetimes are read as is.\u001b[39;00m\n\u001b[0;32m 262\u001b[0m \u001b[38;5;66;03m# For numpy IO, datetimes are read as string values to preserve timezone info\u001b[39;00m\n\u001b[0;32m 263\u001b[0m \u001b[38;5;66;03m# as numpy does not directly support timezones.\u001b[39;00m\n\u001b[0;32m 264\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdatetime_as_string\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m--> 265\u001b[0m result \u001b[38;5;241m=\u001b[39m read_func(\n\u001b[0;32m 266\u001b[0m path_or_buffer,\n\u001b[0;32m 267\u001b[0m layer\u001b[38;5;241m=\u001b[39mlayer,\n\u001b[0;32m 268\u001b[0m encoding\u001b[38;5;241m=\u001b[39mencoding,\n\u001b[0;32m 269\u001b[0m columns\u001b[38;5;241m=\u001b[39mcolumns,\n\u001b[0;32m 270\u001b[0m read_geometry\u001b[38;5;241m=\u001b[39mread_geometry,\n\u001b[0;32m 271\u001b[0m force_2d\u001b[38;5;241m=\u001b[39mgdal_force_2d,\n\u001b[0;32m 272\u001b[0m skip_features\u001b[38;5;241m=\u001b[39mskip_features,\n\u001b[0;32m 273\u001b[0m max_features\u001b[38;5;241m=\u001b[39mmax_features,\n\u001b[0;32m 274\u001b[0m where\u001b[38;5;241m=\u001b[39mwhere,\n\u001b[0;32m 275\u001b[0m bbox\u001b[38;5;241m=\u001b[39mbbox,\n\u001b[0;32m 276\u001b[0m mask\u001b[38;5;241m=\u001b[39mmask,\n\u001b[0;32m 277\u001b[0m fids\u001b[38;5;241m=\u001b[39mfids,\n\u001b[0;32m 278\u001b[0m sql\u001b[38;5;241m=\u001b[39msql,\n\u001b[0;32m 279\u001b[0m sql_dialect\u001b[38;5;241m=\u001b[39msql_dialect,\n\u001b[0;32m 280\u001b[0m return_fids\u001b[38;5;241m=\u001b[39mfid_as_index,\n\u001b[0;32m 281\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[0;32m 282\u001b[0m )\n\u001b[0;32m 284\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m use_arrow:\n\u001b[0;32m 285\u001b[0m meta, table \u001b[38;5;241m=\u001b[39m result\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyogrio\\raw.py:198\u001b[0m, in \u001b[0;36mread\u001b[1;34m(path_or_buffer, layer, encoding, columns, read_geometry, force_2d, skip_features, max_features, where, bbox, mask, fids, sql, sql_dialect, return_fids, datetime_as_string, **kwargs)\u001b[0m\n\u001b[0;32m 59\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Read OGR data source into numpy arrays.\u001b[39;00m\n\u001b[0;32m 60\u001b[0m \n\u001b[0;32m 61\u001b[0m \u001b[38;5;124;03mIMPORTANT: non-linear geometry types (e.g., MultiSurface) are converted\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 194\u001b[0m \n\u001b[0;32m 195\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 196\u001b[0m dataset_kwargs \u001b[38;5;241m=\u001b[39m _preprocess_options_key_value(kwargs) \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;28;01melse\u001b[39;00m {}\n\u001b[1;32m--> 198\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mogr_read\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 199\u001b[0m \u001b[43m \u001b[49m\u001b[43mget_vsi_path_or_buffer\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath_or_buffer\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 200\u001b[0m \u001b[43m \u001b[49m\u001b[43mlayer\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlayer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 201\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 202\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 203\u001b[0m \u001b[43m \u001b[49m\u001b[43mread_geometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mread_geometry\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 204\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_2d\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_2d\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 205\u001b[0m \u001b[43m \u001b[49m\u001b[43mskip_features\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mskip_features\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 206\u001b[0m \u001b[43m \u001b[49m\u001b[43mmax_features\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmax_features\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 207\u001b[0m \u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwhere\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 208\u001b[0m \u001b[43m \u001b[49m\u001b[43mbbox\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbbox\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 209\u001b[0m \u001b[43m \u001b[49m\u001b[43mmask\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_mask_to_wkb\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmask\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 210\u001b[0m \u001b[43m \u001b[49m\u001b[43mfids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfids\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 211\u001b[0m \u001b[43m \u001b[49m\u001b[43msql\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msql\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 212\u001b[0m \u001b[43m \u001b[49m\u001b[43msql_dialect\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msql_dialect\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 213\u001b[0m \u001b[43m \u001b[49m\u001b[43mreturn_fids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mreturn_fids\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 214\u001b[0m \u001b[43m \u001b[49m\u001b[43mdataset_kwargs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdataset_kwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 215\u001b[0m \u001b[43m \u001b[49m\u001b[43mdatetime_as_string\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdatetime_as_string\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 216\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32mpyogrio\\\\_io.pyx:1240\u001b[0m, in \u001b[0;36mpyogrio._io.ogr_read\u001b[1;34m()\u001b[0m\n",
"File \u001b[1;32mpyogrio\\\\_io.pyx:220\u001b[0m, in \u001b[0;36mpyogrio._io.ogr_open\u001b[1;34m()\u001b[0m\n",
"\u001b[1;31mDataSourceError\u001b[0m: input.shp: No such file or directory"
]
}
],
"source": [
"import geopandas as gpd\n",
"import ezdxf\n",
"\n",
"# Load the Shapefile\n",
"gdf = gpd.read_file('input.shp')\n",
"\n",
"# Create a new DXF document\n",
"doc = ezdxf.new(dxfversion='R2010')\n",
"\n",
"# Add a new layer to the DXF document\n",
"msp = doc.modelspace()\n",
"\n",
"# Iterate through the GeoDataFrame and add geometries to the DXF\n",
"for _, row in gdf.iterrows():\n",
" if row.geometry.type == 'Point':\n",
" msp.add_point((row.geometry.x, row.geometry.y))\n",
" elif row.geometry.type in ['LineString', 'MultiLineString']:\n",
" for line in row.geometry:\n",
" msp.add_lwpolyline(line.coords)\n",
" elif row.geometry.type in ['Polygon', 'MultiPolygon']:\n",
" for poly in row.geometry:\n",
" msp.add_lwpolyline(poly.exterior.coords, is_closed=True)\n",
"\n",
"# Save the DXF file\n",
"doc.saveas('output.dxf')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3b2d17c5",
"metadata": {},
"outputs": [],
"source": [
"# Для проекции в МСК \n",
"# В начале определяем зону по файлу с районами, далее преобразуем в эту зону\n",
"# НЕ ДОДЕЛАН!!!!\n",
"\n",
"for shp in shp_lst[:3]:\n",
" gdf = gpd.read_file(shp).union_all\n",
" centroid = gdf.centroid\n",
" centroid_gdf = gpd.GeoDataFrame(geometry=gpd.points_from_xy(centroid.x, centroid.y)).set_crs(3857)\n",
" gdf_joined = gpd.sjoin(\n",
" \n",
" \n",
" gdf = gdf.to_crs(msk23_1)\n",
" \n",
" filepath = os.path.join(outfolder, os.path.basename(shp))\n",
" gdf.to_file(filepath)\n",
"\n",
" \n",
"# Преобразуем данные в формат DWG-DXF\n",
"import osgeo import ogr\n",
"driver = ogr.GetDriverByName('DXF')\n",
"ds = driver.CreateCopy('output.dxf', gdf)\n",
"ds = None\n",
"\n",
"import pydxf\n",
"dxf = pydxf.DxfFile('input.dxf')\n",
"# Преобразуем DXF в DWG\n",
"dwg = pydxf.DwfFile('output.dwg')\n",
"dwg.write(dxf)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "84e4e74e",
"metadata": {},
"outputs": [],
"source": [
"import pyproj\n",
"x, y = gdf.centroid.x, gdf.centroid.y\n",
"lon, lat = pyproj.transform(pyproj.Proj('epsg:3857'), pyproj.Proj('epsg:4326'), x, y)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d696791f",
"metadata": {},
"outputs": [],
"source": [
"# Определите зону MSK\n",
"if central_meridian >= 45 and central_meridian < 48:\n",
" print(\"Проекция: MSK-23.1\")\n",
"elif central_meridian >= 48 and central_meridian <= 51:\n",
" print(\"Проекция: MSK-23.2\")\n",
"else:\n",
" print(\"Проекция: MSK, но зона не определена\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aedd1949",
"metadata": {},
"outputs": [],
"source": [
"centroid = gdf.centroid\n",
"gdf_joined = gpd.sjoin(centroid, gdf, how='inner', op='within').explore()"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "7efffd0c",
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'gpd' is not defined",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m centroid_gdf \u001b[38;5;241m=\u001b[39m \u001b[43mgpd\u001b[49m\u001b[38;5;241m.\u001b[39mGeoDataFrame(geometry\u001b[38;5;241m=\u001b[39mgpd\u001b[38;5;241m.\u001b[39mpoints_from_xy(centroid\u001b[38;5;241m.\u001b[39mx, centroid\u001b[38;5;241m.\u001b[39my))\u001b[38;5;241m.\u001b[39mset_crs(msk23_1)\n",
"\u001b[1;31mNameError\u001b[0m: name 'gpd' is not defined"
]
}
],
"source": [
"centroid_gdf = gpd.GeoDataFrame(geometry=gpd.points_from_xy(centroid.x, centroid.y)).set_crs(msk23_1)"
]
},
{
"cell_type": "markdown",
"id": "3b530859",
"metadata": {},
"source": [
"## 2. Создание таблицы с координатами (поворотные точки) ТОЛЬКО МСК23"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "70de8c1d",
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "DataSourceError",
"evalue": "11111\\sch-aibga-grushevn_pp_orz-new_MSK23_2.shp: No such file or directory",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mDataSourceError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[9], line 4\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# Извлекаем имя файла\u001b[39;00m\n\u001b[0;32m 3\u001b[0m shp_name \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39msplitext(os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mbasename(shp))[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m----> 4\u001b[0m gdf \u001b[38;5;241m=\u001b[39m \u001b[43mgpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43mshp\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 6\u001b[0m \u001b[38;5;66;03m# Извлекаем координаты вертексов полигона (формат X, Y в текущей координатной системе)\u001b[39;00m\n\u001b[0;32m 7\u001b[0m df \u001b[38;5;241m=\u001b[39m gdf\u001b[38;5;241m.\u001b[39mget_coordinates()\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\geopandas\\io\\file.py:299\u001b[0m, in \u001b[0;36m_read_file\u001b[1;34m(filename, bbox, mask, columns, rows, engine, **kwargs)\u001b[0m\n\u001b[0;32m 296\u001b[0m from_bytes \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m 298\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m engine \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpyogrio\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m--> 299\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _read_file_pyogrio(\n\u001b[0;32m 300\u001b[0m filename, bbox\u001b[38;5;241m=\u001b[39mbbox, mask\u001b[38;5;241m=\u001b[39mmask, columns\u001b[38;5;241m=\u001b[39mcolumns, rows\u001b[38;5;241m=\u001b[39mrows, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs\n\u001b[0;32m 301\u001b[0m )\n\u001b[0;32m 303\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m engine \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfiona\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m 304\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m pd\u001b[38;5;241m.\u001b[39mapi\u001b[38;5;241m.\u001b[39mtypes\u001b[38;5;241m.\u001b[39mis_file_like(filename):\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\geopandas\\io\\file.py:549\u001b[0m, in \u001b[0;36m_read_file_pyogrio\u001b[1;34m(path_or_bytes, bbox, mask, rows, **kwargs)\u001b[0m\n\u001b[0;32m 540\u001b[0m warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[0;32m 541\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThe \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124minclude_fields\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m and \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mignore_fields\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m keywords are deprecated, and \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 542\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwill be removed in a future release. You can use the \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcolumns\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m keyword \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 545\u001b[0m stacklevel\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m3\u001b[39m,\n\u001b[0;32m 546\u001b[0m )\n\u001b[0;32m 547\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcolumns\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m kwargs\u001b[38;5;241m.\u001b[39mpop(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minclude_fields\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m--> 549\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m pyogrio\u001b[38;5;241m.\u001b[39mread_dataframe(path_or_bytes, bbox\u001b[38;5;241m=\u001b[39mbbox, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyogrio\\geopandas.py:265\u001b[0m, in \u001b[0;36mread_dataframe\u001b[1;34m(path_or_buffer, layer, encoding, columns, read_geometry, force_2d, skip_features, max_features, where, bbox, mask, fids, sql, sql_dialect, fid_as_index, use_arrow, on_invalid, arrow_to_pandas_kwargs, **kwargs)\u001b[0m\n\u001b[0;32m 260\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m use_arrow:\n\u001b[0;32m 261\u001b[0m \u001b[38;5;66;03m# For arrow, datetimes are read as is.\u001b[39;00m\n\u001b[0;32m 262\u001b[0m \u001b[38;5;66;03m# For numpy IO, datetimes are read as string values to preserve timezone info\u001b[39;00m\n\u001b[0;32m 263\u001b[0m \u001b[38;5;66;03m# as numpy does not directly support timezones.\u001b[39;00m\n\u001b[0;32m 264\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdatetime_as_string\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m--> 265\u001b[0m result \u001b[38;5;241m=\u001b[39m read_func(\n\u001b[0;32m 266\u001b[0m path_or_buffer,\n\u001b[0;32m 267\u001b[0m layer\u001b[38;5;241m=\u001b[39mlayer,\n\u001b[0;32m 268\u001b[0m encoding\u001b[38;5;241m=\u001b[39mencoding,\n\u001b[0;32m 269\u001b[0m columns\u001b[38;5;241m=\u001b[39mcolumns,\n\u001b[0;32m 270\u001b[0m read_geometry\u001b[38;5;241m=\u001b[39mread_geometry,\n\u001b[0;32m 271\u001b[0m force_2d\u001b[38;5;241m=\u001b[39mgdal_force_2d,\n\u001b[0;32m 272\u001b[0m skip_features\u001b[38;5;241m=\u001b[39mskip_features,\n\u001b[0;32m 273\u001b[0m max_features\u001b[38;5;241m=\u001b[39mmax_features,\n\u001b[0;32m 274\u001b[0m where\u001b[38;5;241m=\u001b[39mwhere,\n\u001b[0;32m 275\u001b[0m bbox\u001b[38;5;241m=\u001b[39mbbox,\n\u001b[0;32m 276\u001b[0m mask\u001b[38;5;241m=\u001b[39mmask,\n\u001b[0;32m 277\u001b[0m fids\u001b[38;5;241m=\u001b[39mfids,\n\u001b[0;32m 278\u001b[0m sql\u001b[38;5;241m=\u001b[39msql,\n\u001b[0;32m 279\u001b[0m sql_dialect\u001b[38;5;241m=\u001b[39msql_dialect,\n\u001b[0;32m 280\u001b[0m return_fids\u001b[38;5;241m=\u001b[39mfid_as_index,\n\u001b[0;32m 281\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[0;32m 282\u001b[0m )\n\u001b[0;32m 284\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m use_arrow:\n\u001b[0;32m 285\u001b[0m meta, table \u001b[38;5;241m=\u001b[39m result\n",
"File \u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyogrio\\raw.py:198\u001b[0m, in \u001b[0;36mread\u001b[1;34m(path_or_buffer, layer, encoding, columns, read_geometry, force_2d, skip_features, max_features, where, bbox, mask, fids, sql, sql_dialect, return_fids, datetime_as_string, **kwargs)\u001b[0m\n\u001b[0;32m 59\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Read OGR data source into numpy arrays.\u001b[39;00m\n\u001b[0;32m 60\u001b[0m \n\u001b[0;32m 61\u001b[0m \u001b[38;5;124;03mIMPORTANT: non-linear geometry types (e.g., MultiSurface) are converted\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 194\u001b[0m \n\u001b[0;32m 195\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 196\u001b[0m dataset_kwargs \u001b[38;5;241m=\u001b[39m _preprocess_options_key_value(kwargs) \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;28;01melse\u001b[39;00m {}\n\u001b[1;32m--> 198\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mogr_read\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 199\u001b[0m \u001b[43m \u001b[49m\u001b[43mget_vsi_path_or_buffer\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath_or_buffer\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 200\u001b[0m \u001b[43m \u001b[49m\u001b[43mlayer\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlayer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 201\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 202\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 203\u001b[0m \u001b[43m \u001b[49m\u001b[43mread_geometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mread_geometry\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 204\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_2d\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_2d\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 205\u001b[0m \u001b[43m \u001b[49m\u001b[43mskip_features\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mskip_features\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 206\u001b[0m \u001b[43m \u001b[49m\u001b[43mmax_features\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmax_features\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 207\u001b[0m \u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwhere\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 208\u001b[0m \u001b[43m \u001b[49m\u001b[43mbbox\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbbox\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 209\u001b[0m \u001b[43m \u001b[49m\u001b[43mmask\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_mask_to_wkb\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmask\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 210\u001b[0m \u001b[43m \u001b[49m\u001b[43mfids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfids\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 211\u001b[0m \u001b[43m \u001b[49m\u001b[43msql\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msql\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 212\u001b[0m \u001b[43m \u001b[49m\u001b[43msql_dialect\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msql_dialect\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 213\u001b[0m \u001b[43m \u001b[49m\u001b[43mreturn_fids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mreturn_fids\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 214\u001b[0m \u001b[43m \u001b[49m\u001b[43mdataset_kwargs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdataset_kwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 215\u001b[0m \u001b[43m \u001b[49m\u001b[43mdatetime_as_string\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdatetime_as_string\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 216\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32mpyogrio\\\\_io.pyx:1240\u001b[0m, in \u001b[0;36mpyogrio._io.ogr_read\u001b[1;34m()\u001b[0m\n",
"File \u001b[1;32mpyogrio\\\\_io.pyx:220\u001b[0m, in \u001b[0;36mpyogrio._io.ogr_open\u001b[1;34m()\u001b[0m\n",
"\u001b[1;31mDataSourceError\u001b[0m: 11111\\sch-aibga-grushevn_pp_orz-new_MSK23_2.shp: No such file or directory"
]
}
],
"source": [
"shp = '11111\\\\sch-aibga-grushevn_pp_orz-new_MSK23_2.shp'\n",
"# Извлекаем имя файла\n",
"shp_name = os.path.splitext(os.path.basename(shp))[0]\n",
"gdf = gpd.read_file(shp)\n",
"\n",
"# Извлекаем координаты вертексов полигона (формат X, Y в текущей координатной системе)\n",
"df = gdf.get_coordinates()\n",
"# Добавляем индекс к таблице\n",
"df.reset_index(inplace = True, drop = True)\n",
"# Первая строка с 1\n",
"df.index += 1\n",
"df = df.reset_index()\n",
"# Округляем\n",
"df = round(df)\n",
"# Переименовываем столбцы\n",
"df.columns = ['N', 'X_MSK23', 'Y_MSK23']\n",
"# Добавляет первую строку в конец таблицы\n",
"df = df.take(list(range(len(df) - 1)) + [0])\n",
"df.to_excel(shp_name + '.xlsx', index=False)"
]
},
{
"cell_type": "markdown",
"id": "7c473b4b",
"metadata": {},
"source": [
"## 3. Поворотные точки градусы, минуты, секунды в ГСК 2011 (для проверки по ГЕОЛОГИИ)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "1e5a4710",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"import pandas as pd\n",
"from os.path import splitext\n",
"import os"
]
},
{
"cell_type": "markdown",
"id": "198e699a",
"metadata": {},
"source": [
"#### Функции"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "2e3cf25c",
"metadata": {},
"outputs": [],
"source": [
"# Функция создания списка шейпфайлов для обработки\n",
"def shp_lst(folder):\n",
" lst = []\n",
" for file in os.listdir(folder):\n",
" if file.endswith(\".shp\"):\n",
" lst.append(os.path.join(folder, file))\n",
" print(lst[:2], '\\n', f'Всего: {len(lst)} файл(-а, -ов)')\n",
" return lst"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "52edaf9c",
"metadata": {},
"outputs": [],
"source": [
"# Создает таблицу с координатами градусы-минуты-секунды для полигона в GeoDataFrame (должен быть один объект)\n",
"def coordinates(gdf):\n",
" df = gdf.get_coordinates()\n",
" # Добавляем индекс к таблице\n",
" df.reset_index(inplace = True, drop = True)\n",
" # Первая строка с 1\n",
" df.index += 1\n",
" df = df.reset_index()\n",
" \n",
" df['latitude_deg'] = df['y'].astype(int)\n",
" df['latitude_min_full'] = ((df['y'] - df['latitude_deg']) * 60).abs()\n",
" df['latitude_min'] = df['latitude_min_full'].astype(int)\n",
" df['latitude_sec'] = round((df['latitude_min_full'] - df['latitude_min']) * 60, 3)\n",
"\n",
" df['longitude_deg'] = df['x'].astype(int)\n",
" df['longitude_min_full'] = ((df['x'] - df['longitude_deg']) * 60).abs()\n",
" df['longitude_min'] = df['longitude_min_full'].astype(int)\n",
" df['longitude_sec'] = round((df['longitude_min_full'] - df['longitude_min']) * 60, 3)\n",
"\n",
" df.drop(['x', 'y', 'latitude_min_full', 'longitude_min_full'], axis=1, inplace=True)\n",
" df = df.rename(columns={'index': 'N'})\n",
"\n",
" # Добавляем в конец дубликат первой строки\n",
" df = df.take(list(range(len(df) - 1)) + [0])\n",
" return df"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "23bd2b42",
"metadata": {},
"outputs": [],
"source": [
"##### Функция шаблона Excel c шапкой для координат ГСК-2011\n",
"\n",
"from openpyxl import Workbook\n",
"from openpyxl.styles import Alignment, Font, Border, Side\n",
"\n",
"def template_gc(output_file):\n",
" wb = Workbook()\n",
" ws = wb.active\n",
"\n",
" # --- Первая строка: заголовок \"ГСК-2011\", объединённый над всеми столбцами ---\n",
" max_col = 7 # например, у вас 7 столбцов в шапке ниже\n",
"\n",
" ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=max_col)\n",
" header_cell = ws.cell(row=1, column=1, value='ГСК-2011')\n",
" header_cell.font = Font(bold=False) # простой шрифт (без жирности)\n",
" header_cell.alignment = Alignment(horizontal='center', vertical='center')\n",
" \n",
" # --- Вторая и третья строки: многоуровневая шапка ---\n",
" # Вторая строка — первый уровень шапки\n",
" ws['A3'] = \"№ точки\"\n",
" ws['B3'] = \"Широта [-90:90]\\n(С.Ш. - положительные\\nЮ.Ш. - отрицательные)\"\n",
" ws['E3'] = \"Долгота [-180:180]\\n(В.Д. - положительные\\nЗ.Д. - отрицательные)\"\n",
"\n",
" # Объединение ячеек для первого уровня заголовков\n",
" ws.merge_cells('A3:A4') # \"№ точки\" занимает две строки вертикально\n",
" ws.merge_cells('B3:D3') # \"Широта ...\" над 3 колонками\n",
" ws.merge_cells('E3:G3') # \"Долгота ...\" над 3 колонками\n",
"\n",
" # Третья строка — второй уровень (подзаголовки) с обычным шрифтом\n",
" sub_headers = [\n",
" 'Градусы, \\nцелое',\n",
" 'Минуты, \\nцелое',\n",
" 'Секунды,\\nдробь до \\n3 знаков'\n",
" ]\n",
"\n",
" cols_lat = ['B', 'C', 'D']\n",
" cols_lon = ['E', 'F', 'G']\n",
"\n",
" for col, text in zip(cols_lat, sub_headers):\n",
" c = ws[f\"{col}4\"]\n",
" c.value = text\n",
" c.font = Font(bold=False) # простой шрифт\n",
" c.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)\n",
"\n",
" for col, text in zip(cols_lon, sub_headers):\n",
" c = ws[f\"{col}4\"]\n",
" c.value = text\n",
" c.font = Font(bold=False)\n",
" c.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)\n",
"\n",
" # Выравнивание и жирность для второго уровня заголовка (строка 2)\n",
" for cell in ['A3', 'B3', 'E3']:\n",
" c = ws[cell]\n",
" c.font = Font(bold=True)\n",
" c.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)\n",
"\n",
" # Установим высоту строк для переносов текста\n",
" ws.row_dimensions[1].height = 20\n",
" ws.row_dimensions[2].height = 8\n",
" ws.row_dimensions[3].height = 48\n",
" ws.row_dimensions[4].height = 40\n",
"\n",
" # Подгонка ширины столбцов\n",
" col_widths = [10, 15, 15, 20, 15, 15, 20]\n",
" for i, width in enumerate(col_widths, 1):\n",
" ws.column_dimensions[chr(64 + i)].width = width\n",
"\n",
" # Добавление рамки по всей области шапки (с 1 по 3 строку, с A по G)\n",
" thin_side = Side(border_style=\"thin\", color=\"000000\")\n",
" border = Border(left=thin_side, right=thin_side, top=thin_side, bottom=thin_side)\n",
" for row in ws.iter_rows(min_row=3, max_row=4, min_col=1, max_col=max_col):\n",
" for cell in row:\n",
" # Центрируем все ячейки по горизонтали и вертикали, если текст в ячейке есть\n",
" if cell.value is not None:\n",
" cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)\n",
" # Устанавливаем рамку\n",
" cell.border = border\n",
"\n",
" # Сохраняем файл\n",
" wb.save(output_file)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "4188dffe",
"metadata": {},
"outputs": [],
"source": [
"# Функция форматирования файла Excel, выравнивание всех ячеек по центру и добавления первой строки с номером участка\n",
"from openpyxl import load_workbook\n",
"from openpyxl.styles import Alignment, Font, Border, Side\n",
"\n",
"def format_xlsx(xlsx, counter): # counter - текущий номер участка\n",
" # Открываем существующий файл\n",
" wb = load_workbook(xlsx)\n",
" ws = wb.active # или wb['SheetName']\n",
"\n",
" # Определяем размер текущей таблицы\n",
" min_row, max_row = ws.min_row, ws.max_row\n",
" min_col, max_col = ws.min_column, ws.max_column\n",
"\n",
"# УБРАЛ БЛОК ДОБАВЛЕНИЯ ПЕРВОЙ СТРОКИ С НОМЕРОМ УЧАСТКА, ТАК КАК В СИСТЕМУ МОЖНО ЗАГРУЖАТЬ ТОЛЬКО ПО ОДНОМУ УЧАСТКУ\n",
"# # Вставляем пустую первую строку\n",
"# ws.insert_rows(1)\n",
"# max_row += 1 # сдвигаем нижнюю границу таблицы вниз на 1, т.к. вставили строку\n",
"\n",
"# # Объединяем все ячейки первой строки в одну ячейку\n",
"# merge_range = f\"{ws.cell(row=1, column=min_col).coordinate}:\" \\\n",
"# f\"{ws.cell(row=1, column=max_col).coordinate}\"\n",
"# ws.merge_cells(merge_range)\n",
"\n",
"# header_cell = ws.cell(row=1, column=min_col)\n",
"# header_cell.value = \"Участок \" + str(counter)\n",
"# header_cell.font = Font(bold=True, size=11)\n",
"# header_cell.alignment = Alignment(horizontal='center', vertical='center')\n",
"\n",
"# # Устанавливаем высоту первой строки для читаемости\n",
"# ws.row_dimensions[1].height = 20\n",
"\n",
" # Создаем стиль тонкой рамки\n",
" thin_side = Side(border_style=\"thin\", color=\"000000\")\n",
" thin_border = Border(left=thin_side, right=thin_side, top=thin_side, bottom=thin_side)\n",
"\n",
" # Проходим по всем ячейкам таблицы (включая новую первую строку)\n",
" for row in ws.iter_rows(min_row=0, max_row=max_row, min_col=min_col, max_col=max_col):\n",
" for cell in row:\n",
" # Центрируем содержимое ячеек\n",
" if cell.value is not None:\n",
" cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)\n",
" # Устанавливаем тонкую рамку в каждую ячейку\n",
" cell.border = thin_border\n",
"\n",
" # Сохраняем в тот же файл\n",
" wb.save(xlsx)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "7c5eb821",
"metadata": {},
"outputs": [],
"source": [
"# Функция объединения 2+ файлов-участков от одного ООПТ \n",
"from openpyxl import load_workbook, Workbook\n",
"from openpyxl.styles import Font, PatternFill, Border, Alignment, Protection\n",
"\n",
"def copy_cell_style(src_cell, tgt_cell):\n",
" if src_cell.has_style:\n",
" tgt_cell.font = src_cell.font.copy()\n",
" tgt_cell.border = src_cell.border.copy()\n",
" tgt_cell.fill = src_cell.fill.copy()\n",
" tgt_cell.number_format = src_cell.number_format\n",
" tgt_cell.protection = src_cell.protection.copy()\n",
" tgt_cell.alignment = src_cell.alignment.copy()\n",
"\n",
"def concat_xlsx_with_style(files, output_file):\n",
" wb_new = Workbook()\n",
" ws_new = wb_new.active\n",
" ws_new.title = \"Угловые точки DD⁰MM'SS.SS\"\n",
" \n",
" current_row = 1\n",
" for idx, file in enumerate(files):\n",
" wb_src = load_workbook(file)\n",
" ws_src = wb_src.active\n",
" \n",
" min_row = 1 # Можно поменять на 2 для пропуска заголовков во 2-м и последующих файлах\n",
" \n",
" # Копируем значения и стили по строкам\n",
" for r in range(min_row, ws_src.max_row + 1):\n",
" for c in range(1, ws_src.max_column + 1):\n",
" src_cell = ws_src.cell(row=r, column=c)\n",
" tgt_cell = ws_new.cell(row=current_row, column=c)\n",
" tgt_cell.value = src_cell.value\n",
" copy_cell_style(src_cell, tgt_cell)\n",
" current_row += 1\n",
"\n",
" # Копируем объединённые ячейки (merged cells) с учётом сдвига строк\n",
" row_offset = current_row - (ws_src.max_row + 1)\n",
" for merged_range in ws_src.merged_cells.ranges:\n",
" start_row = merged_range.min_row + row_offset\n",
" end_row = merged_range.max_row + row_offset\n",
" start_col = merged_range.min_col\n",
" end_col = merged_range.max_col\n",
" \n",
" new_range = f\"{ws_src.cell(row=start_row, column=start_col).coordinate}:\" \\\n",
" f\"{ws_src.cell(row=end_row, column=end_col).coordinate}\"\n",
" try:\n",
" ws_new.merge_cells(new_range)\n",
" except Exception as e:\n",
" print(f\"Ошибка объединения: {new_range} - {e}\")\n",
"\n",
" # Копирование высоты строк с учётом сдвига\n",
" for r in range(min_row, ws_src.max_row + 1):\n",
" height = ws_src.row_dimensions[r].height\n",
" if height is not None:\n",
" ws_new.row_dimensions[r + row_offset].height = height\n",
"\n",
" wb_new.save(output_file)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "41cb9036",
"metadata": {},
"outputs": [],
"source": [
"# Функция добавления листа с координатной системой СК-2011 для добавления на сайт с геологической информацией https://efgi.ru/\n",
"from openpyxl import load_workbook\n",
"from openpyxl.utils import get_column_letter\n",
"\n",
"def add_cs(excel_path):\n",
" # Данные для записи\n",
" headers = [\"СК\", \"EPSG\", \"Код в Proj4\"]\n",
" values = [\n",
" \"ГСК-2011\",\n",
" 7683,\n",
" \"+proj=longlat +a=6378136.5 +rf=298.2564151 \"\n",
" \"+towgs84=0.013,-0.092,-0.03,-0.001738,0.003559,-0.004263,0.0074 +no_defs\"\n",
" ]\n",
"\n",
" # Загружаем книгу\n",
" wb = load_workbook(excel_path)\n",
" \n",
" # Если лист с именем \"СК\" существует - удаляем его (чтобы заменить)\n",
" if \"СК\" in wb.sheetnames:\n",
" del wb[\"СК\"]\n",
"\n",
" # Создаём новый лист \"СК\"\n",
" ws = wb.create_sheet(\"СК\")\n",
"\n",
" # Записываем заголовки в первую строку\n",
" for col_num, header in enumerate(headers, start=1):\n",
" cell = ws.cell(row=1, column=col_num, value=header)\n",
"\n",
" # Записываем данные во вторую строку\n",
" for col_num, value in enumerate(values, start=1):\n",
" ws.cell(row=2, column=col_num, value=value)\n",
" \n",
" # Сохраняем файл\n",
" wb.save(excel_path)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "8d0cdc89",
"metadata": {},
"outputs": [],
"source": [
"# Словарь с названиями районов и ООПТ\n",
"dic_oopt = {\n",
"'anp-anap-soch-skal_pp_orz-new_WGS84': 'Анапа_Анапские сочащиеся скалы',\n",
"'anp-stepi-balki-zozulina_pp_orz-new_WGS84': 'Анапа_Степи балки Зозулина',\n",
"'anp-bujor-kodzor-les_orz-new_WGS84': 'Анапа_ПП Бужоро-Кодзорский лес',\n",
"'anp-krasnogor-les_pp_orz-new_WGS84': 'Анапа_ПП Красногорский лес',\n",
"'anp-kumatyr-hrebet_zak_orz_WGS84': 'Анапа_ПП Куматырский лес',\n",
"'anp-shkurat-les_orz-new_WGS84': 'Анапа_ПП Шкуратский лес',\n",
"'anp-yug-gostag-les_orz-new_WGS84': 'Анапа_ПП Южно-Гостагаевскй лес',\n",
"'anp-kurb-bugor_pp_orz-new_WGS84': 'Анапа_ПП Курбацкие бугры',\n",
"'anp-chekon-redkoles_orz-new_WGS84': 'Анапа_ПП Чеконское редколесье',\n",
"'brh-vys-bereg-beysug_pp_orz-new_WGS84': 'Брюховецкий_район_ПП_Высокий берег реки Бейсуг',\n",
"'glj-gebeus-gorn-mass_zak_orz-new_WGS84': 'Геленджик_ПП_Гебеусский горный массив',\n",
"'glj-mojj-redkles-gor-neksis_pp_orz-new_WGS84': 'Геленджик_ПП_Можжевеловые редколесья хребта Нексис',\n",
"'esk-voronts-step_pp_orz-new_WGS84': 'Ейский район_Воронцовская степь',\n",
"'esk-kruglaya-pad_pp_orz-new_WGS84': 'Ейский район_Круглая падь',\n",
"'esk-hans-yasen_zak_orz-new_WGS84': 'Ейский район_Ханско-Ясенский заказник',\n",
"'esk-yasnopol-step_pp_orz-new_WGS84': 'Ейский район_Яснопольская_степь',\n",
"'kvk-obrivistiy-bereg-reki-kuban_pp_orz-new_WGS84': 'Кавказский и Тбилисск район_Обрывистый берег реки Кубань',\n",
"'kvk-temijbek-vysok-bereg_pp_orz-new_WGS84': 'Кавказский_район_ПП_Темижбекский высокий берег',\n",
"'knv-bolot-albashi_lpk_orz-new_WGS84': 'Каневской_район_ ЛПК Болото Албаши',\n",
"'knv-chelbas-plavn_lpk_orz-new_WGS84': 'Каневской_район_ЛПК Челбасские плавни',\n",
"'knv-nijn-beisug-plavn_lpk_orz-new_WGS84': 'Каневской_район_ЛПК Нижнебейсугские плавни',\n",
"'kln-ponur-les_pp-orz-new_WGS84': 'Калининский_район_ПП Понурский лес',\n",
"'kln-ponura-liman_lpk_orz-new_WGS84': 'Калининский_район_ЛПК Понурский лиман',\n",
"'krl-balk-irinovka+_pp_orz-new_WGS84': 'Крыловский_район_ПП_Балка Ириновка',\n",
"'krl-balk-krutaya_pp_orz-new_WGS84': 'Крыловский район_Балка Крутая в долине реки Ея',\n",
"'krl-gryadin-plavn-rek-eya_pp_orz-new_WGS84': 'Крыловский_район_ПП_Грядинские плавни реки Ея',\n",
"'krl-balk-irinovka+_pp_orz-new_WGS84': 'Крыловский_район_ПП_Балка Ириновка',\n",
"'krm-uroch_kovalenkova_baga_pp_orz-new_WGS84': 'Крымский район_Коваленкова бага',\n",
"'ksh-poltavskiy-ostanec_pp_orz-new_WGS84': 'Кущевский район_Полтавский останец степи в долине реки Эльбузд',\n",
"'ksh-uroch-alekseevskoe_pp_orz-new_WGS84': 'Кущевский район_Урочище Алексеевское',\n",
"'ksh-shalfey-step-rek-elbuzd_pp_orz-new_WGS84': 'Кущевский_район_ПП_Шалфеевая_степь',\n",
"'mst-besleneev-pesheri_pp_orz-new_WGS84': 'Мостовской_р-н_ПП_Пещера Бесленеевская',\n",
"'nvk-kutanskaya-step_pp_orz-new_WGS84': 'Успенск_Новокуб_Армавир_р-н_ПП_Кутанская степь',\n",
"'nvp-fedorenk-bugr_pp_orz-new_WGS84': 'Новопокровский_район_ПП_Федоренковы бугры',\n",
"'nvk-fortshtadt-nagorn-step_pp_orz-new_WGS84': 'Армавир_Новокубанск_р-н_ПП_Фортштадская степь',\n",
"'nvr-abrau_zak+_orz-new_WGS84': 'Новороссийск_Абраусский заказник',\n",
"'nvr-abrau_zak_orz-IZMENENIE_WGS84': 'Новороссийск_Абраусский заказник_расширение Щурова',\n",
"'nvr-atakay-markoth_zak_orz-new_WGS84': 'Новороссийск_Атакайско-Маркотхский',\n",
"'nvr-kovilskaya-step_pp_orz-new_WGS84': 'Новороссийск_Ковыльская_степь_хребта_Сенетх',\n",
"'nvr-petrof-step-hr-seneth_pp_orz-new_WGS84': 'Новороссийск_Петрофитные_степи_Гора Самбурова',\n",
"'otr-dzheltmesskie-vysoty_zak_orz-new_WGS84': 'Отрадненский район_Джельтмесские Высоты',\n",
"'otr-chehrak+_zak_orz-new_WGS84': 'Отрадненский район_заказник Чехрак',\n",
"'otr-chehrak+_zak_orz-IZMENENIE_WGS84': 'Отрадненский район_заказник Чехрак_изменения ООПТ',\n",
"'pvl-urch-mugan_pp_orz-new_WGS84': 'Павловский_район_ПП_Урочище Муган',\n",
"'svr-hrebet-dlinn-gor_prz_orz-new_WGS84': 'Cеверский_район_ПРЗ Хребет Длинная гора',\n",
"'sch-aibga-grushevn_pp_orz-new_WGS84': 'Сочи_ПП_Аибгинский грушевник',\n",
"'sch-mamay-lesopark_zak_orz-new_WGS84': 'Сочи_Мамайский лесопарк',\n",
"'sch-urch-dzhegosh_pp_orz-new_WGS84': 'Сочи_ПП_Урочище Джегош',\n",
"'tmr-urochische-strelka-yuzhnaya_pp_orz-new_WGS84': 'Темрюкский район_Урочище Стрелка Южная',\n",
"'tbl-tbiliss_visokiy_bereg_pp_orz-new_WGS84': 'Тбилисский_р-н_ПП_Тбилисский высокий берег',\n",
"'tbl-savk-kruch_pp_orz-new_WGS84': 'Тбилисский_р-н_ПП_Савкины кручи',\n",
"'tps-gebeus-gorn-mass_zak_orz-new_WGS84': 'Туапсинский район_ПП_Гебеусский горный массив',\n",
"'usp-stepnoy_zak++_orz-new_WGS84': 'Успенский_р-н_заказник Степной',\n",
"'usp-uspen-poim-les_zak_orz-new_WGS84': 'Успенский_Отрадн_р-н_ПП_Успенские пойменные леса',\n",
"'ulb-uch-lesostep-rek-2-zelench_pp_orz-new_WGS84': 'Усть-Лаб_р-н_ПП_Участки лесостепи на р. Зеленчук',\n",
"'ulb-urochische-ladozhskoe_pp_orz-new_WGS84': 'Усть-Лабинский район_Урочище Ладожское',\n",
"'ulb-urochische-pyatihatskoe_pp_orz-new_WGS84': 'Усть-Лабинский район_Урочище Пятихатское',\n",
"'shr-eisk-plavn_lpk_orz-new_WGS84': 'Щербиновский район_ЛПК Ейские плавни',\n",
"'shr-uroch-tureckaya-krepost_ppk_orz-new_WGS84': 'Щербиновский район_ППК Турецкая крепость',\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "39a10e18",
"metadata": {},
"source": [
"#### Начало обработки"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "9730503b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['Input_processing\\\\tbl-tbiliss_visokiy_bereg_pp_orz-new_WGS84.shp', 'Input_processing\\\\Орнитологический Границы тропы.shp'] \n",
" Всего: 2 файл(-а, -ов)\n"
]
}
],
"source": [
"## Список файлов\n",
"folder = 'Input_processing' # папка для обработки\n",
"\n",
"lst = shp_lst(folder)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "cfbad0f3",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:7: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.font = src_cell.font.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:8: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.border = src_cell.border.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:9: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.fill = src_cell.fill.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:11: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.protection = src_cell.protection.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:12: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.alignment = src_cell.alignment.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:7: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.font = src_cell.font.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:8: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.border = src_cell.border.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:9: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.fill = src_cell.fill.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:11: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.protection = src_cell.protection.copy()\n",
"C:\\Users\\Evgenii\\AppData\\Local\\Temp\\ipykernel_43168\\1470149036.py:12: DeprecationWarning: Call to deprecated function copy (Use copy(obj) or cell.obj = cell.obj + other).\n",
" tgt_cell.alignment = src_cell.alignment.copy()\n"
]
},
{
"ename": "KeyError",
"evalue": "'Орнитологический Границы тропы'",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[10], line 40\u001b[0m\n\u001b[0;32m 37\u001b[0m merge_lst\u001b[38;5;241m.\u001b[39minsert(\u001b[38;5;241m0\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtemplate_gc.xlsx\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m 39\u001b[0m \u001b[38;5;66;03m# Имя из словаря со списком район+ООПТ по имени shape-файла\u001b[39;00m\n\u001b[1;32m---> 40\u001b[0m final_name \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mКоординаты_\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;241m+\u001b[39m \u001b[43mdic_oopt\u001b[49m\u001b[43m[\u001b[49m\u001b[43mshp_name\u001b[49m\u001b[43m]\u001b[49m \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_Участок_\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mstr\u001b[39m(counter) \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m.xlsx\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[0;32m 42\u001b[0m \u001b[38;5;66;03m# Объединяем все файлы из списка с сохранением исходного форматирования (функция)\u001b[39;00m\n\u001b[0;32m 43\u001b[0m concat_xlsx_with_style(merge_lst, final_name)\n",
"\u001b[1;31mKeyError\u001b[0m: 'Орнитологический Границы тропы'"
]
}
],
"source": [
"# Пакетная обработка\n",
"for shp in lst:\n",
" # Считываем файл\n",
" gdf = gpd.read_file(shp) \n",
" gdf = gdf.to_crs(7683) # Переводим в ГСК-2011\n",
" # Извлекаем имя файла\n",
" shp_name = os.path.basename(shp).split('.')[0]\n",
" # Счетчик для сохранения разных участков одной ООПТ\n",
" counter = 0\n",
" \n",
" # Превращаем возможных мултисоставной объект (multipart) в односоставной (singlepart)\n",
" gdf = gdf.explode(index_parts=False).reset_index(drop=True)\n",
" \n",
" # Создает список фреймов из каждой объекта (если многосоставной) \n",
" list_of_single_row_gdfs = [gdf.iloc[[i]] for i in range(len(gdf))]\n",
"\n",
" \n",
" for el in list_of_single_row_gdfs:\n",
" # Счетчик для номера участка внутри одного шейпа\n",
" counter += 1\n",
" merge_lst = []\n",
" # Вызов функции для расчета и форматирования координат\n",
" df = coordinates(el)\n",
" \n",
" name_xlsx = shp_name + '.xlsx'\n",
" df.to_excel(name_xlsx, header=False, index=False)\n",
" \n",
" # Форматируем файл через функцию\n",
" format_xlsx(name_xlsx, counter) \n",
" merge_lst.append(name_xlsx)\n",
" \n",
" # Создаем шапку для таблицы (функция), если файл не существует\n",
" if not os.path.exists('template_gc.xlsx'):\n",
" template_gc('template_gc.xlsx') \n",
" \n",
" # Добавлеем шапку таблицы в список файлов для обработки под номером 0\n",
" merge_lst.insert(0, 'template_gc.xlsx')\n",
" \n",
" # Имя из словаря со списком район+ООПТ по имени shape-файла\n",
" final_name = str('Координаты_') + dic_oopt[shp_name] + \"_Участок_\" + str(counter) + '.xlsx'\n",
" \n",
" # Объединяем все файлы из списка с сохранением исходного форматирования (функция)\n",
" concat_xlsx_with_style(merge_lst, final_name)\n",
" \n",
" # Добавляем второй лист с параметрами преобразования координат для геологического сервиса\n",
" add_cs(final_name)"
]
},
{
"cell_type": "markdown",
"id": "41efeb91",
"metadata": {},
"source": [
"## 4. Поворотные точки с 3 координатными системами (WGS84, МСК23, ГСК2011) - АНАПСКАЯ ПЕРЕСЫПЬ"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "1393e5ee",
"metadata": {},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"import pandas as pd\n",
"from os.path import splitext\n",
"import os"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "c264ba85",
"metadata": {},
"outputs": [],
"source": [
"# Функция создания списка шейпфайлов для обработки\n",
"def shp_lst(folder):\n",
" lst = []\n",
" for file in os.listdir(folder):\n",
" if file.endswith(\".shp\"):\n",
" lst.append(os.path.join(folder, file))\n",
" print(lst[:2], '\\n', f'Всего: {len(lst)} файл(-а, -ов)')\n",
" return lst\n",
"\n",
"### Функция создания таблицы с коодинатными системами\n",
"# Извлекаем имя файла\n",
"def coord_crs(shp):\n",
" shp_name = os.path.splitext(os.path.basename(shp))[0]\n",
" gdf = gpd.read_file(shp)\n",
" \n",
" # WGS84\n",
" gdf1 = gdf.to_crs(4326)\n",
" # Извлекаем координаты вертексов полигона (формат X, Y в текущей координатной системе)\n",
" df1 = gdf1.get_coordinates()\n",
" # Добавляем индекс к таблице\n",
" df1.reset_index(inplace = True, drop = True)\n",
" # Первая строка с 1\n",
" df1.index += 1\n",
" df1 = df1.reset_index()\n",
" df1 = round(df1,6)\n",
" df1.columns = ['N', 'Dolgota_X_WGS84', 'Shirota_Y_WGS84', ]\n",
" df1 = df1[['N', 'Shirota_Y_WGS84', 'Dolgota_X_WGS84']]\n",
"\n",
" #MSK23\n",
" gdf2 = gdf.to_crs(msk23_1)\n",
" df2 = gdf2.get_coordinates()\n",
" # Добавляем индекс к таблице\n",
" df2.reset_index(inplace = True, drop = True)\n",
" # Первая строка с 1\n",
" df2.index += 1\n",
" df2 = df2.reset_index()\n",
" # Округляем\n",
" df2 = round(df2)\n",
" df2.columns = ['N', 'Dolgota_X_MSK23', 'Shirota_Y_MSK23', ]\n",
" df2 = df2[['N', 'Shirota_Y_MSK23', 'Dolgota_X_MSK23']]\n",
"\n",
" #GSK2011\n",
" gdf3 = gdf.to_crs(7683)\n",
" df3 = gdf3.get_coordinates()\n",
" # Добавляем индекс к таблице\n",
" df3.reset_index(inplace = True, drop = True)\n",
" # Первая строка с 1\n",
" df3.index += 1\n",
" df3 = df3.reset_index()\n",
" df3 = round(df3,6)\n",
" df3.columns = ['N', 'Dolgota_X_GSK2011', 'Shirota_Y_GSK2011',]\n",
" df3 = df3[['N', 'Shirota_Y_GSK2011','Dolgota_X_GSK2011']]\n",
"\n",
" # Объединение таблиц с координатами (df1 и df2)\n",
" df1 = df1.merge(df2,left_on='N', right_on='N')\n",
" df1 = df1.merge(df3,left_on='N', right_on='N')\n",
" # Добавляем в конец дубликат первой строки\n",
" df1 = df1.take(list(range(len(df1) - 1)) + [0])\n",
" # Файлы Excel помещаются в папку скрипта с именем исходном файла\n",
" df1.to_excel(shp_name + '.xlsx', index=False)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "5ba0c820",
"metadata": {},
"outputs": [],
"source": [
"# Считываем проекцию в формате WKT и сохраняем ее в переменной\n",
"from pyproj import CRS\n",
"with open(r'F:\\PROJECT-Colormap\\Преобразования географических проекций (СК, ГСК-2011, МСК)\\МСК23 проекции Краснодар\\MCK-23_Zone_1N.prj', 'r') as f:\n",
" #wkt = f.read()\n",
" msk23_1 = f.read()\n",
"# crs = CRS.from_wkt(wkt)\n",
"\n",
"with open(r'F:\\PROJECT-Colormap\\Преобразования географических проекций (СК, ГСК-2011, МСК)\\МСК23 проекции Краснодар\\MCK-23_Zone_2N.prj', 'r') as f:\n",
" msk23_2 = f.read()"
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "b2077b77",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['Input_processing\\\\Орнитологический Границы тропы.shp'] \n",
" Всего: 1 файл(-а, -ов)\n"
]
}
],
"source": [
"## Список файлов\n",
"folder = 'Input_processing' # папка для обработки\n",
"\n",
"lst = shp_lst(folder)"
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "f97e8123",
"metadata": {},
"outputs": [],
"source": [
"# Обработка \n",
"for shp in lst:\n",
" coord_crs(shp)"
]
},
{
"cell_type": "markdown",
"id": "e5e45902",
"metadata": {},
"source": [
"### Тоже, что и выше, но создают для каждого элемента в шейпе отдельный файл Excel и название файла по номеру кад. участка (делал через Perplexity)"
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "1627e21e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['Input_processing\\\\selected_cad_numbers.shp'] \n",
" Всего: 1 файл(-а, -ов)\n",
"Готово: selected_cad_numbers -> Output_excel\n"
]
}
],
"source": [
"\n",
"\n",
"import geopandas as gpd\n",
"import pandas as pd\n",
"from os.path import splitext, basename, join\n",
"import os\n",
"from pyproj import CRS\n",
"\n",
"# ---------- Настройки ----------\n",
"INPUT_FOLDER = 'Input_processing' # папка для обработки\n",
"OUTPUT_FOLDER = 'Output_excel' # куда сохранять Excel\n",
"CAD_FIELD = 'cad_number' # имя столбца с кадастровым номером\n",
"MSK23_WKT_FILE = r'F:\\PROJECT-Colormap\\Преобразования географических проекций (СК, ГСК-2011, МСК)\\МСК23 проекции Краснодар\\MCK-23_Zone_1N.prj'\n",
"\n",
"# ---------- Вспомогательные ----------\n",
"def ensure_dir(path):\n",
" os.makedirs(path, exist_ok=True)\n",
"\n",
"def shp_lst(folder):\n",
" lst = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith(\".shp\")]\n",
" print(lst[:2], '\\n', f'Всего: {len(lst)} файл(-а, -ов)')\n",
" return lst\n",
"\n",
"def load_wkt(path):\n",
" with open(path, 'r', encoding='utf-8') as f:\n",
" return f.read()\n",
"\n",
"# ---------- Основная функция ----------\n",
"def export_features_to_excels(shp, msk23_wkt, output_dir=OUTPUT_FOLDER, cad_field=CAD_FIELD):\n",
" ensure_dir(output_dir)\n",
" shp_name = os.path.splitext(os.path.basename(shp))[0]\n",
" gdf = gpd.read_file(shp)\n",
"\n",
" if cad_field not in gdf.columns:\n",
" print(f'WARNING: {cad_field} не найден в {shp_name}. Будут использованы имена по индексу.')\n",
"\n",
" # Преобразования систем координат заранее\n",
" gdf_wgs = gdf.to_crs(4326) # WGS84\n",
" gdf_msk = gdf.to_crs(msk23_wkt) # MSK23 WKT\n",
" gdf_gsk = gdf.to_crs(7683) # GSK2011 / EPSG:7683\n",
"\n",
" # Проходим по каждому объекту\n",
" for i, (wgs_geom, msk_geom, gsk_geom, row) in enumerate(zip(gdf_wgs.geometry, gdf_msk.geometry, gdf_gsk.geometry, gdf.itertuples(index=False))):\n",
" # Имя файла\n",
" base_name = getattr(row, cad_field) if cad_field in gdf.columns else f'{shp_name}_feat_{i+1}'\n",
" base_name = str(base_name).replace(':', '_')\n",
"\n",
" # Собираем координаты вершин полигона/мультиполигона\n",
" def coords_as_df(geom, x_name, y_name, round_ndigits=None, round0=False):\n",
" # Разворачиваем в список колец\n",
" def extract_rings(g):\n",
" if g is None or g.is_empty:\n",
" return []\n",
" if g.geom_type == 'Polygon':\n",
" return [g.exterior] + list(g.interiors)\n",
" if g.geom_type == 'MultiPolygon':\n",
" rings = []\n",
" for p in g.geoms:\n",
" rings.append(p.exterior)\n",
" rings.extend(list(p.interiors))\n",
" return rings\n",
" # Для LineString/Point fallback\n",
" return [g]\n",
" pts = []\n",
" for ring in extract_rings(geom):\n",
" for x, y in ring.coords:\n",
" pts.append((y, x)) # хотим сначала Y, потом X\n",
" df = pd.DataFrame(pts, columns=[y_name, x_name]).reset_index(drop=True)\n",
" df.index += 1\n",
" df.insert(0, 'N', df.index)\n",
" if round0:\n",
" df[[y_name, x_name]] = df[[y_name, x_name]].round(0)\n",
" elif round_ndigits is not None:\n",
" df[[y_name, x_name]] = df[[y_name, x_name]].round(round_ndigits)\n",
" # Добавляем дубликат первой строки в конец\n",
" if len(df) > 0:\n",
" first_row = df.iloc[[0]].copy()\n",
" df = pd.concat([df.iloc[:-1], first_row], ignore_index=True)\n",
" df.index += 1\n",
" df['N'] = df.index\n",
" return df\n",
"\n",
" df_wgs = coords_as_df(wgs_geom, 'Dolgota_X_WGS84', 'Shirota_Y_WGS84', round_ndigits=6)\n",
" df_msk = coords_as_df(msk_geom, 'Dolgota_X_MSK23', 'Shirota_Y_MSK23', round0=True)\n",
" df_gsk = coords_as_df(gsk_geom, 'Dolgota_X_GSK2011', 'Shirota_Y_GSK2011', round_ndigits=6)\n",
"\n",
" # Объединяем по N\n",
" df = df_wgs.merge(df_msk, on='N', how='outer').merge(df_gsk, on='N', how='outer')\n",
"\n",
" # Сохраняем в Excel\n",
" out_path = os.path.join(output_dir, f'{base_name}.xlsx')\n",
" df.to_excel(out_path, index=False)\n",
"\n",
" print(f'Готово: {shp_name} -> {output_dir}')\n",
"\n",
"# ---------- Инициализация ----------\n",
"msk23_wkt = load_wkt(MSK23_WKT_FILE)\n",
"\n",
"# ---------- Запуск ----------\n",
"for shp in shp_lst(INPUT_FOLDER):\n",
" export_features_to_excels(shp, msk23_wkt)\n"
]
},
{
"cell_type": "markdown",
"id": "90e191f7",
"metadata": {},
"source": [
"## 5. Преобразование в MapInfo"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "afff19d6",
"metadata": {},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"import pandas as pd\n",
"from os.path import splitext\n",
"import os\n",
"\n",
"# Функция создания списка шейпфайлов для обработки\n",
"def shp_lst(folder):\n",
" lst = []\n",
" for file in os.listdir(folder):\n",
" if file.endswith(\".shp\"):\n",
" lst.append(os.path.join(folder, file))\n",
" print(lst[:2], '\\n', f'Всего: {len(lst)} файл(-а, -ов)')\n",
" return lst\n"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "76cbf432",
"metadata": {},
"outputs": [],
"source": [
"### Перевод в MapInfo\n",
"folder = 'Output'\n",
"for shp in lst:\n",
" shp_name = os.path.splitext(os.path.basename(shp))[0]\n",
" gdf = gpd.read_file(shp)\n",
" gdf.to_file(folder + '\\\\' + shp_name, driver='MapInfo File')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.14.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}