UNPKG

cesium-gizmo

Version:

A Simple Cesium Gizmo using Cesium's Public API.

632 lines (631 loc) 18.3 kB
import * as E from "cesium"; import { Cartesian2 as p, Cartesian3 as i, Matrix4 as n, defaultValue as Ae, Material as W, Color as z, CylinderGeometry as Q, GeometryInstance as f, BlendingState as Ie, Primitive as C, MaterialAppearance as L, PolylineGeometry as Ce, PolylineMaterialAppearance as F, ArcType as Ne, BoxGeometry as ge, Matrix3 as b, Math as G, Transforms as D, destroyObject as Se, ScreenSpaceEventHandler as Ue, defined as B, ScreenSpaceEventType as S, Cartographic as R, SceneTransforms as k, BoundingSphere as be } from "cesium"; function Ge(s, e, t) { const o = new E.BoundingSphere(); return o.center = s, o.radius = e, t.camera.getPixelSize( o, t.context.drawingBufferWidth, t.context.drawingBufferHeight ); } function Le(s, e) { const t = new E.Cartesian3(), o = new E.Cartographic(), c = e.context, a = Math.max( c.drawingBufferWidth, c.drawingBufferHeight ), r = s.modelMatrix; if (t.x = r[12], t.y = r[13], t.z = r[14], e.camera._scene.mode !== E.SceneMode.SCENE3D) { const h = e.mapProjection, m = h.ellipsoid.cartesianToCartographic( t, o ); h.project(m, t), E.Cartesian3.fromElements( t.z, t.x, t.y, t ); } const l = 1, M = Ge(t, l, e), _ = 1 / M, w = Math.min( _ * 2 * l, a ); let u = 1; return w < s.length && (u = s.length * M / (2 * l)), u; } const d = Object.freeze({ xAxis: "xAxis", yAxis: "yAxis", zAxis: "zAxis" }), x = Object.freeze({ translate: "translate", rotate: "rotate", scale: "scale" }), O = Object.freeze({ local: "local", surface: "surface" }); class X { constructor(e, t) { this._gizmo = e, this._part = [], this._show = !0, this._scale = 1, this._scaleMatrix = new n(), this._mode = t; } update(e) { if (this._show) { if (this._scale = Le(this._gizmo, e), this._mode === x.translate) { const t = D.eastNorthUpToFixedFrame( n.getTranslation(this._gizmo.modelMatrix, new i()) ); this._scaleMatrix = n.multiplyByUniformScale( t, this._scale, t ); } else this._scaleMatrix = n.multiplyByUniformScale( this._gizmo.modelMatrix, this._scale, new n() ); for (const t of this._part) t.modelMatrix = this._scaleMatrix, t.update(e); } } isDestroyed() { return !1; } destroy() { for (const e of this._part) e.destroy(); return this._part = [], Se(this); } } class Ze { constructor(e) { e = Ae(e, {}), this.mode = null, this.applyTransformationToMountedPrimitive = !0, this.modelMatrix = n.IDENTITY, this.length = 250, this.transMode = null, this._viewer = null, this._mountedPrimitive = null, this._transPrimitives = null, this._rotatePrimitives = null, this._scalePrimitives = null, this._xMaterial = W.fromType("Color", { color: new z(1, 0, 0, 0.99) }), this._yMaterial = W.fromType("Color", { color: new z(0, 1, 0, 0.99) }), this._zMaterial = W.fromType("Color", { color: new z(0, 0, 1, 0.99) }), this._highlightMaterial = W.fromType("Color", { color: new z(1, 1, 0, 0.99) }), this.onGizmoPointerDown = e.onGizmoPointerDown, this.onGizmoPointerUp = e.onGizmoPointerUp, this.onGizmoPointerMove = e.onGizmoPointerMove, this.createGizmoPrimitive(); } createGizmoPrimitive() { const a = new Q({ length: 0.2, topRadius: 0, bottomRadius: 0.06 }), r = new Q({ length: 0.8, topRadius: 0.01, bottomRadius: 0.01 }), l = y( i.UNIT_X, 0.2 / 2 + 0.8 ), M = y( i.UNIT_X, 0.8 / 2 ), _ = y( i.UNIT_Y, 0.2 / 2 + 0.8 ), w = y( i.UNIT_Y, 0.8 / 2 ), u = y( i.UNIT_Z, 0.2 / 2 + 0.8 ), h = y( i.UNIT_Z, 0.8 / 2 ), m = new f({ id: d.xAxis, geometry: a, modelMatrix: l }), U = new f({ id: d.xAxis, geometry: r, modelMatrix: M }), g = new f({ id: d.yAxis, geometry: a, modelMatrix: _ }), H = new f({ id: d.yAxis, geometry: r, modelMatrix: w }), te = new f({ id: d.zAxis, geometry: a, modelMatrix: u }), q = new f({ id: d.zAxis, geometry: r, modelMatrix: h }), A = { depthTest: { enabled: !1 }, depthMask: !1, blending: Ie.ALPHA_BLEND }, I = n.IDENTITY, ie = new C({ geometryInstances: [m, U], appearance: new L({ material: this._xMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), ne = new C({ geometryInstances: [g, H], appearance: new L({ material: this._yMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), oe = new C({ geometryInstances: [te, q], appearance: new L({ material: this._zMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), K = new X( this, x.translate ); K._part.push( ie, ne, oe ), this._transPrimitives = K; const re = Re(1), Z = new Ce({ positions: re, width: 5, arcType: Ne.NONE, vertexFormat: F.VERTEX_FORMAT }), ae = y(i.UNIT_X, 0), se = y(i.UNIT_Y, 0), ce = y(i.UNIT_Z, 0), le = new f({ id: d.xAxis, geometry: Z, modelMatrix: ae }), de = new f({ id: d.yAxis, geometry: Z, modelMatrix: se }), me = new f({ id: d.zAxis, geometry: Z, modelMatrix: ce }), he = new C({ geometryInstances: le, appearance: new F({ material: this._xMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), xe = new C({ geometryInstances: de, appearance: new F({ material: this._yMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), pe = new C({ geometryInstances: me, appearance: new F({ material: this._zMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), $ = new X(this, x.rotate); $._part.push( he, xe, pe ), this._rotatePrimitives = $; const V = ge.fromDimensions({ dimensions: new i( 0.2 / 2, 0.2 / 2, 0.2 / 2 ) }), ue = y(i.UNIT_X, 0.8), Me = y(i.UNIT_Y, 0.8), _e = y(i.UNIT_Z, 0.8), we = new f({ id: d.xAxis, geometry: V, modelMatrix: ue }), fe = new f({ id: d.yAxis, geometry: V, modelMatrix: Me }), ye = new f({ id: d.zAxis, geometry: V, modelMatrix: _e }), Pe = new C({ geometryInstances: [we, U], appearance: new L({ material: this._xMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), ve = new C({ geometryInstances: [fe, H], appearance: new L({ material: this._yMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), Te = new C({ geometryInstances: [ye, q], appearance: new L({ material: this._zMaterial, renderState: A }), modelMatrix: I, asynchronous: !1 }), J = new X(this, x.scale); J._part.push( Pe, ve, Te ), this._scalePrimitives = J; } attach(e) { this._viewer = e, this._viewer.scene.primitives.add(this._transPrimitives), this._viewer.scene.primitives.add(this._rotatePrimitives), this._viewer.scene.primitives.add(this._scalePrimitives), this.setMode(x.translate), this.transMode = O.local, De(this._viewer, this); } detach() { this._viewer.scene.primitives.remove(this._transPrimitives), this._viewer.scene.primitives.remove(this._rotatePrimitives), this._viewer.scene.primitives.remove(this._scalePrimitives), this._viewer = null, ke(); } isGizmoPrimitive(e) { return this._transPrimitives._part.indexOf(e) !== -1 || this._rotatePrimitives._part.indexOf(e) !== -1 || this._scalePrimitives._part.indexOf(e) !== -1; } setMode(e) { e === x.translate ? (this.mode = x.translate, this._transPrimitives._show = !0, this._rotatePrimitives._show = !1, this._scalePrimitives._show = !1) : e === x.rotate ? (this.mode = x.rotate, this._transPrimitives._show = !1, this._rotatePrimitives._show = !0, this._scalePrimitives._show = !1) : e === x.scale && (this.mode = x.scale, this._transPrimitives._show = !1, this._rotatePrimitives._show = !1, this._scalePrimitives._show = !0); } } function y(s, e) { const t = n.IDENTITY.clone(); if (i.equals(s, i.UNIT_Y)) { const o = b.fromRotationX(G.toRadians(-90)), c = i.fromElements(0, e, 0); n.setTranslation(t, c, t), n.setRotation(t, o, t); } else if (i.equals(s, i.UNIT_X)) { const o = b.fromRotationY(G.toRadians(90)), c = i.fromElements(e, 0, 0); n.setTranslation(t, c, t), n.setRotation(t, o, t); } else if (i.equals(s, i.UNIT_Z)) { const o = b.IDENTITY, c = i.fromElements(0, 0, e); n.setTranslation(t, c, t), n.setRotation(t, o, t); } return t; } function Re(s) { const e = []; for (let t = 0; t <= 360; t++) { const o = G.toRadians(t), c = Math.cos(o) * s, a = Math.sin(o) * s; e.push(new i(c, a, 0)); } return e; } let Y = new p(), T = new i(), P = new n(), j = new n(), N = null, v; const Be = new n(), Ee = new i(), Oe = new n(), ee = new n(); function De(s, e) { v = new Ue(s.canvas), v.setInputAction((t) => { const o = s.scene.pick(t.position); B(o) && (e.isGizmoPrimitive(o.primitive) || o.primitive.modelMatrix instanceof n && (e._mountedPrimitive = o.primitive, e.modelMatrix = o.primitive.modelMatrix.clone())); }, S.LEFT_CLICK), v.setInputAction((t) => { const o = s.scene.pick(t.position); B(o) && (o.id === d.xAxis || o.id === d.yAxis || o.id === d.zAxis ? (console.log(o.id), N = o.id, s.scene.screenSpaceCameraController.enableRotate = !1, s.scene.screenSpaceCameraController.enableTranslate = !1, Y = t.position, T = new i( e.modelMatrix[12], e.modelMatrix[13], e.modelMatrix[14] ), P = e.modelMatrix.clone(), j = e._mountedPrimitive.modelMatrix.clone(), typeof e.onGizmoPointerDown == "function" && e.onGizmoPointerDown()) : (N = null, s.scene.screenSpaceCameraController.enableRotate = !0, s.scene.screenSpaceCameraController.enableTranslate = !0)); }, S.LEFT_DOWN), v.setInputAction((t) => { N && (N = null, Y = new p(), T = new i(), P = new n(), j = new n(), typeof e.onGizmoPointerUp == "function" && e.onGizmoPointerDown()), s.scene.screenSpaceCameraController.enableRotate = !0, s.scene.screenSpaceCameraController.enableTranslate = !0; }, S.LEFT_UP), v.setInputAction((t) => { if (!N) { const c = s.scene.pick(t.endPosition), a = B(c) && c.id === d.xAxis ? e._highlightMaterial : e._xMaterial, r = B(c) && c.id === d.yAxis ? e._highlightMaterial : e._yMaterial, l = B(c) && c.id === d.zAxis ? e._highlightMaterial : e._zMaterial; e._transPrimitives._part[0].appearance.material = a, e._transPrimitives._part[1].appearance.material = r, e._transPrimitives._part[2].appearance.material = l, e._rotatePrimitives._part[0].appearance.material = a, e._rotatePrimitives._part[1].appearance.material = r, e._rotatePrimitives._part[2].appearance.material = l, e._scalePrimitives._part[0].appearance.material = a, e._scalePrimitives._part[1].appearance.material = r, e._scalePrimitives._part[2].appearance.material = l; return; } const o = new p( t.endPosition.x - Y.x, t.endPosition.y - Y.y ); if (!(o.x === 0 && o.y === 0)) { if (e.mode === x.translate) { const c = We( N, s, o ); if (e.transMode === O.local) { const a = n.fromTranslation(c, Be), r = n.multiply( a, P, a ); if (isNaN(r[12]) || isNaN(r[13]) || isNaN(r[14])) return; if (e.modelMatrix[12] = r[12], e.modelMatrix[13] = r[13], e.modelMatrix[14] = r[14], typeof e.onGizmoPointerMove == "function" && e.onGizmoPointerMove({ mode: x.translate, transMode: O.local, result: n.getTranslation(r, new i()) }), e.applyTransformationToMountedPrimitive) { const l = e._mountedPrimitive; l.modelMatrix[12] = r[12], l.modelMatrix[13] = r[13], l.modelMatrix[14] = r[14]; } } else if (e.transMode === O.surface) { const a = R.fromCartesian(T), r = new R(), l = new i(); switch (N) { case d.xAxis: { const m = n.fromTranslation(c, new n()); n.multiply(m, P, m), l.x = m[12], l.y = m[13], l.z = m[14], R.fromCartesian( l, void 0, r ), r.height = a.height, r.latitude = a.latitude; break; } case d.yAxis: { const m = n.fromTranslation(c, new n()); n.multiply(m, P, m), l.x = m[12], l.y = m[13], l.z = m[14], R.fromCartesian( l, void 0, r ), r.height = a.height; break; } case d.zAxis: { a.height += c.z, R.clone(a, r); break; } } R.toCartesian(r, void 0, l); const M = D.eastNorthUpToFixedFrame(T), _ = n.inverseTransformation( M, new n() ), w = n.multiply( _, P, new n() ), u = D.eastNorthUpToFixedFrame(l), h = n.multiply( u, w, new n() ); if (isNaN(h[12]) || isNaN(h[13]) || isNaN(h[14])) return; if (n.clone(h, e.modelMatrix), typeof e.onGizmoPointerMove == "function" && e.onGizmoPointerMove({ mode: x.translate, transMode: O.surface, result: h.clone() }), e.applyTransformationToMountedPrimitive) { const m = e._mountedPrimitive; n.clone(h, m.modelMatrix); } } } else if (e.mode === x.rotate) { const c = ze( N, s, T, P, t.startPosition, t.endPosition ); n.multiplyByMatrix3( P, c, P ), n.clone(P, e.modelMatrix); const a = e._mountedPrimitive, r = n.getScale( a.modelMatrix, Ee ), l = n.multiplyByScale( P, r, Oe ); typeof e.onGizmoPointerMove == "function" && e.onGizmoPointerMove({ mode: x.rotate, result: D.fixedFrameToHeadingPitchRoll(l) }), e.applyTransformationToMountedPrimitive && n.clone(l, a.modelMatrix); } else if (e.mode === x.scale) { const c = Fe( N, s, T, P, o ); if (typeof e.onGizmoPointerMove == "function" && e.onGizmoPointerMove({ mode: x.scale, result: n.fromScale(c, ee) }), e.applyTransformationToMountedPrimitive) { const a = e._mountedPrimitive, r = n.multiplyByScale( j, c, ee ); n.clone(r, a.modelMatrix); } } } }, S.MOUSE_MOVE); } function ke() { v.removeInputAction(S.LEFT_CLICK), v.removeInputAction(S.LEFT_DOWN), v.removeInputAction(S.LEFT_UP), v.removeInputAction(S.MOUSE_MOVE), v = v && v.destroy(); } function We(s, e, t) { let o; switch (s) { case d.xAxis: o = i.UNIT_X; break; case d.yAxis: o = i.UNIT_Y; break; case d.zAxis: o = i.UNIT_Z; break; } const c = D.eastNorthUpToFixedFrame(T), a = n.multiplyByPointAsVector( c, o, new i() ), r = k.worldToWindowCoordinates( e.scene, T ), l = i.add( T, a, new i() ), M = k.worldToWindowCoordinates( e.scene, l ), _ = p.subtract( M, r, new p() ), w = p.dot(_, t) / p.magnitude(_), u = e.camera.getPixelSize( new be( T, i.magnitude(a) ), e.canvas.width, e.canvas.height ); return i.multiplyByScalar( a, w * u, new i() ); } function ze(s, e, t, o, c, a) { const r = k.worldToWindowCoordinates( e.scene, t ), l = p.subtract( c, r, new p() ), M = p.subtract( a, r, new p() ), _ = G.signNotZero( p.cross(l, M) ), w = p.angleBetween( l, M ), u = -_, h = i.subtract( e.scene.camera.positionWC, t, new i() ); let m; const U = new b(), g = new i(); switch (s) { case d.xAxis: n.multiplyByPointAsVector( o, i.UNIT_X, g ), m = G.signNotZero( i.dot(g, h) ), b.fromRotationX( w * u * m, U ); break; case d.yAxis: n.multiplyByPointAsVector( o, i.UNIT_Y, g ), m = G.signNotZero( i.dot(g, h) ), b.fromRotationY( w * u * m, U ); break; case d.zAxis: n.multiplyByPointAsVector( o, i.UNIT_Z, g ), m = G.signNotZero( i.dot(g, h) ), b.fromRotationZ( w * u * m, U ); break; } return U; } function Fe(s, e, t, o, c) { const a = new i(); switch (s) { case d.xAxis: n.multiplyByPointAsVector( o, i.UNIT_X, a ); break; case d.yAxis: n.multiplyByPointAsVector( o, i.UNIT_Y, a ); break; case d.zAxis: n.multiplyByPointAsVector( o, i.UNIT_Z, a ); break; } const r = k.worldToWindowCoordinates( e.scene, t ), l = i.add( t, a, new i() ), M = k.worldToWindowCoordinates( e.scene, l ), _ = p.subtract( M, r, new p() ), u = p.dot(_, c) / p.magnitude(_) / 10 + 1; let h; switch (s) { case d.xAxis: h = new i(u, 1, 1); break; case d.yAxis: h = new i(1, u, 1); break; case d.zAxis: h = new i(1, 1, u); break; } return h; } export { Ze as Gizmo, x as GizmoMode, O as TranslateMode };