Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added DeckGL.Polygon Layer w/ JS controls #4227

Merged
merged 15 commits into from Jan 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions superset/assets/javascripts/explore/stores/controls.jsx
Expand Up @@ -571,6 +571,16 @@ export const controls = {
}),
},

polygon: {
type: 'SelectControl',
label: t('Polygon Column'),
validators: [v.nonEmpty],
description: t('Select the polygon column. Each row should contain JSON.array(N) of [longitude, latitude] points'),
mapStateToProps: state => ({
choices: (state.datasource) ? state.datasource.all_cols : [],
}),
},

point_radius_scale: {
type: 'SelectControl',
freeForm: true,
Expand Down
40 changes: 40 additions & 0 deletions superset/assets/javascripts/explore/stores/visTypes.js
Expand Up @@ -517,6 +517,46 @@ export const visTypes = {
],
},

deck_polygon: {
label: t('Deck.gl - Polygon'),
requiresTime: true,
controlPanelSections: [
{
label: t('Query'),
expanded: true,
controlSetRows: [
['line_column', 'line_type'],
['row_limit', null],
],
},
{
label: t('Map'),
controlSetRows: [
['mapbox_style', 'viewport'],
['reverse_long_lat', null],
],
},
{
label: t('Polygon Settings'),
controlSetRows: [
['fill_color_picker', 'stroke_color_picker'],
['filled', 'stroked'],
['extruded', null],
['point_radius_scale', null],
],
},
{
label: t('Advanced'),
controlSetRows: [
['js_columns'],
['js_datapoint_mutator'],
['js_tooltip'],
['js_onclick_href'],
],
},
],
},

deck_arc: {
label: t('Deck.gl - Arc'),
requiresTime: true,
Expand Down
2 changes: 2 additions & 0 deletions superset/assets/visualizations/deckgl/layers/index.js
Expand Up @@ -6,6 +6,7 @@ import deck_hex from './hex';
import deck_scatter from './scatter';
import deck_geojson from './geojson';
import deck_arc from './arc';
import deck_polygon from './polygon';

const layerGenerators = {
deck_grid,
Expand All @@ -15,5 +16,6 @@ const layerGenerators = {
deck_scatter,
deck_geojson,
deck_arc,
deck_polygon,
};
export default layerGenerators;
28 changes: 28 additions & 0 deletions superset/assets/visualizations/deckgl/layers/polygon.jsx
@@ -0,0 +1,28 @@
import { PolygonLayer } from 'deck.gl';

import * as common from './common';
import sandboxedEval from '../../../javascripts/modules/sandbox';

export default function polygonLayer(formData, payload, slice) {
const fd = formData;
const fc = fd.fill_color_picker;
let data = payload.data.features.map(d => ({
...d,
fillColor: [fc.r, fc.g, fc.b, 255 * fc.a],
}));

if (fd.js_datapoint_mutator) {
// Applying user defined data mutator if defined
const jsFnMutator = sandboxedEval(fd.js_datapoint_mutator);
data = data.map(jsFnMutator);
}

return new PolygonLayer({
id: `path-layer-${fd.slice_id}`,
data,
filled: fd.filled,
stroked: fd.stoked,
extruded: fd.extruded,
...common.commonLayerProps(fd, slice),
});
}
2 changes: 2 additions & 0 deletions superset/assets/visualizations/main.js
Expand Up @@ -48,6 +48,7 @@ export const VIZ_TYPES = {
deck_geojson: 'deck_geojson',
deck_multi: 'deck_multi',
deck_arc: 'deck_arc',
deck_polygon: 'deck_polygon',
};

const vizMap = {
Expand Down Expand Up @@ -95,6 +96,7 @@ const vizMap = {
[VIZ_TYPES.deck_path]: deckglFactory,
[VIZ_TYPES.deck_geojson]: deckglFactory,
[VIZ_TYPES.deck_arc]: deckglFactory,
[VIZ_TYPES.deck_polygon]: deckglFactory,
[VIZ_TYPES.deck_multi]: require('./deckgl/multi.jsx'),
};
export default vizMap;
30 changes: 30 additions & 0 deletions superset/data/__init__.py
Expand Up @@ -1552,6 +1552,36 @@ def load_paris_iris_geojson():
tbl.fetch_metadata()


def load_sf_population_polygons():
tbl_name = 'sf_population_polygons'

with gzip.open(os.path.join(DATA_FOLDER, 'sf_population.json.gz')) as f:
df = pd.read_json(f)
df['contour'] = df.contour.map(json.dumps)

df.to_sql(
tbl_name,
db.engine,
if_exists='replace',
chunksize=500,
dtype={
'zipcode': BigInteger,
'population': BigInteger,
'contour': Text,
'area': BigInteger,
},
index=False)
print("Creating table {} reference".format(tbl_name))
tbl = db.session.query(TBL).filter_by(table_name=tbl_name).first()
if not tbl:
tbl = TBL(table_name=tbl_name)
tbl.description = "Population density of San Francisco"
tbl.database = get_or_create_main_db()
db.session.merge(tbl)
db.session.commit()
tbl.fetch_metadata()


def load_bart_lines():
tbl_name = 'bart_lines'
with gzip.open(os.path.join(DATA_FOLDER, 'bart-lines.json.gz')) as f:
Expand Down
Binary file added superset/data/sf_population.json.gz
Binary file not shown.
14 changes: 12 additions & 2 deletions superset/viz.py
Expand Up @@ -1895,6 +1895,7 @@ def get_data(self, df):
if extra_props:
feature['extraProps'] = extra_props
features.append(feature)

return {
'features': features,
'mapboxApiKey': config.get('MAPBOX_API_KEY'),
Expand Down Expand Up @@ -1978,11 +1979,11 @@ class DeckPathViz(BaseDeckGLViz):

viz_type = 'deck_path'
verbose_name = _('Deck.gl - Paths')
deck_viz_key = 'path'
deser_map = {
'json': json.loads,
'polyline': polyline.decode,
}
spatial_control_keys = ['spatial']

def query_obj(self):
d = super(DeckPathViz, self).query_obj()
Expand All @@ -2000,10 +2001,19 @@ def get_properties(self, d):
if fd.get('reverse_long_lat'):
path = (path[1], path[0])
return {
'path': path,
self.deck_viz_key: path,
}


class DeckPolygon(DeckPathViz):

"""deck.gl's Polygon Layer"""

viz_type = 'deck_polygon'
deck_viz_key = 'polygon'
verbose_name = _('Deck.gl - Polygon')


class DeckHex(BaseDeckGLViz):

"""deck.gl's DeckLayer"""
Expand Down