Skip to content

Commit

Permalink
Support linestring (#92)
Browse files Browse the repository at this point in the history
* Add LinestringViz class with associated geojson and vector-based templates

* Add data-driven styling to vector linestring viz

* Example linestring viz and vector linestring viz

* Refine linestring iz with data-driven styles for line width; update viz arguments; refine default color and line width handling

* Testing linestring viz examples (further refinements pending)

* Add tests for numeric_map, LinestringViz

* Delete out.geojson

* Fix link to example data (#91)

* Refine linestring iz with data-driven styles for line width; update viz arguments; refine default color and line width handling

* Testing linestring viz examples (further refinements pending)

* Add tests for numeric_map, LinestringViz

* Fix utils import for test_utils.py

* Update linestring viz notebook

* Add line_width_property to vector LinestringViz test

* Update label style to match CircleViz properties

* Add linestring viz docs
  • Loading branch information
akacarlyann authored and ryanbaumann committed Apr 26, 2018
1 parent b3bc6cd commit ea49a97
Show file tree
Hide file tree
Showing 9 changed files with 901 additions and 4 deletions.
72 changes: 71 additions & 1 deletion docs-markdown/viz.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,4 +458,74 @@ viz.show()
![RasterTilesViz](https://user-images.githubusercontent.com/10407788/37537676-b055a108-2924-11e8-94cb-ad3203b736af.jpg)


[Complete example](https://github.com/mapbox/mapboxgl-jupyter/blob/master/examples/rastertile-viz-types-example.ipynb)
[Complete example](https://github.com/mapbox/mapboxgl-jupyter/blob/master/examples/rastertile-viz-types-example.ipynb)


## class LinestringViz

The `LinestringViz` object handles the creation of a vector or GeoJSON-based Linestring visualization and inherits from the `MapViz` class.

### Params
**LinestringViz**(_data, vector_url=None, vector_layer_name=None, vector_join_property=None, data_join_property=None, label_property=None, label_size=8, label_color='#131516', label_halo_color='white', label_halo_width=1, color_property=None, color_stops=None, color_default='grey', color_function_type='interpolate', line_stroke='solid', line_width_property=None, line_width_stops=None, line_width_default=1, line_width_function_type='interpolate', *args, **kwargs_)


Parameter | Description | Example
--|--|--
data | can be either GeoJSON (containing polygon features) or JSON for data-join technique with vector polygons |
vector_url | optional property to define vector linestring source | "mapbox://mapbox.mapbox-terrain-v2"
vector_layer_name | property to define target layer of vector source if using vector linestring source | "contour"
vector_join_property | property to aid in determining color for styling vector lines | "ele"
data_join_property | property of json data to use as link to vector features | "elevation"
label_property | property to use for marker label | "elevation"
label_size | size of label text | 8
label_color | color of label text | '#131516'
label_halo_color | color of label text halo | 'white'
label_halo_width | width of label text halo | 1
color_property | property to determine line color | "elevation"
color_stops | property to determine line color | [[0, "red"], [0.5, "blue"], [1, "green"]]
color_default | property to determine default line color if match lookup fails | "#F0F0F0"
color_function_type | property to determine type of expression used by Mapbox to assign color | "interpolate"
line_stroke | property to determine line stroke (one of solid (-), dashed (--), dotted (:), dash dot (-.)) | "solid" or "-"
line_width_property | feature property for determining line width | "elevation"
line_width_stops | property to determine line width | [[0, 1], [50000, 2], [150000, 3]]
line_width_default | property to determine default line width if match lookup fails | 1.0
line_width_function_type | property to determine `type` used by Mapbox to assign line width | "interpolate"

[MapViz options](https://github.com/mapbox/mapboxgl-jupyter/blob/master/docs-markdown/viz.md#params)

### Usage
```python
import random
import os

from mapboxgl.viz import LinestringViz
from mapboxgl.utils import create_color_stops

# Must be a public token, starting with `pk`
token = os.getenv('MAPBOX_ACCESS_TOKEN')

# JSON join-data object
data = [{"elevation": x, "weight": random.randint(0,100)} for x in range(0, 21000, 10)]

viz = LinestringViz(data,
vector_url='mapbox://mapbox.mapbox-terrain-v2',
vector_layer_name='contour',
vector_join_property='ele',
data_join_property='elevation',
color_property='elevation',
color_stops=create_color_stops([0, 25, 50, 75, 100], colors='YlOrRd'),
line_stroke='-',
line_width_default=2,
opacity=0.8,
center=(-122.48, 37.83),
zoom=16,
below_layer='waterway-label'
)
viz.show()
```

![LinestringViz](https://user-images.githubusercontent.com/13527707/39278071-02b6b2fc-48a6-11e8-8492-ae1f991b4b9e.png)


[Complete example](https://github.com/mapbox/mapboxgl-jupyter/blob/master/examples/notebooks/linestring-viz.ipynb)

179 changes: 179 additions & 0 deletions examples/notebooks/linestring-viz.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Mapboxgl Python Library for location data visualizaiton\n",
"\n",
"https://github.com/mapbox/mapboxgl-jupyter\n",
"\n",
"\n",
"# Linestring Visualizations"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import random\n",
"import os\n",
"\n",
"from mapboxgl.viz import LinestringViz\n",
"from mapboxgl.utils import create_color_stops, create_numeric_stops\n",
"\n",
"# Must be a public token, starting with `pk`\n",
"token = os.getenv('MAPBOX_ACCESS_TOKEN')\n",
"\n",
"# JSON join-data object\n",
"data = [{\"elevation\": x, \"weight\": random.randint(0,100)} for x in range(0, 21000, 10)]\n",
"\n",
"# GeoJSON data object\n",
"geojson = {\n",
" \"type\": \"FeatureCollection\",\n",
" \"features\": [{\n",
" \"type\": \"Feature\",\n",
" \"id\": \"01\", \n",
" \"properties\": {\"sample\": 50, \"weight\": 1}, \n",
" \"geometry\": {\n",
" \"type\": \"LineString\",\n",
" \"coordinates\": [\n",
" [-122.4833858013153, 37.829607404976734],\n",
" [-122.4830961227417, 37.82932776098012],\n",
" [-122.4830746650696, 37.82932776098012],\n",
" [-122.48218417167662, 37.82889558180985],\n",
" [-122.48218417167662, 37.82890193740421],\n",
" [-122.48221099376678, 37.82868372835086],\n",
" [-122.4822163581848, 37.82868372835086],\n",
" [-122.48205006122589, 37.82801003030873]\n",
" ]\n",
" }\n",
" }, {\n",
" \"type\": \"Feature\",\n",
" \"id\": \"02\",\n",
" \"properties\": {\"sample\": 500, \"weight\": 2},\n",
" \"geometry\": {\n",
" \"type\": \"LineString\",\n",
" \"coordinates\": [\n",
" [-122.4833858013153, 37.929607404976734],\n",
" [-122.4830961227417, 37.83]\n",
" ]\n",
" }\n",
" }, {\n",
" \"type\": \"Feature\",\n",
" \"properties\": {\"sample\": 5000, \"weight\": 1},\n",
" \"geometry\": {\n",
" \"type\": \"LineString\",\n",
" \"coordinates\": [\n",
" [-122.48369693756104, 37.83381888486939],\n",
" [-122.48348236083984, 37.83317489144141],\n",
" [-122.48339653015138, 37.83270036637107],\n",
" [-122.48356819152832, 37.832056363179625],\n",
" [-122.48404026031496, 37.83114119107971],\n",
" [-122.48404026031496, 37.83049717427869],\n",
" [-122.48348236083984, 37.829920943955045],\n",
" [-122.48356819152832, 37.82954808664175],\n",
" [-122.48507022857666, 37.82944639795659],\n",
" [-122.48610019683838, 37.82880236636284],\n",
" [-122.48695850372314, 37.82931081282506],\n",
" [-122.48700141906738, 37.83080223556934],\n",
" [-122.48751640319824, 37.83168351665737],\n",
" [-122.48803138732912, 37.832158048267786],\n",
" [-122.48888969421387, 37.83297152392784],\n",
" [-122.48987674713133, 37.83263257682617],\n",
" [-122.49043464660643, 37.832937629287755],\n",
" [-122.49125003814696, 37.832429207817725],\n",
" [-122.49163627624512, 37.832564787218985],\n",
" [-122.49223709106445, 37.83337825839438],\n",
" [-122.49378204345702, 37.83368330777276]\n",
" ]\n",
" }\n",
" }]\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## GeoJSON Test Linestring Source"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"# make viz with GeoJSON source\n",
"viz = LinestringViz(geojson, \n",
" color_property='sample',\n",
" color_stops=create_color_stops([0, 50, 100, 500, 1500], colors='Blues'),\n",
" line_stroke='--',\n",
" line_width_property='weight',\n",
" line_width_stops=create_numeric_stops([0, 1, 2, 3, 4, 5], 0, 10),\n",
" opacity=0.8,\n",
" center=(-122.48, 37.83),\n",
" zoom=16,\n",
" below_layer='waterway-label'\n",
" )\n",
"viz.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vector Linestring Source (Topography)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"viz = LinestringViz(data, \n",
" vector_url='mapbox://mapbox.mapbox-terrain-v2',\n",
" vector_layer_name='contour',\n",
" vector_join_property='ele',\n",
" data_join_property='elevation',\n",
" color_property='elevation',\n",
" color_stops=create_color_stops([0, 25, 50, 75, 100], colors='YlOrRd'),\n",
" line_stroke='-',\n",
" line_width_default=2,\n",
" opacity=0.8,\n",
" center=(-122.48, 37.83),\n",
" zoom=16,\n",
" below_layer='waterway-label'\n",
" )\n",
"viz.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
132 changes: 132 additions & 0 deletions mapboxgl/templates/linestring.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{% extends "base.html" %}

<!-- update legend item key style -->
{% block extra_css %}
<style type='text/css'>
.legend div span { border-radius: 20%; height: 4px; margin-bottom: 3px; }
</style>
{% endblock extra_css %}

{% block legend %}

var legend = document.getElementById('legend');

{% if colorStops and colorProperty and widthProperty %}
{% if colorProperty != widthProperty %}
calcCircleColorLegend({{ colorStops }}, "{{ colorProperty }} vs. {{ widthProperty }}");
{% else %}
calcCircleColorLegend({{ colorStops }}, "{{ colorProperty }}");
{% endif %}
{% elif colorStops and colorProperty %}
calcCircleColorLegend({{ colorStops }}, "{{ colorProperty }}");
{% else %}
document.getElementById('legend').style.visibility='hidden';
{% endif %}

{% endblock legend %}

{% block map %}

map.on('style.load', function() {

{% block linestring %}

// Add geojson data source
map.addSource("data", {
"type": "geojson",
"data": {{ geojson_data }},
"buffer": 1,
"maxzoom": 14
});

// Add data layer
map.addLayer({
"id": "linestring",
"source": "data",
"type": "line",
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
{% if lineDashArray %}
"line-dasharray": {{ lineDashArray }},
{% endif %}
{% if colorProperty %}
"line-color": generatePropertyExpression("{{ colorType }}", "{{ colorProperty }}", {{ colorStops }}, "{{ defaultColor }}"),
{% else %}
"line-color": "{{ defaultColor }}",
{% endif %}
{% if widthProperty %}
"line-width": generatePropertyExpression("{{ widthType }}", "{{ widthProperty }}", {{ widthStops }}, "{{ defaultWidth }}"),
{% else %}
"line-width": {{ defaultWidth }},
{% endif %}
"line-opacity": {{ opacity }}
}
}, "{{ belowLayer }}" );

// Add label layer
map.addLayer({
"id": "linestring-label",
"source": "data",
"type": "symbol",
"layout": {
{% if labelProperty %}
"text-field": "{{ labelProperty }}",
{% endif %}
"text-size" : generateInterpolateExpression('zoom', [[0,8],[22,16]] ),
"text-offset": [0,-1]
},
"paint": {
"text-halo-color": "{{ labelHaloColor }}",
"text-halo-width": generatePropertyExpression('interpolate', 'zoom', [[0,{{ labelHaloWidth }}], [18,5* {{ labelHaloWidth }}]]),
"text-color": "{{ labelColor }}"
}
}, "{{belowLayer}}" );

{% endblock linestring %}

// Create a popup
var popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
});

{% block linestring_popup %}

// Show the popup on mouseover
map.on('mousemove', 'linestring', function(e) {
map.getCanvas().style.cursor = 'pointer';

let f = e.features[0];
let popup_html = '<div>';

for (key in f.properties) {
popup_html += '<li><b> ' + key + '</b>: ' + f.properties[key] + ' </li>'
}

popup_html += '</div>'
popup.setLngLat(e.lngLat)
.setHTML(popup_html)
.addTo(map);
});

{% endblock linestring_popup %}

map.on('mouseleave', 'linestring', function() {
map.getCanvas().style.cursor = '';
popup.remove();
});

// Fly to on click
map.on('click', 'linestring', function(e) {
map.flyTo({
center: e.lngLat,
zoom: map.getZoom() + 1
});
});

});

{% endblock map %}
Loading

0 comments on commit ea49a97

Please sign in to comment.