Skip to content

Commit

Permalink
Merge 85fc681 into 274a24c
Browse files Browse the repository at this point in the history
  • Loading branch information
mikecolonna committed Sep 21, 2020
2 parents 274a24c + 85fc681 commit 7b7c405
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 21 deletions.
37 changes: 26 additions & 11 deletions modules/edit-modes/src/lib/draw-90degree-polygon-mode.ts
Expand Up @@ -8,22 +8,20 @@ import {
getPickedEditHandle,
getEditHandlesForGeometry,
} from '../utils';
import { ClickEvent, PointerMoveEvent, ModeProps, GuideFeatureCollection } from '../types';
import {
ClickEvent,
PointerMoveEvent,
ModeProps,
GuideFeatureCollection,
TentativeFeature,
} from '../types';
import { Polygon, LineString, Position, FeatureCollection } from '../geojson-types';
import { GeoJsonEditMode } from './geojson-edit-mode';

export class Draw90DegreePolygonMode extends GeoJsonEditMode {
getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
const guides: GuideFeatureCollection = {
type: 'FeatureCollection',
features: [],
};

createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature {
const clickSequence = this.getClickSequence();

if (clickSequence.length === 0 || !props.lastPointerMoveEvent) {
return guides;
}
const { mapCoords } = props.lastPointerMoveEvent;

let p3;
Expand Down Expand Up @@ -63,6 +61,22 @@ export class Draw90DegreePolygonMode extends GeoJsonEditMode {
};
}

return tentativeFeature;
}

getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
const guides: GuideFeatureCollection = {
type: 'FeatureCollection',
features: [],
};

const clickSequence = this.getClickSequence();

if (clickSequence.length === 0 || !props.lastPointerMoveEvent) {
return guides;
}
const tentativeFeature = this.createTentativeFeature(props);

guides.features.push(tentativeFeature);

guides.features = guides.features.concat(
Expand All @@ -75,8 +89,9 @@ export class Draw90DegreePolygonMode extends GeoJsonEditMode {
return guides;
}

handlePointerMove({ mapCoords }: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
props.onUpdateCursor('cell');
super.handlePointerMove(event, props);
}

handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>) {
Expand Down
30 changes: 22 additions & 8 deletions modules/edit-modes/src/lib/draw-polygon-mode.ts
@@ -1,20 +1,21 @@
import { ClickEvent, PointerMoveEvent, ModeProps, GuideFeatureCollection } from '../types';
import {
ClickEvent,
PointerMoveEvent,
ModeProps,
GuideFeatureCollection,
TentativeFeature,
} from '../types';
import { Polygon, FeatureCollection } from '../geojson-types';
import { getPickedEditHandle } from '../utils';
import { GeoJsonEditMode } from './geojson-edit-mode';

export class DrawPolygonMode extends GeoJsonEditMode {
getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature {
const { lastPointerMoveEvent } = props;
const clickSequence = this.getClickSequence();

const lastCoords = lastPointerMoveEvent ? [lastPointerMoveEvent.mapCoords] : [];

const guides = {
type: 'FeatureCollection',
features: [],
};

let tentativeFeature;
if (clickSequence.length === 1 || clickSequence.length === 2) {
tentativeFeature = {
Expand All @@ -40,6 +41,18 @@ export class DrawPolygonMode extends GeoJsonEditMode {
};
}

return tentativeFeature;
}

getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
const clickSequence = this.getClickSequence();

const guides = {
type: 'FeatureCollection',
features: [],
};

const tentativeFeature = this.createTentativeFeature(props);
if (tentativeFeature) {
guides.features.push(tentativeFeature);
}
Expand Down Expand Up @@ -125,7 +138,8 @@ export class DrawPolygonMode extends GeoJsonEditMode {
}
}
}
handlePointerMove({ mapCoords }: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
props.onUpdateCursor('cell');
super.handlePointerMove(event, props);
}
}
17 changes: 16 additions & 1 deletion modules/edit-modes/src/lib/geojson-edit-mode.ts
Expand Up @@ -238,8 +238,23 @@ export class GeoJsonEditMode implements EditMode<FeatureCollection, GuideFeature
return this.getAddFeatureAction(featureOrGeometry, props.data);
}

createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature {
return null;
}

handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>): void {}
handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void {}
handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void {
const tentativeFeature = this.createTentativeFeature(props);
if (tentativeFeature) {
props.onEdit({
updatedData: props.data,
editType: 'updateTentativeFeature',
editContext: {
feature: tentativeFeature,
},
});
}
}
handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>): void {}
handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>): void {}
handleDragging(event: DraggingEvent, props: ModeProps<FeatureCollection>): void {}
Expand Down
28 changes: 27 additions & 1 deletion modules/edit-modes/src/lib/three-click-polygon-mode.ts
@@ -1,4 +1,10 @@
import { ClickEvent, PointerMoveEvent, ModeProps, GuideFeatureCollection } from '../types';
import {
ClickEvent,
PointerMoveEvent,
ModeProps,
GuideFeatureCollection,
TentativeFeature,
} from '../types';
import { Position, Polygon, FeatureOf, FeatureCollection } from '../geojson-types';
import { GeoJsonEditMode } from './geojson-edit-mode';

Expand Down Expand Up @@ -81,5 +87,25 @@ export class ThreeClickPolygonMode extends GeoJsonEditMode {

handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
props.onUpdateCursor('cell');
super.handlePointerMove(event, props);
}

createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature {
const { lastPointerMoveEvent } = props;
const clickSequence = this.getClickSequence();

const lastCoords = lastPointerMoveEvent ? [lastPointerMoveEvent.mapCoords] : [];

let tentativeFeature;
if (clickSequence.length === 2) {
tentativeFeature = this.getThreeClickPolygon(
clickSequence[0],
clickSequence[1],
lastCoords[0],
props.modeConfig
);
}

return tentativeFeature;
}
}
16 changes: 16 additions & 0 deletions modules/edit-modes/src/lib/two-click-polygon-mode.ts
Expand Up @@ -5,6 +5,7 @@ import {
PointerMoveEvent,
ModeProps,
GuideFeatureCollection,
TentativeFeature,
} from '../types';
import { Polygon, FeatureCollection, FeatureOf, Position } from '../geojson-types';
import { GeoJsonEditMode } from './geojson-edit-mode';
Expand Down Expand Up @@ -112,5 +113,20 @@ export class TwoClickPolygonMode extends GeoJsonEditMode {

handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
props.onUpdateCursor('cell');
super.handlePointerMove(event, props);
}

createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature {
const { lastPointerMoveEvent } = props;
const clickSequence = this.getClickSequence();

const lastCoords = lastPointerMoveEvent ? [lastPointerMoveEvent.mapCoords] : [];

let tentativeFeature;
if (clickSequence.length === 1) {
tentativeFeature = this.getTwoClickPolygon(clickSequence[0], lastCoords[0], props.modeConfig);
}

return tentativeFeature;
}
}
1 change: 1 addition & 0 deletions modules/layers/package.json
Expand Up @@ -76,6 +76,7 @@
"cubic-hermite-spline": "^1.0.1",
"geojson-types": "^2.0.1",
"global": ">=4.3.0",
"h3-js": "^3.6.4",
"viewport-mercator-project": ">=6.0.0"
},
"peerDependencies": {
Expand Down
1 change: 1 addition & 0 deletions modules/layers/src/index.ts
Expand Up @@ -2,6 +2,7 @@ export { ArrowStyles, DEFAULT_ARROWS, MAX_ARROWS } from './style';

// Layers
export { default as EditableGeoJsonLayer } from './layers/editable-geojson-layer';
export { default as EditableH3Layer } from './layers/editable-h3-layer';
export { default as SelectionLayer } from './layers/selection-layer';
export { default as ElevatedEditHandleLayer } from './layers/elevated-edit-handle-layer';

Expand Down
152 changes: 152 additions & 0 deletions modules/layers/src/layers/editable-h3-layer.ts
@@ -0,0 +1,152 @@
/* eslint-env browser */

import { H3ClusterLayer } from '@deck.gl/geo-layers';
import { ViewMode } from '@nebula.gl/edit-modes';
import { polyfill } from 'h3-js';
import EditableGeoJsonLayer from './editable-geojson-layer';
import EditableLayer from './editable-layer';

const DEFAULT_EDIT_MODE = ViewMode;
const DEFAULT_H3_RESOLUTION = 9;

const defaultProps = {
mode: DEFAULT_EDIT_MODE,

// EditableGeoJsonLayer
geoJsonData: {},
...EditableGeoJsonLayer.defaultProps,

// h3 layer
h3Data: {},
filled: false,
stroked: true,
lineWidthScale: 1,
lineWidthMinPixels: 1,
lineWidthMaxPixels: Number.MAX_SAFE_INTEGER,
lineWidthUnits: 'pixels',
getHexagons: (d) => d.hexIds,
resolution: DEFAULT_H3_RESOLUTION,
};

export default class EditableH3Layer extends EditableLayer {
static layerName = 'EditableH3Layer';
static defaultProps = defaultProps;

initializeState() {
super.initializeState();

this.setState({
tentativeHexagonIDs: [],
});
}

getDerivedHexagonIDs(coords) {
return polyfill(coords, this.props.resolution, true);
}

renderLayers() {
const layers: any = [
new EditableGeoJsonLayer(
this.getSubLayerProps({
id: 'editable-geojson',

mode: this.props.mode,
data: {
type: 'FeatureCollection',
features: [],
},
selectedFeatureIndexes: this.props.selectedFeatureIndexes || [],

onEdit: (editAction) => {
const { editType, editContext } = editAction;

switch (editType) {
case 'updateTentativeFeature':
// tentative feature updates, updated on every pointer move
if (editContext.feature.geometry.type === 'Polygon') {
const coords = editContext.feature.geometry.coordinates;
const hexIDs = this.getDerivedHexagonIDs(coords);

this.setState({ tentativeHexagonIDs: hexIDs });
}
break;
case 'addFeature':
// once the shape is finished drawing, calculate final hexagons
let finalHexagonIDs;
const committedHexagonIDs = new Set(this.getHexIdsFromH3Data());
const tentativeHexagonIDs = new Set(this.state.tentativeHexagonIDs);

switch (this.props.modeConfig.booleanOperation) {
case 'union':
finalHexagonIDs = [
...new Set([...committedHexagonIDs, ...tentativeHexagonIDs]),
];
break;
case 'intersection':
finalHexagonIDs = [...committedHexagonIDs].filter((hexID: string) =>
tentativeHexagonIDs.has(hexID)
);
break;
case 'difference':
finalHexagonIDs = [...committedHexagonIDs].filter(
(hexID: string) => !tentativeHexagonIDs.has(hexID)
);
break;
default:
break;
}

this.setState({
tentativeHexagonIDs: [],
});

this.props.onEdit({ updatedData: finalHexagonIDs });
break;
default:
break;
}
},
})
),

new H3ClusterLayer(
this.getSubLayerProps({
id: 'tentative-hexagons',
data: [
{
count: this.state.tentativeHexagonIDs.length,
hexIds: this.state.tentativeHexagonIDs,
},
],
getHexagons: (d) => d.hexIds,
})
),
new H3ClusterLayer(
this.getSubLayerProps({
id: 'hexagons',
data: this.props.h3Data,
getHexagons: this.props.getHexagons,
})
),
];
return layers;
}

// because h3Data is an array of hexagon data, we take the cumulative hexIds from all entries
getHexIdsFromH3Data() {
let cumulativeHexIds = [];
this.props.h3Data.forEach(
(h3Data) => (cumulativeHexIds = cumulativeHexIds.concat(h3Data.hexIds))
);
return cumulativeHexIds;
}

getCursor({ isDragging }: { isDragging: boolean }) {
let { cursor } = this.state;
if (!cursor) {
// default cursor
cursor = isDragging ? 'grabbing' : 'grab';
}
return cursor;
}
}
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -55,6 +55,7 @@
"@babel/preset-typescript": "7.9.0",
"@babel/register": "7.9.0",
"@deck.gl/core": "^8.0.6",
"@deck.gl/geo-layers": "^8.2.8",
"@deck.gl/layers": "^8.0.6",
"@deck.gl/mesh-layers": "^8.0.6",
"@deck.gl/react": "^8.0.6",
Expand Down

0 comments on commit 7b7c405

Please sign in to comment.