@@ -110,7 +110,16 @@ function createCorridorGeometry (positions, width, height) {
110
110
return Cesium . Cartographic . toCartesian ( cartographic )
111
111
}
112
112
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 ) => {
114
123
let direction
115
124
116
125
if ( ! previous ) {
@@ -129,55 +138,81 @@ function createCorridorGeometry (positions, width, height) {
129
138
Cesium . Cartesian3 . normalize ( direction , direction )
130
139
131
140
// Compute the perpendicular vector
132
- const up = Cesium . Cartesian3 . UNIT_Z
141
+ const up = normal || Cesium . Cartesian3 . UNIT_Z
133
142
const perpendicular = Cesium . Cartesian3 . cross ( direction , up , new Cesium . Cartesian3 ( ) )
134
143
Cesium . Cartesian3 . normalize ( perpendicular , perpendicular )
135
144
136
145
// Apply the offset
137
146
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 ( ) ) }
139
148
}
140
149
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 ] )
142
157
const distances = [ 0 ]
143
158
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
+ }
144
184
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
157
192
)
193
+
194
+ lastLeftPoint = left . position
195
+ lastRightPoint = right . position
196
+ lastDirection = left . direction
158
197
}
159
198
160
199
let percent = 0
161
200
const st = [ ]
162
- const corridorPositions = [ ]
201
+ const indices = [ ]
163
202
for ( let i = 0 ; i < positions . length ; i ++ ) {
164
203
// Normalize distances for texture coordinates
165
204
percent += distances [ i ] / lineLength
166
205
if ( i === positions . length - 1 ) percent = 1
167
206
st . push ( 1 - percent , 0 , 1 - percent , 1 )
168
207
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
+ }
181
216
}
182
217
183
218
return {
0 commit comments