cesium-gizmo
Version:
A Simple Cesium Gizmo using Cesium's Public API.
632 lines (631 loc) • 18.3 kB
JavaScript
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
};