diff --git a/packages/react-components/src/lib/cesium-map/data-sources/drawings.data-source.stories.tsx b/packages/react-components/src/lib/cesium-map/data-sources/drawings.data-source.stories.tsx index 608bb4d0..f1dd7692 100644 --- a/packages/react-components/src/lib/cesium-map/data-sources/drawings.data-source.stories.tsx +++ b/packages/react-components/src/lib/cesium-map/data-sources/drawings.data-source.stories.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; -import { DrawType } from '../../models'; +import { BboxCorner, DrawType } from '../../models'; +import { CesiumSceneMode } from '../map.types'; import { CesiumMap } from '../map'; import { CesiumDrawingsDataSource, @@ -43,6 +44,7 @@ export const Drawings: Story = (args) => { type: DrawType.UNKNOWN, }, ]); + const [center] = useState<[number, number]>([34.9578094, 32.8178637]); const createDrawPrimitive = (type: DrawType): IDrawingObject => { return { @@ -84,8 +86,62 @@ export const Drawings: Story = (args) => { > Box + +
- + = }, [mapViewer]); useEffect(() => { - if (drawState.drawing && drawHelper) { - switch (drawState.type) { - case DrawType.POLYGON: - // eslint-disable-next-line - (drawHelper as any).startDrawingPolygon({ - callback: (positions: PrimitiveCoordinates) => { - //// MAKE polygon editable example - // var polygon = new DrawHelper.PolygonPrimitive({ - // positions: positions, - // width: 5, - // geodesic: true - // }); - // mapViewer.scene.primitives.add(polygon); - // polygon.setStrokeStyle(Color.AQUA,1); - // polygon.setEditable(); - // polygon.addListener('onEdited', function(event) { - // console.log('Polygone edited, ' + event.positions.length + ' points'); - // }); - drawState.handler({ - primitive: positions, - type: DrawType.POLYGON, - geojson: polygonToGeoJSON(positions as Cartesian3[]), - }); - }, - }); - break; - case DrawType.BOX: - // eslint-disable-next-line - (drawHelper as any).startDrawingExtent({ - callback: (positions: PrimitiveCoordinates) => { - //// MAKE box editable example - // var extentPrimitive = new DrawHelper.ExtentPrimitive({ - // extent: positions, - // material: Cesium.Material.fromType(Cesium.Material.StripeType) - // }); - // mapViewer.scene.primitives.add(extentPrimitive); - // extentPrimitive.setStrokeStyle(Color.AQUA,1); - // extentPrimitive.setEditable(); - // extentPrimitive.addListener('onEdited', function(event) { - // console.log('Extent edited: extent is (N: ' + event.extent.north.toFixed(3) + ', E: ' + event.extent.east.toFixed(3) + ', S: ' + event.extent.south.toFixed(3) + ', W: ' + event.extent.west.toFixed(3) + ')'); - // }); - drawState.handler({ - primitive: positions, - type: DrawType.BOX, - geojson: rectangleToGeoJSON(positions as Rectangle), - }); - }, - }); - break; - default: - break; + if (drawHelper) { + // eslint-disable-next-line + const drawHelperInstance = drawHelper as any; + if (drawState.drawing) { + switch (drawState.type) { + case DrawType.POLYGON: + // eslint-disable-next-line + drawHelperInstance.startDrawingPolygon({ + callback: (positions: PrimitiveCoordinates) => { + //// MAKE polygon editable example + // var polygon = new DrawHelper.PolygonPrimitive({ + // positions: positions, + // width: 5, + // geodesic: true + // }); + // mapViewer.scene.primitives.add(polygon); + // polygon.setStrokeStyle(Color.AQUA,1); + // polygon.setEditable(); + // polygon.addListener('onEdited', function(event) { + // console.log('Polygone edited, ' + event.positions.length + ' points'); + // }); + drawState.handler({ + primitive: positions, + type: DrawType.POLYGON, + geojson: polygonToGeoJSON(positions as Cartesian3[]), + }); + }, + }); + break; + case DrawType.BOX: + // eslint-disable-next-line + drawHelperInstance.startDrawingExtent({ + callback: (positions: PrimitiveCoordinates) => { + //// MAKE box editable example + // var extentPrimitive = new DrawHelper.ExtentPrimitive({ + // extent: positions, + // material: Cesium.Material.fromType(Cesium.Material.StripeType) + // }); + // mapViewer.scene.primitives.add(extentPrimitive); + // extentPrimitive.setStrokeStyle(Color.AQUA,1); + // extentPrimitive.setEditable(); + // extentPrimitive.addListener('onEdited', function(event) { + // console.log('Extent edited: extent is (N: ' + event.extent.north.toFixed(3) + ', E: ' + event.extent.east.toFixed(3) + ', S: ' + event.extent.south.toFixed(3) + ', W: ' + event.extent.west.toFixed(3) + ')'); + // }); + drawState.handler({ + primitive: positions, + type: DrawType.BOX, + geojson: rectangleToGeoJSON(positions as Rectangle), + }); + }, + }); + break; + default: + throw new Error( + `[CESIUM DRAW]: ${drawState.type} unrecognized primitive to draw.` + ); + break; + } + } else { + // eslint-disable-next-line + drawHelperInstance.stopDrawing(); } } }, [drawState, drawHelper]); @@ -113,11 +125,18 @@ export const CesiumDrawingsDataSource: React.FC = const renderGraphicsComponent = ( drawEntity: IDrawing ): React.ReactElement => { + const coordinates = + drawEntity.coordinates !== undefined + ? drawEntity.coordinates + : geoJSONToPrimitive( + drawEntity.type, + drawEntity.geojson as FeatureCollection + ); switch (drawEntity.type) { case DrawType.BOX: return ( @@ -125,9 +144,7 @@ export const CesiumDrawingsDataSource: React.FC = case DrawType.POLYGON: return ( diff --git a/packages/react-components/src/lib/cesium-map/layers/wms.layer.tsx b/packages/react-components/src/lib/cesium-map/layers/wms.layer.tsx index 26891c28..faeecb6c 100644 --- a/packages/react-components/src/lib/cesium-map/layers/wms.layer.tsx +++ b/packages/react-components/src/lib/cesium-map/layers/wms.layer.tsx @@ -3,9 +3,12 @@ import React from 'react'; import { WebMapServiceImageryProvider } from 'cesium'; import { CesiumImageryLayer, RCesiumImageryLayerProps } from './imagery.layer'; +export interface RCesiumWMSLayerOptions + extends WebMapServiceImageryProvider.ConstructorOptions {} + export interface RCesiumWMSLayerProps extends Partial { - options: WebMapServiceImageryProvider.ConstructorOptions; + options: RCesiumWMSLayerOptions; } export const CesiumWMSLayer: React.FC = (props) => { diff --git a/packages/react-components/src/lib/cesium-map/layers/wmts.layer.tsx b/packages/react-components/src/lib/cesium-map/layers/wmts.layer.tsx index 679b7e8d..f1f3711a 100644 --- a/packages/react-components/src/lib/cesium-map/layers/wmts.layer.tsx +++ b/packages/react-components/src/lib/cesium-map/layers/wmts.layer.tsx @@ -3,9 +3,12 @@ import React from 'react'; import { WebMapTileServiceImageryProvider } from 'cesium'; import { CesiumImageryLayer, RCesiumImageryLayerProps } from './imagery.layer'; +export interface RCesiumWMTSLayerOptions + extends WebMapTileServiceImageryProvider.ConstructorOptions {} + export interface RCesiumWMTSLayerProps extends Partial { - options: WebMapTileServiceImageryProvider.ConstructorOptions; + options: RCesiumWMTSLayerOptions; } export const CesiumWMTSLayer: React.FC = (props) => { diff --git a/packages/react-components/src/lib/cesium-map/layers/xyz.layer.tsx b/packages/react-components/src/lib/cesium-map/layers/xyz.layer.tsx index 35830979..b76d086c 100644 --- a/packages/react-components/src/lib/cesium-map/layers/xyz.layer.tsx +++ b/packages/react-components/src/lib/cesium-map/layers/xyz.layer.tsx @@ -3,6 +3,9 @@ import React from 'react'; import { UrlTemplateImageryProvider } from 'cesium'; import { CesiumImageryLayer, RCesiumImageryLayerProps } from './imagery.layer'; +export interface RCesiumXYZLayerOptions + extends UrlTemplateImageryProvider.ConstructorOptions {} + export interface RCesiumXYZLayerProps extends Partial { options: UrlTemplateImageryProvider.ConstructorOptions; diff --git a/packages/react-components/src/lib/cesium-map/map.tsx b/packages/react-components/src/lib/cesium-map/map.tsx index b0353395..17ba715d 100644 --- a/packages/react-components/src/lib/cesium-map/map.tsx +++ b/packages/react-components/src/lib/cesium-map/map.tsx @@ -79,7 +79,8 @@ export const CesiumMap: React.FC = (props) => { }, [props.showScale]); useEffect(() => { - const { zoom, center } = props; + const zoom = props.zoom; + const center = props.center; if (mapViewRef && isNumber(zoom) && isArray(center)) { void mapViewRef.camera.flyTo({ destination: Cartesian3.fromDegrees( @@ -90,7 +91,7 @@ export const CesiumMap: React.FC = (props) => { duration: 0, }); } - }, [props, mapViewRef]); + }, [props.zoom, props.center, mapViewRef]); return ( diff --git a/packages/react-components/src/lib/cesium-map/tools/draw/drawHelper.ts b/packages/react-components/src/lib/cesium-map/tools/draw/drawHelper.ts index 513c53df..bf652edb 100644 --- a/packages/react-components/src/lib/cesium-map/tools/draw/drawHelper.ts +++ b/packages/react-components/src/lib/cesium-map/tools/draw/drawHelper.ts @@ -10,7 +10,7 @@ var DrawHelper = (function () { // constructor function _(cesiumWidget) { this._scene = cesiumWidget.scene; - //ALEX + //MC_CHANGE disable/override tooltip this._tooltip = { setVisible: () => {}, showAt: () => {}, @@ -300,7 +300,7 @@ var DrawHelper = (function () { depthTest: { enabled: true, }, - //ALEX + //MC_CHANGE lineWidth: this.strokeWidth || 4.0, // lineWidth : Math.min(this.strokeWidth || 4.0, context._aliasedLineWidthRange[1]) }, @@ -902,6 +902,7 @@ var DrawHelper = (function () { markers.remove(); mouseHandler.destroy(); tooltip.setVisible(false); + unsetDrawCursor(scene); }); var _self = this; @@ -923,6 +924,7 @@ var DrawHelper = (function () { var markers = new _.BillboardGroup(this, defaultBillboard); var mouseHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas); + setDrawCursor(scene); // Now wait for start mouseHandler.setInputAction(function (movement) { @@ -991,6 +993,7 @@ var DrawHelper = (function () { } else { var cartesian = scene.camera.pickEllipsoid(position, ellipsoid); if (cartesian) { + unsetDrawCursor(scene); _self.stopDrawing(); if (typeof options.callback == 'function') { // remove overlapping ones @@ -1012,6 +1015,20 @@ var DrawHelper = (function () { ]); } + // MC_CHANGE add to change draw mode cursor + function setDrawCursor(scene) { + if (scene) { + scene.canvas.style.cursor = 'crosshair'; + } + } + + // MC_CHANGE add to restore regular mode + function unsetDrawCursor(scene) { + if (scene) { + scene.canvas.style.cursor = ''; + } + } + _.prototype.startDrawingExtent = function (options) { var options = copyOptions(options, defaultSurfaceOptions); @@ -1019,12 +1036,13 @@ var DrawHelper = (function () { if (extent != null) { primitives.remove(extent); } - //ALEX if added + //MC_CHANGE if added if (markers != null) { markers.remove(); } mouseHandler.destroy(); tooltip.setVisible(false); + unsetDrawCursor(scene); }); var _self = this; @@ -1037,10 +1055,11 @@ var DrawHelper = (function () { var markers = null; var mouseHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas); + setDrawCursor(scene); function updateExtent(value) { if (extent == null) { - //ALEX + //MC_CHANGE extent = new Cesium.GroundPrimitive(); //extent = new Cesium.RectanglePrimitive(); //extent.asynchronous = false; diff --git a/packages/react-components/src/lib/cesium-map/tools/geojson/geojson-to-primitive.ts b/packages/react-components/src/lib/cesium-map/tools/geojson/geojson-to-primitive.ts new file mode 100644 index 00000000..b27e6bac --- /dev/null +++ b/packages/react-components/src/lib/cesium-map/tools/geojson/geojson-to-primitive.ts @@ -0,0 +1,54 @@ +import { FeatureCollection, Feature, Point } from 'geojson'; +import { Rectangle } from 'cesium'; +import { find } from 'lodash'; +import { PrimitiveCoordinates } from '../../data-sources'; +import { BboxCorner, DrawType } from '../../../models/enums'; + +const POINTS_NUM = 2; + +export const geoJSONToPrimitive = ( + type: DrawType, + geojson: FeatureCollection +): PrimitiveCoordinates | never => { + switch (type) { + case DrawType.BOX: { + if (geojson.features.length !== POINTS_NUM) + throw new Error(`${type} must have 2 points`); + + const bottomLeftPoint = find(geojson.features, (feat) => { + return feat.properties?.type === BboxCorner.BOTTOM_LEFT; + }) as Feature; + + const rightTopPoint = find(geojson.features, (feat) => { + return feat.properties?.type === BboxCorner.TOP_RIGHT; + }) as Feature; + + // eslint-disable-next-line + if (rightTopPoint && bottomLeftPoint) { + if ( + bottomLeftPoint.geometry.coordinates[0] === + rightTopPoint.geometry.coordinates[0] && + bottomLeftPoint.geometry.coordinates[1] === + rightTopPoint.geometry.coordinates[1] + ) { + throw new Error( + `${type} must define BOTTOM_LEFT and TOP_RIGHT different points` + ); + } else { + return Rectangle.fromDegrees( + bottomLeftPoint.geometry.coordinates[0], + bottomLeftPoint.geometry.coordinates[1], + rightTopPoint.geometry.coordinates[0], + rightTopPoint.geometry.coordinates[1] + ); + } + } else { + throw new Error( + `${type} geojson must define BOTTOM_LEFT and TOP_RIGHT points` + ); + } + } + default: + throw new Error(`${type} type geoJSON still not supported`); + } +}; diff --git a/packages/react-components/src/lib/models/enums.ts b/packages/react-components/src/lib/models/enums.ts index 77a892fc..eb4a288c 100644 --- a/packages/react-components/src/lib/models/enums.ts +++ b/packages/react-components/src/lib/models/enums.ts @@ -8,3 +8,8 @@ export enum SupportedLocales { HE = 'he', EN = 'en', } + +export enum BboxCorner { + TOP_RIGHT = 'TOP_RIGHT', + BOTTOM_LEFT = 'BOTTOM_LEFT', +}