Created
March 22, 2017 19:27
-
-
Save brikeats/52689a72a19f1b85f3942fd6e04652df to your computer and use it in GitHub Desktop.
Create a google maps webpage with polygons and heatmaps from geojson annotations and yield shapefiles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import shapely | |
html_template_part1 = """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>%s</title> | |
<style> | |
/* Always set the map height explicitly to define the size of the div | |
* element that contains the map. */ | |
#map { | |
height: 100%%; | |
} | |
/* Optional: Makes the sample page fill the window. */ | |
html, body { | |
height: 100%%; | |
margin: 0; | |
padding: 0; | |
} | |
#floating-panel { | |
position: absolute; | |
top: 10px; | |
left: 25%%; | |
z-index: 5; | |
background-color: #fff; | |
padding: 5px; | |
border: 1px solid #999; | |
text-align: center; | |
font-family: 'Roboto','sans-serif'; | |
line-height: 30px; | |
padding-left: 10px; | |
} | |
#floating-panel { | |
background-color: #fff; | |
border: 1px solid #999; | |
left: 25%%; | |
padding: 5px; | |
position: absolute; | |
top: 10px; | |
z-index: 5; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="floating-panel"> | |
<button onclick="toggleHeatmap()" id="heatmapToggleButton">Show Heatmaps</button> | |
</div> | |
<div id="map"></div> | |
<script> | |
// This example requires the Visualization library. Include the libraries=visualization | |
// parameter when you first load the API. For example: | |
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=visualization"> | |
var polygons = []; | |
var heatmaps = []; | |
function initMap() { | |
var bounds = new google.maps.LatLngBounds(); | |
bounds.extend(new google.maps.LatLng(%.6f, %.6f)); | |
bounds.extend(new google.maps.LatLng(%.6f, %.6f)); | |
map = new google.maps.Map(document.getElementById('map'), { | |
center: {lat: %.4f, lng: %.4f}, | |
mapTypeId: 'satellite' | |
}); | |
map.fitBounds(bounds); | |
map.addListener('zoom_changed', function() { | |
onZoomChange(map.getZoom()); | |
}); | |
""" | |
html_template_part2 = """ | |
} | |
function toggleHeatmap() { | |
var button = document.getElementById("heatmapToggleButton"); | |
// change label | |
if (button.innerHTML=="Show Heatmaps") { | |
button.innerHTML = "Show Polygons"; | |
for (var i=0; i < polygons.length; i++) | |
polygons[i].setMap(null); | |
for (var i=0; i < heatmaps.length; i++) | |
heatmaps[i].setMap(map); | |
} | |
else { | |
button.innerHTML = "Show Heatmaps"; | |
for (var i=0; i < polygons.length; i++) | |
polygons[i].setMap(map); | |
for (var i=0; i < heatmaps.length; i++) | |
heatmaps[i].setMap(null); | |
} | |
} | |
function onZoomChange(zoom){ | |
var button = document.getElementById("heatmapToggleButton"); | |
console.log('new zoom level: '+zoom); | |
if (button.innerHTML=="Show Polygons") { // when button has "Show Polygons", the heatmap is being displayed | |
for (var i=0; i < heatmaps.length; i++){ | |
heatmaps[i].radius = Math.pow(2, zoom-16); | |
console.log('new radius: '+heatmaps[i].radius); | |
} | |
} | |
} | |
</script> | |
<script async defer | |
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDZ6DjC_TDxBNQjkscsdV3ffPW4SCWC7-E&libraries=visualization&callback=initMap"> | |
</script> | |
</body> | |
</html> | |
""" | |
def points_to_javascript_polygon(points, poly_index=0): | |
html = 'var coords%i = [\n' % poly_index | |
for pt_num, pt in enumerate(points): | |
html += """\t\t{lat: %.6f, lng: %.6f}""" % (pt[1], pt[0]) | |
if pt_num != len(points) - 1: | |
html += ',\n' | |
html += '];' | |
html += """ | |
var polygon%i = new google.maps.Polygon({ | |
paths: coords%i, | |
strokeColor: '#FF0000', | |
strokeOpacity: 0.7, | |
strokeWeight: 0, | |
fillColor: '#FF0000', | |
fillOpacity: 0.35 | |
}); | |
polygon%i.setMap(map); | |
polygons.push(polygon%i); | |
""" % (poly_index, poly_index, poly_index, poly_index) | |
return html | |
def points_to_javascript_heatmap(points, weights, heatmap_index=0): | |
html = """var heatmap%i = new google.maps.visualization.HeatmapLayer({ | |
data: [""" % heatmap_index | |
for pt_num, (pt, weight) in enumerate(zip(points, weights)): | |
html += '\t\t\t{location: new google.maps.LatLng(%.6f, %.6f), weight: %.3f}' % (pt[1], pt[0], weight) | |
if pt_num != len(points) - 1: | |
html += ',' | |
html += '\n' | |
html += """], | |
radius: 0.5, | |
opacity: 0.7 | |
}); | |
heatmaps.push(heatmap%i); | |
""" % heatmap_index | |
return html | |
def fill_heatmap_template(yield_data, field_polygons, title=''): | |
if len(field_polygons) == 1: | |
field_polygons = shapely.geometry.MultiPolygon([field_polygons]) | |
else: | |
field_polygons = shapely.geometry.MultiPolygon(field_polygons) | |
min_lng, min_lat, max_lng, max_lat = field_polygons.bounds | |
center = np.array([(min_lng + max_lng) / 2, (min_lat + max_lat) / 2]) | |
TR = max_lng, max_lat | |
BL = min_lng, min_lat | |
if not title: | |
title = '(lat, lng) = (%.3f, %.3f)' % (center[1], center[0]) | |
html = html_template_part1 % (title, TR[1], TR[0], BL[1], BL[0], center[1], center[0]) | |
# Add polygons for field boundaries | |
for poly_num, polygon in enumerate(field_polygons): | |
html += points_to_javascript_polygon(np.array(polygon.boundary), poly_num) | |
# Add heatmaps | |
for num, weighted_pts in enumerate(yield_data): | |
pts = weighted_pts[:, :2] | |
weights = weighted_pts[:, 2] | |
html += points_to_javascript_heatmap(pts, weights, num) | |
html += html_template_part2 | |
# write the html and open the webpage | |
html_fn = 'webpage.html' | |
with open(html_fn, 'wt') as f: | |
f.write(html) | |
import geopandas | |
from shapely.geometry import MultiPoint | |
field_polygons = [] | |
with open('yield_data/gridded_data_field.json') as f: | |
polygon = shape(geojson.load(f)) | |
field_polygons.append(polygon) | |
with open('yield_data/gridded_data_2016_corn_field1.json') as f: | |
polygon = shape(geojson.load(f)) | |
field_polygons.append(polygon) | |
# yield_data = [] | |
# gdf = geopandas.read_file('yield_data/gridded_data.shp') | |
# points = np.asarray(MultiPoint(gdf.geometry)) | |
# yield_data.append(np.hstack([points, np.expand_dims(gdf.dry_yield.values, -1)])) | |
# gdf = geopandas.read_file('yield_data/gridded_data_2016_corn.shp') | |
# points = np.asarray(MultiPoint(gdf.geometry)) | |
# yield_data.append(np.hstack([points, np.expand_dims(gdf.dry_yield.values, -1)])) | |
fill_heatmap_template(yield_data, field_polygons) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment