Skip to content

Commit 2dad30f

Browse files
authored
Merge pull request #8 from JonasCinquini/main
Merging main into dev
2 parents 7a37acc + 5d2675b commit 2dad30f

9 files changed

+174
-363
lines changed

PtsLine.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
class PtsLine:
1313
"""
1414
Class to compute the equation of a line passing through two points.
15+
Note: this class does not check if:
16+
- the two points are the same
17+
- the two points are aligned [Vertical or Horizontal Line]
1518
"""
1619
def __init__(self, x_pt1: float, y_pt1: float,
1720
x_pt2: float, y_pt2: float) -> None:

generate_grid.py

Lines changed: 1 addition & 358 deletions
Large diffs are not rendered by default.

iride_csk_frame_grid_utils.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from shapely.geometry import Polygon
2222
from shapely.affinity import rotate
2323
from math import ceil
24+
from typing import Tuple
2425

2526

2627
def add_frame_code_field(grid_gdf):
@@ -123,10 +124,13 @@ def get_fishnet_grid(xmin: float, ymin: float, xmax: float, ymax: float,
123124
return gdf
124125

125126

126-
def rotate_polygon_to_north_up(geometry):
127+
def rotate_polygon_to_north_up(geometry: Polygon) -> Tuple[Polygon, float]:
127128
"""
128129
Rotate a polygon to align its orientation with the north.
129130
131+
NOTE: The function assumes that the polygon has approximately
132+
a rectangular shape. The rotation angle is calculated
133+
based on the orientation of the shorted side of the polygon.
130134
Parameters:
131135
geometry (Polygon): Input polygon.
132136
@@ -135,9 +139,27 @@ def rotate_polygon_to_north_up(geometry):
135139
angle (float): Angle of rotation.
136140
"""
137141
exterior_coords_list = geometry.exterior.coords[:-1]
138-
p1 = min(exterior_coords_list, key=lambda t: t[0])
139-
ind_p1 = exterior_coords_list.index(p1)
140-
p2 = exterior_coords_list[ind_p1+1]
142+
# - Find the lowest corner in the north-south direction
143+
p_south = min(exterior_coords_list, key=lambda t: t[1])
144+
145+
# - Find the furthest corners in the x-direction
146+
# - to approximate the orientation of the polygon
147+
p_east = max(exterior_coords_list, key=lambda t: t[0])
148+
ind_p_east = exterior_coords_list.index(p_east)
149+
p_west = min(exterior_coords_list, key=lambda t: t[0])
150+
ind_p_west = exterior_coords_list.index(p_west)
151+
152+
# - Find the corner closest to the south corner
153+
# - to approximate the orientation of the polygon
154+
dist_east = math.sqrt((p_south[0] - p_east[0])**2
155+
+ (p_south[1] - p_east[1])**2)
156+
dist_west = math.sqrt((p_south[0] - p_west[0])**2
157+
+ (p_south[1] - p_west[1])**2)
158+
p1 = p_south
159+
if dist_east < dist_west:
160+
p2 = exterior_coords_list[ind_p_east]
161+
else:
162+
p2 = exterior_coords_list[ind_p_west]
141163

142164
angle = math.degrees(math.atan2(p2[1] - p1[1], p2[0] - p1[0]))
143165
centroid = (geometry.centroid.x, geometry.centroid.y)

mapitaly_at_grid.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# - Python Dependencies
2+
from __future__ import print_function
3+
import os
4+
import argparse
5+
from datetime import datetime
6+
import numpy as np
7+
import geopandas as gpd
8+
from rm_z_coord import rm_z_coord
9+
10+
11+
def main() -> None:
12+
# - Path to data
13+
dat_path = os.path.join(os.path.expanduser("~"), 'Desktop', 'MapItaly',
14+
'MAPITALY_CSG1_2_CSK1_2.shp')
15+
16+
# - Read data
17+
gdf = gpd.read_file(dat_path)
18+
print(f"# - Data loaded: {dat_path}")
19+
print(f"# - Data shape: {gdf.shape}")
20+
print(f"# - Data columns: {gdf.columns}")
21+
22+
# - Remove Z-Coordinate from geometry
23+
gdf = rm_z_coord(gdf)
24+
25+
# - Loop through the GeoDataFrame lines and extract a reference grid
26+
# - for each sub-track.
27+
for _, row in gdf.iterrows():
28+
# - Check Polygon Validity
29+
print(row['geometry'].is_valid)
30+
31+
32+
# - run main program
33+
if __name__ == '__main__':
34+
start_time = datetime.now()
35+
main()
36+
end_time = datetime.now()
37+
print(f"# - Computation Time: {end_time - start_time}")

reproject_geometry.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python
2+
"""
3+
Written by Enrico Ciraci'
4+
January 2024
5+
6+
Reproject a Shapely geometry.
7+
"""
8+
from shapely.geometry import Polygon, Point
9+
from pyproj import CRS, Transformer
10+
from shapely.ops import transform
11+
12+
13+
def reproject_geometry(geometry: Polygon | Point,
14+
source_epsg: int, target_epsg: int) -> Polygon | Point:
15+
"""
16+
Reproject a Shapely geometry.
17+
Args:
18+
geometry: shapely.geometry.Polygon | shapely.geometry.Point
19+
source_epsg: source EPSG code
20+
target_epsg: target EPSG code
21+
22+
Returns: shapely.geometry.Polygon | shapely.geometry.Point
23+
"""
24+
# Set up coordinate reference systems
25+
target_crs = CRS.from_epsg(target_epsg)
26+
# Create a transformer for the coordinate transformation
27+
transformer = Transformer.from_crs(source_epsg, target_crs, always_xy=True)
28+
try:
29+
# - Polygon
30+
return geometry.apply(lambda geom:
31+
transform(transformer.transform, geom))
32+
except AttributeError:
33+
# - Point
34+
return transform(transformer.transform, geometry)

rm_z_coord.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env python
2+
import geopandas as gpd
3+
from shapely.geometry import Polygon
4+
"""
5+
Written by Enrico Ciraci'
6+
January 2024
7+
8+
Remove z coordinate from a GeoDataFrame.
9+
Convert a GeoDataFrame with z coordinate to a GeoDataFrame without z coordinate.
10+
"""
11+
12+
13+
def rm_z_coord(gdf) -> gpd.GeoDataFrame:
14+
"""
15+
Remove z coordinate from a GeoDataFrame
16+
Args:
17+
gdf: GeoDataFrame
18+
19+
Returns:
20+
21+
"""
22+
# - remove z coordinate
23+
no_z_coord = []
24+
for _, row in gdf.iterrows():
25+
# - remove z coordinate
26+
z_coords = row['geometry'].exterior.coords[:-1]
27+
no_z_coord.append(Polygon([(crd[0], crd[1]) for crd in z_coords]))
28+
gdf['geometry'] = no_z_coord
29+
30+
return gdf

test/reproj_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
""" Unit tests for the reproject_geometry function. """
33
import pytest
44
from shapely.geometry import Point, Polygon
5-
from generate_grid import reproject_geometry
5+
from reproject_geometry import reproject_geometry
66

77
@pytest.fixture
88
def example_polygon():

test/test_generate_grid.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import geopandas as gpd
2+
from shapely.geometry import Polygon
3+
from generate_grid import generate_grid
4+
5+
6+
def test_generate_grid():
7+
# Create a sample GeoDataFrame for testing
8+
d = {'index': 1,
9+
'geometry': Polygon([(12, 36), (11.5, 38), (14, 38.5),
10+
(14, 36.5), (12, 36)])}
11+
gdf_t = gpd.GeoDataFrame(d, crs='EPSG:4326', index=[0])
12+
13+
n_c = 3
14+
az_res = 5000
15+
buffer_dist = 1000
16+
17+
# Ensure the function runs without errors
18+
result_gdf = generate_grid(gdf_t, n_c, az_res, buffer_dist)
19+
20+
# Perform assertions based on your expectations for the result
21+
assert isinstance(result_gdf, gpd.GeoDataFrame)
22+
assert len(result_gdf) > 0

test/test_rotate_nu.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import geopandas as gpd
2+
from shapely.geometry import Polygon
3+
from iride_csk_frame_grid_utils import rotate_polygon_to_north_up
4+
from math import isclose
5+
6+
7+
def test_rotate_polygon_to_north_up():
8+
"""
9+
Test the rotate_polygon_to_north_up function.
10+
"""
11+
# Create a sample GeoDataFrame for testing
12+
polygon = Polygon([(12, 36), (11.5, 38), (14, 38.5),
13+
(14, 36.5), (12, 36)])
14+
15+
# Ensure the function runs without errors
16+
rotated_polygon, angle = rotate_polygon_to_north_up(polygon)
17+
18+
# Perform assertions based on your expectations for the result
19+
assert isinstance(rotated_polygon, Polygon)
20+
assert isinstance(angle, float)

0 commit comments

Comments
 (0)