From 93a573167a4d1c3de149c9298b67934564623303 Mon Sep 17 00:00:00 2001 From: Sara <sarasdj@stud.ntnu.no> Date: Mon, 11 Mar 2024 14:34:30 +0100 Subject: [PATCH] upadte: intiaial split shape --- app/lib/pages/widgets/cloropleth_map.dart | 72 +----------------- .../__pycache__/get_relation.cpython-311.pyc | Bin 4594 -> 5253 bytes server/map/get_relation.py | 46 +++++++---- 3 files changed, 35 insertions(+), 83 deletions(-) diff --git a/app/lib/pages/widgets/cloropleth_map.dart b/app/lib/pages/widgets/cloropleth_map.dart index 6cd8d968..9c59c4fd 100644 --- a/app/lib/pages/widgets/cloropleth_map.dart +++ b/app/lib/pages/widgets/cloropleth_map.dart @@ -59,82 +59,14 @@ class _ChoroplethMapState extends State<ChoroplethMap> { primaryValueMapper: (int index) => iceThicknessList[index].subDivID, shapeColorValueMapper: (int index) => iceThicknessList[index].thickness, ), - color: Colors.lightBlueAccent, // Map color + color: Colors.blue.shade400, // Map color zoomPanBehavior: _zoomPanBehavior, - strokeColor: Colors.orange, + strokeColor: Colors.black, ), ], ), - CustomPaint( // Render polygons clipped on map - size: Size.infinite, - painter: OverlayPainter(mapData: widget.relation), - ), ], ); } } - -/// OverlayPainter is a class extending CustomPainter to -class OverlayPainter extends CustomPainter { - final Uint8List mapData; - - const OverlayPainter({ - required this.mapData, // Pass map shape - }); - - @override - void paint(Canvas canvas, Size size) { - // NB: test polygon - Path testPol = Path(); - testPol.moveTo(60.8015, 10.5908); - testPol.lineTo(60.5146, 10.8270); - testPol.lineTo(60.7115, 11.3242); - testPol.close(); - - // Decode map data - var mapShape = json.decode(utf8.decode(mapData)); - - // Extract polygons and render them - for (var feature in mapShape['features']) { - var geometry = feature['geometry']; - var coordinates = geometry['coordinates']; - - for (var ring in coordinates) { - var points = <Offset>[]; - for (var point in ring) { - points.add(Offset(point[0], point[1])); - } - var path = Path()..addPolygon(points, true); - - // Render each map shape - canvas.drawPath(path, Paint()..color = Colors.lightBlueAccent); - } - } - - // Now clip the rendering to the map shape - var mapBoundsPath = Path(); - for (var feature in mapShape['features']) { - var geometry = feature['geometry']; - var coordinates = geometry['coordinates']; - - for (var ring in coordinates) { - var points = <Offset>[]; - for (var point in ring) { - points.add(Offset(point[0], point[1])); - } - mapBoundsPath.addPolygon(points, true); - } - } - canvas.clipPath(mapBoundsPath); - - // Render test shape over map, not clipped to map - canvas.drawPath(testPol, Paint()..color = Colors.pink.shade900); - } - - - @override - bool shouldRepaint(covariant CustomPainter oldDelegate) { - return false; - } -} diff --git a/server/map/__pycache__/get_relation.cpython-311.pyc b/server/map/__pycache__/get_relation.cpython-311.pyc index 1a49b7006d65c76c71c4ebaa80c673617677d1bd..f8284994a9998d150a327d0e5a06b482735e9e22 100644 GIT binary patch delta 2394 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 b6_D3vP-cdh_$pWjCm6^Ktb&I@JNkbBffRqt delta 1770 zcma)6UrZxK7~g4Uw}04f+vQH+JfH`7P&uj87$Z5aA)&xkC7gFLIUa0EXX*8B>DK9T z98f|v7&Y;Mb4}>OCHBE!E}${;f=^z2@VVPGfowto51Q~|>Ypd0;>`9>fSifb+3)+! zH{X0SU%%hX2mar>g)dz$CqtTi_>1%%|4?WJ6AybkR{(<;1Y~a3Hf672$CMLUrKTAR zf~#<fN9-yy<w6{h0s=P~zwL;|nebZ;+oU2dB$SlFPAbWiYB=9WrlgxHPNouuYg$1I zQDr7NA5$e9x6n1U#u9BM-|u<L_7D(2Fbk1mgLrH<yp~xN)ZG~dIXB2?vta>@_KxL3 zE8>xBOV}WxHfcDs0Y-IePb}xOkD#DctSoS7D(v=hS*Bp7U-#3}*47|kh`Fh5I;oKd zc~76n^yNvgu4@$Db=BPqLLHsdS+3wdIj&<QYKztmEzPo^dHX)w4uD7dj7z?iSUUIh z*x}-8Xwe&fAjRiY3Hea+zAqk=WdlyjbCSU+IF?FCiE5~W5Geo~S7Zen4hbcs8k9*1 z=95Uhqy1=mfdv1<*4t&cNvI@}qF9n+YLXNTre#GntZ7*_VCIf8uYGI3?ywOo$upSK zpyTputeTXijNvp@^lnB;Wo%??U$tSHwZSJOwGk8#5EFIDi~=q1$lm%1I*QIt9s0`9 zSA@QO{@MI^0qJ~yneWeq_vviA4m--QqX;`H9K$+4jJzLNd%N&p=cQakhoLeI6=7%} z+E&Nki>yX+kqW0h*R%jU+n+ZDt)iFgbwnw1M9c37*sdK4ef@@$a8be;DXwM=E|yM9 zDTLdIhry3Y%1BI&jpEp><agqJt;g--XeIF#E#eNjX;QeoE}q~1!u<nS@sRN;{&K`% z^7j#8<T`VTsQ`h~yeTwTOI9@+vYcjgp~3uy3jt>2!I}mA-_TaVu#3&h7M0ebz8E4l zp?&Xd??Di8i8H$|!>sk>IkkVl1<x{@g=dXdmbt9u>1WNdXEW0Bmdj&^Auon~0@M8P zi&W66`7KogwGvEIG(`;`{e66VocQbUucbGqCqsUSq1JA1S;6$-@Y``ebswUFmd;=) z<p--OXgJJKG_A;07&KuMxfB%8*D7Ntt7<g%Re9_^b3dX%93f5<<jZUkkz@9S=9RVK zwRb<h_sP9o!B-M|1+Ol2mxb<KVW1=od^PvYjUDiKX=`aWFkA`@Ke?m_M#_N^T?m(j zaBgg$e<sfrxMEAM&i9r1KEi*~Vk@@v>Ab(p`*Yy~&-r!!Q$Bx7_jHv#UAgOfrwmt# z<v?uP6?;lzPvN#M2FhY!R~#ydLp!hPVz?}ZbFb4Mri}Hw4M##!(y<hZWpJCOi#^)0 zcyXnZ%o%KIZZ^GuU#8faQL%Y-tHh^yWBOE@QOv*RPy5wb1<lFQHGG3iP(o+ciKtis z0DDYJvEKKXSBn4L_n6Kiqy60MzAYA+TCZ?EFj$CJ7^2RKQE&;IuP_ZU4(wnQRG6nr H^SJ*4KNO=! diff --git a/server/map/get_relation.py b/server/map/get_relation.py index 6c7db641..360d2451 100644 --- a/server/map/get_relation.py +++ b/server/map/get_relation.py @@ -1,7 +1,10 @@ import geopandas as gpd -from shapely.geometry import Polygon, Point, LineString +from shapely.geometry import Polygon, Point, LineString, MultiLineString, MultiPolygon import matplotlib.pyplot as plt +from shapely.ops import linemerge, unary_union, polygonize +import matplotlib.ticker as ticker import numpy as np +import pandas as pd def get_relation(self, body_of_water: str): @@ -19,14 +22,32 @@ def get_relation(self, body_of_water: str): print("Failed to convert to polygons") return + ######################################################################################## print("Performing div call") - tiles = divide_relation(polygons, 0.01) # NB: any size under 0.02 will require patience - print("Executed div call") + # NB: any cell size under 0.02 will require patience + # For example, 0.007 requires up to 3 minutes to compute + # tiles = divide_relation(polygons, 0.02) - # NB: temp test plot of map - tiles.plot(color='blue', edgecolor='orange', linewidth=0.5) + test_line = LineString([(10.4600, 60.7451), (11.2000, 60.7451)]) + line_pol = test_line.buffer(1e-3) + + new_polygon = polygons[0].difference(line_pol) + + tiles = gpd.GeoDataFrame(geometry=[new_polygon]) + + fig, ax = plt.subplots() + + ax.set_aspect(1.5) + ax.xaxis.set_major_locator(ticker.MultipleLocator(0.2)) + tiles.plot(ax=ax, color='blue', edgecolor='blue', alpha=0.5, label='Original Polygon') plt.show() + if test_line.intersects(polygons[0].boundary): + print("Intersects!") + else: + print("Test line does not intersect the polygon") + + ######################################################################################## # Convert GeoDataFrame to GeoJSON tiles_json = tiles.to_json() @@ -39,6 +60,7 @@ def get_relation(self, body_of_water: str): self.wfile.write(tiles_json.encode('utf-8')) +######################### Approach 1 ################################# def divide_relation(polygons, cell_size): # Calculate the combined bounding box of all polygons combined_bounds = polygons[0].bounds @@ -75,12 +97,10 @@ def divide_relation(polygons, cell_size): return tiles_gdf -def divide_relation_2(polygons, cell_size): - polygon = Point(0, 0).buffer(2).difference(Point(0, 0).buffer(1)) - line1 = LineString([(0, 0), (3, 3)]) - line2 = LineString([(0, 0), (3, -3)]) - - line1_pol = line1.buffer(1e-3) - line2_pol = line2.buffer(1e-3) +######################### Approach 2 ################################# - new_polygon = polygon.difference(line1_pol).difference(line2_pol) +def cut_polygon_by_line(polygon, line): + merged = linemerge([polygon.boundary, line]) + borders = unary_union(merged) + polygons = polygonize(borders) + return list(polygons) -- GitLab