# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
# ---

# # CoastSeg Prototype: Generating Polygons along a CoastLine
# - Author: <NAME>
# - Date: 1/13/2022
#
# ## Description
# This prototype is meant to show how you can generate polygons of various sizes along a coastline. The coastline in this prototype is only a geojson LineString for a small segment of the coast. Various widgets used to control the polygon generation are showcased, but none are implement with the exception of the size slider for the polygons.
#
# ## Dependencies
# 1. ipyleaflet
# 2. ipywidgets
# 3. leafmap

# +
from ipyleaflet import DrawControl
import leafmap
from ipyleaflet import Map, Polygon
from ipywidgets import Layout

# Center the map at the location where the coastvector is (swap the lat and lng)
shapes_list=[]
m = leafmap.Map(center=( 36.46098029888645, -121.9725021429323), zoom=13, layout=Layout(width='100%', height='100px'))

draw_control = DrawControl()
draw_control.polygon = {
    "shapeOptions": {
        "fillColor": "#a45df0",
        "color": "#6be5c3",
        "fillOpacity": 0.4
    },
    "drawError": {
        "color": "#dd253b",
        "message": "Ops!"
    },
    "allowIntersection": False,
    "transform":True
}

# Disable polyline, circle, and rectangle 
draw_control.polyline = {}
draw_control.circlemarker = {}
draw_control.rectangle = {}

# Each time a shape is drawn it is appended to the shapeslist which is used to create the bounding box
def handle_draw(target, action, geo_json):
    if draw_control.last_action == 'created':
        shapes_list.append( draw_control.last_draw['geometry'])
    print("\nshapes_list: ",shapes_list)

draw_control.on_draw(handle_draw)
m.add_control(draw_control)

m
# -

# # Adding Widgets
# ------

# ## Custom widget to show coordindates on hover
# 1. The first widget is completely optional. It allows the user to to the coordinates of their mouse on the map
#
# ### Try it Out
# - Hover your mouse on the map and watch how the coordinates below change

# +
from ipywidgets import Label
from ipyleaflet import Map


label = Label()
display(label)

def handle_interaction(**kwargs):
    if kwargs.get('type') == 'mousemove':
        label.value = str(kwargs.get('coordinates'))

m.on_interaction(handle_interaction)
m
# -

# ## More Widgets
# 1. Location of super bounding box from geojson
#     - A textarea that is used to hold the geojson of the bounding box
# 2. Size of the polygon ROI's
#     - The size of the polygons generated along the coast line vector can be manipulated with a slider
# 3. Percent Overlap
#     - The percentage of overlap between polygons generated along the coast line vector can be manipulated with a slider
# 4. Interval of ROI generation
#     - The distance between polygons that are generated along the coast line vector

# +
import ipywidgets as widgets
from ipywidgets import  Layout
style = {'description_width': 'initial'}

# Slider for the number of polygons to generate
# Not currently implement as of 1/3/2022
interval_slider=widgets.IntSlider(
    value=7,
    min=1,
    max=10,
    step=1,
    description='Interval for Polygon Generation(m):',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d',
    style=style,
    layout=Layout(width='45%', height='30px')
)

# Slider for the size of the polygons to generate
size_slider=widgets.FloatSlider(
    value=0.00005,
    min=0.00005,
    max=0.0002,
    step=0.00001,
    description='Polygon Size:',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='.5f',
)

# Slider for the size of the polygons to generate
# Not currently implement as of 1/3/2022
overlap_percent_slider=widgets.FloatSlider(
    value=0.0,
    min=0.0,
    max=0.5,
    step=0.01,
    description='% Overlap:',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='.2f',
)

# Textarea to hold the geojson of the bounding box
# Not currently implement as of 1/3/2022
bounding_box_geojson=widgets.Textarea(
    value="{\'type\':\'Polygon\', \'coordinates\': [[[-121.929078, 36.459534], [-121.929078, 36.463013], [-121.926211, 36.463013], [-121.926211, 36.459534], [-121.929078, 36.459534]]]}",
    placeholder='Type something',
    description='BBox GeoJson:',
    disabled=False,
    layout=Layout(width='50%', height='80px')
    , style=style
)


display(interval_slider)
display(size_slider)
display(overlap_percent_slider)
display(bounding_box_geojson)

# Set the polygon's size to the slider's value
polygon_size= size_slider.value
m
# -

polygon_size= size_slider.value
print(f"polygon_size: {polygon_size:.5f}")


# ## Convert ipyleaflet Polygon points to GeoJson
# 1. Ipyleaflet draws its shapes in lat,lng format and it must be converted to lng, lat for geojson.
# 2. In order to correctly draw a rectangle in geojson the order of the points matters as well.

def convert_to_geojson(upper_right_y, upper_right_x,upper_left_y, upper_left_x,lower_left_y,  lower_left_x,lower_right_y,lower_right_x):
    geojson_feature={}
    geojson_feature["type"]="Feature"
    geojson_feature["properties"]={}
    geojson_feature["geometry"]={}
    
    geojson_polygon={}
    geojson_polygon["type"]="Polygon"
    geojson_polygon["coordinates"]=[]
#     The coordinates(which are 1,2 arrays) are nested within a parent array
    nested_array=[]
    nested_array.append([upper_right_x, upper_right_y])
    nested_array.append([upper_left_x, upper_left_y])
    nested_array.append([lower_left_x, lower_left_y])
    nested_array.append([lower_right_x, lower_right_y])
    #GeoJson rectangles have the first point repeated again as the last point
    nested_array.append([upper_right_x, upper_right_y])

    geojson_polygon["coordinates"].append(nested_array)
    
    geojson_feature["geometry"]=geojson_polygon
#     new_polygon_list.append(new_polygon)
#     print(geojson_feature)
    return geojson_feature


# ## Generating Polygons Along a Vector
# 1. Import the geojson, LineString, that represents the coastline  vector.
# 2. Using the size slider from earlier the size of each polygon is chosen
# 3. The points of the each polygon are generated based on the size provided and their location along the LineString
# 4. Once all the polygons are generated they are converted to geojson for future use with geopandas.
# 5. To display the polygons on the map simply add each polygon as layer

# +
# TEMPORARY: hard coded vector (linestring) that holds the coast vector
# This would be replaced by the real coast vector
coast_vector_geojson={"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"LineString","coordinates":[[-121.92830801010132,36.46290061292468],[-121.92837238311768,36.46217580890998],[-121.92805051803589,36.46177888955466],[-121.92787885665892,36.46224483815569],[-121.92768573760988,36.46186517654388],[-121.92764282226564,36.461520028010895],[-121.92755699157713,36.46115762039776],[-121.92755699157713,36.46103681748364],[-121.92721366882324,36.46103681748364],[-121.92702054977417,36.46103681748364],[-121.9269347190857,36.461019559909126],[-121.92687034606932,36.46088149917467],[-121.92676305770874,36.460570861623395],[-121.92676305770874,36.46034651150687],[-121.92674160003662,36.4601911918152],[-121.92663431167601,36.460070387395476],[-121.9269347190857,36.45984603583096],[-121.92667722702028,36.45974248873611]]}}]}
m.add_geojson(coast_vector_geojson, layer_name="coast line")
m
# Get only the coordinates from the geojson these will be used to create the polygons and geojson
vector_points=coast_vector_geojson['features'][0]['geometry']['coordinates']
vector_points

from ipyleaflet import Map, Polygon
size=polygon_size
new_polygon_list=[]
geojson_polygons={"type": "FeatureCollection","features":[]}

# Create a rectangle at each point on the line
# Swap the x and y for each point because ipyleaflet swaps them for draw methods
for point in vector_points:
    upper_right_x=point[0]-(size/2)
    upper_right_y=point[1]-(size/2)
    upper_left_x=point[0]+(size/2)
    upper_left_y=point[1]-(size/2)
    lower_left_x=point[0]+(size/2)
    lower_left_y=point[1]+(size/2)
    lower_right_x=point[0]-(size/2)
    lower_right_y=point[1]+(size/2)
    
    #NOTE: the x and y are swapped because ipyleaflet swaps the latitude and the longtitude for polygons
    new_polygon=Polygon(
    locations=[(upper_right_y, upper_right_x),(upper_left_y, upper_left_x),( lower_left_y,  lower_left_x),(lower_right_y,lower_right_x)],
    color="pink",
    fill_color="pink")
    
    #Append the polygon we created to the list of polygons to draw onto the map
    new_polygon_list.append(new_polygon)
    
    #Convert each set of points to geojson (DONT swap x and y this time)
    geojson_polygon=convert_to_geojson(upper_right_y, upper_right_x,upper_left_y, upper_left_x,lower_left_y,  lower_left_x,lower_right_y,lower_right_x)
    geojson_polygons["features"].append(geojson_polygon)


# Draw all the polygons along the coast vector to the map  
for item in new_polygon_list:
    m.add_layer(item);

display(interval_slider)
display(size_slider)
display(overlap_percent_slider)
display(bounding_box_geojson)

polygon_size= size_slider.value
m.on_interaction(handle_interaction)
m

# -

# Print the geojson of the polygons generated by the application along the coast line
geojson_polygons



StarcoderdataJupyterScriptsDedupFiltered