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

Remove dependency on deck.gl from ElevationHandler #223

Merged
merged 4 commits into from
May 8, 2019
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions docs/api-reference/mode-handlers/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,28 +169,35 @@ User can split a polygon by drawing a new `LineString` feature on top of the pol

* If the clicked position is inside the polygon, it will not split the polygon

## [ElevationHandler](https://github.com/uber/nebula.gl/blob/master/modules/layers/src/mode-handlers/)
## [ElevationHandler](https://github.com/uber/nebula.gl/blob/master/modules/layers/src/mode-handlers/elevation-handler.js)

* Mode name: `elevation`

User can move a point up and down. `min` and `max` can be configured in `modeConfig`.
User can move a point up and down.

### ModeConfig

The following options can be provided in the `modeConfig` object:

* `gap` (optional): `x <number>`
* If gap: `x` means the spacing between the polygon would be `x`.
* Gap value should be greater than 0.
* Default gap is `0.1`
* `minElevation` (Number, optional)
* The minimum elevation to allow
* Default: `0`

* `unit` (optional): `centimeters|feet|inches|meters|kilometers|miles|yards`
* If unit: `x` means the unit used for the spacing would be of `x` unit.
* Default unit is `centimeters`
* `maxElevation` (Number, optional)
* The maximum elevation to allow
* Default: `20000`

* `lock90Degree` (Boolean, optional)
* Default: `false`
* If true, all angles will be guaranteed to be 90 degrees.
* `calculateElevationChange` (Function, optional)
* A function to use to calculate the elevation change in response to mouse movement
* Default: `10 * <vertical movement in pixels>`
* Configure to use movement based on viewport:

```javascript
if (mode === 'elevation') {
modeConfig.calculateElevationChange = (opts) =>
ElevationHandler.calculateElevationChangeWithViewport(viewport, opts);
}
```

## Boolean Operations

Expand Down
6 changes: 6 additions & 0 deletions examples/deck/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
SelectionLayer,
CompositeModeHandler,
ModifyHandler,
ElevationHandler,
DrawLineStringHandler,
ElevatedEditHandleLayer,
SELECTION_TYPE
Expand Down Expand Up @@ -532,6 +533,11 @@ export default class Example extends Component<
width: window.innerWidth
};

if (mode === 'elevation') {
modeConfig.calculateElevationChange = opts =>
ElevationHandler.calculateElevationChangeWithViewport(viewport, opts);
}

const editableGeoJsonLayer = new EditableGeoJsonLayer({
id: 'geojson',
data: testFeatures,
Expand Down
1 change: 1 addition & 0 deletions modules/core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ export { DrawCircleFromCenterHandler } from '@nebula.gl/layers';
export { DrawCircleByBoundingBoxHandler } from '@nebula.gl/layers';
export { DrawEllipseByBoundingBoxHandler } from '@nebula.gl/layers';
export { DrawEllipseUsingThreePointsHandler } from '@nebula.gl/layers';
export { ElevationHandler } from '@nebula.gl/layers';
1 change: 1 addition & 0 deletions modules/layers/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export {
export {
DrawEllipseUsingThreePointsHandler
} from './mode-handlers/draw-ellipse-using-three-points-handler.js';
export { ElevationHandler } from './mode-handlers/elevation-handler.js';

// Utils
export { toDeckColor } from './utils.js';
Expand Down
53 changes: 46 additions & 7 deletions modules/layers/src/mode-handlers/elevation-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,39 @@ import type { EditAction } from './mode-handler.js';
import { getPickedEditHandle } from './mode-handler.js';
import { ModifyHandler } from './modify-handler.js';

function defaultCalculateElevationChange({
pointerDownScreenCoords,
screenCoords
}: {
pointerDownScreenCoords: Position,
screenCoords: Position
}) {
return 10 * (pointerDownScreenCoords[1] - screenCoords[1]);
}

export class ElevationHandler extends ModifyHandler {
makeElevatedEvent(event: PointerMoveEvent | StopDraggingEvent, position: Position): Object {
const { min = 0, max = 20000 } = this._modeConfig || {};
if (!event.pointerDownScreenCoords) {
return event;
}

const [, yBot] = this._context.viewport.project([position[0], position[1], 0]);
const [, yTop] = this._context.viewport.project([position[0], position[1], 1000]);
const [, y] = event.screenCoords;
const {
minElevation = 0,
maxElevation = 20000,
calculateElevationChange = defaultCalculateElevationChange
} =
this._modeConfig || {};

let elevation = ((yBot - y) * 1000.0) / (yBot - yTop);
elevation = Math.min(elevation, max);
elevation = Math.max(elevation, min);
// $FlowFixMe - really, I know it has something at index 2
let elevation = position.length === 3 ? position[2] : 0;

// calculateElevationChange is configurable becase (at this time) modes are not aware of the viewport
elevation += calculateElevationChange({
pointerDownScreenCoords: event.pointerDownScreenCoords,
screenCoords: event.screenCoords
});
elevation = Math.min(elevation, maxElevation);
elevation = Math.max(elevation, minElevation);

return Object.assign({}, event, {
groundCoords: [position[0], position[1], elevation]
Expand All @@ -41,4 +63,21 @@ export class ElevationHandler extends ModifyHandler {
}
return cursor;
}

static calculateElevationChangeWithViewport(
viewport: any,
{
pointerDownScreenCoords,
screenCoords
}: {
pointerDownScreenCoords: Position,
screenCoords: Position
}
): number {
// Source: https://gis.stackexchange.com/a/127949/111804
const metersPerPixel =
(156543.03392 * Math.cos((viewport.latitude * Math.PI) / 180)) / Math.pow(2, viewport.zoom);

return (metersPerPixel * (pointerDownScreenCoords[1] - screenCoords[1])) / 2;
}
}