-
Notifications
You must be signed in to change notification settings - Fork 17
/
itownsUtil.js
161 lines (145 loc) · 5.24 KB
/
itownsUtil.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Everything there should be contributed at some point in itowns
const THREE = require('three');
const itowns = require('itowns');
/** CAMERA */
/**
* Compute a distance automatically for travel features of itowns Planar View
*
* Note: Code retrieve itowns - {@link https://github.com/iTowns/itowns/blob/1bad0d627764c73b606179c636ad7b70105dd633/src/Controls/PlanarControls.js#L712}
*
* @param {itowns.PlanarControls} controls - planar controls of itownsView
* @param {THREE.Vector3} targetPos - position of our target
* @returns {number} the duration of travel to focus a targetPosition
*/
function autoDurationTravel(controls, targetPos) {
const normalizedDistance = Math.min(
1,
targetPos.distanceTo(controls.camera.position) / controls.autoTravelTimeDist
);
return THREE.MathUtils.lerp(
controls.autoTravelTimeMin,
controls.autoTravelTimeMax,
normalizedDistance
);
}
/**
* Makes the camera move to focus on the target position.
*
* @param {itowns.PlanarView} view The iTowns view.
* @param {itowns.PlanarControls} controls The camera controls.
* @param {THREE.Vector3} targetPos The target position.
* @param {*} [options] Optional parameters for the travel. Accepted entries
* are :
* - `duration` : the duration of the movement, in seconds. The promise will
* resolve after this value. If not specified, the value `auto` is used for
* the movement (see the `PlanarControls.initateTravel` method), and the promise
* resolves imediatly.
* - `verticalDistance` : Desired height of the camera relative to the target
* position.
* - `horizontalDistance` : Desired distance of the camera from the target
* position.
* @returns {Promise} Promise of the camera focusing on target
* @todo this function is used by widget should be contributed or removed
*/
export function focusCameraOn(view, controls, targetPos, options = {}) {
return new Promise((resolve, reject) => {
try {
const duration = options.duration || null;
const verticalDist = options.verticalDistance || 800;
const horizontalDist = options.horizontalDistance || 1000;
const cameraPos = view.camera.camera3D.position.clone();
const direction = new THREE.Vector3().subVectors(targetPos, cameraPos);
const currentDist = Math.sqrt(
direction.x * direction.x + direction.y * direction.y
);
cameraPos.addScaledVector(direction, 1 - horizontalDist / currentDist);
cameraPos.z = targetPos.z + verticalDist;
const noControls = !view.controls;
if (noControls) controls = new itowns.PlanarControls(view);
const travelDuration =
duration || duration == 0
? duration
: autoDurationTravel(controls, targetPos);
const timeoutDuration = travelDuration * 1000;
controls.initiateTravel(cameraPos, travelDuration, targetPos, true);
setTimeout(() => {
if (noControls) {
view.controls.dispose();
view.controls = undefined;
}
resolve(targetPos);
}, timeoutDuration);
} catch (e) {
reject(e);
}
});
}
/**
* Focus a C3DTiles Layer
*
* @param {itowns.PlanarView} itownsView - view
* @param {itowns.C3DTilesLayer} layer - layer to focus
* @returns {Promise | null} Promise of the camera focusing on C3DTiles
* @todo this function is used by widget should be contributed or removed
*/
export function focusC3DTilesLayer(itownsView, layer) {
if (!layer.isC3DTilesLayer) return null;
const coordinates = itownsView.camera.position();
const extent = layer.extent;
coordinates.x = (extent.east + extent.west) / 2;
coordinates.y = (extent.north + extent.south) / 2;
coordinates.z = 200;
if (layer.tileset.tiles[0])
coordinates.z = layer.tileset.tiles[0].boundingVolume.box.max.z;
return focusCameraOn(
itownsView,
itownsView.controls,
new THREE.Vector3().copy(coordinates),
{
verticalDistance: 200,
horizontalDistance: 200,
}
);
}
/**
* fetchC3DTileFeatureWithNodeText takes a parameter `batchTableKey` and returns a feature from a `3DTileslayer` if
* the batch table content of the feature contains a given `batchTableValue` string in the given key. Returns an object
* containing the first matching feature and its layer.
*
* @param {itowns.PlanarView} itownsView - view
* @param {string} batchTableKey a given batch table key
* @param {string} batchTableValue a given batch table value
* @returns {object} containting the feature and the layer containing the feature
*/
export function fetchC3DTileFeatureWithNodeText(
itownsView,
batchTableKey,
batchTableValue
) {
let result = null;
itownsView
.getLayers()
.filter((el) => el.isC3DTilesLayer)
.forEach((c3DTilesLayer) => {
for (const [
// eslint-disable-next-line no-unused-vars
tileId,
tileC3DTileFeatures,
] of c3DTilesLayer.tilesC3DTileFeatures) {
// eslint-disable-next-line no-unused-vars
for (const [batchId, c3DTileFeature] of tileC3DTileFeatures) {
if (
c3DTileFeature.getInfo().batchTable[batchTableKey] ==
batchTableValue
) {
result = {
feature: c3DTileFeature,
layer: c3DTilesLayer,
};
break;
}
}
}
});
return result;
}