@@ -231,7 +231,7 @@ import Rectangle from './Rectangle.js';
231
231
232
232
var scratchOffset = new Cartesian3 ( ) ;
233
233
var scratchScale = new Cartesian3 ( ) ;
234
- function fromTangentPlaneExtents ( tangentPlane , minimumX , maximumX , minimumY , maximumY , minimumZ , maximumZ , result ) {
234
+ function fromPlaneExtents ( planeOrigin , planeXAxis , planeYAxis , planeZAxis , minimumX , maximumX , minimumY , maximumY , minimumZ , maximumZ , result ) {
235
235
//>>includeStart('debug', pragmas.debug);
236
236
if ( ! defined ( minimumX ) ||
237
237
! defined ( maximumX ) ||
@@ -248,9 +248,9 @@ import Rectangle from './Rectangle.js';
248
248
}
249
249
250
250
var halfAxes = result . halfAxes ;
251
- Matrix3 . setColumn ( halfAxes , 0 , tangentPlane . xAxis , halfAxes ) ;
252
- Matrix3 . setColumn ( halfAxes , 1 , tangentPlane . yAxis , halfAxes ) ;
253
- Matrix3 . setColumn ( halfAxes , 2 , tangentPlane . zAxis , halfAxes ) ;
251
+ Matrix3 . setColumn ( halfAxes , 0 , planeXAxis , halfAxes ) ;
252
+ Matrix3 . setColumn ( halfAxes , 1 , planeYAxis , halfAxes ) ;
253
+ Matrix3 . setColumn ( halfAxes , 2 , planeZAxis , halfAxes ) ;
254
254
255
255
var centerOffset = scratchOffset ;
256
256
centerOffset . x = ( minimumX + maximumX ) / 2.0 ;
@@ -264,17 +264,40 @@ import Rectangle from './Rectangle.js';
264
264
265
265
var center = result . center ;
266
266
centerOffset = Matrix3 . multiplyByVector ( halfAxes , centerOffset , centerOffset ) ;
267
- Cartesian3 . add ( tangentPlane . origin , centerOffset , center ) ;
267
+ Cartesian3 . add ( planeOrigin , centerOffset , center ) ;
268
268
Matrix3 . multiplyByScale ( halfAxes , scale , halfAxes ) ;
269
269
270
270
return result ;
271
271
}
272
272
273
273
var scratchRectangleCenterCartographic = new Cartographic ( ) ;
274
274
var scratchRectangleCenter = new Cartesian3 ( ) ;
275
- var perimeterCartographicScratch = [ new Cartographic ( ) , new Cartographic ( ) , new Cartographic ( ) , new Cartographic ( ) , new Cartographic ( ) , new Cartographic ( ) , new Cartographic ( ) , new Cartographic ( ) ] ;
276
- var perimeterCartesianScratch = [ new Cartesian3 ( ) , new Cartesian3 ( ) , new Cartesian3 ( ) , new Cartesian3 ( ) , new Cartesian3 ( ) , new Cartesian3 ( ) , new Cartesian3 ( ) , new Cartesian3 ( ) ] ;
277
- var perimeterProjectedScratch = [ new Cartesian2 ( ) , new Cartesian2 ( ) , new Cartesian2 ( ) , new Cartesian2 ( ) , new Cartesian2 ( ) , new Cartesian2 ( ) , new Cartesian2 ( ) , new Cartesian2 ( ) ] ;
275
+ var scratchPerimeterCartographicNC = new Cartographic ( ) ;
276
+ var scratchPerimeterCartographicNW = new Cartographic ( ) ;
277
+ var scratchPerimeterCartographicCW = new Cartographic ( ) ;
278
+ var scratchPerimeterCartographicSW = new Cartographic ( ) ;
279
+ var scratchPerimeterCartographicSC = new Cartographic ( ) ;
280
+ var scratchPerimeterCartesianNC = new Cartesian3 ( ) ;
281
+ var scratchPerimeterCartesianNW = new Cartesian3 ( ) ;
282
+ var scratchPerimeterCartesianCW = new Cartesian3 ( ) ;
283
+ var scratchPerimeterCartesianSW = new Cartesian3 ( ) ;
284
+ var scratchPerimeterCartesianSC = new Cartesian3 ( ) ;
285
+ var scratchPerimeterProjectedNC = new Cartesian2 ( ) ;
286
+ var scratchPerimeterProjectedNW = new Cartesian2 ( ) ;
287
+ var scratchPerimeterProjectedCW = new Cartesian2 ( ) ;
288
+ var scratchPerimeterProjectedSW = new Cartesian2 ( ) ;
289
+ var scratchPerimeterProjectedSC = new Cartesian2 ( ) ;
290
+
291
+ var scratchPlaneOrigin = new Cartesian3 ( ) ;
292
+ var scratchPlaneNormal = new Cartesian3 ( ) ;
293
+ var scratchPlaneXAxis = new Cartesian3 ( ) ;
294
+ var scratchHorizonCartesian = new Cartesian3 ( ) ;
295
+ var scratchHorizonProjected = new Cartesian2 ( ) ;
296
+ var scratchMaxY = new Cartesian3 ( ) ;
297
+ var scratchMinY = new Cartesian3 ( ) ;
298
+ var scratchZ = new Cartesian3 ( ) ;
299
+ var scratchPlane = new Plane ( Cartesian3 . UNIT_X , 0.0 ) ;
300
+
278
301
/**
279
302
* Computes an OrientedBoundingBox that bounds a {@link Rectangle} on the surface of an {@link Ellipsoid}.
280
303
* There are no guarantees about the orientation of the bounding box.
@@ -310,59 +333,86 @@ import Rectangle from './Rectangle.js';
310
333
maximumHeight = defaultValue ( maximumHeight , 0.0 ) ;
311
334
ellipsoid = defaultValue ( ellipsoid , Ellipsoid . WGS84 ) ;
312
335
313
- // The bounding box will be aligned with the tangent plane at the center of the rectangle.
314
- var tangentPointCartographic = Rectangle . center ( rectangle , scratchRectangleCenterCartographic ) ;
315
- var tangentPoint = ellipsoid . cartographicToCartesian ( tangentPointCartographic , scratchRectangleCenter ) ;
316
- var tangentPlane = new EllipsoidTangentPlane ( tangentPoint , ellipsoid ) ;
317
- var plane = tangentPlane . plane ;
318
-
319
- // Corner arrangement:
320
- // N/+y
321
- // [0] [1] [2]
322
- // W/-x [7] [3] E/+x
323
- // [6] [5] [4]
324
- // S/-y
325
- // "C" refers to the central lat/long, which by default aligns with the tangent point (above).
326
- // If the rectangle spans the equator, CW and CE are instead aligned with the equator.
327
- var perimeterNW = perimeterCartographicScratch [ 0 ] ;
328
- var perimeterNC = perimeterCartographicScratch [ 1 ] ;
329
- var perimeterNE = perimeterCartographicScratch [ 2 ] ;
330
- var perimeterCE = perimeterCartographicScratch [ 3 ] ;
331
- var perimeterSE = perimeterCartographicScratch [ 4 ] ;
332
- var perimeterSC = perimeterCartographicScratch [ 5 ] ;
333
- var perimeterSW = perimeterCartographicScratch [ 6 ] ;
334
- var perimeterCW = perimeterCartographicScratch [ 7 ] ;
335
-
336
- var lonCenter = tangentPointCartographic . longitude ;
337
- var latCenter = ( rectangle . south < 0.0 && rectangle . north > 0.0 ) ? 0.0 : tangentPointCartographic . latitude ;
338
- perimeterSW . latitude = perimeterSC . latitude = perimeterSE . latitude = rectangle . south ;
339
- perimeterCW . latitude = perimeterCE . latitude = latCenter ;
340
- perimeterNW . latitude = perimeterNC . latitude = perimeterNE . latitude = rectangle . north ;
341
- perimeterSW . longitude = perimeterCW . longitude = perimeterNW . longitude = rectangle . west ;
342
- perimeterSC . longitude = perimeterNC . longitude = lonCenter ;
343
- perimeterSE . longitude = perimeterCE . longitude = perimeterNE . longitude = rectangle . east ;
344
-
345
- // Compute XY extents using the rectangle at maximum height
346
- perimeterNE . height = perimeterNC . height = perimeterNW . height = perimeterCW . height = perimeterSW . height = perimeterSC . height = perimeterSE . height = perimeterCE . height = maximumHeight ;
347
-
348
- ellipsoid . cartographicArrayToCartesianArray ( perimeterCartographicScratch , perimeterCartesianScratch ) ;
349
- tangentPlane . projectPointsToNearestOnPlane ( perimeterCartesianScratch , perimeterProjectedScratch ) ;
350
- // See the `perimeterXX` definitions above for what these are
351
- var minX = Math . min ( perimeterProjectedScratch [ 6 ] . x , perimeterProjectedScratch [ 7 ] . x , perimeterProjectedScratch [ 0 ] . x ) ;
352
- var maxX = Math . max ( perimeterProjectedScratch [ 2 ] . x , perimeterProjectedScratch [ 3 ] . x , perimeterProjectedScratch [ 4 ] . x ) ;
353
- var minY = Math . min ( perimeterProjectedScratch [ 4 ] . y , perimeterProjectedScratch [ 5 ] . y , perimeterProjectedScratch [ 6 ] . y ) ;
354
- var maxY = Math . max ( perimeterProjectedScratch [ 0 ] . y , perimeterProjectedScratch [ 1 ] . y , perimeterProjectedScratch [ 2 ] . y ) ;
355
-
356
- // Compute minimum Z using the rectangle at minimum height
357
- perimeterNE . height = perimeterNW . height = perimeterSE . height = perimeterSW . height = minimumHeight ;
358
- ellipsoid . cartographicArrayToCartesianArray ( perimeterCartographicScratch , perimeterCartesianScratch ) ;
359
- var minZ = Math . min ( Plane . getPointDistance ( plane , perimeterCartesianScratch [ 0 ] ) ,
360
- Plane . getPointDistance ( plane , perimeterCartesianScratch [ 2 ] ) ,
361
- Plane . getPointDistance ( plane , perimeterCartesianScratch [ 4 ] ) ,
362
- Plane . getPointDistance ( plane , perimeterCartesianScratch [ 6 ] ) ) ;
363
- var maxZ = maximumHeight ; // Since the tangent plane touches the surface at height = 0, this is okay
364
-
365
- return fromTangentPlaneExtents ( tangentPlane , minX , maxX , minY , maxY , minZ , maxZ , result ) ;
336
+ var minX , maxX , minY , maxY , minZ , maxZ , plane ;
337
+
338
+ if ( rectangle . width <= CesiumMath . PI ) {
339
+ // The bounding box will be aligned with the tangent plane at the center of the rectangle.
340
+ var tangentPointCartographic = Rectangle . center ( rectangle , scratchRectangleCenterCartographic ) ;
341
+ var tangentPoint = ellipsoid . cartographicToCartesian ( tangentPointCartographic , scratchRectangleCenter ) ;
342
+ var tangentPlane = new EllipsoidTangentPlane ( tangentPoint , ellipsoid ) ;
343
+ plane = tangentPlane . plane ;
344
+
345
+ // If the rectangle spans the equator, CW is instead aligned with the equator (because it sticks out the farthest at the equator).
346
+ var lonCenter = tangentPointCartographic . longitude ;
347
+ var latCenter = ( rectangle . south < 0.0 && rectangle . north > 0.0 ) ? 0.0 : tangentPointCartographic . latitude ;
348
+
349
+ // Compute XY extents using the rectangle at maximum height
350
+ var perimeterCartographicNC = Cartographic . fromRadians ( lonCenter , rectangle . north , maximumHeight , scratchPerimeterCartographicNC ) ;
351
+ var perimeterCartographicNW = Cartographic . fromRadians ( rectangle . west , rectangle . north , maximumHeight , scratchPerimeterCartographicNW ) ;
352
+ var perimeterCartographicCW = Cartographic . fromRadians ( rectangle . west , latCenter , maximumHeight , scratchPerimeterCartographicCW ) ;
353
+ var perimeterCartographicSW = Cartographic . fromRadians ( rectangle . west , rectangle . south , maximumHeight , scratchPerimeterCartographicSW ) ;
354
+ var perimeterCartographicSC = Cartographic . fromRadians ( lonCenter , rectangle . south , maximumHeight , scratchPerimeterCartographicSC ) ;
355
+
356
+ var perimeterCartesianNC = ellipsoid . cartographicToCartesian ( perimeterCartographicNC , scratchPerimeterCartesianNC ) ;
357
+ var perimeterCartesianNW = ellipsoid . cartographicToCartesian ( perimeterCartographicNW , scratchPerimeterCartesianNW ) ;
358
+ var perimeterCartesianCW = ellipsoid . cartographicToCartesian ( perimeterCartographicCW , scratchPerimeterCartesianCW ) ;
359
+ var perimeterCartesianSW = ellipsoid . cartographicToCartesian ( perimeterCartographicSW , scratchPerimeterCartesianSW ) ;
360
+ var perimeterCartesianSC = ellipsoid . cartographicToCartesian ( perimeterCartographicSC , scratchPerimeterCartesianSC ) ;
361
+
362
+ var perimeterProjectedNC = tangentPlane . projectPointToNearestOnPlane ( perimeterCartesianNC , scratchPerimeterProjectedNC ) ;
363
+ var perimeterProjectedNW = tangentPlane . projectPointToNearestOnPlane ( perimeterCartesianNW , scratchPerimeterProjectedNW ) ;
364
+ var perimeterProjectedCW = tangentPlane . projectPointToNearestOnPlane ( perimeterCartesianCW , scratchPerimeterProjectedCW ) ;
365
+ var perimeterProjectedSW = tangentPlane . projectPointToNearestOnPlane ( perimeterCartesianSW , scratchPerimeterProjectedSW ) ;
366
+ var perimeterProjectedSC = tangentPlane . projectPointToNearestOnPlane ( perimeterCartesianSC , scratchPerimeterProjectedSC ) ;
367
+
368
+ minX = Math . min ( perimeterProjectedNW . x , perimeterProjectedCW . x , perimeterProjectedSW . x ) ;
369
+ maxX = - minX ; // symmetrical
370
+
371
+ maxY = Math . max ( perimeterProjectedNW . y , perimeterProjectedNC . y ) ;
372
+ minY = Math . min ( perimeterProjectedSW . y , perimeterProjectedSC . y ) ;
373
+
374
+ // Compute minimum Z using the rectangle at minimum height, since it will be deeper than the maximum height
375
+ perimeterCartographicNW . height = perimeterCartographicSW . height = minimumHeight ;
376
+ perimeterCartesianNW = ellipsoid . cartographicToCartesian ( perimeterCartographicNW , scratchPerimeterCartesianNW ) ;
377
+ perimeterCartesianSW = ellipsoid . cartographicToCartesian ( perimeterCartographicSW , scratchPerimeterCartesianSW ) ;
378
+
379
+ minZ = Math . min ( Plane . getPointDistance ( plane , perimeterCartesianNW ) , Plane . getPointDistance ( plane , perimeterCartesianSW ) ) ;
380
+ maxZ = maximumHeight ; // Since the tangent plane touches the surface at height = 0, this is okay
381
+
382
+ return fromPlaneExtents ( tangentPlane . origin , tangentPlane . xAxis , tangentPlane . yAxis , tangentPlane . zAxis , minX , maxX , minY , maxY , minZ , maxZ , result ) ;
383
+ }
384
+
385
+ // Handle the case where rectangle width is greater than PI (wraps around more than half the ellipsoid).
386
+ var fullyAboveEquator = rectangle . south > 0.0 ;
387
+ var fullyBelowEquator = rectangle . north < 0.0 ;
388
+ var latitudeNearestToEquator = fullyAboveEquator ? rectangle . south : ( fullyBelowEquator ? rectangle . north : 0.0 ) ;
389
+ var centerLongitude = Rectangle . center ( rectangle , scratchRectangleCenterCartographic ) . longitude ;
390
+
391
+ // Plane is located at the rectangle's center longitude and the rectangle's latitude that is closest to the equator. It rotates around the Z axis.
392
+ // This results in a better fit than the obb approach for smaller rectangles, which orients with the rectangle's center normal.
393
+ var planeOrigin = Cartesian3 . fromRadians ( centerLongitude , latitudeNearestToEquator , maximumHeight , ellipsoid , scratchPlaneOrigin ) ;
394
+ planeOrigin . z = 0.0 ; // center the plane on the equator to simpify plane normal calculation
395
+ var isPole = Math . abs ( planeOrigin . x ) < CesiumMath . EPSILON10 && Math . abs ( planeOrigin . y ) < CesiumMath . EPSILON10 ;
396
+ var planeNormal = ! isPole ? Cartesian3 . normalize ( planeOrigin , scratchPlaneNormal ) : Cartesian3 . UNIT_X ;
397
+ var planeYAxis = Cartesian3 . UNIT_Z ;
398
+ var planeXAxis = Cartesian3 . cross ( planeNormal , planeYAxis , scratchPlaneXAxis ) ;
399
+ plane = Plane . fromPointNormal ( planeOrigin , planeNormal , scratchPlane ) ;
400
+
401
+ // Get the horizon point relative to the center. This will be the farthest extent in the plane's X dimension.
402
+ var horizonCartesian = Cartesian3 . fromRadians ( centerLongitude + CesiumMath . PI_OVER_TWO , latitudeNearestToEquator , maximumHeight , ellipsoid , scratchHorizonCartesian ) ;
403
+ maxX = Cartesian3 . dot ( Plane . projectPointOntoPlane ( plane , horizonCartesian , scratchHorizonProjected ) , planeXAxis ) ;
404
+ minX = - maxX ; // symmetrical
405
+
406
+ // Get the min and max Y, using the height that will give the largest extent
407
+ maxY = Cartesian3 . fromRadians ( 0.0 , rectangle . north , fullyBelowEquator ? minimumHeight : maximumHeight , ellipsoid , scratchMaxY ) . z ;
408
+ minY = Cartesian3 . fromRadians ( 0.0 , rectangle . south , fullyAboveEquator ? minimumHeight : maximumHeight , ellipsoid , scratchMinY ) . z ;
409
+
410
+ var farZ = Cartesian3 . fromRadians ( rectangle . east , latitudeNearestToEquator , maximumHeight , ellipsoid , scratchZ ) ;
411
+ minZ = Plane . getPointDistance ( plane , farZ ) ;
412
+ maxZ = 0.0 ; // plane origin starts at maxZ already
413
+
414
+ // min and max are local to the plane axes
415
+ return fromPlaneExtents ( planeOrigin , planeXAxis , planeYAxis , planeNormal , minX , maxX , minY , maxY , minZ , maxZ , result ) ;
366
416
} ;
367
417
368
418
/**
0 commit comments