Skip to content

Commit

Permalink
Merge 484e6b7 into fbc8c63
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisgervang committed Feb 11, 2020
2 parents fbc8c63 + 484e6b7 commit 823dccd
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 43 deletions.
2 changes: 1 addition & 1 deletion examples/experimental/terrain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"dependencies": {
"@loaders.gl/images": "2.0.2",
"@mapbox/martini": "^0.1.0",
"@mapbox/martini": "^0.2.0",
"deck.gl": "^8.1.0-alpha.1",
"react": "^16.3.0",
"react-dom": "^16.3.0",
Expand Down
155 changes: 116 additions & 39 deletions examples/experimental/terrain/src/app.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* eslint-disable max-statements */
import React, {PureComponent} from 'react';
import React, {useState} from 'react';
import {render} from 'react-dom';
import DeckGL from '@deck.gl/react';
import {WebMercatorViewport, COORDINATE_SYSTEM} from '@deck.gl/core';
import {load} from '@loaders.gl/core';
import {TileLayer} from '@deck.gl/geo-layers';

import TerrainLayer from './terrain-layer/terrain-layer';
import {getSurface} from './surface';
import {getViewState} from './locations';

// Set your mapbox token here
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line
Expand All @@ -20,10 +22,7 @@ const INITIAL_VIEW_STATE = {
};

// Constants
// const STREET = 'https://c.tile.openstreetmap.org';
// const SECTIONAL = 'https://wms.chartbundle.com/tms/1.0.0/sec';
const TERRAIN_RGB = 'https://api.mapbox.com/v4/mapbox.terrain-rgb';
const SATELLITE = 'https://api.mapbox.com/v4/mapbox.satellite';

const getTerrainData = ({x, y, z}) => {
const terrainTile = `${TERRAIN_RGB}/${z}/${x}/${y}.pngraw?access_token=${MAPBOX_TOKEN}`;
Expand All @@ -32,45 +31,123 @@ const getTerrainData = ({x, y, z}) => {
return load(terrainTile).catch(err => null);
};

const getSurfaceImage = ({x, y, z}) => {
return `${SATELLITE}/${z}/${x}/${y}@2x.png?access_token=${MAPBOX_TOKEN}`;
const SurfaceDropdown = ({surface, setSurface}) => {
return (
<select value={surface} onChange={e => setSurface(e.currentTarget.value)}>
<option value="none">None</option>
<option value="sectional">FAA Sectional</option>
<option value="satellite">Satellite</option>
<option value="street">OSM Street</option>
</select>
);
};

export default class App extends PureComponent {
render() {
const layer = new TileLayer({
id: 'loader',
minZoom: 0,
maxZoom: 23,
maxCacheSize: 100,
getTileData: getTerrainData,
renderSubLayers: props => {
const {bbox, z} = props.tile;

const viewport = new WebMercatorViewport({
longitude: (bbox.west + bbox.east) / 2,
latitude: (bbox.north + bbox.south) / 2,
zoom: z
});
const bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
const topRight = viewport.projectFlat([bbox.east, bbox.north]);

return new TerrainLayer({
id: props.id,
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
bounds: [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]],
surfaceImage: getSurfaceImage(props.tile),
terrainImage: props.data,
// https://docs.mapbox.com/help/troubleshooting/access-elevation-data/#mapbox-terrain-rgb
// Note - the elevation rendered by this example is greatly exagerated!
getElevation: (r, g, b) => (r * 65536 + g * 256 + b) / 10 - 10000
});
}
const LocationDropdown = ({location, setLocation}) => {
return (
<select value={location} onChange={e => setLocation(e.currentTarget.value)}>
<option value="helens">St Helens</option>
<option value="dallas">Dallas</option>
<option value="la">Los Angeles</option>
<option value="melbourne">Melbourne</option>
<option value="nyc">New York City</option>
<option value="sf">San Francisco</option>
</select>
);
};

const WireframeCheckbox = ({wireframe, setWireframe}) => {
return (
<div>
<input
type="checkbox"
name="wireframe"
checked={wireframe}
onChange={e => {
setWireframe(!wireframe);
}}
/>
<label htmlFor="wireframe">Wireframe</label>
</div>
);
};

const App = () => {
const [surface, setSurface] = useState('satellite');
const [location, setLocation] = useState('helens');
const [viewState, setViewState] = useState(INITIAL_VIEW_STATE);
const [wireframe, setWireframe] = useState(false);

const setLocationProp = l => {
const vs = getViewState(l);
setLocation(l);
setViewState(vs);
};

const renderSubLayers = props => {
const {bbox, z} = props.tile;

const viewport = new WebMercatorViewport({
longitude: (bbox.west + bbox.east) / 2,
latitude: (bbox.north + bbox.south) / 2,
zoom: z
});
const bottomLeft = viewport.projectFlat([bbox.west, bbox.south]);
const topRight = viewport.projectFlat([bbox.east, bbox.north]);

return <DeckGL initialViewState={INITIAL_VIEW_STATE} controller={true} layers={[layer]} />;
}
}
return new TerrainLayer({
id: props.id,
wireframe,
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
bounds: [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]],
surfaceImage: getSurface(props.tile, surface),
terrainImage: props.data,
// https://docs.mapbox.com/help/troubleshooting/access-elevation-data/#mapbox-terrain-rgb
// Note - the elevation rendered by this example is greatly exagerated!
getElevation: (r, g, b) => (r * 65536 + g * 256 + b) / 10 - 10000
// getElevation: (r, g, b) => -10000 + ((r * 65536 + g * 256 + b) * 0.1)
});
};

const layer = new TileLayer({
id: 'loader',
minZoom: 0,
maxZoom: 23,
strategy: 'no-overlap',
getTileData: getTerrainData,
renderSubLayers
});

const setSurfaceProp = val => {
setSurface(val);
layer.setState({
tileset: null
});
};

const setWireframeProp = wf => {
setWireframe(wf);
if (wf) {
setSurfaceProp('none');
} else {
setSurfaceProp('satellite');
}
};

return (
<div>
<DeckGL initialViewState={viewState} controller={true} layers={[layer]} />
<div
style={{
position: 'absolute'
}}
>
<SurfaceDropdown surface={surface} setSurface={setSurfaceProp} />
<LocationDropdown location={location} setLocation={setLocationProp} />
<WireframeCheckbox wireframe={wireframe} setWireframe={setWireframeProp} />
</div>
</div>
);
};

export function renderToDOM(container) {
render(<App />, container);
Expand Down
53 changes: 53 additions & 0 deletions examples/experimental/terrain/src/locations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
export const getViewState = location => {
switch (location) {
case 'nyc':
return {
latitude: 40.731073741099145,
longitude: -73.98384590997735,
zoom: 13,
pitch: 60,
bearing: 0
};
case 'melbourne':
return {
latitude: -37.817349971409804,
longitude: 144.9656091270625,
zoom: 11.5,
pitch: 60,
bearing: 0
};
case 'dallas':
return {
latitude: 32.8,
longitude: -97.03755072303063,
zoom: 10,
pitch: 60,
bearing: 1
};
case 'la':
return {
latitude: 34.05243053697479,
longitude: -118.24128468120529,
zoom: 10,
pitch: 60,
bearing: 45
};
case 'sf':
return {
latitude: 37.6,
longitude: -122.11731552444683,
zoom: 10,
pitch: 60,
bearing: 25
};
case 'helens':
default:
return {
latitude: 46.24,
longitude: -122.18,
zoom: 11.5,
bearing: 140,
pitch: 60
};
}
};
26 changes: 26 additions & 0 deletions examples/experimental/terrain/src/surface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const STREET = 'https://c.tile.openstreetmap.org';
const SECTIONAL = 'https://wms.chartbundle.com/tms/1.0.0/sec';
const SATELLITE = 'https://api.mapbox.com/v4/mapbox.satellite';

// Set your mapbox token here
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line

export const getSurface = ({x, y, z}, surface) => {
let surfaceImage = null;
switch (surface) {
case 'sectional':
surfaceImage = `${SECTIONAL}/${z}/${x}/${y}.png?origin=nw`;
break;
case 'satellite':
surfaceImage = `${SATELLITE}/${z}/${x}/${y}@2x.png?access_token=${MAPBOX_TOKEN}`;
break;
case 'street':
surfaceImage = `${STREET}/${z}/${x}/${y}.png`;
break;
case 'none':
default:
surfaceImage = null;
break;
}
return surfaceImage;
};
17 changes: 14 additions & 3 deletions examples/experimental/terrain/src/terrain-layer/terrain-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ const defaultProps = {
// Color to use if surfaceImage is unavailable
color: {type: 'color', value: [255, 255, 255]},
// Function to decode height data, from (r, g, b) to height in meters
getElevation: {type: 'accessor', value: (r, g, b) => r}
getElevation: {type: 'accessor', value: (r, g, b) => r},
// Same as SimpleMeshLayer wireframe
wireframe: false
};

function getTerrain(imageData, tileSize, getElevation) {
Expand Down Expand Up @@ -100,7 +102,15 @@ function getMartiniTileMesh(terrainImage, getElevation, meshMaxError, bounds) {

export default class TerrainLayer extends CompositeLayer {
renderLayers() {
const {bounds, color, getElevation, meshMaxError, terrainImage, surfaceImage} = this.props;
const {
bounds,
color,
getElevation,
meshMaxError,
terrainImage,
surfaceImage,
wireframe
} = this.props;

return new SimpleMeshLayer(
this.getSubLayerProps({
Expand All @@ -111,7 +121,8 @@ export default class TerrainLayer extends CompositeLayer {
mesh: getMartiniTileMesh(terrainImage, getElevation, meshMaxError, bounds),
texture: surfaceImage,
getPosition: d => [0, 0, 0],
getColor: d => color
getColor: d => color,
wireframe
}
);
}
Expand Down

0 comments on commit 823dccd

Please sign in to comment.