@reearth/core 0.0.7-alpha.13 → 0.0.7-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/core.js +6864 -5606
  2. package/dist/core.umd.cjs +71 -71
  3. package/dist/index.d.ts +56 -13
  4. package/package.json +8 -5
  5. package/src/Map/Layer/hooks.ts +6 -3
  6. package/src/Map/Layer/index.tsx +2 -0
  7. package/src/Map/Layers/hooks.ts +17 -0
  8. package/src/Map/Layers/index.tsx +12 -1
  9. package/src/Map/Layers/keys.ts +1 -0
  10. package/src/Map/Sketch/hooks.ts +405 -399
  11. package/src/Map/Sketch/index.tsx +65 -18
  12. package/src/Map/Sketch/sketchMachine.ts +359 -4
  13. package/src/Map/Sketch/sketchMachine.typegen.ts +58 -1
  14. package/src/Map/Sketch/types.ts +10 -20
  15. package/src/Map/Sketch/usePluginSketchLayer.ts +105 -0
  16. package/src/Map/Sketch/useSketch.ts +559 -0
  17. package/src/Map/Sketch/useSketchFeature.ts +198 -0
  18. package/src/Map/hooks.ts +32 -1
  19. package/src/Map/index.tsx +24 -0
  20. package/src/Map/ref.ts +8 -0
  21. package/src/Map/types/index.ts +21 -1
  22. package/src/Map/types/viewerProperty.ts +2 -0
  23. package/src/Visualizer/coreContext.tsx +2 -0
  24. package/src/Visualizer/hooks.ts +25 -0
  25. package/src/Visualizer/index.tsx +13 -0
  26. package/src/engines/Cesium/Feature/index.tsx +6 -2
  27. package/src/engines/Cesium/Sketch/ControlPoint.tsx +128 -24
  28. package/src/engines/Cesium/Sketch/ExtrudedControlPoints.tsx +70 -25
  29. package/src/engines/Cesium/Sketch/ExtrudedMeasurement.tsx +3 -1
  30. package/src/engines/Cesium/Sketch/ExtrudedPolygonEntity.tsx +14 -14
  31. package/src/engines/Cesium/Sketch/PolylineEntity.tsx +7 -4
  32. package/src/engines/Cesium/Sketch/SurfaceAddingPoints.tsx +60 -0
  33. package/src/engines/Cesium/Sketch/SurfaceControlPoints.tsx +125 -35
  34. package/src/engines/Cesium/Sketch/constants.ts +5 -0
  35. package/src/engines/Cesium/Sketch/index.tsx +68 -29
  36. package/src/engines/Cesium/core/labels/JapanGSIOptimalBVmapVectorMapLabel/JapanGSIOptimalBVmapLabelImagery.tsx +8 -1
  37. package/src/engines/Cesium/core/labels/JapanGSIOptimalBVmapVectorMapLabel/JapanGSIOptimalBVmapVectorMapLabel.tsx +14 -2
  38. package/src/engines/Cesium/core/labels/LabelImageryLayers.tsx +10 -1
  39. package/src/engines/Cesium/hooks/useEngineRef.ts +36 -0
@@ -5,37 +5,42 @@ import {
5
5
  type PositionProperty,
6
6
  type Property,
7
7
  } from "@cesium/engine";
8
- import { useMemo, useRef, type FC } from "react";
8
+ import { useCallback, useMemo, useRef, type FC } from "react";
9
9
  import { Entity } from "resium";
10
10
  import invariant from "tiny-invariant";
11
11
 
12
12
  import { useConstant } from "../../../utils";
13
13
 
14
- let image: HTMLCanvasElement | undefined;
14
+ import { ADDING_POINT_COLOR, DEFAULT_EDIT_COLOR, SELECTED_EDIT_COLOR } from "./constants";
15
15
 
16
- function getImage(): HTMLCanvasElement {
17
- if (image != null) {
18
- return image;
19
- }
20
- image = document.createElement("canvas");
21
- image.width = 16;
22
- image.height = 16;
23
- const context = image.getContext("2d");
24
- invariant(context != null);
25
- context.fillStyle = "white";
26
- context.fillRect(3, 3, 10, 10);
27
- context.strokeStyle = "black";
28
- context.lineWidth = 2;
29
- context.strokeRect(3, 3, 10, 10);
30
- return image;
31
- }
16
+ import { ControlPointMouseEventHandler } from ".";
17
+
18
+ let drawPointImage: HTMLCanvasElement | undefined;
19
+ let editPointImage: HTMLCanvasElement | undefined;
20
+ let selectedPointImage: HTMLCanvasElement | undefined;
21
+ let addingPointImage: HTMLCanvasElement | undefined;
32
22
 
33
23
  export interface ControlPointProps {
34
24
  position: Property | Cartesian3;
35
25
  clampToGround?: boolean;
26
+ index: number;
27
+ isEditing?: boolean;
28
+ isSelected?: boolean;
29
+ isAddingPoint?: boolean;
30
+ isExtrudedControlPoint?: boolean;
31
+ handleControlPointMouseEvent?: ControlPointMouseEventHandler;
36
32
  }
37
33
 
38
- export const ControlPoint: FC<ControlPointProps> = ({ position, clampToGround = false }) => {
34
+ export const ControlPoint: FC<ControlPointProps> = ({
35
+ position,
36
+ clampToGround = false,
37
+ index,
38
+ isEditing,
39
+ isSelected,
40
+ isAddingPoint,
41
+ isExtrudedControlPoint,
42
+ handleControlPointMouseEvent,
43
+ }) => {
39
44
  const positionRef = useRef(position);
40
45
  positionRef.current = position;
41
46
  const positionProperty = useConstant(
@@ -53,15 +58,114 @@ export const ControlPoint: FC<ControlPointProps> = ({ position, clampToGround =
53
58
  () => ({
54
59
  position: positionProperty,
55
60
  billboard: {
56
- image: getImage(),
57
- width: 8,
58
- height: 8,
61
+ image: isEditing
62
+ ? isAddingPoint
63
+ ? getAddingPointImage()
64
+ : isSelected
65
+ ? getSelectedPointImage()
66
+ : getEditPointImage()
67
+ : getDrawPointImage(),
68
+ width: isEditing ? 16 : 8,
69
+ height: isEditing ? 16 : 8,
59
70
  heightReference: clampToGround ? HeightReference.CLAMP_TO_GROUND : HeightReference.NONE,
60
71
  disableDepthTestDistance: Infinity,
61
72
  },
62
73
  }),
63
- [clampToGround, positionProperty],
74
+ [clampToGround, positionProperty, isAddingPoint, isEditing, isSelected],
64
75
  );
65
76
 
66
- return <Entity {...options} />;
77
+ const handleMouseDown = useCallback(() => {
78
+ handleControlPointMouseEvent?.(index, !!isExtrudedControlPoint, "mousedown");
79
+ }, [index, isExtrudedControlPoint, handleControlPointMouseEvent]);
80
+
81
+ const handleMouseClick = useCallback(() => {
82
+ handleControlPointMouseEvent?.(index, !!isExtrudedControlPoint, "click");
83
+ }, [index, isExtrudedControlPoint, handleControlPointMouseEvent]);
84
+
85
+ return <Entity {...options} onMouseDown={handleMouseDown} onClick={handleMouseClick} />;
67
86
  };
87
+
88
+ function getDrawPointImage(): HTMLCanvasElement {
89
+ if (drawPointImage != null) {
90
+ return drawPointImage;
91
+ }
92
+ drawPointImage = document.createElement("canvas");
93
+ drawPointImage.width = 16;
94
+ drawPointImage.height = 16;
95
+ const ctx = drawPointImage.getContext("2d");
96
+ invariant(ctx != null);
97
+ ctx.fillStyle = "white";
98
+ ctx.fillRect(3, 3, 10, 10);
99
+ ctx.strokeStyle = "black";
100
+ ctx.lineWidth = 2;
101
+ ctx.strokeRect(3, 3, 10, 10);
102
+ return drawPointImage;
103
+ }
104
+
105
+ function getEditPointImage(): HTMLCanvasElement {
106
+ return getImage(editPointImage, {
107
+ size: 32,
108
+ color: "white",
109
+ strokeColor: DEFAULT_EDIT_COLOR,
110
+ });
111
+ }
112
+
113
+ function getSelectedPointImage(): HTMLCanvasElement {
114
+ return getImage(selectedPointImage, {
115
+ size: 32,
116
+ color: "white",
117
+ strokeColor: SELECTED_EDIT_COLOR,
118
+ });
119
+ }
120
+
121
+ function getAddingPointImage(): HTMLCanvasElement {
122
+ if (addingPointImage != null) {
123
+ return addingPointImage;
124
+ }
125
+ addingPointImage = document.createElement("canvas");
126
+ addingPointImage.width = 32;
127
+ addingPointImage.height = 32;
128
+ const ctx = addingPointImage.getContext("2d");
129
+ invariant(ctx != null);
130
+ ctx.beginPath();
131
+ ctx.arc(16, 16, 12, 0, 2 * Math.PI);
132
+ ctx.fillStyle = "white";
133
+ ctx.fill();
134
+ ctx.strokeStyle = ADDING_POINT_COLOR;
135
+ ctx.lineWidth = 4;
136
+ ctx.stroke();
137
+ ctx.beginPath();
138
+ ctx.moveTo(16, 8);
139
+ ctx.lineTo(16, 24);
140
+ ctx.stroke();
141
+ ctx.moveTo(8, 16);
142
+ ctx.lineTo(24, 16);
143
+ ctx.stroke();
144
+ return addingPointImage;
145
+ }
146
+
147
+ function getImage(
148
+ canvas: HTMLCanvasElement | undefined,
149
+ options: {
150
+ size: number;
151
+ color: string;
152
+ strokeColor: string;
153
+ },
154
+ ): HTMLCanvasElement {
155
+ if (canvas != null) {
156
+ return canvas;
157
+ }
158
+ canvas = document.createElement("canvas");
159
+ canvas.width = options.size;
160
+ canvas.height = options.size;
161
+ const ctx = canvas.getContext("2d");
162
+ invariant(ctx != null);
163
+ ctx.beginPath();
164
+ ctx.arc(options.size / 2, options.size / 2, options.size / 2 - 4, 0, 2 * Math.PI);
165
+ ctx.fillStyle = options.color;
166
+ ctx.fill();
167
+ ctx.strokeStyle = options.strokeColor;
168
+ ctx.lineWidth = 4;
169
+ ctx.stroke();
170
+ return canvas;
171
+ }
@@ -1,46 +1,91 @@
1
- import { Cartesian3, type Color } from "@cesium/engine";
1
+ import { Cartesian3, Color } from "@cesium/engine";
2
2
  import { memo, type FC } from "react";
3
- import { useCesium } from "resium";
4
- import invariant from "tiny-invariant";
5
3
 
4
+ import { Position3d } from "../../../types";
5
+
6
+ import { DEFAULT_EDIT_COLOR } from "./constants";
6
7
  import { ControlPoint } from "./ControlPoint";
7
8
  import { type GeometryOptions } from "./createGeometry";
8
9
  import { ExtrudedMeasurement } from "./ExtrudedMeasurement";
9
10
 
11
+ import { ControlPointMouseEventHandler } from ".";
12
+
10
13
  export interface ExtrudedControlPointsProps {
11
14
  geometryOptions: GeometryOptions;
12
15
  extrudedHeight: number;
16
+ extrudedPoint?: Position3d;
17
+ centroidBasePoint?: Position3d;
18
+ centroidExtrudedPoint?: Position3d;
19
+ catchedExtrudedPoint?: boolean;
13
20
  color?: Color;
21
+ isEditing?: boolean;
22
+ handleControlPointMouseEvent?: ControlPointMouseEventHandler;
14
23
  }
15
24
 
16
- const cartesianScratch = new Cartesian3();
17
-
18
25
  const ExtrudedControlPoints: FC<ExtrudedControlPointsProps> = memo(
19
- ({ geometryOptions: { controlPoints }, extrudedHeight, color }) => {
20
- const { viewer } = useCesium();
26
+ ({
27
+ geometryOptions: { controlPoints, type },
28
+ extrudedHeight,
29
+ color,
30
+ isEditing,
31
+ extrudedPoint: extrudedPointPosition,
32
+ centroidBasePoint: extrudeBasePointPosition,
33
+ centroidExtrudedPoint: extrudeControlPointPosition,
34
+ catchedExtrudedPoint,
35
+ handleControlPointMouseEvent,
36
+ }) => {
21
37
  const controlPoint = controlPoints[controlPoints.length - 1];
22
- const normal = viewer?.scene?.globe.ellipsoid.geodeticSurfaceNormal(
23
- controlPoint,
24
- cartesianScratch,
25
- );
26
38
 
27
- invariant(normal !== undefined);
28
- const extrudedPoint = Cartesian3.add(
29
- controlPoint,
30
- Cartesian3.multiplyByScalar(normal, extrudedHeight, cartesianScratch),
31
- cartesianScratch,
32
- );
39
+ const extrudedPoint = extrudedPointPosition
40
+ ? new Cartesian3(...extrudedPointPosition)
41
+ : undefined;
42
+
43
+ const heightBasePoint = extrudeBasePointPosition
44
+ ? new Cartesian3(...extrudeBasePointPosition)
45
+ : undefined;
46
+
47
+ const centroidExtrudedPoint = extrudeControlPointPosition
48
+ ? new Cartesian3(...extrudeControlPointPosition)
49
+ : undefined;
33
50
 
34
51
  return (
35
52
  <>
36
- <ControlPoint position={controlPoint} clampToGround />
37
- <ControlPoint position={extrudedPoint} />
38
- <ExtrudedMeasurement
39
- a={controlPoint}
40
- b={extrudedPoint}
41
- extrudedHeight={extrudedHeight}
42
- color={color}
43
- />
53
+ {extrudedPoint && (
54
+ <>
55
+ <ControlPoint
56
+ index={-1}
57
+ position={extrudedPoint}
58
+ isEditing={isEditing}
59
+ isExtrudedControlPoint
60
+ handleControlPointMouseEvent={handleControlPointMouseEvent}
61
+ />
62
+ {(!isEditing || catchedExtrudedPoint) && (
63
+ <ExtrudedMeasurement
64
+ a={controlPoint}
65
+ b={extrudedPoint}
66
+ extrudedHeight={extrudedHeight}
67
+ color={isEditing ? Color.fromCssColorString(DEFAULT_EDIT_COLOR) : color}
68
+ showLine={type !== "extrudedPolygon"}
69
+ />
70
+ )}
71
+ </>
72
+ )}
73
+ {heightBasePoint && (
74
+ <ControlPoint
75
+ index={-1}
76
+ position={heightBasePoint}
77
+ isEditing={isEditing}
78
+ isExtrudedControlPoint
79
+ />
80
+ )}
81
+ {centroidExtrudedPoint && (
82
+ <ControlPoint
83
+ index={-1}
84
+ position={centroidExtrudedPoint}
85
+ isEditing={isEditing}
86
+ isExtrudedControlPoint
87
+ />
88
+ )}
44
89
  </>
45
90
  );
46
91
  },
@@ -46,6 +46,7 @@ export interface ExtrudedMeasurementProps {
46
46
  b: Cartesian3;
47
47
  extrudedHeight: number;
48
48
  color?: Color;
49
+ showLine?: boolean;
49
50
  }
50
51
 
51
52
  export const ExtrudedMeasurement: FC<ExtrudedMeasurementProps> = ({
@@ -53,6 +54,7 @@ export const ExtrudedMeasurement: FC<ExtrudedMeasurementProps> = ({
53
54
  b,
54
55
  extrudedHeight,
55
56
  color,
57
+ showLine,
56
58
  }) => {
57
59
  const position = useConstant(() => new Cartesian3());
58
60
  return (
@@ -64,7 +66,7 @@ export const ExtrudedMeasurement: FC<ExtrudedMeasurementProps> = ({
64
66
  : `${(extrudedHeight / 1000).toFixed(1)} km`}
65
67
  </MeasurementText>
66
68
  </ScreenSpaceElement>
67
- <MeasurementLine a={a} b={b} color={color} />
69
+ {showLine && <MeasurementLine a={a} b={b} color={color} />}
68
70
  </>
69
71
  );
70
72
  };
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  CallbackProperty,
3
3
  ClassificationType,
4
+ Color,
4
5
  ColorMaterialProperty,
5
6
  HeightReference,
6
7
  ShadowMode,
7
- type Color,
8
8
  type PolygonHierarchy,
9
9
  } from "@cesium/engine";
10
10
  import { useMemo, useRef, type FC } from "react";
@@ -12,60 +12,60 @@ import { useMemo, useRef, type FC } from "react";
12
12
  import { useConstant } from "../../../utils";
13
13
  import { useContext } from "../Feature/context";
14
14
 
15
+ import { DEFAULT_EDIT_COLOR } from "./constants";
15
16
  import { Entity, type EntityProps } from "./Entity";
16
17
 
17
18
  export interface ExtrudedPolygonEntityProps {
18
- dynamic?: boolean;
19
19
  id?: string;
20
20
  hierarchy: PolygonHierarchy;
21
21
  extrudedHeight: number;
22
22
  color?: Color;
23
23
  disableShadow?: boolean;
24
- enableRelativeHeight?: boolean;
24
+ isEditing?: boolean;
25
25
  }
26
26
 
27
27
  export const ExtrudedPolygonEntity: FC<ExtrudedPolygonEntityProps> = ({
28
- dynamic = false,
29
28
  id,
30
29
  hierarchy: hierarchyProp,
31
30
  extrudedHeight: extrudedHeightProp,
32
31
  color,
33
32
  disableShadow = false,
34
- enableRelativeHeight = false,
33
+ isEditing,
35
34
  }) => {
36
35
  const hierarchyRef = useRef(hierarchyProp);
37
36
  hierarchyRef.current = hierarchyProp;
38
37
  const hierarchyProperty = useConstant(
39
38
  () => new CallbackProperty(() => hierarchyRef.current, false),
40
39
  );
41
- const hierarchy = dynamic ? hierarchyProperty : hierarchyProp;
40
+ const hierarchy = hierarchyProperty;
42
41
 
43
42
  const extrudedHeightRef = useRef(extrudedHeightProp);
44
43
  extrudedHeightRef.current = extrudedHeightProp;
45
44
  const extrudedHeightProperty = useConstant(
46
45
  () => new CallbackProperty(() => extrudedHeightRef.current, false),
47
46
  );
48
- const extrudedHeight = dynamic ? extrudedHeightProperty : extrudedHeightProp;
47
+ const extrudedHeight = extrudedHeightProperty;
49
48
 
50
49
  const options = useMemo(
51
50
  (): EntityProps => ({
52
51
  polygon: {
53
52
  hierarchy,
53
+ heightReference: HeightReference.RELATIVE_TO_TERRAIN,
54
54
  extrudedHeight,
55
- extrudedHeightReference: HeightReference.RELATIVE_TO_GROUND,
55
+ extrudedHeightReference: HeightReference.RELATIVE_TO_TERRAIN,
56
+ // extrudedHeightReference: HeightReference.NONE,
56
57
  fill: true,
57
58
  outline: true,
58
59
  outlineWidth: 1,
59
- outlineColor: color?.withAlpha(1),
60
- material: new ColorMaterialProperty(color),
60
+ outlineColor: isEditing
61
+ ? Color.fromCssColorString(DEFAULT_EDIT_COLOR)
62
+ : color?.withAlpha(1),
63
+ material: new ColorMaterialProperty(isEditing ? color?.withAlpha(0.2) : color),
61
64
  classificationType: ClassificationType.TERRAIN,
62
65
  shadows: disableShadow ? ShadowMode.DISABLED : ShadowMode.ENABLED,
63
- ...(enableRelativeHeight
64
- ? { height: 0, heightReference: HeightReference.RELATIVE_TO_GROUND }
65
- : undefined),
66
66
  },
67
67
  }),
68
- [extrudedHeight, disableShadow, hierarchy, color, enableRelativeHeight],
68
+ [extrudedHeight, disableShadow, hierarchy, color, isEditing],
69
69
  );
70
70
 
71
71
  const { requestRender } = useContext();
@@ -1,21 +1,24 @@
1
- import { CallbackProperty, ClassificationType, type Cartesian3, type Color } from "@cesium/engine";
1
+ import { CallbackProperty, ClassificationType, Color, type Cartesian3 } from "@cesium/engine";
2
2
  import { useMemo, useRef, type FC } from "react";
3
3
 
4
4
  import { useConstant } from "../../../utils";
5
5
  import { useContext } from "../Feature/context";
6
6
 
7
+ import { DEFAULT_EDIT_COLOR } from "./constants";
7
8
  import { Entity, type EntityProps } from "./Entity";
8
9
 
9
10
  export interface PolylineEntityProps {
10
11
  dynamic?: boolean;
11
12
  positions: Cartesian3[];
12
13
  color?: Color;
14
+ isEditing?: boolean;
13
15
  }
14
16
 
15
17
  export const PolylineEntity: FC<PolylineEntityProps> = ({
16
18
  dynamic = false,
17
19
  positions: positionsProp,
18
20
  color,
21
+ isEditing,
19
22
  }) => {
20
23
  const positionsRef = useRef(positionsProp);
21
24
  positionsRef.current = positionsProp;
@@ -28,13 +31,13 @@ export const PolylineEntity: FC<PolylineEntityProps> = ({
28
31
  (): EntityProps => ({
29
32
  polyline: {
30
33
  positions,
31
- width: 1.5,
32
- material: color,
34
+ width: isEditing ? 1.5 : 1.5,
35
+ material: isEditing ? Color.fromCssColorString(DEFAULT_EDIT_COLOR) : color,
33
36
  classificationType: ClassificationType.TERRAIN,
34
37
  clampToGround: true,
35
38
  },
36
39
  }),
37
- [color, positions],
40
+ [color, positions, isEditing],
38
41
  );
39
42
 
40
43
  const { requestRender } = useContext();
@@ -0,0 +1,60 @@
1
+ import { Cartesian3 } from "@cesium/engine";
2
+ import { memo, type FC } from "react";
3
+
4
+ import { Position3d } from "../../../types";
5
+
6
+ import { ControlPoint } from "./ControlPoint";
7
+ import { type GeometryOptions } from "./createGeometry";
8
+
9
+ export interface SurfaceAddingPointsProps {
10
+ geometryOptions: GeometryOptions;
11
+ isEditing?: boolean;
12
+ handleAddControlPoint?: (position: Position3d, index: number) => void;
13
+ }
14
+
15
+ const cartesianScratch1 = new Cartesian3();
16
+
17
+ const SurfaceAddingPoints: FC<SurfaceAddingPointsProps> = memo(
18
+ ({ geometryOptions: { type, controlPoints }, isEditing, handleAddControlPoint }) => {
19
+ if (!["polyline", "polygon", "extrudedPolygon"].includes(type)) return null;
20
+
21
+ const addingPoints = [];
22
+
23
+ for (let i = 0; i < controlPoints.length - 1; i++) {
24
+ const nextPoint = controlPoints[i + 1];
25
+ const midPoint = Cartesian3.midpoint(controlPoints[i], nextPoint, cartesianScratch1);
26
+ addingPoints.push(midPoint.clone());
27
+ }
28
+
29
+ if (type === "polygon" || type === "extrudedPolygon") {
30
+ const midPoint = Cartesian3.midpoint(
31
+ controlPoints[controlPoints.length - 1],
32
+ controlPoints[0],
33
+ cartesianScratch1,
34
+ );
35
+ addingPoints.push(midPoint.clone());
36
+ }
37
+
38
+ return (
39
+ <>
40
+ {addingPoints.map((addingPoint, index) => (
41
+ <ControlPoint
42
+ key={index}
43
+ position={addingPoint}
44
+ isAddingPoint
45
+ index={index}
46
+ clampToGround
47
+ isEditing={isEditing}
48
+ handleControlPointMouseEvent={() =>
49
+ handleAddControlPoint?.([addingPoint.x, addingPoint.y, addingPoint.z], index)
50
+ }
51
+ />
52
+ ))}
53
+ </>
54
+ );
55
+ },
56
+ );
57
+
58
+ SurfaceAddingPoints.displayName = "SurfaceAddingPoints";
59
+
60
+ export default SurfaceAddingPoints;