Skip to content

Commit d46cbd9

Browse files
committed
wip: improve corridor geometry generation to avoid overlapping (#1089)
1 parent 1f48d74 commit d46cbd9

File tree

1 file changed

+64
-29
lines changed

1 file changed

+64
-29
lines changed

map/client/cesium/utils/utils.cesium.js

+64-29
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,16 @@ function createCorridorGeometry (positions, width, height) {
110110
return Cesium.Cartographic.toCartesian(cartographic)
111111
}
112112

113-
const computeOffset = (current, previous, next, offset) => {
113+
const angleBetweenThreePoints = (A, B, C) => {
114+
const AB = Cesium.Cartesian3.subtract(B, A, new Cesium.Cartesian3())
115+
const AC = Cesium.Cartesian3.subtract(C, A, new Cesium.Cartesian3())
116+
const dot = Cesium.Cartesian3.dot(AB, AC)
117+
const lengthAB = Cesium.Cartesian3.magnitude(AB)
118+
const lengthAC = Cesium.Cartesian3.magnitude(AC)
119+
return Math.acos(dot / (lengthAB * lengthAC))
120+
}
121+
122+
const computeOffset = (current, previous, next, offset, normal) => {
114123
let direction
115124

116125
if (!previous) {
@@ -129,55 +138,81 @@ function createCorridorGeometry (positions, width, height) {
129138
Cesium.Cartesian3.normalize(direction, direction)
130139

131140
// Compute the perpendicular vector
132-
const up = Cesium.Cartesian3.UNIT_Z
141+
const up = normal || Cesium.Cartesian3.UNIT_Z
133142
const perpendicular = Cesium.Cartesian3.cross(direction, up, new Cesium.Cartesian3())
134143
Cesium.Cartesian3.normalize(perpendicular, perpendicular)
135144

136145
// Apply the offset
137146
const offsetVector = Cesium.Cartesian3.multiplyByScalar(perpendicular, offset, new Cesium.Cartesian3())
138-
return Cesium.Cartesian3.add(current, offsetVector, new Cesium.Cartesian3())
147+
return { direction, position: Cesium.Cartesian3.add(current, offsetVector, new Cesium.Cartesian3()) }
139148
}
140149

141-
const indices = []
150+
for (let i = 0; i < positions.length; i++) {
151+
positions[i] = setHeight(positions[i], height)
152+
}
153+
154+
// Find local normal
155+
// Implies that if the corridor extends over very large distances, the normal may be incorrect
156+
const normal = Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(positions[0])
142157
const distances = [0]
143158
let lineLength = 0
159+
const corridorPositions = []
160+
161+
let lastLeftPoint = null
162+
let lastRightPoint = null
163+
let lastDirection = null
164+
for (let i = 0; i < positions.length; i++) {
165+
// Compute the offset positions to create the corridor
166+
const left = computeOffset(positions[i], positions[i - 1], positions[i + 1], -width / 2, normal)
167+
const right = computeOffset(positions[i], positions[i - 1], positions[i + 1], width / 2, normal)
168+
169+
// Check if [left, right] segment intersects with the previous one
170+
if (i > 0) {
171+
const turnLeft = Cesium.Cartesian3.cross(left.direction, lastDirection, new Cesium.Cartesian3()).z < 0
172+
173+
const previousAngle = angleBetweenThreePoints(positions[i - 1], positions[i], turnLeft ? lastLeftPoint : lastRightPoint)
174+
const currentAngle = angleBetweenThreePoints(positions[i - 1], positions[i], turnLeft ? left.position : right.position)
175+
if (currentAngle > previousAngle) {
176+
if (turnLeft) left.position = lastLeftPoint
177+
else right.position = lastRightPoint
178+
}
179+
180+
const distance = Cesium.Cartesian3.distance(positions[i - 1], positions[i])
181+
distances.push(distance)
182+
lineLength += distance
183+
}
144184

145-
for (let i = 0; i < positions.length - 1; i++) {
146-
const p0 = positions[i]
147-
const p1 = positions[i + 1]
148-
const distance = Cesium.Cartesian3.distance(p0, p1)
149-
distances.push(distance)
150-
lineLength += distance
151-
152-
// Add indices
153-
const baseIndex = i * 2
154-
indices.push(
155-
baseIndex, baseIndex + 1, baseIndex + 2,
156-
baseIndex + 1, baseIndex + 3, baseIndex + 2
185+
corridorPositions.push(
186+
left.position.x,
187+
left.position.y,
188+
left.position.z,
189+
right.position.x,
190+
right.position.y,
191+
right.position.z
157192
)
193+
194+
lastLeftPoint = left.position
195+
lastRightPoint = right.position
196+
lastDirection = left.direction
158197
}
159198

160199
let percent = 0
161200
const st = []
162-
const corridorPositions = []
201+
const indices = []
163202
for (let i = 0; i < positions.length; i++) {
164203
// Normalize distances for texture coordinates
165204
percent += distances[i] / lineLength
166205
if (i === positions.length - 1) percent = 1
167206
st.push(1 - percent, 0, 1 - percent, 1)
168207

169-
// Compute the offset positions to create the corridor
170-
const leftOffset = setHeight(computeOffset(positions[i], positions[i - 1], positions[i + 1], -width / 2), height)
171-
const rightOffset = setHeight(computeOffset(positions[i], positions[i - 1], positions[i + 1], width / 2), height)
172-
173-
corridorPositions.push(
174-
leftOffset.x,
175-
leftOffset.y,
176-
leftOffset.z,
177-
rightOffset.x,
178-
rightOffset.y,
179-
rightOffset.z
180-
)
208+
// Add indices for triangulation
209+
if (i < positions.length - 1) {
210+
const baseIndex = i * 2
211+
indices.push(
212+
baseIndex, baseIndex + 1, baseIndex + 2,
213+
baseIndex + 1, baseIndex + 3, baseIndex + 2
214+
)
215+
}
181216
}
182217

183218
return {

0 commit comments

Comments
 (0)