@@ -9,8 +9,10 @@ import {number as interpolate} from '../style-spec/util/interpolate';
9
9
import EXTENT from '../data/extent' ;
10
10
import { vec4 , mat4 , mat2 , vec2 } from 'gl-matrix' ;
11
11
import { Aabb , Frustum } from '../util/primitives.js' ;
12
+ import EdgeInsets from './edge_insets' ;
12
13
13
14
import { UnwrappedTileID , OverscaledTileID , CanonicalTileID } from '../source/tile_id' ;
15
+ import type { PaddingOptions } from './edge_insets' ;
14
16
15
17
/**
16
18
* A single transform, generally used for a single tile to be
@@ -49,6 +51,7 @@ class Transform {
49
51
_minPitch : number ;
50
52
_maxPitch : number ;
51
53
_center : LngLat ;
54
+ _edgeInsets : EdgeInsets ;
52
55
_constraining : boolean ;
53
56
_posMatrixCache : { [ string ] : Float32Array } ;
54
57
_alignedPosMatrixCache: { [ string ] : Float32Array } ;
@@ -74,6 +77,7 @@ class Transform {
74
77
this . _fov = 0.6435011087932844 ;
75
78
this . _pitch = 0 ;
76
79
this . _unmodified = true ;
80
+ this . _edgeInsets = new EdgeInsets ( ) ;
77
81
this . _posMatrixCache = { } ;
78
82
this . _alignedPosMatrixCache = { } ;
79
83
}
@@ -90,6 +94,7 @@ class Transform {
90
94
clone . _fov = this . _fov ;
91
95
clone . _pitch = this . _pitch ;
92
96
clone . _unmodified = this . _unmodified ;
97
+ clone . _edgeInsets = this . _edgeInsets . clone ( ) ;
93
98
clone . _calcMatrices ( ) ;
94
99
return clone ;
95
100
}
@@ -137,8 +142,8 @@ class Transform {
137
142
return this . tileSize * this . scale ;
138
143
}
139
144
140
- get centerPoint ( ) : Point {
141
- return this . size . _div ( 2 ) ;
145
+ get centerOffset ( ) : Point {
146
+ return this . centerPoint . _sub ( this . size . _div ( 2 ) ) ;
142
147
}
143
148
144
149
get size ( ) : Point {
@@ -204,6 +209,52 @@ class Transform {
204
209
this . _calcMatrices ( ) ;
205
210
}
206
211
212
+ get padding ( ) : PaddingOptions { return this . _edgeInsets . toJSON ( ) ; }
213
+ set padding ( padding : PaddingOptions ) {
214
+ if ( this . _edgeInsets . equals ( padding ) ) return ;
215
+ this . _unmodified = false ;
216
+ //Update edge-insets inplace
217
+ this . _edgeInsets . interpolate ( this . _edgeInsets , padding , 1 ) ;
218
+ this . _calcMatrices ( ) ;
219
+ }
220
+
221
+ /**
222
+ * The center of the screen in pixels with the top-left corner being (0,0)
223
+ * and +y axis pointing downwards. This accounts for padding.
224
+ *
225
+ * @readonly
226
+ * @type {Point }
227
+ * @memberof Transform
228
+ */
229
+ get centerPoint ( ) : Point {
230
+ return this . _edgeInsets . getCenter ( this . width , this . height ) ;
231
+ }
232
+
233
+ /**
234
+ * Returns if the padding params match
235
+ *
236
+ * @param {PaddingOptions } padding
237
+ * @returns {boolean }
238
+ * @memberof Transform
239
+ */
240
+ isPaddingEqual ( padding : PaddingOptions ) : boolean {
241
+ return this . _edgeInsets . equals ( padding ) ;
242
+ }
243
+
244
+ /**
245
+ * Helper method to upadte edge-insets inplace
246
+ *
247
+ * @param {PaddingOptions } target
248
+ * @param {number } t
249
+ * @memberof Transform
250
+ */
251
+ interpolatePadding ( start : PaddingOptions , target : PaddingOptions , t : number ) {
252
+ this . _unmodified = false ;
253
+ this . _edgeInsets . interpolate ( start , target , t ) ;
254
+ this . _constrain ( ) ;
255
+ this . _calcMatrices ( ) ;
256
+ }
257
+
207
258
/**
208
259
* Return a zoom level that will cover all tiles the transform
209
260
* @param {Object } options
@@ -281,9 +332,10 @@ class Transform {
281
332
const centerPoint = [ numTiles * centerCoord . x , numTiles * centerCoord . y , 0 ] ;
282
333
const cameraFrustum = Frustum . fromInvProjectionMatrix ( this . invProjMatrix , this . worldSize , z ) ;
283
334
284
- // No change of LOD behavior for pitch lower than 60: return only tile ids from the requested zoom level
335
+ // No change of LOD behavior for pitch lower than 60 and when there is no top padding : return only tile ids from the requested zoom level
285
336
let minZoom = options . minzoom || 0 ;
286
- if ( this . pitch <= 60.0 )
337
+ // Use 0.1 as an epsilon to avoid for explicit == 0.0 floating point checks
338
+ if ( this . pitch <= 60.0 && this . _edgeInsets . top < 0.1 )
287
339
minZoom = z ;
288
340
289
341
// There should always be a certain number of maximum zoom level tiles surrounding the center location
@@ -616,15 +668,17 @@ class Transform {
616
668
_calcMatrices ( ) {
617
669
if ( ! this . height ) return ;
618
670
619
- this . cameraToCenterDistance = 0.5 / Math . tan ( this . _fov / 2 ) * this . height ;
671
+ const halfFov = this . _fov / 2 ;
672
+ const offset = this . centerOffset ;
673
+ this . cameraToCenterDistance = 0.5 / Math . tan ( halfFov ) * this . height ;
620
674
621
- // Find the distance from the center point [width/2, height/2] to the
622
- // center top point [width/2, 0] in Z units, using the law of sines.
675
+ // Find the distance from the center point [width/2 + offset.x , height/2 + offset.y ] to the
676
+ // center top point [width/2 + offset.x , 0] in Z units, using the law of sines.
623
677
// 1 Z unit is equivalent to 1 horizontal px at the center of the map
624
678
// (the distance between[width/2, height/2] and [width/2 + 1, height/2])
625
- const halfFov = this . _fov / 2 ;
626
679
const groundAngle = Math . PI / 2 + this . _pitch ;
627
- const topHalfSurfaceDistance = Math . sin ( halfFov ) * this . cameraToCenterDistance / Math . sin ( clamp ( Math . PI - groundAngle - halfFov , 0.01 , Math . PI - 0.01 ) ) ;
680
+ const fovAboveCenter = this . _fov * ( 0.5 + offset . y / this . height ) ;
681
+ const topHalfSurfaceDistance = Math . sin ( fovAboveCenter ) * this . cameraToCenterDistance / Math . sin ( clamp ( Math . PI - groundAngle - fovAboveCenter , 0.01 , Math . PI - 0.01 ) ) ;
628
682
const point = this . point ;
629
683
const x = point . x , y = point . y ;
630
684
@@ -646,6 +700,10 @@ class Transform {
646
700
let m = new Float64Array ( 16 ) ;
647
701
mat4 . perspective ( m , this . _fov , this . width / this . height , nearZ , farZ ) ;
648
702
703
+ //Apply center of perspective offset
704
+ m [ 8 ] = - offset . x * 2 / this . width ;
705
+ m [ 9 ] = offset . y * 2 / this . height ;
706
+
649
707
mat4 . scale ( m , m , [ 1 , - 1 , 1 ] ) ;
650
708
mat4 . translate ( m , m , [ 0 , 0 , - this . cameraToCenterDistance ] ) ;
651
709
mat4 . rotateX ( m , m , this . _pitch ) ;
0 commit comments