3dtiles-inspector 0.2.2 → 0.2.4
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.
- package/CHANGELOG.md +22 -0
- package/README.md +6 -5
- package/dist/inspector-assets/viewer/app.js +1359 -122
- package/package.json +1 -1
- package/src/server/viewerHtml.js +112 -3
- package/src/viewer/app.js +8 -3
- package/src/viewer/navigation/cameraFlyTo.js +730 -0
- package/src/viewer/navigation/flyTo.js +78 -16
- package/src/viewer/scene/cameraController.js +2 -2
- package/src/viewer/scene/sceneSetup.js +3 -6
- package/src/viewer/screenSelection/cropController.js +418 -6
- package/src/viewer/screenSelection/editOverlay.js +348 -0
- package/src/viewer/screenSelection/geometry.js +66 -52
- package/src/viewer/screenSelection/index.js +61 -0
- package/src/viewer/screenSelection/pointerTracker.js +19 -11
|
@@ -45136,10 +45136,10 @@ function createGeoCameraController({
|
|
|
45136
45136
|
const right = new Vector3();
|
|
45137
45137
|
const backward = new Vector3();
|
|
45138
45138
|
const quaternion = new Quaternion();
|
|
45139
|
-
function
|
|
45139
|
+
function isCenterModePosition2(value) {
|
|
45140
45140
|
return value.lengthSq() <= centerModeDistanceSq;
|
|
45141
45141
|
}
|
|
45142
|
-
function
|
|
45142
|
+
function getLocalFrame2(referencePoint) {
|
|
45143
45143
|
const ellipsoid = getActiveEllipsoid();
|
|
45144
45144
|
ellipsoid.getPositionToCartographic(referencePoint, cartographicTarget);
|
|
45145
45145
|
ellipsoid.getEastNorthUpFrame(
|
|
@@ -45186,7 +45186,7 @@ function createGeoCameraController({
|
|
|
45186
45186
|
if (referencePoint.lengthSq() < centerModeDistanceSq || !getActiveEllipsoid()) {
|
|
45187
45187
|
return target.identity();
|
|
45188
45188
|
}
|
|
45189
|
-
|
|
45189
|
+
getLocalFrame2(referencePoint);
|
|
45190
45190
|
basis.makeBasis(east, north, up);
|
|
45191
45191
|
return target.setFromRotationMatrix(basis);
|
|
45192
45192
|
}
|
|
@@ -45201,7 +45201,7 @@ function createGeoCameraController({
|
|
|
45201
45201
|
);
|
|
45202
45202
|
return Math.max(radius / Math.sin(limitingHalfFov), 1);
|
|
45203
45203
|
}
|
|
45204
|
-
function
|
|
45204
|
+
function getCenterModeHeadingPitchRollForward2(heading, pitch) {
|
|
45205
45205
|
const cosPitch = Math.cos(pitch);
|
|
45206
45206
|
forward.set(
|
|
45207
45207
|
Math.sin(heading) * cosPitch,
|
|
@@ -45210,14 +45210,14 @@ function createGeoCameraController({
|
|
|
45210
45210
|
);
|
|
45211
45211
|
return forward.normalize();
|
|
45212
45212
|
}
|
|
45213
|
-
function
|
|
45214
|
-
if (
|
|
45215
|
-
return
|
|
45213
|
+
function getHeadingPitchRollForward2(referencePoint, heading, pitch) {
|
|
45214
|
+
if (isCenterModePosition2(referencePoint)) {
|
|
45215
|
+
return getCenterModeHeadingPitchRollForward2(heading, pitch);
|
|
45216
45216
|
}
|
|
45217
45217
|
if (referencePoint.lengthSq() < 1e-6) {
|
|
45218
45218
|
return forward.set(0, 0, -1);
|
|
45219
45219
|
}
|
|
45220
|
-
|
|
45220
|
+
getLocalFrame2(referencePoint);
|
|
45221
45221
|
const cosPitch = Math.cos(pitch);
|
|
45222
45222
|
const sinPitch = Math.sin(pitch);
|
|
45223
45223
|
const cosHeading = Math.cos(heading);
|
|
@@ -45225,8 +45225,8 @@ function createGeoCameraController({
|
|
|
45225
45225
|
forward.copy(north).multiplyScalar(cosHeading * cosPitch).addScaledVector(east, sinHeading * cosPitch).addScaledVector(up, sinPitch).normalize();
|
|
45226
45226
|
return forward;
|
|
45227
45227
|
}
|
|
45228
|
-
function
|
|
45229
|
-
|
|
45228
|
+
function getCenterModeHeadingPitchRollBasis2(heading, pitch, roll) {
|
|
45229
|
+
getCenterModeHeadingPitchRollForward2(heading, pitch);
|
|
45230
45230
|
right.copy(WORLD_RIGHT).multiplyScalar(Math.cos(heading)).addScaledVector(CENTER_NORTH, -Math.sin(heading)).normalize();
|
|
45231
45231
|
up.crossVectors(right, forward).normalize();
|
|
45232
45232
|
if (roll !== 0) {
|
|
@@ -45235,14 +45235,14 @@ function createGeoCameraController({
|
|
|
45235
45235
|
}
|
|
45236
45236
|
backward.copy(forward).negate();
|
|
45237
45237
|
}
|
|
45238
|
-
function
|
|
45239
|
-
if (
|
|
45240
|
-
|
|
45238
|
+
function getHeadingPitchRollQuaternion2(referencePoint, heading, pitch, roll) {
|
|
45239
|
+
if (isCenterModePosition2(referencePoint)) {
|
|
45240
|
+
getCenterModeHeadingPitchRollBasis2(heading, pitch, roll);
|
|
45241
45241
|
} else if (referencePoint.lengthSq() < 1e-6) {
|
|
45242
45242
|
quaternion.identity();
|
|
45243
45243
|
return quaternion;
|
|
45244
45244
|
} else {
|
|
45245
|
-
|
|
45245
|
+
getHeadingPitchRollForward2(referencePoint, heading, pitch);
|
|
45246
45246
|
right.copy(east).multiplyScalar(Math.cos(heading)).addScaledVector(north, -Math.sin(heading)).normalize();
|
|
45247
45247
|
up.crossVectors(right, forward).normalize();
|
|
45248
45248
|
if (roll !== 0) {
|
|
@@ -45254,7 +45254,7 @@ function createGeoCameraController({
|
|
|
45254
45254
|
basis.makeBasis(right, up, backward);
|
|
45255
45255
|
return quaternion.setFromRotationMatrix(basis);
|
|
45256
45256
|
}
|
|
45257
|
-
function
|
|
45257
|
+
function getBoundingSphereFlyToPosition2(target, range, options) {
|
|
45258
45258
|
const { heading, pitch } = options;
|
|
45259
45259
|
if (heading === void 0 && pitch === void 0) {
|
|
45260
45260
|
const direction = target.lengthSq() > 1e-6 ? position.copy(target).normalize() : camera.position.lengthSq() > 1e-6 ? position.copy(camera.position).normalize() : position.set(0, -1, 0);
|
|
@@ -45262,15 +45262,15 @@ function createGeoCameraController({
|
|
|
45262
45262
|
}
|
|
45263
45263
|
const resolvedHeading = heading ?? 0;
|
|
45264
45264
|
const resolvedPitch = pitch ?? -Math.PI / 2;
|
|
45265
|
-
const centerForward =
|
|
45265
|
+
const centerForward = getCenterModeHeadingPitchRollForward2(
|
|
45266
45266
|
resolvedHeading,
|
|
45267
45267
|
resolvedPitch
|
|
45268
45268
|
);
|
|
45269
45269
|
const centerPosition = position.copy(target).addScaledVector(centerForward, -range);
|
|
45270
|
-
if (
|
|
45270
|
+
if (isCenterModePosition2(centerPosition)) {
|
|
45271
45271
|
return centerPosition;
|
|
45272
45272
|
}
|
|
45273
|
-
const resolvedForward =
|
|
45273
|
+
const resolvedForward = getHeadingPitchRollForward2(
|
|
45274
45274
|
target,
|
|
45275
45275
|
resolvedHeading,
|
|
45276
45276
|
resolvedPitch
|
|
@@ -45291,13 +45291,13 @@ function createGeoCameraController({
|
|
|
45291
45291
|
} else {
|
|
45292
45292
|
offsetDistance = getCameraDistanceForBoundingSphere(safeRadius);
|
|
45293
45293
|
}
|
|
45294
|
-
const nextPosition =
|
|
45294
|
+
const nextPosition = getBoundingSphereFlyToPosition2(
|
|
45295
45295
|
target,
|
|
45296
45296
|
offsetDistance,
|
|
45297
45297
|
options
|
|
45298
45298
|
);
|
|
45299
|
-
const nextQuaternion =
|
|
45300
|
-
|
|
45299
|
+
const nextQuaternion = getHeadingPitchRollQuaternion2(
|
|
45300
|
+
isCenterModePosition2(nextPosition) ? nextPosition : target,
|
|
45301
45301
|
options.heading ?? 0,
|
|
45302
45302
|
options.pitch ?? -Math.PI / 2,
|
|
45303
45303
|
options.roll ?? 0
|
|
@@ -65854,7 +65854,7 @@ var init_cameraController = __esm({
|
|
|
65854
65854
|
const minScale = 0;
|
|
65855
65855
|
metrics.distanceScale = baseScale;
|
|
65856
65856
|
metrics.transitionWeight = 0;
|
|
65857
|
-
if (!__privateGet(this, _ellipsoid)) {
|
|
65857
|
+
if (!__privateGet(this, _ellipsoid) || __privateMethod(this, _CameraController_instances, isCameraCenterMode_fn).call(this)) {
|
|
65858
65858
|
return metrics;
|
|
65859
65859
|
}
|
|
65860
65860
|
const taperStartRadius = __privateGet(this, _ellipsoidMaxRadius) * 1.5;
|
|
@@ -65903,7 +65903,7 @@ var init_cameraController = __esm({
|
|
|
65903
65903
|
const source = _vec4.copy(__privateGet(this, _camera3).position);
|
|
65904
65904
|
let distanceScale = 1;
|
|
65905
65905
|
let transitionWeight = 0;
|
|
65906
|
-
if (zoomAmount < 0 && __privateGet(this, _ellipsoid)) {
|
|
65906
|
+
if (zoomAmount < 0 && __privateGet(this, _ellipsoid) && !__privateMethod(this, _CameraController_instances, isCameraCenterMode_fn).call(this)) {
|
|
65907
65907
|
const metrics = __privateMethod(this, _CameraController_instances, getZoomOutMetrics_fn).call(this, source, hit.virtual ? null : hit);
|
|
65908
65908
|
distanceScale = metrics.distanceScale;
|
|
65909
65909
|
transitionWeight = metrics.transitionWeight;
|
|
@@ -66096,9 +66096,9 @@ function createViewerScene({
|
|
|
66096
66096
|
60,
|
|
66097
66097
|
window.innerWidth / window.innerHeight,
|
|
66098
66098
|
1,
|
|
66099
|
-
|
|
66099
|
+
12e6
|
|
66100
66100
|
);
|
|
66101
|
-
camera.position.set(0, 0,
|
|
66101
|
+
camera.position.set(0, 0, 12e6);
|
|
66102
66102
|
camera.updateMatrixWorld(true);
|
|
66103
66103
|
const contentGroup = new Group();
|
|
66104
66104
|
scene.add(contentGroup);
|
|
@@ -67650,6 +67650,505 @@ var init_setPositionController = __esm({
|
|
|
67650
67650
|
}
|
|
67651
67651
|
});
|
|
67652
67652
|
|
|
67653
|
+
// src/viewer/navigation/cameraFlyTo.js
|
|
67654
|
+
function eastNorthUpToFixedFrame(origin) {
|
|
67655
|
+
_geoUp.copy(origin).multiply(_oneOverRadiiSquared).normalize();
|
|
67656
|
+
_geoEast.set(0, 0, 1).cross(_geoUp).normalize();
|
|
67657
|
+
_geoNorth.copy(_geoUp).cross(_geoEast).normalize();
|
|
67658
|
+
return _matrix3.set(
|
|
67659
|
+
_geoEast.x,
|
|
67660
|
+
_geoNorth.x,
|
|
67661
|
+
_geoUp.x,
|
|
67662
|
+
origin.x,
|
|
67663
|
+
_geoEast.y,
|
|
67664
|
+
_geoNorth.y,
|
|
67665
|
+
_geoUp.y,
|
|
67666
|
+
origin.y,
|
|
67667
|
+
_geoEast.z,
|
|
67668
|
+
_geoNorth.z,
|
|
67669
|
+
_geoUp.z,
|
|
67670
|
+
origin.z,
|
|
67671
|
+
0,
|
|
67672
|
+
0,
|
|
67673
|
+
0,
|
|
67674
|
+
1
|
|
67675
|
+
);
|
|
67676
|
+
}
|
|
67677
|
+
function createCameraFlight(camera, position, target, options = {}) {
|
|
67678
|
+
const duration = options.duration ?? 2500;
|
|
67679
|
+
const endPosition = position.clone();
|
|
67680
|
+
const endQuaternion = getEndQuaternion(endPosition, target, options);
|
|
67681
|
+
const endPose = getUprightHeadingPitchAtPose(endPosition, endQuaternion);
|
|
67682
|
+
const endRoll = getRollAtPose(endPosition, endQuaternion);
|
|
67683
|
+
const endZoom = camera instanceof OrthographicCamera ? Math.max(options.endZoom ?? camera.zoom, 1e-6) : null;
|
|
67684
|
+
return buildFlightState(camera, {
|
|
67685
|
+
duration,
|
|
67686
|
+
endPosition,
|
|
67687
|
+
endQuaternion,
|
|
67688
|
+
endZoom,
|
|
67689
|
+
endHeading: endPose.heading,
|
|
67690
|
+
endPitch: endPose.pitch,
|
|
67691
|
+
endRoll
|
|
67692
|
+
});
|
|
67693
|
+
}
|
|
67694
|
+
function getFlyToParamsFromBoundingSphere(camera, target, radius, options = {}) {
|
|
67695
|
+
const safeRadius = Math.max(radius, 1);
|
|
67696
|
+
let offsetDistance = safeRadius;
|
|
67697
|
+
let endZoom = options.endZoom;
|
|
67698
|
+
if (camera instanceof PerspectiveCamera) {
|
|
67699
|
+
const verticalFov = MathUtils.degToRad(camera.fov);
|
|
67700
|
+
const horizontalFov = 2 * Math.atan(Math.tan(verticalFov / 2) * camera.aspect);
|
|
67701
|
+
const minHalfFov = Math.max(0.1, Math.min(verticalFov, horizontalFov) / 2);
|
|
67702
|
+
offsetDistance = safeRadius / Math.sin(minHalfFov) + safeRadius * 0.75;
|
|
67703
|
+
} else if (camera instanceof OrthographicCamera) {
|
|
67704
|
+
const visibleHeight = Math.max(safeRadius * 2.8, 1);
|
|
67705
|
+
endZoom = (camera.top - camera.bottom) / visibleHeight;
|
|
67706
|
+
offsetDistance = Math.max(safeRadius * 2, visibleHeight * 0.5);
|
|
67707
|
+
}
|
|
67708
|
+
const position = getBoundingSphereFlyToPosition(
|
|
67709
|
+
camera,
|
|
67710
|
+
target,
|
|
67711
|
+
offsetDistance,
|
|
67712
|
+
options
|
|
67713
|
+
);
|
|
67714
|
+
return {
|
|
67715
|
+
position,
|
|
67716
|
+
target: target.clone(),
|
|
67717
|
+
options: {
|
|
67718
|
+
...options,
|
|
67719
|
+
endZoom
|
|
67720
|
+
}
|
|
67721
|
+
};
|
|
67722
|
+
}
|
|
67723
|
+
function flyTo(camera, flight, time) {
|
|
67724
|
+
if (flight.startTime === null) {
|
|
67725
|
+
flight.startTime = time;
|
|
67726
|
+
}
|
|
67727
|
+
const rawT = MathUtils.clamp(
|
|
67728
|
+
(time - flight.startTime) / flight.duration,
|
|
67729
|
+
0,
|
|
67730
|
+
1
|
|
67731
|
+
);
|
|
67732
|
+
const easedT = rawT < 0.5 ? 4 * rawT * rawT * rawT : 1 - Math.pow(-2 * rawT + 2, 3) / 2;
|
|
67733
|
+
const position = getFlyToPosition(flight, easedT);
|
|
67734
|
+
const quaternion = flight.maintainUpright ? getUprightInterpolatedQuaternion(flight, position, easedT) : _flyQuaternion.slerpQuaternions(
|
|
67735
|
+
flight.startQuaternion,
|
|
67736
|
+
flight.endQuaternion,
|
|
67737
|
+
easedT
|
|
67738
|
+
);
|
|
67739
|
+
const zoom = flight.startZoom !== null && flight.endZoom !== null ? MathUtils.lerp(flight.startZoom, flight.endZoom, easedT) : null;
|
|
67740
|
+
applyFlyToPose(camera, position, quaternion, zoom);
|
|
67741
|
+
return rawT === 1;
|
|
67742
|
+
}
|
|
67743
|
+
function getFlyToPosition(flight, t2) {
|
|
67744
|
+
const { startPosition, endPosition, arcHeight } = flight;
|
|
67745
|
+
const startLength = startPosition.length();
|
|
67746
|
+
const endLength = endPosition.length();
|
|
67747
|
+
if (startLength < 1e-6 || endLength < 1e-6) {
|
|
67748
|
+
return _flyDirection.lerpVectors(startPosition, endPosition, t2);
|
|
67749
|
+
}
|
|
67750
|
+
_flyDirectionStart.copy(startPosition).divideScalar(startLength);
|
|
67751
|
+
_flyDirectionEnd.copy(endPosition).divideScalar(endLength);
|
|
67752
|
+
const angle = _flyDirectionStart.angleTo(_flyDirectionEnd);
|
|
67753
|
+
if (angle > 1e-5) {
|
|
67754
|
+
if (angle < Math.PI - 1e-5) {
|
|
67755
|
+
_flyAxis.crossVectors(_flyDirectionStart, _flyDirectionEnd).normalize();
|
|
67756
|
+
} else {
|
|
67757
|
+
_flyAxis.crossVectors(_flyDirectionStart, _flyWorldUp);
|
|
67758
|
+
if (_flyAxis.lengthSq() < 1e-6) {
|
|
67759
|
+
_flyAxis.crossVectors(_flyDirectionStart, _flyWorldNorth);
|
|
67760
|
+
}
|
|
67761
|
+
_flyAxis.normalize();
|
|
67762
|
+
}
|
|
67763
|
+
_flyDirection.copy(_flyDirectionStart).applyAxisAngle(_flyAxis, angle * t2).normalize();
|
|
67764
|
+
} else {
|
|
67765
|
+
_flyDirection.copy(_flyDirectionStart);
|
|
67766
|
+
}
|
|
67767
|
+
const radius = MathUtils.lerp(startLength, endLength, t2) + Math.sin(Math.PI * t2) * arcHeight;
|
|
67768
|
+
return _flyDirection.multiplyScalar(radius);
|
|
67769
|
+
}
|
|
67770
|
+
function getUprightInterpolatedQuaternion(flight, position, t2) {
|
|
67771
|
+
const heading = lerpAngle(flight.startHeading, flight.endHeading, t2);
|
|
67772
|
+
const pitch = MathUtils.lerp(flight.startPitch, flight.endPitch, t2);
|
|
67773
|
+
return getHeadingPitchRollQuaternion(position, heading, pitch, 0);
|
|
67774
|
+
}
|
|
67775
|
+
function buildFlightState(camera, {
|
|
67776
|
+
duration,
|
|
67777
|
+
endPosition,
|
|
67778
|
+
endQuaternion,
|
|
67779
|
+
endZoom,
|
|
67780
|
+
endHeading,
|
|
67781
|
+
endPitch,
|
|
67782
|
+
endRoll
|
|
67783
|
+
}) {
|
|
67784
|
+
const startPosition = camera.position.clone();
|
|
67785
|
+
const startQuaternion = camera.quaternion.clone();
|
|
67786
|
+
const startPose = getUprightHeadingPitchAtPose(
|
|
67787
|
+
startPosition,
|
|
67788
|
+
startQuaternion
|
|
67789
|
+
);
|
|
67790
|
+
const startRoll = getRollAtPose(startPosition, startQuaternion);
|
|
67791
|
+
const startZoom = camera instanceof OrthographicCamera ? camera.zoom : null;
|
|
67792
|
+
if (isImmediateFlight(
|
|
67793
|
+
duration,
|
|
67794
|
+
startPosition,
|
|
67795
|
+
endPosition,
|
|
67796
|
+
startQuaternion,
|
|
67797
|
+
endQuaternion,
|
|
67798
|
+
startZoom,
|
|
67799
|
+
endZoom
|
|
67800
|
+
)) {
|
|
67801
|
+
applyFlyToPose(camera, endPosition, endQuaternion, endZoom);
|
|
67802
|
+
return null;
|
|
67803
|
+
}
|
|
67804
|
+
return {
|
|
67805
|
+
startTime: null,
|
|
67806
|
+
duration,
|
|
67807
|
+
startPosition,
|
|
67808
|
+
endPosition,
|
|
67809
|
+
startQuaternion,
|
|
67810
|
+
endQuaternion,
|
|
67811
|
+
startZoom,
|
|
67812
|
+
endZoom,
|
|
67813
|
+
arcHeight: getArcHeight(startPosition, endPosition),
|
|
67814
|
+
maintainUpright: shouldMaintainUpright(startRoll, endRoll),
|
|
67815
|
+
startHeading: startPose.heading,
|
|
67816
|
+
endHeading,
|
|
67817
|
+
startPitch: startPose.pitch,
|
|
67818
|
+
endPitch
|
|
67819
|
+
};
|
|
67820
|
+
}
|
|
67821
|
+
function isImmediateFlight(duration, startPosition, endPosition, startQuaternion, endQuaternion, startZoom, endZoom) {
|
|
67822
|
+
return duration <= 0 || startPosition.distanceToSquared(endPosition) < 1e-6 && startQuaternion.angleTo(endQuaternion) < 1e-6 && (startZoom === null || endZoom === null || Math.abs(startZoom - endZoom) < 1e-6);
|
|
67823
|
+
}
|
|
67824
|
+
function getArcHeight(startPosition, endPosition) {
|
|
67825
|
+
const chordLength = startPosition.distanceTo(endPosition);
|
|
67826
|
+
return Math.max(
|
|
67827
|
+
chordLength * 0.35,
|
|
67828
|
+
Math.abs(endPosition.length() - startPosition.length()) * 0.5,
|
|
67829
|
+
500
|
|
67830
|
+
);
|
|
67831
|
+
}
|
|
67832
|
+
function shouldMaintainUpright(startRoll, endRoll) {
|
|
67833
|
+
return Math.abs(startRoll) <= UPRIGHT_ROLL_THRESHOLD && Math.abs(endRoll) <= UPRIGHT_ROLL_THRESHOLD;
|
|
67834
|
+
}
|
|
67835
|
+
function getLookAtQuaternion(position, target) {
|
|
67836
|
+
if (isCenterModePosition(position)) {
|
|
67837
|
+
_matrix3.lookAt(position, target, _flyCenterUp);
|
|
67838
|
+
return new Quaternion().setFromRotationMatrix(_matrix3);
|
|
67839
|
+
}
|
|
67840
|
+
_flyUp.copy(target);
|
|
67841
|
+
if (_flyUp.lengthSq() < 1e-6) {
|
|
67842
|
+
_flyUp.copy(_flyWorldUp);
|
|
67843
|
+
} else {
|
|
67844
|
+
_flyUp.normalize();
|
|
67845
|
+
}
|
|
67846
|
+
_flyEast.crossVectors(_flyWorldNorth, _flyUp);
|
|
67847
|
+
if (_flyEast.lengthSq() < 1e-6) {
|
|
67848
|
+
_flyEast.crossVectors(_flyWorldUp, _flyUp);
|
|
67849
|
+
}
|
|
67850
|
+
if (_flyEast.lengthSq() < 1e-6) {
|
|
67851
|
+
_flyEast.set(1, 0, 0);
|
|
67852
|
+
}
|
|
67853
|
+
_flyEast.normalize();
|
|
67854
|
+
_flyUp.crossVectors(_flyUp, _flyEast).normalize();
|
|
67855
|
+
_matrix3.lookAt(position, target, _flyUp);
|
|
67856
|
+
return new Quaternion().setFromRotationMatrix(_matrix3);
|
|
67857
|
+
}
|
|
67858
|
+
function getForwardFromQuaternion(quaternion, target) {
|
|
67859
|
+
return target.set(0, 0, -1).applyQuaternion(quaternion).normalize();
|
|
67860
|
+
}
|
|
67861
|
+
function getUprightHeadingPitchAtPose(position, quaternion) {
|
|
67862
|
+
if (isCenterModePosition(position)) {
|
|
67863
|
+
const forward2 = getForwardFromQuaternion(quaternion, _flyForward);
|
|
67864
|
+
_flyCameraRight.set(1, 0, 0).applyQuaternion(quaternion);
|
|
67865
|
+
_flyReferenceRight.copy(_flyCameraRight).projectOnPlane(_flyCenterUp);
|
|
67866
|
+
let heading2 = 0;
|
|
67867
|
+
if (_flyReferenceRight.lengthSq() > HEADING_RIGHT_DEGENERATE_EPSILON) {
|
|
67868
|
+
_flyReferenceRight.normalize();
|
|
67869
|
+
heading2 = Math.atan2(
|
|
67870
|
+
-_flyReferenceRight.dot(_flyCenterNorth),
|
|
67871
|
+
_flyReferenceRight.dot(_flyWorldRight)
|
|
67872
|
+
);
|
|
67873
|
+
} else {
|
|
67874
|
+
const horizontalForward = _flyDirection.copy(forward2).projectOnPlane(_flyCenterUp);
|
|
67875
|
+
if (horizontalForward.lengthSq() > HEADING_RIGHT_DEGENERATE_EPSILON) {
|
|
67876
|
+
horizontalForward.normalize();
|
|
67877
|
+
heading2 = Math.atan2(
|
|
67878
|
+
horizontalForward.dot(_flyWorldRight),
|
|
67879
|
+
horizontalForward.dot(_flyCenterNorth)
|
|
67880
|
+
);
|
|
67881
|
+
}
|
|
67882
|
+
}
|
|
67883
|
+
return {
|
|
67884
|
+
heading: heading2,
|
|
67885
|
+
pitch: Math.asin(MathUtils.clamp(forward2.dot(_flyCenterUp), -1, 1))
|
|
67886
|
+
};
|
|
67887
|
+
}
|
|
67888
|
+
if (position.lengthSq() < 1e-6) {
|
|
67889
|
+
return {
|
|
67890
|
+
heading: 0,
|
|
67891
|
+
pitch: 0
|
|
67892
|
+
};
|
|
67893
|
+
}
|
|
67894
|
+
const forward = getForwardFromQuaternion(quaternion, _flyForward);
|
|
67895
|
+
getLocalFrame(position);
|
|
67896
|
+
_flyCameraRight.set(1, 0, 0).applyQuaternion(quaternion);
|
|
67897
|
+
_flyReferenceRight.copy(_flyCameraRight).projectOnPlane(_flyUp);
|
|
67898
|
+
let heading = 0;
|
|
67899
|
+
if (_flyReferenceRight.lengthSq() > HEADING_RIGHT_DEGENERATE_EPSILON) {
|
|
67900
|
+
_flyReferenceRight.normalize();
|
|
67901
|
+
heading = Math.atan2(
|
|
67902
|
+
-_flyReferenceRight.dot(_flyNorth),
|
|
67903
|
+
_flyReferenceRight.dot(_flyEast)
|
|
67904
|
+
);
|
|
67905
|
+
} else {
|
|
67906
|
+
const horizontalForward = _flyDirection.copy(forward).projectOnPlane(_flyUp);
|
|
67907
|
+
if (horizontalForward.lengthSq() > HEADING_RIGHT_DEGENERATE_EPSILON) {
|
|
67908
|
+
horizontalForward.normalize();
|
|
67909
|
+
heading = Math.atan2(
|
|
67910
|
+
horizontalForward.dot(_flyEast),
|
|
67911
|
+
horizontalForward.dot(_flyNorth)
|
|
67912
|
+
);
|
|
67913
|
+
}
|
|
67914
|
+
}
|
|
67915
|
+
return {
|
|
67916
|
+
heading,
|
|
67917
|
+
pitch: Math.asin(MathUtils.clamp(forward.dot(_flyUp), -1, 1))
|
|
67918
|
+
};
|
|
67919
|
+
}
|
|
67920
|
+
function getRollAtPose(position, quaternion) {
|
|
67921
|
+
const forward = getForwardFromQuaternion(quaternion, _flyForward);
|
|
67922
|
+
if (isCenterModePosition(position)) {
|
|
67923
|
+
if (Math.abs(forward.dot(_flyCenterUp)) >= ROLL_UNDEFINED_DOT_THRESHOLD) {
|
|
67924
|
+
return 0;
|
|
67925
|
+
}
|
|
67926
|
+
getReferenceBasis(
|
|
67927
|
+
forward,
|
|
67928
|
+
_flyWorldRight,
|
|
67929
|
+
_flyCenterUp,
|
|
67930
|
+
_flyReferenceRight,
|
|
67931
|
+
_flyReferenceUp
|
|
67932
|
+
);
|
|
67933
|
+
} else {
|
|
67934
|
+
if (position.lengthSq() < 1e-6) {
|
|
67935
|
+
return 0;
|
|
67936
|
+
}
|
|
67937
|
+
getLocalFrame(position);
|
|
67938
|
+
if (Math.abs(forward.dot(_flyUp)) >= ROLL_UNDEFINED_DOT_THRESHOLD) {
|
|
67939
|
+
return 0;
|
|
67940
|
+
}
|
|
67941
|
+
getReferenceBasis(
|
|
67942
|
+
forward,
|
|
67943
|
+
_flyEast,
|
|
67944
|
+
_flyUp,
|
|
67945
|
+
_flyReferenceRight,
|
|
67946
|
+
_flyReferenceUp
|
|
67947
|
+
);
|
|
67948
|
+
}
|
|
67949
|
+
_flyReferenceUp.projectOnPlane(forward);
|
|
67950
|
+
_flyCameraUp.set(0, 1, 0).applyQuaternion(quaternion).projectOnPlane(forward);
|
|
67951
|
+
if (_flyReferenceUp.lengthSq() < 1e-6 || _flyCameraUp.lengthSq() < 1e-6) {
|
|
67952
|
+
return 0;
|
|
67953
|
+
}
|
|
67954
|
+
_flyReferenceUp.normalize();
|
|
67955
|
+
_flyCameraUp.normalize();
|
|
67956
|
+
return Math.atan2(
|
|
67957
|
+
_flyDirection.crossVectors(_flyReferenceUp, _flyCameraUp).dot(forward),
|
|
67958
|
+
_flyReferenceUp.dot(_flyCameraUp)
|
|
67959
|
+
);
|
|
67960
|
+
}
|
|
67961
|
+
function getEndQuaternion(position, target, options) {
|
|
67962
|
+
const { heading, pitch, roll } = options;
|
|
67963
|
+
if (heading === void 0 && pitch === void 0 && roll === void 0) {
|
|
67964
|
+
return getLookAtQuaternion(position, target);
|
|
67965
|
+
}
|
|
67966
|
+
if (heading === void 0 && pitch === void 0) {
|
|
67967
|
+
const quaternion = getLookAtQuaternion(position, target);
|
|
67968
|
+
if (roll) {
|
|
67969
|
+
_flyForward.subVectors(target, position).normalize();
|
|
67970
|
+
quaternion.multiply(_flyQuaternion.setFromAxisAngle(_flyForward, roll));
|
|
67971
|
+
}
|
|
67972
|
+
return quaternion;
|
|
67973
|
+
}
|
|
67974
|
+
return getHeadingPitchRollQuaternion(
|
|
67975
|
+
isCenterModePosition(position) ? position : target,
|
|
67976
|
+
heading ?? 0,
|
|
67977
|
+
pitch ?? -Math.PI / 2,
|
|
67978
|
+
roll ?? 0
|
|
67979
|
+
);
|
|
67980
|
+
}
|
|
67981
|
+
function getBoundingSphereFlyToPosition(camera, target, range, options) {
|
|
67982
|
+
const { heading, pitch } = options;
|
|
67983
|
+
if (heading === void 0 && pitch === void 0) {
|
|
67984
|
+
const direction = target.lengthSq() > 1e-6 ? _flyDirection.copy(target).normalize() : camera.position.lengthSq() > 1e-6 ? _flyDirection.copy(camera.position).normalize() : _flyDirection.set(0, -1, 0);
|
|
67985
|
+
return direction.multiplyScalar(range).add(target);
|
|
67986
|
+
}
|
|
67987
|
+
const resolvedHeading = heading ?? 0;
|
|
67988
|
+
const resolvedPitch = pitch ?? -Math.PI / 2;
|
|
67989
|
+
const centerForward = getCenterModeHeadingPitchRollForward(
|
|
67990
|
+
resolvedHeading,
|
|
67991
|
+
resolvedPitch
|
|
67992
|
+
);
|
|
67993
|
+
const centerPosition = _flyDirection.copy(target).addScaledVector(centerForward, -range);
|
|
67994
|
+
if (isCenterModePosition(centerPosition)) {
|
|
67995
|
+
return centerPosition;
|
|
67996
|
+
}
|
|
67997
|
+
const forward = getHeadingPitchRollForward(
|
|
67998
|
+
target,
|
|
67999
|
+
resolvedHeading,
|
|
68000
|
+
resolvedPitch
|
|
68001
|
+
);
|
|
68002
|
+
return _flyDirection.copy(target).addScaledVector(forward, -range);
|
|
68003
|
+
}
|
|
68004
|
+
function getHeadingPitchRollQuaternion(referencePoint, heading, pitch, roll) {
|
|
68005
|
+
if (isCenterModePosition(referencePoint)) {
|
|
68006
|
+
getCenterModeHeadingPitchRollBasis(heading, pitch, roll);
|
|
68007
|
+
_matrix1.makeBasis(_flyRight, _flyUp, _flyBackward);
|
|
68008
|
+
return new Quaternion().setFromRotationMatrix(_matrix1);
|
|
68009
|
+
}
|
|
68010
|
+
if (referencePoint.lengthSq() < 1e-6) {
|
|
68011
|
+
return new Quaternion();
|
|
68012
|
+
}
|
|
68013
|
+
getHeadingPitchRollBasis(referencePoint, heading, pitch, roll);
|
|
68014
|
+
_matrix1.makeBasis(_flyRight, _flyUp, _flyBackward);
|
|
68015
|
+
return new Quaternion().setFromRotationMatrix(_matrix1);
|
|
68016
|
+
}
|
|
68017
|
+
function getHeadingPitchRollForward(referencePoint, heading, pitch) {
|
|
68018
|
+
if (isCenterModePosition(referencePoint)) {
|
|
68019
|
+
return getCenterModeHeadingPitchRollForward(heading, pitch);
|
|
68020
|
+
}
|
|
68021
|
+
if (referencePoint.lengthSq() < 1e-6) {
|
|
68022
|
+
return _flyForward.set(0, 0, -1);
|
|
68023
|
+
}
|
|
68024
|
+
getLocalFrame(referencePoint);
|
|
68025
|
+
const cosPitch = Math.cos(pitch);
|
|
68026
|
+
const sinPitch = Math.sin(pitch);
|
|
68027
|
+
const cosHeading = Math.cos(heading);
|
|
68028
|
+
const sinHeading = Math.sin(heading);
|
|
68029
|
+
_flyForward.copy(_flyNorth).multiplyScalar(cosHeading * cosPitch).addScaledVector(_flyEast, sinHeading * cosPitch).addScaledVector(_flyUp, sinPitch).normalize();
|
|
68030
|
+
return _flyForward;
|
|
68031
|
+
}
|
|
68032
|
+
function getCenterModeHeadingPitchRollForward(heading, pitch) {
|
|
68033
|
+
const cosPitch = Math.cos(pitch);
|
|
68034
|
+
const sinPitch = Math.sin(pitch);
|
|
68035
|
+
const cosHeading = Math.cos(heading);
|
|
68036
|
+
const sinHeading = Math.sin(heading);
|
|
68037
|
+
_flyForward.set(
|
|
68038
|
+
sinHeading * cosPitch,
|
|
68039
|
+
cosHeading * cosPitch,
|
|
68040
|
+
sinPitch
|
|
68041
|
+
);
|
|
68042
|
+
return _flyForward.normalize();
|
|
68043
|
+
}
|
|
68044
|
+
function getHeadingPitchRollBasis(referencePoint, heading, pitch, roll) {
|
|
68045
|
+
if (isCenterModePosition(referencePoint)) {
|
|
68046
|
+
getCenterModeHeadingPitchRollBasis(heading, pitch, roll);
|
|
68047
|
+
return;
|
|
68048
|
+
}
|
|
68049
|
+
getHeadingPitchRollForward(referencePoint, heading, pitch);
|
|
68050
|
+
_flyRight.copy(_flyEast).multiplyScalar(Math.cos(heading)).addScaledVector(_flyNorth, -Math.sin(heading)).normalize();
|
|
68051
|
+
_flyUp.crossVectors(_flyRight, _flyForward).normalize();
|
|
68052
|
+
if (roll !== 0) {
|
|
68053
|
+
_flyRight.applyAxisAngle(_flyForward, roll).normalize();
|
|
68054
|
+
_flyUp.applyAxisAngle(_flyForward, roll).normalize();
|
|
68055
|
+
}
|
|
68056
|
+
_flyBackward.copy(_flyForward).negate();
|
|
68057
|
+
}
|
|
68058
|
+
function getCenterModeHeadingPitchRollBasis(heading, pitch, roll) {
|
|
68059
|
+
getCenterModeHeadingPitchRollForward(heading, pitch);
|
|
68060
|
+
_flyRight.copy(_flyWorldRight).multiplyScalar(Math.cos(heading)).addScaledVector(_flyCenterNorth, -Math.sin(heading)).normalize();
|
|
68061
|
+
_flyUp.crossVectors(_flyRight, _flyForward).normalize();
|
|
68062
|
+
if (roll !== 0) {
|
|
68063
|
+
_flyRight.applyAxisAngle(_flyForward, roll).normalize();
|
|
68064
|
+
_flyUp.applyAxisAngle(_flyForward, roll).normalize();
|
|
68065
|
+
}
|
|
68066
|
+
_flyBackward.copy(_flyForward).negate();
|
|
68067
|
+
}
|
|
68068
|
+
function getLocalFrame(target) {
|
|
68069
|
+
_matrix1.copy(eastNorthUpToFixedFrame(target));
|
|
68070
|
+
_flyEast.setFromMatrixColumn(_matrix1, 0).normalize();
|
|
68071
|
+
_flyNorth.setFromMatrixColumn(_matrix1, 1).normalize();
|
|
68072
|
+
_flyUp.setFromMatrixColumn(_matrix1, 2).normalize();
|
|
68073
|
+
}
|
|
68074
|
+
function isCenterModePosition(position) {
|
|
68075
|
+
return position.lengthSq() <= CAMERA_CENTER_MODE_DISTANCE_SQ;
|
|
68076
|
+
}
|
|
68077
|
+
function getReferenceBasis(forward, east, up, rightTarget, upTarget) {
|
|
68078
|
+
rightTarget.crossVectors(forward, up);
|
|
68079
|
+
if (rightTarget.lengthSq() < 1e-6) {
|
|
68080
|
+
rightTarget.copy(east).projectOnPlane(forward);
|
|
68081
|
+
if (rightTarget.lengthSq() < 1e-6) {
|
|
68082
|
+
rightTarget.set(1, 0, 0).projectOnPlane(forward);
|
|
68083
|
+
}
|
|
68084
|
+
}
|
|
68085
|
+
rightTarget.normalize();
|
|
68086
|
+
upTarget.crossVectors(rightTarget, forward).normalize();
|
|
68087
|
+
}
|
|
68088
|
+
function lerpAngle(start, end, t2) {
|
|
68089
|
+
let delta = end - start;
|
|
68090
|
+
if (delta > Math.PI) {
|
|
68091
|
+
delta -= Math.PI * 2;
|
|
68092
|
+
} else if (delta < -Math.PI) {
|
|
68093
|
+
delta += Math.PI * 2;
|
|
68094
|
+
}
|
|
68095
|
+
return start + delta * t2;
|
|
68096
|
+
}
|
|
68097
|
+
function applyFlyToPose(camera, position, quaternion, zoom = null) {
|
|
68098
|
+
camera.position.copy(position);
|
|
68099
|
+
camera.quaternion.copy(quaternion);
|
|
68100
|
+
if (camera instanceof OrthographicCamera && zoom !== null) {
|
|
68101
|
+
camera.zoom = Math.max(zoom, 1e-6);
|
|
68102
|
+
camera.updateProjectionMatrix();
|
|
68103
|
+
}
|
|
68104
|
+
camera.updateMatrixWorld();
|
|
68105
|
+
}
|
|
68106
|
+
var _matrix3, _matrix1, _flyDirectionStart, _flyDirectionEnd, _flyDirection, _flyAxis, _flyWorldNorth, _flyWorldRight, _flyCenterNorth, _flyCenterUp, _flyWorldUp, _flyUp, _flyEast, _flyNorth, _flyForward, _flyRight, _flyBackward, _flyCameraUp, _flyCameraRight, _flyReferenceUp, _flyReferenceRight, _flyQuaternion, _ellipsoidRadii, _oneOverRadiiSquared, _geoEast, _geoNorth, _geoUp, UPRIGHT_ROLL_THRESHOLD, ROLL_UNDEFINED_DOT_THRESHOLD, HEADING_RIGHT_DEGENERATE_EPSILON;
|
|
68107
|
+
var init_cameraFlyTo = __esm({
|
|
68108
|
+
"src/viewer/navigation/cameraFlyTo.js"() {
|
|
68109
|
+
init_three_module();
|
|
68110
|
+
init_config();
|
|
68111
|
+
_matrix3 = new Matrix4();
|
|
68112
|
+
_matrix1 = new Matrix4();
|
|
68113
|
+
_flyDirectionStart = new Vector3();
|
|
68114
|
+
_flyDirectionEnd = new Vector3();
|
|
68115
|
+
_flyDirection = new Vector3();
|
|
68116
|
+
_flyAxis = new Vector3();
|
|
68117
|
+
_flyWorldNorth = new Vector3(0, 0, 1);
|
|
68118
|
+
_flyWorldRight = new Vector3(1, 0, 0);
|
|
68119
|
+
_flyCenterNorth = new Vector3(0, 1, 0);
|
|
68120
|
+
_flyCenterUp = new Vector3(0, 0, 1);
|
|
68121
|
+
_flyWorldUp = new Vector3(0, 1, 0);
|
|
68122
|
+
_flyUp = new Vector3();
|
|
68123
|
+
_flyEast = new Vector3();
|
|
68124
|
+
_flyNorth = new Vector3();
|
|
68125
|
+
_flyForward = new Vector3();
|
|
68126
|
+
_flyRight = new Vector3();
|
|
68127
|
+
_flyBackward = new Vector3();
|
|
68128
|
+
_flyCameraUp = new Vector3();
|
|
68129
|
+
_flyCameraRight = new Vector3();
|
|
68130
|
+
_flyReferenceUp = new Vector3();
|
|
68131
|
+
_flyReferenceRight = new Vector3();
|
|
68132
|
+
_flyQuaternion = new Quaternion();
|
|
68133
|
+
_ellipsoidRadii = new Vector3(
|
|
68134
|
+
6378137,
|
|
68135
|
+
6378137,
|
|
68136
|
+
6356752314245179e-9
|
|
68137
|
+
);
|
|
68138
|
+
_oneOverRadiiSquared = new Vector3(
|
|
68139
|
+
1 / (_ellipsoidRadii.x * _ellipsoidRadii.x),
|
|
68140
|
+
1 / (_ellipsoidRadii.y * _ellipsoidRadii.y),
|
|
68141
|
+
1 / (_ellipsoidRadii.z * _ellipsoidRadii.z)
|
|
68142
|
+
);
|
|
68143
|
+
_geoEast = new Vector3();
|
|
68144
|
+
_geoNorth = new Vector3();
|
|
68145
|
+
_geoUp = new Vector3();
|
|
68146
|
+
UPRIGHT_ROLL_THRESHOLD = MathUtils.degToRad(5);
|
|
68147
|
+
ROLL_UNDEFINED_DOT_THRESHOLD = Math.cos(MathUtils.degToRad(5));
|
|
68148
|
+
HEADING_RIGHT_DEGENERATE_EPSILON = 1e-6;
|
|
68149
|
+
}
|
|
68150
|
+
});
|
|
68151
|
+
|
|
67653
68152
|
// src/viewer/navigation/flyTo.js
|
|
67654
68153
|
function createFlyToController({
|
|
67655
68154
|
camera,
|
|
@@ -67669,6 +68168,8 @@ function createFlyToController({
|
|
|
67669
68168
|
const pickRaycaster = new Raycaster();
|
|
67670
68169
|
const pickTargets = [];
|
|
67671
68170
|
const sphere = new Sphere();
|
|
68171
|
+
let activeCameraFlight = null;
|
|
68172
|
+
let activeCameraFlightStatus = "";
|
|
67672
68173
|
function getActiveEllipsoid() {
|
|
67673
68174
|
return getTiles()?.ellipsoid || globeController.getEllipsoid();
|
|
67674
68175
|
}
|
|
@@ -67710,6 +68211,43 @@ function createFlyToController({
|
|
|
67710
68211
|
}
|
|
67711
68212
|
return geoCamera.getCartographicFromWorldPosition(coordinateWorldPosition);
|
|
67712
68213
|
}
|
|
68214
|
+
function startCameraFlight(position, target, options = {}, { activeStatus = "Moving camera.", doneStatus = "Moved camera." } = {}) {
|
|
68215
|
+
cameraController.setCamera(camera);
|
|
68216
|
+
activeCameraFlight = createCameraFlight(camera, position, target, options);
|
|
68217
|
+
activeCameraFlightStatus = doneStatus;
|
|
68218
|
+
if (!activeCameraFlight) {
|
|
68219
|
+
cameraController.setCamera(camera);
|
|
68220
|
+
setStatus(doneStatus);
|
|
68221
|
+
return;
|
|
68222
|
+
}
|
|
68223
|
+
setStatus(activeStatus);
|
|
68224
|
+
}
|
|
68225
|
+
function startBoundingSphereFlight(target, radius, options = {}, status = {}) {
|
|
68226
|
+
const flyToParams = getFlyToParamsFromBoundingSphere(
|
|
68227
|
+
camera,
|
|
68228
|
+
target,
|
|
68229
|
+
radius,
|
|
68230
|
+
options
|
|
68231
|
+
);
|
|
68232
|
+
startCameraFlight(
|
|
68233
|
+
flyToParams.position,
|
|
68234
|
+
flyToParams.target,
|
|
68235
|
+
flyToParams.options,
|
|
68236
|
+
status
|
|
68237
|
+
);
|
|
68238
|
+
}
|
|
68239
|
+
function update(time = performance.now()) {
|
|
68240
|
+
if (!activeCameraFlight) {
|
|
68241
|
+
return false;
|
|
68242
|
+
}
|
|
68243
|
+
const done = flyTo(camera, activeCameraFlight, time);
|
|
68244
|
+
if (done) {
|
|
68245
|
+
activeCameraFlight = null;
|
|
68246
|
+
setStatus(activeCameraFlightStatus);
|
|
68247
|
+
activeCameraFlightStatus = "";
|
|
68248
|
+
}
|
|
68249
|
+
return true;
|
|
68250
|
+
}
|
|
67713
68251
|
async function applyTilesSetPositionFromPointerEvent(event) {
|
|
67714
68252
|
const coordinate = pickCoordinateFromPointerEvent(event);
|
|
67715
68253
|
if (!coordinate) {
|
|
@@ -67731,27 +68269,29 @@ function createFlyToController({
|
|
|
67731
68269
|
return null;
|
|
67732
68270
|
}
|
|
67733
68271
|
}
|
|
67734
|
-
function frameTileset(
|
|
68272
|
+
function frameTileset({
|
|
68273
|
+
activeStatus = "Moving camera to the tileset.",
|
|
68274
|
+
doneStatus = "Moved camera to the tileset."
|
|
68275
|
+
} = {}) {
|
|
67735
68276
|
if (!getTilesetBoundingSphere(sphere)) {
|
|
67736
68277
|
return false;
|
|
67737
68278
|
}
|
|
67738
|
-
|
|
68279
|
+
startBoundingSphereFlight(
|
|
67739
68280
|
sphere.center,
|
|
67740
|
-
sphere.radius,
|
|
67741
|
-
moveToTilesPose
|
|
68281
|
+
sphere.radius / 2,
|
|
68282
|
+
moveToTilesPose,
|
|
68283
|
+
{
|
|
68284
|
+
activeStatus,
|
|
68285
|
+
doneStatus
|
|
68286
|
+
}
|
|
67742
68287
|
);
|
|
67743
|
-
camera.position.copy(pose.position);
|
|
67744
|
-
camera.quaternion.copy(pose.quaternion);
|
|
67745
|
-
camera.updateMatrixWorld(true);
|
|
67746
|
-
cameraController.setCamera(camera);
|
|
67747
68288
|
return true;
|
|
67748
68289
|
}
|
|
67749
68290
|
function moveCameraToTiles() {
|
|
67750
68291
|
if (frameTileset()) {
|
|
67751
|
-
|
|
67752
|
-
} else {
|
|
67753
|
-
setStatus("Tileset is not ready to frame yet.", true);
|
|
68292
|
+
return;
|
|
67754
68293
|
}
|
|
68294
|
+
setStatus("Tileset is not ready to frame yet.", true);
|
|
67755
68295
|
}
|
|
67756
68296
|
function moveCameraToCoordinate(coordinate) {
|
|
67757
68297
|
geoCamera.getCoordinateWorldPosition(
|
|
@@ -67760,16 +68300,15 @@ function createFlyToController({
|
|
|
67760
68300
|
coordinate.height,
|
|
67761
68301
|
coordinateWorldPosition
|
|
67762
68302
|
);
|
|
67763
|
-
|
|
68303
|
+
startBoundingSphereFlight(
|
|
67764
68304
|
coordinateWorldPosition,
|
|
67765
68305
|
moveToCoordinateRadius,
|
|
67766
|
-
moveToTilesPose
|
|
68306
|
+
moveToTilesPose,
|
|
68307
|
+
{
|
|
68308
|
+
activeStatus: "Moving camera to the specified coordinate.",
|
|
68309
|
+
doneStatus: "Moved camera to the specified coordinate."
|
|
68310
|
+
}
|
|
67767
68311
|
);
|
|
67768
|
-
camera.position.copy(pose.position);
|
|
67769
|
-
camera.quaternion.copy(pose.quaternion);
|
|
67770
|
-
camera.updateMatrixWorld(true);
|
|
67771
|
-
cameraController.setCamera(camera);
|
|
67772
|
-
setStatus("Moved camera to the specified coordinate.");
|
|
67773
68312
|
}
|
|
67774
68313
|
return {
|
|
67775
68314
|
applyTilesSetPositionFromPointerEvent,
|
|
@@ -67777,12 +68316,14 @@ function createFlyToController({
|
|
|
67777
68316
|
getActiveEllipsoid,
|
|
67778
68317
|
moveCameraToCoordinate,
|
|
67779
68318
|
moveCameraToTiles,
|
|
67780
|
-
pickCoordinateFromPointerEvent
|
|
68319
|
+
pickCoordinateFromPointerEvent,
|
|
68320
|
+
update
|
|
67781
68321
|
};
|
|
67782
68322
|
}
|
|
67783
68323
|
var init_flyTo = __esm({
|
|
67784
68324
|
"src/viewer/navigation/flyTo.js"() {
|
|
67785
68325
|
init_three_module();
|
|
68326
|
+
init_cameraFlyTo();
|
|
67786
68327
|
init_utils();
|
|
67787
68328
|
}
|
|
67788
68329
|
});
|
|
@@ -67954,6 +68495,15 @@ function clientPointToNdc(point, domRect) {
|
|
|
67954
68495
|
y: 1 - (point.y - domRect.top) / domRect.height * 2
|
|
67955
68496
|
};
|
|
67956
68497
|
}
|
|
68498
|
+
function getClientSelectionQuad(start, end) {
|
|
68499
|
+
const clientRect = getClientSelectionRect(start, end);
|
|
68500
|
+
return [
|
|
68501
|
+
new Vector2(clientRect.minX, clientRect.minY),
|
|
68502
|
+
new Vector2(clientRect.maxX, clientRect.minY),
|
|
68503
|
+
new Vector2(clientRect.maxX, clientRect.maxY),
|
|
68504
|
+
new Vector2(clientRect.minX, clientRect.maxY)
|
|
68505
|
+
];
|
|
68506
|
+
}
|
|
67957
68507
|
function getNdcSelectionRect(clientRect, domRect) {
|
|
67958
68508
|
const topLeft = clientPointToNdc(
|
|
67959
68509
|
new Vector2(clientRect.minX, clientRect.minY),
|
|
@@ -67970,6 +68520,19 @@ function getNdcSelectionRect(clientRect, domRect) {
|
|
|
67970
68520
|
maxY: Math.max(topLeft.y, bottomRight.y)
|
|
67971
68521
|
};
|
|
67972
68522
|
}
|
|
68523
|
+
function getNdcSelectionQuad(clientPoints, domRect) {
|
|
68524
|
+
return clientPoints.map((point) => clientPointToNdc(point, domRect));
|
|
68525
|
+
}
|
|
68526
|
+
function getNdcBounds(points) {
|
|
68527
|
+
const xs2 = points.map((point) => point.x);
|
|
68528
|
+
const ys2 = points.map((point) => point.y);
|
|
68529
|
+
return {
|
|
68530
|
+
maxX: Math.max(...xs2),
|
|
68531
|
+
maxY: Math.max(...ys2),
|
|
68532
|
+
minX: Math.min(...xs2),
|
|
68533
|
+
minY: Math.min(...ys2)
|
|
68534
|
+
};
|
|
68535
|
+
}
|
|
67973
68536
|
function updateOverlayRect(overlayEl, rectEl, clientRect) {
|
|
67974
68537
|
if (!overlayEl || !rectEl) {
|
|
67975
68538
|
return;
|
|
@@ -68151,10 +68714,10 @@ function createFarPlaneData({
|
|
|
68151
68714
|
width
|
|
68152
68715
|
};
|
|
68153
68716
|
}
|
|
68154
|
-
function
|
|
68717
|
+
function createFrustumDataFromQuad(camera, quad, depthRange) {
|
|
68155
68718
|
const { farDepth, nearDepth } = normalizeDepthRange(camera, depthRange);
|
|
68156
|
-
const centerX = (
|
|
68157
|
-
const centerY = (
|
|
68719
|
+
const centerX = quad.reduce((total, point) => total + point.x, 0) / quad.length;
|
|
68720
|
+
const centerY = quad.reduce((total, point) => total + point.y, 0) / quad.length;
|
|
68158
68721
|
const nearCenter = createPointAtViewDepth(
|
|
68159
68722
|
camera,
|
|
68160
68723
|
centerX,
|
|
@@ -68181,55 +68744,13 @@ function createFrustumData(camera, rect, depthRange) {
|
|
|
68181
68744
|
const insidePoint = selectionForward.clone().multiplyScalar((nearDistance + farDistance) * 0.5).add(camera.position);
|
|
68182
68745
|
plane.setFromNormalAndCoplanarPoint(selectionForward, farCenter);
|
|
68183
68746
|
const farClipPlane = plane.clone();
|
|
68184
|
-
const farTopLeft =
|
|
68185
|
-
camera,
|
|
68186
|
-
rect.minX,
|
|
68187
|
-
rect.maxY,
|
|
68188
|
-
farClipPlane
|
|
68189
|
-
);
|
|
68190
|
-
const farTopRight = createPointOnPlane(
|
|
68191
|
-
camera,
|
|
68192
|
-
rect.maxX,
|
|
68193
|
-
rect.maxY,
|
|
68194
|
-
farClipPlane
|
|
68195
|
-
);
|
|
68196
|
-
const farBottomRight = createPointOnPlane(
|
|
68197
|
-
camera,
|
|
68198
|
-
rect.maxX,
|
|
68199
|
-
rect.minY,
|
|
68200
|
-
farClipPlane
|
|
68201
|
-
);
|
|
68202
|
-
const farBottomLeft = createPointOnPlane(
|
|
68203
|
-
camera,
|
|
68204
|
-
rect.minX,
|
|
68205
|
-
rect.minY,
|
|
68206
|
-
farClipPlane
|
|
68747
|
+
const [farTopLeft, farTopRight, farBottomRight, farBottomLeft] = quad.map(
|
|
68748
|
+
(point) => createPointOnPlane(camera, point.x, point.y, farClipPlane)
|
|
68207
68749
|
);
|
|
68208
68750
|
plane.setFromNormalAndCoplanarPoint(selectionForward, nearCenter);
|
|
68209
68751
|
const nearPlane = plane.clone();
|
|
68210
|
-
const nearTopLeft =
|
|
68211
|
-
camera,
|
|
68212
|
-
rect.minX,
|
|
68213
|
-
rect.maxY,
|
|
68214
|
-
nearPlane
|
|
68215
|
-
);
|
|
68216
|
-
const nearTopRight = createPointOnPlane(
|
|
68217
|
-
camera,
|
|
68218
|
-
rect.maxX,
|
|
68219
|
-
rect.maxY,
|
|
68220
|
-
nearPlane
|
|
68221
|
-
);
|
|
68222
|
-
const nearBottomRight = createPointOnPlane(
|
|
68223
|
-
camera,
|
|
68224
|
-
rect.maxX,
|
|
68225
|
-
rect.minY,
|
|
68226
|
-
nearPlane
|
|
68227
|
-
);
|
|
68228
|
-
const nearBottomLeft = createPointOnPlane(
|
|
68229
|
-
camera,
|
|
68230
|
-
rect.minX,
|
|
68231
|
-
rect.minY,
|
|
68232
|
-
nearPlane
|
|
68752
|
+
const [nearTopLeft, nearTopRight, nearBottomRight, nearBottomLeft] = quad.map(
|
|
68753
|
+
(point) => createPointOnPlane(camera, point.x, point.y, nearPlane)
|
|
68233
68754
|
);
|
|
68234
68755
|
if (!farTopLeft || !farTopRight || !farBottomRight || !farBottomLeft || !nearTopLeft || !nearTopRight || !nearBottomRight || !nearBottomLeft) {
|
|
68235
68756
|
return null;
|
|
@@ -68306,8 +68827,21 @@ function createFrustumData(camera, rect, depthRange) {
|
|
|
68306
68827
|
selectionForward: selectionForward.toArray()
|
|
68307
68828
|
};
|
|
68308
68829
|
}
|
|
68830
|
+
function createFrustumData(camera, rect, depthRange) {
|
|
68831
|
+
return createFrustumDataFromQuad(
|
|
68832
|
+
camera,
|
|
68833
|
+
[
|
|
68834
|
+
{ x: rect.minX, y: rect.maxY },
|
|
68835
|
+
{ x: rect.maxX, y: rect.maxY },
|
|
68836
|
+
{ x: rect.maxX, y: rect.minY },
|
|
68837
|
+
{ x: rect.minX, y: rect.minY }
|
|
68838
|
+
],
|
|
68839
|
+
depthRange
|
|
68840
|
+
);
|
|
68841
|
+
}
|
|
68309
68842
|
function createSelectionData({
|
|
68310
68843
|
camera,
|
|
68844
|
+
clientPoints,
|
|
68311
68845
|
domElement,
|
|
68312
68846
|
end,
|
|
68313
68847
|
getDepthRange,
|
|
@@ -68317,19 +68851,27 @@ function createSelectionData({
|
|
|
68317
68851
|
if (domRect.width <= 0 || domRect.height <= 0) {
|
|
68318
68852
|
return null;
|
|
68319
68853
|
}
|
|
68320
|
-
const
|
|
68854
|
+
const hasClientQuad = Array.isArray(clientPoints) && clientPoints.length === 4;
|
|
68855
|
+
const points = hasClientQuad ? clientPoints : getClientSelectionQuad(start, end);
|
|
68856
|
+
const clientRect = {
|
|
68857
|
+
maxX: Math.max(...points.map((point) => point.x)),
|
|
68858
|
+
maxY: Math.max(...points.map((point) => point.y)),
|
|
68859
|
+
minX: Math.min(...points.map((point) => point.x)),
|
|
68860
|
+
minY: Math.min(...points.map((point) => point.y))
|
|
68861
|
+
};
|
|
68321
68862
|
const width = clientRect.maxX - clientRect.minX;
|
|
68322
68863
|
const height = clientRect.maxY - clientRect.minY;
|
|
68323
68864
|
if (width * width + height * height < SCREEN_SELECTION_MIN_DRAG_DISTANCE_SQ) {
|
|
68324
68865
|
return null;
|
|
68325
68866
|
}
|
|
68326
|
-
const
|
|
68867
|
+
const quad = getNdcSelectionQuad(points, domRect);
|
|
68868
|
+
const rect = hasClientQuad ? getNdcBounds(quad) : getNdcSelectionRect(clientRect, domRect);
|
|
68327
68869
|
camera.updateProjectionMatrix();
|
|
68328
68870
|
camera.updateMatrixWorld(true);
|
|
68329
68871
|
cameraPosition.copy(camera.position);
|
|
68330
68872
|
const depthRange = normalizeDepthRange(camera, getDepthRange());
|
|
68331
68873
|
const viewProjectionMatrix = new Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse).toArray();
|
|
68332
|
-
const frustum = createFrustumData(camera, rect, depthRange);
|
|
68874
|
+
const frustum = hasClientQuad ? createFrustumDataFromQuad(camera, quad, depthRange) : createFrustumData(camera, rect, depthRange);
|
|
68333
68875
|
if (!frustum) {
|
|
68334
68876
|
return null;
|
|
68335
68877
|
}
|
|
@@ -68687,6 +69229,8 @@ function createScreenSelectionPointerTracker({
|
|
|
68687
69229
|
camera,
|
|
68688
69230
|
domElement,
|
|
68689
69231
|
getDepthRange,
|
|
69232
|
+
onOverlayClear,
|
|
69233
|
+
onOverlayUpdate,
|
|
68690
69234
|
onSelectionCreated,
|
|
68691
69235
|
overlayEl,
|
|
68692
69236
|
rectEl
|
|
@@ -68695,8 +69239,18 @@ function createScreenSelectionPointerTracker({
|
|
|
68695
69239
|
let drag = null;
|
|
68696
69240
|
function clearDrag() {
|
|
68697
69241
|
drag = null;
|
|
69242
|
+
onOverlayClear?.();
|
|
68698
69243
|
clearOverlay(overlayEl, rectEl);
|
|
68699
69244
|
}
|
|
69245
|
+
function updateDragOverlay() {
|
|
69246
|
+
const clientRect = {
|
|
69247
|
+
...getClientSelectionRect(drag.start, drag.current)
|
|
69248
|
+
};
|
|
69249
|
+
if (onOverlayUpdate?.(clientRect) === true) {
|
|
69250
|
+
return;
|
|
69251
|
+
}
|
|
69252
|
+
updateOverlayRect(overlayEl, rectEl, clientRect);
|
|
69253
|
+
}
|
|
68700
69254
|
function setActive(nextActive) {
|
|
68701
69255
|
active = !!nextActive;
|
|
68702
69256
|
if (!active) {
|
|
@@ -68715,11 +69269,7 @@ function createScreenSelectionPointerTracker({
|
|
|
68715
69269
|
start: dragStart.clone(),
|
|
68716
69270
|
current: dragCurrent.clone()
|
|
68717
69271
|
};
|
|
68718
|
-
|
|
68719
|
-
overlayEl,
|
|
68720
|
-
rectEl,
|
|
68721
|
-
getClientSelectionRect(drag.start, drag.current)
|
|
68722
|
-
);
|
|
69272
|
+
updateDragOverlay();
|
|
68723
69273
|
domElement.setPointerCapture?.(event.pointerId);
|
|
68724
69274
|
event.preventDefault();
|
|
68725
69275
|
event.stopPropagation();
|
|
@@ -68731,11 +69281,7 @@ function createScreenSelectionPointerTracker({
|
|
|
68731
69281
|
}
|
|
68732
69282
|
const domRect = domElement.getBoundingClientRect();
|
|
68733
69283
|
getClampedClientPoint(event, domRect, drag.current);
|
|
68734
|
-
|
|
68735
|
-
overlayEl,
|
|
68736
|
-
rectEl,
|
|
68737
|
-
getClientSelectionRect(drag.start, drag.current)
|
|
68738
|
-
);
|
|
69284
|
+
updateDragOverlay();
|
|
68739
69285
|
event.preventDefault();
|
|
68740
69286
|
event.stopPropagation();
|
|
68741
69287
|
return true;
|
|
@@ -68744,6 +69290,9 @@ function createScreenSelectionPointerTracker({
|
|
|
68744
69290
|
if (!active || !drag || event.pointerId !== drag.pointerId) {
|
|
68745
69291
|
return false;
|
|
68746
69292
|
}
|
|
69293
|
+
const clientRect = {
|
|
69294
|
+
...getClientSelectionRect(drag.start, drag.current)
|
|
69295
|
+
};
|
|
68747
69296
|
const selection = createSelectionData({
|
|
68748
69297
|
camera,
|
|
68749
69298
|
domElement,
|
|
@@ -68753,7 +69302,7 @@ function createScreenSelectionPointerTracker({
|
|
|
68753
69302
|
});
|
|
68754
69303
|
domElement.releasePointerCapture?.(event.pointerId);
|
|
68755
69304
|
clearDrag();
|
|
68756
|
-
onSelectionCreated(selection);
|
|
69305
|
+
onSelectionCreated(selection, clientRect);
|
|
68757
69306
|
event.preventDefault();
|
|
68758
69307
|
event.stopPropagation();
|
|
68759
69308
|
return true;
|
|
@@ -68832,6 +69381,56 @@ function getScreenSelectionPayload(selection) {
|
|
|
68832
69381
|
viewProjectionMatrix: selection.viewProjectionMatrix.slice()
|
|
68833
69382
|
};
|
|
68834
69383
|
}
|
|
69384
|
+
function setScreenSelectionShape(selection, {
|
|
69385
|
+
cameraPosition: sourceCameraPosition,
|
|
69386
|
+
depthRange,
|
|
69387
|
+
farPlane,
|
|
69388
|
+
planeMatrices,
|
|
69389
|
+
rect,
|
|
69390
|
+
selectionForward: sourceSelectionForward,
|
|
69391
|
+
viewProjectionMatrix
|
|
69392
|
+
}, currentTransformMatrix) {
|
|
69393
|
+
if (!selection) {
|
|
69394
|
+
return;
|
|
69395
|
+
}
|
|
69396
|
+
const previousFarDepth = Number(selection.depthRange?.farDepth);
|
|
69397
|
+
const copiedPlaneMatrices = planeMatrices.map((matrix) => matrix.slice());
|
|
69398
|
+
const referenceTransformMatrix = copyMatrix4Array(currentTransformMatrix);
|
|
69399
|
+
selection.basePlaneMatrices = copiedPlaneMatrices.map(
|
|
69400
|
+
(matrix) => matrix.slice()
|
|
69401
|
+
);
|
|
69402
|
+
selection.cameraPosition = copyVectorArray(sourceCameraPosition);
|
|
69403
|
+
selection.currentTransformMatrix = referenceTransformMatrix.slice();
|
|
69404
|
+
selection.depthRange = copyDepthRange(depthRange);
|
|
69405
|
+
selection.farPlane = copyFarPlane(farPlane);
|
|
69406
|
+
selection.planeMatrices = copiedPlaneMatrices;
|
|
69407
|
+
selection.referenceTransformMatrix = referenceTransformMatrix;
|
|
69408
|
+
selection.rect = copyRect(rect);
|
|
69409
|
+
selection.selectionForward = copyVectorArray(sourceSelectionForward, [
|
|
69410
|
+
0,
|
|
69411
|
+
0,
|
|
69412
|
+
-1
|
|
69413
|
+
]);
|
|
69414
|
+
selection.viewProjectionMatrix = viewProjectionMatrix.slice();
|
|
69415
|
+
updateScreenSelectionWorldState(selection, currentTransformMatrix);
|
|
69416
|
+
if (!Number.isFinite(previousFarDepth)) {
|
|
69417
|
+
return;
|
|
69418
|
+
}
|
|
69419
|
+
const nextFarDepth = Math.min(
|
|
69420
|
+
selection.depthRange.maxFarDepth,
|
|
69421
|
+
Math.max(
|
|
69422
|
+
selection.depthRange.nearDepth + SCREEN_SELECTION_MIN_DEPTH_RANGE,
|
|
69423
|
+
previousFarDepth
|
|
69424
|
+
)
|
|
69425
|
+
);
|
|
69426
|
+
if (Math.abs(nextFarDepth - selection.depthRange.farDepth) > 1e-9) {
|
|
69427
|
+
setScreenSelectionFarDepth(
|
|
69428
|
+
selection,
|
|
69429
|
+
nextFarDepth,
|
|
69430
|
+
currentTransformMatrix
|
|
69431
|
+
);
|
|
69432
|
+
}
|
|
69433
|
+
}
|
|
68835
69434
|
function updateScreenSelectionWorldState(selection, currentTransformMatrix, active = selection?.farHandle?.visible) {
|
|
68836
69435
|
if (!selection) {
|
|
68837
69436
|
return;
|
|
@@ -68876,6 +69475,313 @@ var init_screenSelection = __esm({
|
|
|
68876
69475
|
}
|
|
68877
69476
|
});
|
|
68878
69477
|
|
|
69478
|
+
// src/viewer/screenSelection/editOverlay.js
|
|
69479
|
+
function clampValue(value, min, max) {
|
|
69480
|
+
return Math.min(max, Math.max(min, value));
|
|
69481
|
+
}
|
|
69482
|
+
function copyClientPoint(point) {
|
|
69483
|
+
return {
|
|
69484
|
+
x: Number(point?.x) || 0,
|
|
69485
|
+
y: Number(point?.y) || 0
|
|
69486
|
+
};
|
|
69487
|
+
}
|
|
69488
|
+
function copyClientPoints(points) {
|
|
69489
|
+
return points.map(copyClientPoint);
|
|
69490
|
+
}
|
|
69491
|
+
function getClientPointsBounds(points) {
|
|
69492
|
+
const xs2 = points.map((point) => point.x);
|
|
69493
|
+
const ys2 = points.map((point) => point.y);
|
|
69494
|
+
return {
|
|
69495
|
+
maxX: Math.max(...xs2),
|
|
69496
|
+
maxY: Math.max(...ys2),
|
|
69497
|
+
minX: Math.min(...xs2),
|
|
69498
|
+
minY: Math.min(...ys2)
|
|
69499
|
+
};
|
|
69500
|
+
}
|
|
69501
|
+
function getClientRectPoints(rect) {
|
|
69502
|
+
return [
|
|
69503
|
+
{ x: Number(rect?.minX) || 0, y: Number(rect?.minY) || 0 },
|
|
69504
|
+
{ x: Number(rect?.maxX) || 0, y: Number(rect?.minY) || 0 },
|
|
69505
|
+
{ x: Number(rect?.maxX) || 0, y: Number(rect?.maxY) || 0 },
|
|
69506
|
+
{ x: Number(rect?.minX) || 0, y: Number(rect?.maxY) || 0 }
|
|
69507
|
+
];
|
|
69508
|
+
}
|
|
69509
|
+
function clampClientPoint(point, domRect) {
|
|
69510
|
+
return {
|
|
69511
|
+
x: clampValue(point.x, domRect.left, domRect.right),
|
|
69512
|
+
y: clampValue(point.y, domRect.top, domRect.bottom)
|
|
69513
|
+
};
|
|
69514
|
+
}
|
|
69515
|
+
function clampClientPoints(points, domElement) {
|
|
69516
|
+
const domRect = domElement.getBoundingClientRect();
|
|
69517
|
+
return points.map((point) => clampClientPoint(point, domRect));
|
|
69518
|
+
}
|
|
69519
|
+
function getPointTurnCross(a2, b5, c2) {
|
|
69520
|
+
return (b5.x - a2.x) * (c2.y - b5.y) - (b5.y - a2.y) * (c2.x - b5.x);
|
|
69521
|
+
}
|
|
69522
|
+
function isConvexClientQuad(points) {
|
|
69523
|
+
if (!Array.isArray(points) || points.length !== 4) {
|
|
69524
|
+
return false;
|
|
69525
|
+
}
|
|
69526
|
+
let turnSign = 0;
|
|
69527
|
+
for (let index = 0; index < points.length; index++) {
|
|
69528
|
+
const cross = getPointTurnCross(
|
|
69529
|
+
points[index],
|
|
69530
|
+
points[(index + 1) % points.length],
|
|
69531
|
+
points[(index + 2) % points.length]
|
|
69532
|
+
);
|
|
69533
|
+
if (Math.abs(cross) <= SCREEN_EDIT_MIN_CONVEX_CROSS_ABS) {
|
|
69534
|
+
return false;
|
|
69535
|
+
}
|
|
69536
|
+
const nextSign = Math.sign(cross);
|
|
69537
|
+
if (turnSign === 0) {
|
|
69538
|
+
turnSign = nextSign;
|
|
69539
|
+
} else if (nextSign !== turnSign) {
|
|
69540
|
+
return false;
|
|
69541
|
+
}
|
|
69542
|
+
}
|
|
69543
|
+
return true;
|
|
69544
|
+
}
|
|
69545
|
+
function getPartPoint(points, part) {
|
|
69546
|
+
const indices = SCREEN_EDIT_PART_POINT_INDICES[part] || [];
|
|
69547
|
+
if (indices.length === 0) {
|
|
69548
|
+
return { x: 0, y: 0 };
|
|
69549
|
+
}
|
|
69550
|
+
const x5 = indices.reduce((total, index) => total + points[index].x, 0) / indices.length;
|
|
69551
|
+
const y6 = indices.reduce((total, index) => total + points[index].y, 0) / indices.length;
|
|
69552
|
+
return { x: x5, y: y6 };
|
|
69553
|
+
}
|
|
69554
|
+
function getPartAngle(points, part) {
|
|
69555
|
+
const indices = SCREEN_EDIT_PART_POINT_INDICES[part] || [];
|
|
69556
|
+
if (indices.length !== 2) {
|
|
69557
|
+
return null;
|
|
69558
|
+
}
|
|
69559
|
+
const start = points[indices[0]];
|
|
69560
|
+
const end = points[indices[1]];
|
|
69561
|
+
return Math.atan2(end.y - start.y, end.x - start.x);
|
|
69562
|
+
}
|
|
69563
|
+
function getPartLength(points, part) {
|
|
69564
|
+
const indices = SCREEN_EDIT_PART_POINT_INDICES[part] || [];
|
|
69565
|
+
if (indices.length !== 2) {
|
|
69566
|
+
return null;
|
|
69567
|
+
}
|
|
69568
|
+
const start = points[indices[0]];
|
|
69569
|
+
const end = points[indices[1]];
|
|
69570
|
+
return Math.hypot(end.x - start.x, end.y - start.y);
|
|
69571
|
+
}
|
|
69572
|
+
function interpolatePoint(a2, b5, t2) {
|
|
69573
|
+
return {
|
|
69574
|
+
x: a2.x + (b5.x - a2.x) * t2,
|
|
69575
|
+
y: a2.y + (b5.y - a2.y) * t2
|
|
69576
|
+
};
|
|
69577
|
+
}
|
|
69578
|
+
function updateScreenEditGrid(grid, localPoints, visible) {
|
|
69579
|
+
if (!grid) {
|
|
69580
|
+
return;
|
|
69581
|
+
}
|
|
69582
|
+
grid.replaceChildren();
|
|
69583
|
+
grid.hidden = !visible;
|
|
69584
|
+
if (!visible) {
|
|
69585
|
+
return;
|
|
69586
|
+
}
|
|
69587
|
+
const [topLeft, topRight, bottomRight, bottomLeft] = localPoints;
|
|
69588
|
+
for (let index = 1; index < SCREEN_EDIT_GRID_DIVISIONS; index++) {
|
|
69589
|
+
const t2 = index / SCREEN_EDIT_GRID_DIVISIONS;
|
|
69590
|
+
const top = interpolatePoint(topLeft, topRight, t2);
|
|
69591
|
+
const bottom = interpolatePoint(bottomLeft, bottomRight, t2);
|
|
69592
|
+
const left = interpolatePoint(topLeft, bottomLeft, t2);
|
|
69593
|
+
const right = interpolatePoint(topRight, bottomRight, t2);
|
|
69594
|
+
const verticalLine = document.createElementNS(
|
|
69595
|
+
"http://www.w3.org/2000/svg",
|
|
69596
|
+
"line"
|
|
69597
|
+
);
|
|
69598
|
+
const horizontalLine = document.createElementNS(
|
|
69599
|
+
"http://www.w3.org/2000/svg",
|
|
69600
|
+
"line"
|
|
69601
|
+
);
|
|
69602
|
+
verticalLine.setAttribute("x1", String(top.x));
|
|
69603
|
+
verticalLine.setAttribute("y1", String(top.y));
|
|
69604
|
+
verticalLine.setAttribute("x2", String(bottom.x));
|
|
69605
|
+
verticalLine.setAttribute("y2", String(bottom.y));
|
|
69606
|
+
horizontalLine.setAttribute("x1", String(left.x));
|
|
69607
|
+
horizontalLine.setAttribute("y1", String(left.y));
|
|
69608
|
+
horizontalLine.setAttribute("x2", String(right.x));
|
|
69609
|
+
horizontalLine.setAttribute("y2", String(right.y));
|
|
69610
|
+
grid.append(verticalLine, horizontalLine);
|
|
69611
|
+
}
|
|
69612
|
+
}
|
|
69613
|
+
function ensureEditableRectHandles(rectEl) {
|
|
69614
|
+
if (!rectEl || rectEl.dataset.editHandlesReady === "true") {
|
|
69615
|
+
return;
|
|
69616
|
+
}
|
|
69617
|
+
const svg2 = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
69618
|
+
const polygon = document.createElementNS(
|
|
69619
|
+
"http://www.w3.org/2000/svg",
|
|
69620
|
+
"polygon"
|
|
69621
|
+
);
|
|
69622
|
+
const grid = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
69623
|
+
svg2.classList.add("screen-selection-edit-svg");
|
|
69624
|
+
grid.classList.add("screen-selection-edit-grid");
|
|
69625
|
+
polygon.classList.add("screen-selection-edit-polygon");
|
|
69626
|
+
svg2.append(polygon, grid);
|
|
69627
|
+
rectEl.appendChild(svg2);
|
|
69628
|
+
SCREEN_EDIT_HANDLE_PARTS.forEach((part) => {
|
|
69629
|
+
const handle = document.createElement("span");
|
|
69630
|
+
handle.classList.add(
|
|
69631
|
+
"screen-selection-edit-handle",
|
|
69632
|
+
`screen-selection-edit-${part}`
|
|
69633
|
+
);
|
|
69634
|
+
handle.dataset.editPart = part;
|
|
69635
|
+
rectEl.appendChild(handle);
|
|
69636
|
+
});
|
|
69637
|
+
rectEl.dataset.editHandlesReady = "true";
|
|
69638
|
+
}
|
|
69639
|
+
function pointSegmentDistanceSq(point, start, end) {
|
|
69640
|
+
const dx = end.x - start.x;
|
|
69641
|
+
const dy = end.y - start.y;
|
|
69642
|
+
const lengthSq = dx * dx + dy * dy;
|
|
69643
|
+
if (lengthSq <= 1e-12) {
|
|
69644
|
+
const px2 = point.x - start.x;
|
|
69645
|
+
const py2 = point.y - start.y;
|
|
69646
|
+
return px2 * px2 + py2 * py2;
|
|
69647
|
+
}
|
|
69648
|
+
const t2 = clampValue(
|
|
69649
|
+
((point.x - start.x) * dx + (point.y - start.y) * dy) / lengthSq,
|
|
69650
|
+
0,
|
|
69651
|
+
1
|
|
69652
|
+
);
|
|
69653
|
+
const x5 = start.x + dx * t2;
|
|
69654
|
+
const y6 = start.y + dy * t2;
|
|
69655
|
+
const px = point.x - x5;
|
|
69656
|
+
const py = point.y - y6;
|
|
69657
|
+
return px * px + py * py;
|
|
69658
|
+
}
|
|
69659
|
+
function createScreenEditOverlay({ overlayEl, rectEl }) {
|
|
69660
|
+
let activePart = null;
|
|
69661
|
+
function applyActivePart() {
|
|
69662
|
+
SCREEN_EDIT_HANDLE_PARTS.forEach((part) => {
|
|
69663
|
+
const handle = rectEl?.querySelector(`[data-edit-part="${part}"]`);
|
|
69664
|
+
handle?.classList.toggle("active", part === activePart);
|
|
69665
|
+
});
|
|
69666
|
+
}
|
|
69667
|
+
function render(clientPoints, { showGrid = false } = {}) {
|
|
69668
|
+
ensureEditableRectHandles(rectEl);
|
|
69669
|
+
rectEl?.classList.add("editable");
|
|
69670
|
+
rectEl?.classList.toggle("drawing", showGrid);
|
|
69671
|
+
const bounds = getClientPointsBounds(clientPoints);
|
|
69672
|
+
updateOverlayRect(overlayEl, rectEl, bounds);
|
|
69673
|
+
const width = Math.max(1, bounds.maxX - bounds.minX);
|
|
69674
|
+
const height = Math.max(1, bounds.maxY - bounds.minY);
|
|
69675
|
+
const localPoints = clientPoints.map((point) => ({
|
|
69676
|
+
x: point.x - bounds.minX,
|
|
69677
|
+
y: point.y - bounds.minY
|
|
69678
|
+
}));
|
|
69679
|
+
const svg2 = rectEl?.querySelector(".screen-selection-edit-svg");
|
|
69680
|
+
const polygon = rectEl?.querySelector(".screen-selection-edit-polygon");
|
|
69681
|
+
const grid = rectEl?.querySelector(".screen-selection-edit-grid");
|
|
69682
|
+
svg2?.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
69683
|
+
polygon?.setAttribute(
|
|
69684
|
+
"points",
|
|
69685
|
+
localPoints.map((point) => `${point.x},${point.y}`).join(" ")
|
|
69686
|
+
);
|
|
69687
|
+
updateScreenEditGrid(grid, localPoints, showGrid);
|
|
69688
|
+
SCREEN_EDIT_HANDLE_PARTS.forEach((part) => {
|
|
69689
|
+
const point = getPartPoint(localPoints, part);
|
|
69690
|
+
const handle = rectEl?.querySelector(`[data-edit-part="${part}"]`);
|
|
69691
|
+
if (!handle) {
|
|
69692
|
+
return;
|
|
69693
|
+
}
|
|
69694
|
+
handle.style.left = `${point.x}px`;
|
|
69695
|
+
handle.style.top = `${point.y}px`;
|
|
69696
|
+
const angle = getPartAngle(localPoints, part);
|
|
69697
|
+
const length = getPartLength(localPoints, part);
|
|
69698
|
+
if (length != null) {
|
|
69699
|
+
const maxVisualLength = Math.max(0, length - 2);
|
|
69700
|
+
const visualLength = Math.max(
|
|
69701
|
+
0,
|
|
69702
|
+
Math.min(SCREEN_EDIT_EDGE_HANDLE_MAX_LENGTH, maxVisualLength)
|
|
69703
|
+
);
|
|
69704
|
+
const activeScaleX = visualLength > 0 ? Math.min(
|
|
69705
|
+
SCREEN_EDIT_EDGE_HANDLE_ACTIVE_SCALE_X,
|
|
69706
|
+
Math.max(1, maxVisualLength / visualLength)
|
|
69707
|
+
) : 1;
|
|
69708
|
+
handle.style.width = `${visualLength}px`;
|
|
69709
|
+
handle.style.height = `${length <= SCREEN_EDIT_EDGE_HANDLE_MIN_LENGTH ? 2 : 4}px`;
|
|
69710
|
+
handle.style.setProperty(
|
|
69711
|
+
"--screen-selection-edit-active-scale-x",
|
|
69712
|
+
String(activeScaleX)
|
|
69713
|
+
);
|
|
69714
|
+
handle.style.setProperty(
|
|
69715
|
+
"--screen-selection-edit-active-scale-y",
|
|
69716
|
+
String(SCREEN_EDIT_EDGE_HANDLE_ACTIVE_SCALE_Y)
|
|
69717
|
+
);
|
|
69718
|
+
} else {
|
|
69719
|
+
handle.style.width = "";
|
|
69720
|
+
handle.style.height = "";
|
|
69721
|
+
handle.style.removeProperty("--screen-selection-edit-active-scale-x");
|
|
69722
|
+
handle.style.removeProperty("--screen-selection-edit-active-scale-y");
|
|
69723
|
+
}
|
|
69724
|
+
handle.style.transform = angle == null ? "translate(-50%, -50%)" : `translate(-50%, -50%) rotate(${angle}rad)`;
|
|
69725
|
+
});
|
|
69726
|
+
applyActivePart();
|
|
69727
|
+
}
|
|
69728
|
+
function clear() {
|
|
69729
|
+
activePart = null;
|
|
69730
|
+
rectEl?.classList.remove("drawing", "editable");
|
|
69731
|
+
applyActivePart();
|
|
69732
|
+
}
|
|
69733
|
+
function setActivePart(part) {
|
|
69734
|
+
activePart = SCREEN_EDIT_HANDLE_PARTS.includes(part) ? part : null;
|
|
69735
|
+
applyActivePart();
|
|
69736
|
+
}
|
|
69737
|
+
return {
|
|
69738
|
+
clear,
|
|
69739
|
+
render,
|
|
69740
|
+
setActivePart
|
|
69741
|
+
};
|
|
69742
|
+
}
|
|
69743
|
+
var SCREEN_EDIT_EDGE_HIT_SIZE, SCREEN_EDIT_CORNER_HIT_SIZE, SCREEN_EDIT_EDGE_HANDLE_MAX_LENGTH, SCREEN_EDIT_EDGE_HANDLE_MIN_LENGTH, SCREEN_EDIT_EDGE_HANDLE_ACTIVE_SCALE_X, SCREEN_EDIT_EDGE_HANDLE_ACTIVE_SCALE_Y, SCREEN_EDIT_GRID_DIVISIONS, SCREEN_EDIT_MIN_CONVEX_CROSS_ABS, SCREEN_EDIT_HANDLE_PARTS, SCREEN_EDIT_CORNER_PARTS, SCREEN_EDIT_EDGE_PARTS, SCREEN_EDIT_PART_POINT_INDICES;
|
|
69744
|
+
var init_editOverlay = __esm({
|
|
69745
|
+
"src/viewer/screenSelection/editOverlay.js"() {
|
|
69746
|
+
init_geometry();
|
|
69747
|
+
SCREEN_EDIT_EDGE_HIT_SIZE = 8;
|
|
69748
|
+
SCREEN_EDIT_CORNER_HIT_SIZE = 16;
|
|
69749
|
+
SCREEN_EDIT_EDGE_HANDLE_MAX_LENGTH = 26;
|
|
69750
|
+
SCREEN_EDIT_EDGE_HANDLE_MIN_LENGTH = 6;
|
|
69751
|
+
SCREEN_EDIT_EDGE_HANDLE_ACTIVE_SCALE_X = 1.5;
|
|
69752
|
+
SCREEN_EDIT_EDGE_HANDLE_ACTIVE_SCALE_Y = 1.5;
|
|
69753
|
+
SCREEN_EDIT_GRID_DIVISIONS = 8;
|
|
69754
|
+
SCREEN_EDIT_MIN_CONVEX_CROSS_ABS = 1e-3;
|
|
69755
|
+
SCREEN_EDIT_HANDLE_PARTS = [
|
|
69756
|
+
"top-left",
|
|
69757
|
+
"top",
|
|
69758
|
+
"top-right",
|
|
69759
|
+
"right",
|
|
69760
|
+
"bottom-right",
|
|
69761
|
+
"bottom",
|
|
69762
|
+
"bottom-left",
|
|
69763
|
+
"left"
|
|
69764
|
+
];
|
|
69765
|
+
SCREEN_EDIT_CORNER_PARTS = [
|
|
69766
|
+
"top-left",
|
|
69767
|
+
"top-right",
|
|
69768
|
+
"bottom-right",
|
|
69769
|
+
"bottom-left"
|
|
69770
|
+
];
|
|
69771
|
+
SCREEN_EDIT_EDGE_PARTS = ["top", "right", "bottom", "left"];
|
|
69772
|
+
SCREEN_EDIT_PART_POINT_INDICES = {
|
|
69773
|
+
"bottom-left": [3],
|
|
69774
|
+
"bottom-right": [2],
|
|
69775
|
+
bottom: [2, 3],
|
|
69776
|
+
left: [3, 0],
|
|
69777
|
+
right: [1, 2],
|
|
69778
|
+
top: [0, 1],
|
|
69779
|
+
"top-left": [0],
|
|
69780
|
+
"top-right": [1]
|
|
69781
|
+
};
|
|
69782
|
+
}
|
|
69783
|
+
});
|
|
69784
|
+
|
|
68879
69785
|
// src/viewer/dom/cropUi.js
|
|
68880
69786
|
function updateCropControls({
|
|
68881
69787
|
activeScreenSelectionId,
|
|
@@ -68993,9 +69899,13 @@ function createCropController({
|
|
|
68993
69899
|
let nextSelectionId = 1;
|
|
68994
69900
|
let activeSelectionId = null;
|
|
68995
69901
|
let pendingMode = false;
|
|
69902
|
+
let pendingScreenEdit = null;
|
|
69903
|
+
let pendingEditDrag = null;
|
|
69904
|
+
let editCursor = "";
|
|
68996
69905
|
let hasGaussianSplats = false;
|
|
68997
69906
|
const sphere = new Sphere();
|
|
68998
69907
|
const cameraForward2 = new Vector3();
|
|
69908
|
+
const screenEditOverlay = createScreenEditOverlay({ overlayEl, rectEl });
|
|
68999
69909
|
function getActiveSelection() {
|
|
69000
69910
|
if (activeSelectionId == null) {
|
|
69001
69911
|
return null;
|
|
@@ -69011,6 +69921,115 @@ function createCropController({
|
|
|
69011
69921
|
}))
|
|
69012
69922
|
];
|
|
69013
69923
|
}
|
|
69924
|
+
function setEditCursor(cursor) {
|
|
69925
|
+
const nextCursor = cursor || "";
|
|
69926
|
+
if (editCursor === nextCursor) {
|
|
69927
|
+
return;
|
|
69928
|
+
}
|
|
69929
|
+
domElement.style.cursor = nextCursor;
|
|
69930
|
+
editCursor = nextCursor;
|
|
69931
|
+
}
|
|
69932
|
+
function clearEditCursor() {
|
|
69933
|
+
setEditCursor("");
|
|
69934
|
+
}
|
|
69935
|
+
function getActivePendingEdit() {
|
|
69936
|
+
if (!pendingScreenEdit || activeSelectionId !== pendingScreenEdit.selectionId) {
|
|
69937
|
+
return null;
|
|
69938
|
+
}
|
|
69939
|
+
const match = pendingSelections.find(
|
|
69940
|
+
(selection) => selection.id === pendingScreenEdit.selectionId
|
|
69941
|
+
);
|
|
69942
|
+
return match ? pendingScreenEdit : null;
|
|
69943
|
+
}
|
|
69944
|
+
function clearScreenEditOverlay() {
|
|
69945
|
+
screenEditOverlay.clear();
|
|
69946
|
+
clearEditCursor();
|
|
69947
|
+
}
|
|
69948
|
+
function syncPendingEditOverlay() {
|
|
69949
|
+
const edit = getActivePendingEdit();
|
|
69950
|
+
if (!edit) {
|
|
69951
|
+
clearScreenEditOverlay();
|
|
69952
|
+
if (!pendingMode) {
|
|
69953
|
+
clearOverlay(overlayEl, rectEl);
|
|
69954
|
+
}
|
|
69955
|
+
return;
|
|
69956
|
+
}
|
|
69957
|
+
screenEditOverlay.render(edit.clientPoints, { showGrid: false });
|
|
69958
|
+
}
|
|
69959
|
+
function createCameraPoseSnapshot() {
|
|
69960
|
+
camera.updateMatrixWorld(true);
|
|
69961
|
+
return {
|
|
69962
|
+
position: camera.position.toArray(),
|
|
69963
|
+
projectionMatrix: camera.projectionMatrix.toArray(),
|
|
69964
|
+
quaternion: camera.quaternion.toArray()
|
|
69965
|
+
};
|
|
69966
|
+
}
|
|
69967
|
+
function projectionChanged(source, target) {
|
|
69968
|
+
if (!Array.isArray(source) || !Array.isArray(target)) {
|
|
69969
|
+
return true;
|
|
69970
|
+
}
|
|
69971
|
+
return source.some(
|
|
69972
|
+
(value, index) => Math.abs(value - target[index]) > CAMERA_PROJECTION_EPSILON
|
|
69973
|
+
);
|
|
69974
|
+
}
|
|
69975
|
+
function cameraPoseChanged(cameraPose) {
|
|
69976
|
+
if (!cameraPose) {
|
|
69977
|
+
return true;
|
|
69978
|
+
}
|
|
69979
|
+
camera.updateMatrixWorld(true);
|
|
69980
|
+
const dx = camera.position.x - cameraPose.position[0];
|
|
69981
|
+
const dy = camera.position.y - cameraPose.position[1];
|
|
69982
|
+
const dz = camera.position.z - cameraPose.position[2];
|
|
69983
|
+
if (dx * dx + dy * dy + dz * dz > CAMERA_POSITION_EPSILON_SQ) {
|
|
69984
|
+
return true;
|
|
69985
|
+
}
|
|
69986
|
+
const quaternion = cameraPose.quaternion;
|
|
69987
|
+
const quaternionDot = Math.abs(
|
|
69988
|
+
camera.quaternion.x * quaternion[0] + camera.quaternion.y * quaternion[1] + camera.quaternion.z * quaternion[2] + camera.quaternion.w * quaternion[3]
|
|
69989
|
+
);
|
|
69990
|
+
if (1 - Math.min(1, quaternionDot) > CAMERA_QUATERNION_EPSILON) {
|
|
69991
|
+
return true;
|
|
69992
|
+
}
|
|
69993
|
+
return projectionChanged(
|
|
69994
|
+
camera.projectionMatrix.toArray(),
|
|
69995
|
+
cameraPose.projectionMatrix
|
|
69996
|
+
);
|
|
69997
|
+
}
|
|
69998
|
+
function clearPendingScreenEdit() {
|
|
69999
|
+
pendingScreenEdit = null;
|
|
70000
|
+
pendingEditDrag = null;
|
|
70001
|
+
syncPendingEditOverlay();
|
|
70002
|
+
}
|
|
70003
|
+
function freezePendingScreenEdit(showStatus = false) {
|
|
70004
|
+
const hadEdit = !!pendingScreenEdit;
|
|
70005
|
+
if (!hadEdit) {
|
|
70006
|
+
return false;
|
|
70007
|
+
}
|
|
70008
|
+
clearPendingScreenEdit();
|
|
70009
|
+
if (showStatus) {
|
|
70010
|
+
setStatus(
|
|
70011
|
+
"Screen selection shape fixed after camera movement. Drag the 3D far plane, then Confirm or Cancel."
|
|
70012
|
+
);
|
|
70013
|
+
}
|
|
70014
|
+
return true;
|
|
70015
|
+
}
|
|
70016
|
+
function freezePendingScreenEditIfCameraChanged() {
|
|
70017
|
+
if (!pendingScreenEdit || pendingEditDrag) {
|
|
70018
|
+
return false;
|
|
70019
|
+
}
|
|
70020
|
+
if (!cameraPoseChanged(pendingScreenEdit.cameraPose)) {
|
|
70021
|
+
return false;
|
|
70022
|
+
}
|
|
70023
|
+
return freezePendingScreenEdit(true);
|
|
70024
|
+
}
|
|
70025
|
+
function createPendingScreenEdit(selection, clientRect) {
|
|
70026
|
+
pendingScreenEdit = {
|
|
70027
|
+
cameraPose: createCameraPoseSnapshot(),
|
|
70028
|
+
clientPoints: clampClientPoints(getClientRectPoints(clientRect), domElement),
|
|
70029
|
+
selectionId: selection.id
|
|
70030
|
+
};
|
|
70031
|
+
syncPendingEditOverlay();
|
|
70032
|
+
}
|
|
69014
70033
|
function syncWorldState() {
|
|
69015
70034
|
const transform = getCurrentRootTransformArray();
|
|
69016
70035
|
getEntries().forEach(({ selection }) => {
|
|
@@ -69090,10 +70109,171 @@ function createCropController({
|
|
|
69090
70109
|
camera,
|
|
69091
70110
|
domElement,
|
|
69092
70111
|
getDepthRange,
|
|
70112
|
+
onOverlayClear: clearScreenEditOverlay,
|
|
70113
|
+
onOverlayUpdate: (clientRect) => {
|
|
70114
|
+
screenEditOverlay.render(getClientRectPoints(clientRect), {
|
|
70115
|
+
showGrid: true
|
|
70116
|
+
});
|
|
70117
|
+
return true;
|
|
70118
|
+
},
|
|
69093
70119
|
onSelectionCreated: handleSelectionCreated,
|
|
69094
70120
|
overlayEl,
|
|
69095
70121
|
rectEl
|
|
69096
70122
|
});
|
|
70123
|
+
function createEditHit(part) {
|
|
70124
|
+
return { cursor: "grab", part };
|
|
70125
|
+
}
|
|
70126
|
+
function getPendingEditHit(event) {
|
|
70127
|
+
if (freezePendingScreenEditIfCameraChanged()) {
|
|
70128
|
+
return null;
|
|
70129
|
+
}
|
|
70130
|
+
const edit = getActivePendingEdit();
|
|
70131
|
+
if (!edit) {
|
|
70132
|
+
return null;
|
|
70133
|
+
}
|
|
70134
|
+
const pointer = { x: event.clientX, y: event.clientY };
|
|
70135
|
+
for (const part of SCREEN_EDIT_CORNER_PARTS) {
|
|
70136
|
+
const point = getPartPoint(edit.clientPoints, part);
|
|
70137
|
+
const dx = pointer.x - point.x;
|
|
70138
|
+
const dy = pointer.y - point.y;
|
|
70139
|
+
if (dx * dx + dy * dy <= SCREEN_EDIT_CORNER_HIT_SIZE ** 2) {
|
|
70140
|
+
return createEditHit(part);
|
|
70141
|
+
}
|
|
70142
|
+
}
|
|
70143
|
+
for (const part of SCREEN_EDIT_EDGE_PARTS) {
|
|
70144
|
+
const [startIndex, endIndex] = SCREEN_EDIT_PART_POINT_INDICES[part];
|
|
70145
|
+
if (pointSegmentDistanceSq(
|
|
70146
|
+
pointer,
|
|
70147
|
+
edit.clientPoints[startIndex],
|
|
70148
|
+
edit.clientPoints[endIndex]
|
|
70149
|
+
) <= SCREEN_EDIT_EDGE_HIT_SIZE ** 2) {
|
|
70150
|
+
return createEditHit(part);
|
|
70151
|
+
}
|
|
70152
|
+
}
|
|
70153
|
+
return null;
|
|
70154
|
+
}
|
|
70155
|
+
function getPendingEditDragPoints(event) {
|
|
70156
|
+
const { part, startClientX, startClientY, startPoints } = pendingEditDrag;
|
|
70157
|
+
const domRect = domElement.getBoundingClientRect();
|
|
70158
|
+
const indices = SCREEN_EDIT_PART_POINT_INDICES[part] || [];
|
|
70159
|
+
let dx = event.clientX - startClientX;
|
|
70160
|
+
let dy = event.clientY - startClientY;
|
|
70161
|
+
indices.forEach((index) => {
|
|
70162
|
+
const point = startPoints[index];
|
|
70163
|
+
dx = Math.max(dx, domRect.left - point.x);
|
|
70164
|
+
dx = Math.min(dx, domRect.right - point.x);
|
|
70165
|
+
dy = Math.max(dy, domRect.top - point.y);
|
|
70166
|
+
dy = Math.min(dy, domRect.bottom - point.y);
|
|
70167
|
+
});
|
|
70168
|
+
return startPoints.map(
|
|
70169
|
+
(point, index) => indices.includes(index) ? {
|
|
70170
|
+
x: point.x + dx,
|
|
70171
|
+
y: point.y + dy
|
|
70172
|
+
} : copyClientPoint(point)
|
|
70173
|
+
);
|
|
70174
|
+
}
|
|
70175
|
+
function updatePendingEditSelection(clientPoints) {
|
|
70176
|
+
const edit = getActivePendingEdit();
|
|
70177
|
+
if (!edit) {
|
|
70178
|
+
return false;
|
|
70179
|
+
}
|
|
70180
|
+
const match = findSelection(edit.selectionId);
|
|
70181
|
+
if (!match) {
|
|
70182
|
+
return false;
|
|
70183
|
+
}
|
|
70184
|
+
if (!isConvexClientQuad(clientPoints)) {
|
|
70185
|
+
return false;
|
|
70186
|
+
}
|
|
70187
|
+
const selectionData = createSelectionData({
|
|
70188
|
+
camera,
|
|
70189
|
+
clientPoints,
|
|
70190
|
+
domElement,
|
|
70191
|
+
getDepthRange
|
|
70192
|
+
});
|
|
70193
|
+
if (!selectionData) {
|
|
70194
|
+
return false;
|
|
70195
|
+
}
|
|
70196
|
+
edit.clientPoints = copyClientPoints(clientPoints);
|
|
70197
|
+
setScreenSelectionShape(
|
|
70198
|
+
match.selection,
|
|
70199
|
+
selectionData,
|
|
70200
|
+
getCurrentRootTransformArray()
|
|
70201
|
+
);
|
|
70202
|
+
syncPendingEditOverlay();
|
|
70203
|
+
syncTransformControlsState();
|
|
70204
|
+
return true;
|
|
70205
|
+
}
|
|
70206
|
+
function handlePendingEditPointerDown(event) {
|
|
70207
|
+
if (event.button !== 0) {
|
|
70208
|
+
return false;
|
|
70209
|
+
}
|
|
70210
|
+
const hit = getPendingEditHit(event);
|
|
70211
|
+
if (!hit) {
|
|
70212
|
+
return false;
|
|
70213
|
+
}
|
|
70214
|
+
pendingEditDrag = {
|
|
70215
|
+
part: hit.part,
|
|
70216
|
+
pointerId: event.pointerId,
|
|
70217
|
+
startClientX: event.clientX,
|
|
70218
|
+
startClientY: event.clientY,
|
|
70219
|
+
startPoints: copyClientPoints(pendingScreenEdit.clientPoints),
|
|
70220
|
+
updated: false
|
|
70221
|
+
};
|
|
70222
|
+
domElement.setPointerCapture?.(event.pointerId);
|
|
70223
|
+
screenEditOverlay.setActivePart(hit.part);
|
|
70224
|
+
setEditCursor("grabbing");
|
|
70225
|
+
event.preventDefault();
|
|
70226
|
+
event.stopPropagation();
|
|
70227
|
+
return true;
|
|
70228
|
+
}
|
|
70229
|
+
function handlePendingEditPointerMove(event) {
|
|
70230
|
+
if (pendingEditDrag) {
|
|
70231
|
+
if (event.pointerId !== pendingEditDrag.pointerId) {
|
|
70232
|
+
return false;
|
|
70233
|
+
}
|
|
70234
|
+
pendingEditDrag.updated = updatePendingEditSelection(getPendingEditDragPoints(event)) || pendingEditDrag.updated;
|
|
70235
|
+
event.preventDefault();
|
|
70236
|
+
event.stopPropagation();
|
|
70237
|
+
return true;
|
|
70238
|
+
}
|
|
70239
|
+
if (event.buttons) {
|
|
70240
|
+
return false;
|
|
70241
|
+
}
|
|
70242
|
+
const hit = getPendingEditHit(event);
|
|
70243
|
+
screenEditOverlay.setActivePart(hit?.part);
|
|
70244
|
+
setEditCursor(hit?.cursor || "");
|
|
70245
|
+
return false;
|
|
70246
|
+
}
|
|
70247
|
+
function handlePendingEditPointerUp(event) {
|
|
70248
|
+
if (!pendingEditDrag || event.pointerId !== pendingEditDrag.pointerId) {
|
|
70249
|
+
return false;
|
|
70250
|
+
}
|
|
70251
|
+
domElement.releasePointerCapture?.(event.pointerId);
|
|
70252
|
+
const updated = pendingEditDrag.updated;
|
|
70253
|
+
pendingEditDrag = null;
|
|
70254
|
+
const hit = getPendingEditHit(event);
|
|
70255
|
+
screenEditOverlay.setActivePart(hit?.part);
|
|
70256
|
+
setEditCursor(hit?.cursor || "");
|
|
70257
|
+
setStatus(
|
|
70258
|
+
updated ? "Updated screen selection convex quadrilateral." : "Screen selection must stay convex.",
|
|
70259
|
+
!updated
|
|
70260
|
+
);
|
|
70261
|
+
event.preventDefault();
|
|
70262
|
+
event.stopPropagation();
|
|
70263
|
+
return true;
|
|
70264
|
+
}
|
|
70265
|
+
function handlePendingEditPointerCancel(event) {
|
|
70266
|
+
if (!pendingEditDrag || event.pointerId !== pendingEditDrag.pointerId) {
|
|
70267
|
+
return false;
|
|
70268
|
+
}
|
|
70269
|
+
domElement.releasePointerCapture?.(event.pointerId);
|
|
70270
|
+
pendingEditDrag = null;
|
|
70271
|
+
screenEditOverlay.setActivePart(null);
|
|
70272
|
+
clearEditCursor();
|
|
70273
|
+
event.preventDefault();
|
|
70274
|
+
event.stopPropagation();
|
|
70275
|
+
return true;
|
|
70276
|
+
}
|
|
69097
70277
|
function setMode(active) {
|
|
69098
70278
|
pendingMode = active && hasGaussianSplats && pendingSelections.length === 0;
|
|
69099
70279
|
pointerTracker.setActive(pendingMode);
|
|
@@ -69106,6 +70286,7 @@ function createCropController({
|
|
|
69106
70286
|
}
|
|
69107
70287
|
cameraController.enabled = !transformControls.dragging;
|
|
69108
70288
|
syncTransformControlsState();
|
|
70289
|
+
syncPendingEditOverlay();
|
|
69109
70290
|
refreshUi();
|
|
69110
70291
|
}
|
|
69111
70292
|
function cancelMode() {
|
|
@@ -69114,7 +70295,7 @@ function createCropController({
|
|
|
69114
70295
|
}
|
|
69115
70296
|
setMode(false);
|
|
69116
70297
|
}
|
|
69117
|
-
function handleSelectionCreated(selectionData) {
|
|
70298
|
+
function handleSelectionCreated(selectionData, clientRect) {
|
|
69118
70299
|
if (pendingSelections.length > 0) {
|
|
69119
70300
|
setMode(false);
|
|
69120
70301
|
setStatus(
|
|
@@ -69136,12 +70317,13 @@ function createCropController({
|
|
|
69136
70317
|
pendingSelections.push(selection);
|
|
69137
70318
|
activeSelectionId = selection.id;
|
|
69138
70319
|
setMode(false);
|
|
70320
|
+
createPendingScreenEdit(selection, clientRect);
|
|
69139
70321
|
syncEditSdfs();
|
|
69140
70322
|
syncFarHandles();
|
|
69141
70323
|
syncTransformControlsState();
|
|
69142
70324
|
refreshUi();
|
|
69143
70325
|
setStatus(
|
|
69144
|
-
"Added screen exclude selection. Drag the 3D far plane
|
|
70326
|
+
"Added screen exclude selection. Drag corner points or edges into a convex quadrilateral before moving the camera, then adjust the 3D far plane and Confirm or Cancel."
|
|
69145
70327
|
);
|
|
69146
70328
|
}
|
|
69147
70329
|
function toggle() {
|
|
@@ -69173,6 +70355,7 @@ function createCropController({
|
|
|
69173
70355
|
}
|
|
69174
70356
|
const count = pendingSelections.length;
|
|
69175
70357
|
selections.push(...pendingSelections);
|
|
70358
|
+
clearPendingScreenEdit();
|
|
69176
70359
|
pendingSelections = [];
|
|
69177
70360
|
activeSelectionId = null;
|
|
69178
70361
|
setMode(false);
|
|
@@ -69193,6 +70376,7 @@ function createCropController({
|
|
|
69193
70376
|
)) {
|
|
69194
70377
|
activeSelectionId = null;
|
|
69195
70378
|
}
|
|
70379
|
+
clearPendingScreenEdit();
|
|
69196
70380
|
pendingSelections.forEach(disposeScreenSelection);
|
|
69197
70381
|
pendingSelections = [];
|
|
69198
70382
|
syncEditSdfs();
|
|
@@ -69259,10 +70443,12 @@ function createCropController({
|
|
|
69259
70443
|
setTransformMode(null);
|
|
69260
70444
|
syncEditSdfs();
|
|
69261
70445
|
syncFarHandles();
|
|
70446
|
+
syncPendingEditOverlay();
|
|
69262
70447
|
refreshUi();
|
|
69263
70448
|
syncTransformControlsState();
|
|
70449
|
+
const canEditPendingRect = !wasActive && !!getActivePendingEdit();
|
|
69264
70450
|
setStatus(
|
|
69265
|
-
wasActive ? "Screen selection deactivated." : "Drag the 3D far plane handle to adjust screen selection depth."
|
|
70451
|
+
wasActive ? "Screen selection deactivated." : canEditPendingRect ? "Drag corner points or edges into a convex quadrilateral before moving the camera, or drag the 3D far plane to adjust depth." : "Drag the 3D far plane handle to adjust screen selection depth."
|
|
69266
70452
|
);
|
|
69267
70453
|
}
|
|
69268
70454
|
function removeFromList(list, selectionId) {
|
|
@@ -69283,6 +70469,9 @@ function createCropController({
|
|
|
69283
70469
|
if (Number(selectionId) === activeSelectionId) {
|
|
69284
70470
|
activeSelectionId = null;
|
|
69285
70471
|
}
|
|
70472
|
+
if (Number(selectionId) === pendingScreenEdit?.selectionId) {
|
|
70473
|
+
clearPendingScreenEdit();
|
|
70474
|
+
}
|
|
69286
70475
|
syncEditSdfs();
|
|
69287
70476
|
syncFarHandles();
|
|
69288
70477
|
refreshUi();
|
|
@@ -69300,6 +70489,7 @@ function createCropController({
|
|
|
69300
70489
|
selections = [];
|
|
69301
70490
|
pendingSelections = [];
|
|
69302
70491
|
activeSelectionId = null;
|
|
70492
|
+
clearPendingScreenEdit();
|
|
69303
70493
|
syncEditSdfs();
|
|
69304
70494
|
syncFarHandles();
|
|
69305
70495
|
refreshUi();
|
|
@@ -69313,6 +70503,7 @@ function createCropController({
|
|
|
69313
70503
|
activeSelectionId = null;
|
|
69314
70504
|
syncEditSdfs();
|
|
69315
70505
|
syncFarHandles();
|
|
70506
|
+
syncPendingEditOverlay();
|
|
69316
70507
|
cancelMode();
|
|
69317
70508
|
refreshUi();
|
|
69318
70509
|
}
|
|
@@ -69323,8 +70514,44 @@ function createCropController({
|
|
|
69323
70514
|
activeSelectionId = null;
|
|
69324
70515
|
syncEditSdfs();
|
|
69325
70516
|
syncFarHandles();
|
|
70517
|
+
syncPendingEditOverlay();
|
|
69326
70518
|
refreshUi();
|
|
69327
70519
|
}
|
|
70520
|
+
function shouldCapturePointerDown(event) {
|
|
70521
|
+
return event.button === 0 && (pendingMode || getPendingEditHit(event) !== null);
|
|
70522
|
+
}
|
|
70523
|
+
function handlePointerDown(event) {
|
|
70524
|
+
if (pointerTracker.handlePointerDown(event)) {
|
|
70525
|
+
return true;
|
|
70526
|
+
}
|
|
70527
|
+
return handlePendingEditPointerDown(event);
|
|
70528
|
+
}
|
|
70529
|
+
function handlePointerMove(event) {
|
|
70530
|
+
if (pointerTracker.handlePointerMove(event)) {
|
|
70531
|
+
return true;
|
|
70532
|
+
}
|
|
70533
|
+
return handlePendingEditPointerMove(event);
|
|
70534
|
+
}
|
|
70535
|
+
function handlePointerUp(event) {
|
|
70536
|
+
if (pointerTracker.handlePointerUp(event)) {
|
|
70537
|
+
return true;
|
|
70538
|
+
}
|
|
70539
|
+
return handlePendingEditPointerUp(event);
|
|
70540
|
+
}
|
|
70541
|
+
function handlePointerCancel(event) {
|
|
70542
|
+
if (pointerTracker.handlePointerCancel(event)) {
|
|
70543
|
+
return true;
|
|
70544
|
+
}
|
|
70545
|
+
return handlePendingEditPointerCancel(event);
|
|
70546
|
+
}
|
|
70547
|
+
cameraController.addEventListener(
|
|
70548
|
+
"update",
|
|
70549
|
+
freezePendingScreenEditIfCameraChanged
|
|
70550
|
+
);
|
|
70551
|
+
cameraController.addEventListener(
|
|
70552
|
+
"finish",
|
|
70553
|
+
freezePendingScreenEditIfCameraChanged
|
|
70554
|
+
);
|
|
69328
70555
|
return {
|
|
69329
70556
|
cancel,
|
|
69330
70557
|
cancelMode,
|
|
@@ -69334,25 +70561,32 @@ function createCropController({
|
|
|
69334
70561
|
getActiveSelection,
|
|
69335
70562
|
getPayload,
|
|
69336
70563
|
getPendingMode: () => pendingMode,
|
|
69337
|
-
handlePointerCancel
|
|
69338
|
-
handlePointerDown
|
|
69339
|
-
handlePointerMove
|
|
69340
|
-
handlePointerUp
|
|
70564
|
+
handlePointerCancel,
|
|
70565
|
+
handlePointerDown,
|
|
70566
|
+
handlePointerMove,
|
|
70567
|
+
handlePointerUp,
|
|
69341
70568
|
handleSelectionRemove,
|
|
69342
70569
|
handleSelectionSelect,
|
|
69343
70570
|
handleTransformControlObjectChange,
|
|
69344
70571
|
hasPendingSelections: () => pendingSelections.length > 0,
|
|
69345
70572
|
notifyTransformModeChanged,
|
|
69346
70573
|
setHasGaussianSplats,
|
|
70574
|
+
shouldCapturePointerDown,
|
|
69347
70575
|
syncWorldState,
|
|
69348
70576
|
toggle
|
|
69349
70577
|
};
|
|
69350
70578
|
}
|
|
70579
|
+
var CAMERA_POSITION_EPSILON_SQ, CAMERA_QUATERNION_EPSILON, CAMERA_PROJECTION_EPSILON;
|
|
69351
70580
|
var init_cropController = __esm({
|
|
69352
70581
|
"src/viewer/screenSelection/cropController.js"() {
|
|
69353
70582
|
init_three_module();
|
|
69354
70583
|
init_screenSelection();
|
|
70584
|
+
init_geometry();
|
|
70585
|
+
init_editOverlay();
|
|
69355
70586
|
init_cropUi();
|
|
70587
|
+
CAMERA_POSITION_EPSILON_SQ = 1e-12;
|
|
70588
|
+
CAMERA_QUATERNION_EPSILON = 1e-10;
|
|
70589
|
+
CAMERA_PROJECTION_EPSILON = 1e-10;
|
|
69356
70590
|
}
|
|
69357
70591
|
});
|
|
69358
70592
|
|
|
@@ -69961,7 +71195,7 @@ var require_app = __commonJS({
|
|
|
69961
71195
|
savedControlDisabledStates = null;
|
|
69962
71196
|
}
|
|
69963
71197
|
cameraController.setPointerDownFilter((event) => {
|
|
69964
|
-
return !(cropController?.
|
|
71198
|
+
return !(cropController?.shouldCapturePointerDown(event) ?? false);
|
|
69965
71199
|
});
|
|
69966
71200
|
var { transformControls, transformControlsHelper } = createViewerTransformControls({
|
|
69967
71201
|
camera,
|
|
@@ -69993,7 +71227,7 @@ var require_app = __commonJS({
|
|
|
69993
71227
|
var geoCamera = createGeoCameraController({
|
|
69994
71228
|
camera,
|
|
69995
71229
|
centerModeDistanceSq: CAMERA_CENTER_MODE_DISTANCE_SQ,
|
|
69996
|
-
getActiveEllipsoid: () =>
|
|
71230
|
+
getActiveEllipsoid: () => flyTo2.getActiveEllipsoid()
|
|
69997
71231
|
});
|
|
69998
71232
|
var geometricError = createGeometricErrorController({
|
|
69999
71233
|
defaultErrorTarget: DEFAULT_ERROR_TARGET,
|
|
@@ -70012,7 +71246,7 @@ var require_app = __commonJS({
|
|
|
70012
71246
|
target.radius *= editableGroup.matrixWorld.getMaxScaleOnAxis();
|
|
70013
71247
|
return true;
|
|
70014
71248
|
}
|
|
70015
|
-
var
|
|
71249
|
+
var flyTo2 = createFlyToController({
|
|
70016
71250
|
camera,
|
|
70017
71251
|
cameraController,
|
|
70018
71252
|
domElement: renderer.domElement,
|
|
@@ -70034,7 +71268,7 @@ var require_app = __commonJS({
|
|
|
70034
71268
|
syncTransformControlsState: () => transformModeController.syncControls(),
|
|
70035
71269
|
transformControls,
|
|
70036
71270
|
applyTilesPlacementFromPointerEvent: async (event) => {
|
|
70037
|
-
const coordinate = await
|
|
71271
|
+
const coordinate = await flyTo2.applyTilesSetPositionFromPointerEvent(event);
|
|
70038
71272
|
if (coordinate) {
|
|
70039
71273
|
updateCoordinateInputs(
|
|
70040
71274
|
coordinate.latitude,
|
|
@@ -70122,7 +71356,7 @@ var require_app = __commonJS({
|
|
|
70122
71356
|
transformModeController.setMode(null);
|
|
70123
71357
|
function moveCameraToTiles() {
|
|
70124
71358
|
cancelPositionPickModes();
|
|
70125
|
-
|
|
71359
|
+
flyTo2.moveCameraToTiles();
|
|
70126
71360
|
}
|
|
70127
71361
|
function moveCameraToCoordinate() {
|
|
70128
71362
|
cancelPositionPickModes();
|
|
@@ -70130,7 +71364,7 @@ var require_app = __commonJS({
|
|
|
70130
71364
|
if (!coordinate) {
|
|
70131
71365
|
return;
|
|
70132
71366
|
}
|
|
70133
|
-
|
|
71367
|
+
flyTo2.moveCameraToCoordinate(coordinate);
|
|
70134
71368
|
}
|
|
70135
71369
|
async function moveTilesToCoordinate() {
|
|
70136
71370
|
cancelPositionPickModes();
|
|
@@ -70205,9 +71439,11 @@ var require_app = __commonJS({
|
|
|
70205
71439
|
if (framed) {
|
|
70206
71440
|
return;
|
|
70207
71441
|
}
|
|
70208
|
-
if (
|
|
71442
|
+
if (flyTo2.frameTileset({
|
|
71443
|
+
activeStatus: "Framing tileset...",
|
|
71444
|
+
doneStatus: "Tileset ready."
|
|
71445
|
+
})) {
|
|
70209
71446
|
framed = true;
|
|
70210
|
-
setStatus("Tileset ready.");
|
|
70211
71447
|
}
|
|
70212
71448
|
};
|
|
70213
71449
|
next.addEventListener(
|
|
@@ -70328,6 +71564,7 @@ var require_app = __commonJS({
|
|
|
70328
71564
|
loadTileset(TILESET_URL);
|
|
70329
71565
|
function frame() {
|
|
70330
71566
|
cameraController.update();
|
|
71567
|
+
flyTo2.update();
|
|
70331
71568
|
rootTransform.flush();
|
|
70332
71569
|
globeController.update();
|
|
70333
71570
|
tiles?.update();
|