Connor Sutton commited on
Commit
a69a345
1 Parent(s): 6286500

fixed reversed lon/lat with KML uploads

Browse files
geospatial-data-converter/kml_tricks.py CHANGED
@@ -5,6 +5,15 @@ import bs4
5
  import geopandas as gpd
6
  import lxml # nosec
7
  import pandas as pd
 
 
 
 
 
 
 
 
 
8
 
9
 
10
  def parse_descriptions_to_geodf(geodf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
@@ -41,6 +50,48 @@ def parse_descriptions_to_geodf(geodf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
41
  return result_geodf
42
 
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  def load_kmz_as_geodf(file_path: str) -> gpd.GeoDataFrame:
45
  """Loads a KMZ file into a GeoPandas DataFrame, assuming the KMZ contains one KML file"""
46
 
@@ -67,7 +118,6 @@ def load_kmz_as_geodf(file_path: str) -> gpd.GeoDataFrame:
67
 
68
  def load_ge_file(file_path: str) -> gpd.GeoDataFrame:
69
  """Loads a KML or KMZ file and parses its descriptions into a GeoDataFrame"""
70
-
71
  if file_path.endswith(".kml"):
72
  return parse_descriptions_to_geodf(
73
  gpd.read_file(file_path, driver="KML", engine="pyogrio"),
@@ -134,7 +184,6 @@ def extract_kml_code_from_file(file_path: str) -> str:
134
 
135
  def extract_data_from_ge_file(file_path: str) -> gpd.GeoDataFrame:
136
  """Extracts data from a Google Earth file (KML or KMZ) into a GeoDataFrame using SimpleData tags, excluding embedded tables in feature descriptions"""
137
-
138
  data_df = extract_data_from_kml_code(extract_kml_code_from_file(file_path))
139
 
140
  if file_path.endswith(".kmz"):
@@ -147,7 +196,7 @@ def extract_data_from_ge_file(file_path: str) -> gpd.GeoDataFrame:
147
  geometry=ge_file_gdf["geometry"],
148
  crs=ge_file_gdf.crs,
149
  )
150
-
151
  return geo_df
152
 
153
 
 
5
  import geopandas as gpd
6
  import lxml # nosec
7
  import pandas as pd
8
+ from shapely.geometry import (
9
+ Point,
10
+ LineString,
11
+ Polygon,
12
+ MultiPoint,
13
+ MultiLineString,
14
+ MultiPolygon,
15
+ LinearRing,
16
+ )
17
 
18
 
19
  def parse_descriptions_to_geodf(geodf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
 
50
  return result_geodf
51
 
52
 
53
+ def swap_coordinates(geometry):
54
+ """
55
+ Swap the latitude and longitude of Shapely Point, LineString, Polygon,
56
+ MultiPoint, MultiLineString, MultiPolygon, or LinearRing geometry.
57
+
58
+ Parameters:
59
+ - geometry: Shapely geometry (Point, LineString, Polygon, MultiPoint,
60
+ MultiLineString, MultiPolygon, or LinearRing)
61
+
62
+ Returns:
63
+ - Shapely geometry with swapped coordinates
64
+ """
65
+
66
+ def swap_coords(coords):
67
+ return [(coord[1], coord[0]) for coord in coords]
68
+
69
+ if isinstance(geometry, Point):
70
+ return Point([geometry.y, geometry.x])
71
+ elif isinstance(geometry, MultiPoint):
72
+ return MultiPoint(
73
+ [Point(swap_coords(point.coords)) for point in geometry.geoms],
74
+ )
75
+ elif isinstance(geometry, LineString):
76
+ return LineString(swap_coords(geometry.coords))
77
+ elif isinstance(geometry, MultiLineString):
78
+ return MultiLineString(
79
+ [LineString(swap_coords(line.coords)) for line in geometry.geoms],
80
+ )
81
+ elif isinstance(geometry, Polygon):
82
+ exterior_coords = swap_coords(geometry.exterior.coords)
83
+ interior_coords = [
84
+ swap_coords(interior.coords) for interior in geometry.interiors
85
+ ]
86
+ return Polygon(exterior_coords, interior_coords)
87
+ elif isinstance(geometry, MultiPolygon):
88
+ return MultiPolygon([swap_coordinates(poly) for poly in geometry.geoms])
89
+ elif isinstance(geometry, LinearRing):
90
+ return LinearRing(swap_coords(geometry.coords))
91
+ else:
92
+ raise ValueError("Unsupported geometry type")
93
+
94
+
95
  def load_kmz_as_geodf(file_path: str) -> gpd.GeoDataFrame:
96
  """Loads a KMZ file into a GeoPandas DataFrame, assuming the KMZ contains one KML file"""
97
 
 
118
 
119
  def load_ge_file(file_path: str) -> gpd.GeoDataFrame:
120
  """Loads a KML or KMZ file and parses its descriptions into a GeoDataFrame"""
 
121
  if file_path.endswith(".kml"):
122
  return parse_descriptions_to_geodf(
123
  gpd.read_file(file_path, driver="KML", engine="pyogrio"),
 
184
 
185
  def extract_data_from_ge_file(file_path: str) -> gpd.GeoDataFrame:
186
  """Extracts data from a Google Earth file (KML or KMZ) into a GeoDataFrame using SimpleData tags, excluding embedded tables in feature descriptions"""
 
187
  data_df = extract_data_from_kml_code(extract_kml_code_from_file(file_path))
188
 
189
  if file_path.endswith(".kmz"):
 
196
  geometry=ge_file_gdf["geometry"],
197
  crs=ge_file_gdf.crs,
198
  )
199
+ geo_df["geometry"] = geo_df["geometry"].apply(swap_coordinates)
200
  return geo_df
201
 
202
 
geospatial-data-converter/utils.py CHANGED
@@ -3,7 +3,6 @@ import os
3
  import zipfile
4
  from tempfile import TemporaryDirectory
5
  from typing import BinaryIO
6
-
7
  import geopandas as gpd
8
 
9
  from kml_tricks import load_ge_data
@@ -65,6 +64,9 @@ def convert(gdf: gpd.GeoDataFrame, output_name: str, output_format: str) -> byte
65
  if output_format == "CSV":
66
  gdf.to_csv(out_path)
67
  else:
 
 
 
68
  gdf.to_file(out_path, driver=output_format, engine="pyogrio")
69
 
70
  if output_format in ("ESRI Shapefile", "OpenFileGDB"):
 
3
  import zipfile
4
  from tempfile import TemporaryDirectory
5
  from typing import BinaryIO
 
6
  import geopandas as gpd
7
 
8
  from kml_tricks import load_ge_data
 
64
  if output_format == "CSV":
65
  gdf.to_csv(out_path)
66
  else:
67
+ # if output_format == 'KML': # need to longitude and latitude columns
68
+ # # gdf = gdf.apply(lambda row: swap_coordinates(row), axis=1)
69
+ # gdf['geometry'] = gdf['geometry'].apply(swap_coordinates)
70
  gdf.to_file(out_path, driver=output_format, engine="pyogrio")
71
 
72
  if output_format in ("ESRI Shapefile", "OpenFileGDB"):