From c9003defb3a4982961d665c83973a700702f26e0 Mon Sep 17 00:00:00 2001 From: Sara <sarasdj@stud.ntnu.no> Date: Tue, 5 Mar 2024 11:37:10 +0100 Subject: [PATCH] update: divide polygon into tiles --- .../__pycache__/get_relation.cpython-311.pyc | Bin 3440 -> 3400 bytes server/map/get_relation.py | 104 ++++++++---------- 2 files changed, 44 insertions(+), 60 deletions(-) diff --git a/server/map/__pycache__/get_relation.cpython-311.pyc b/server/map/__pycache__/get_relation.cpython-311.pyc index 12b87d51b16f83f1ef4d1dc694a1692b02674d0f..1760906d6404076504fcbd8abf46308b0a8dab2a 100644 GIT binary patch literal 3400 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 literal 3440 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 DbxInr diff --git a/server/map/get_relation.py b/server/map/get_relation.py index 4ffd0409..a24d62ae 100644 --- a/server/map/get_relation.py +++ b/server/map/get_relation.py @@ -1,23 +1,31 @@ -import string import json import geopandas as gpd -from server.map.get_markers import get_all_markers -from shapely.geometry import Polygon, LineString, Point +from shapely.geometry import Polygon -# get_relation returns the geojson data for a selected body of water -def get_relation(self, body_of_water: string): +def get_relation(self, body_of_water: str): # Load GeoJSON data using geopandas geo_data = gpd.read_file("server/map/mjosa.geojson") - # Filter only polygons, exclude points + # Filter only polygons, exclude points and other feature types polygon_data = geo_data[geo_data['geometry'].geom_type == 'Polygon'] - # Convert GeoDataFrame to dictionary - geojson_dict = json.loads(polygon_data.to_json()) + # Extract coordinates from polygons and create polygon objects + polygons = [Polygon(polygon.exterior) for polygon in polygon_data['geometry']] + + if len(polygons) <= 1: + print("Failed to convert to polygons") + + tiles = [] + + for polygon in polygons: + tiles.extend(divide_relation(polygon)) # Divide each polygon from relation and append to tiles + + # Convert polygon coordinates to lists + tiles_json = [list(tile.exterior.coords) for tile in tiles] # Convert response data to JSON string - response_json = json.dumps(divide_relation(self, polygon_data)) + response_json = json.dumps(tiles_json) # Set headers self.send_response(200) @@ -28,54 +36,30 @@ def get_relation(self, body_of_water: string): self.wfile.write(response_json.encode('utf-8')) -def divide_relation(self, polygon): - # Fetch measurements from database - measurements = get_all_markers(self.cursor, False, 'Mjosa') - - # Temporary hardcoded point at which relation is split, should be - splitting_points = [(60.6853, 10.9571), (60.7018, 11.1058)] - - # Lists to hold new polygons - divided_relation = [] - temp_seg_1 = [] - temp_seg_2 = [] - - # Loop through polygon coordinates and split at defined coordinates - for i in range(len(polygon)): - - closest_point = [] - - # Find the closest point on the polygon to the splitting point - for point in splitting_points: - closest_point = polygon.exterior.interpolate(polygon.exterior.project(Point(point)),normalized=True) - - # Check if the closest point is already in the polygon coordinates - if closest_point.coords[0] not in polygon: - # If not, add it to the polygon coordinates - polygon.append(closest_point.coords[0]) - # Add the splitting point (either the original or the closest) to the splitting points list - splitting_points.append(closest_point.coords[0]) - - current_point = polygon[i] - next_point = polygon[(i + 1) % len(polygon)] # Circular index - - # Check if the current segment crosses any splitting point - for splitting_point in splitting_points: - if (current_point != splitting_point and - next_point != splitting_point and - LineString([current_point, next_point]).intersects(Point(splitting_point))): - # Split the segment at the splitting point - temp_seg_1.append(current_point) - temp_seg_2.append(splitting_point) - temp_seg_1.append(splitting_point) - temp_seg_2.append(next_point) - break - else: - # If the segment doesn't cross any splitting point, add it to both lists - temp_seg_1.append(current_point) - temp_seg_2.append(current_point) - - # Return a list containing all the created polygons - divided_relation = [Polygon(temp_seg_1), Polygon(temp_seg_2)] - - return divided_relation +def divide_relation(polygon): + # Define tile size + tile_size = 0.01 + + x_min, y_min, x_max, y_max = polygon.bounds + rows = int((y_max - y_min) / tile_size) + cols = int((x_max - x_min) / tile_size) + + tiles = [] + + if rows == 0 or cols == 0: # Return if the polygon is too small + return [] + + for row in range(rows): + for col in range(cols): + tile_bbox = Polygon([ + (x_min + col * tile_size, y_min + row * tile_size), + (x_min + (col + 1) * tile_size, y_min + row * tile_size), + (x_min + (col + 1) * tile_size, y_min + (row + 1) * tile_size), + (x_min + col * tile_size, y_min + (row + 1) * tile_size) + ]) + tiles.append(tile_bbox) + + if len(tiles) <= 1: + print("Failed to divide polygon into tiles") + + return tiles -- GitLab