1
+ import math
1
2
import numpy as np
2
3
3
4
from matplotlib import _api , rcParams
@@ -73,7 +74,7 @@ def _set_lim_and_transforms(self):
73
74
# This is the transform for longitude ticks.
74
75
self ._xaxis_pretransform = \
75
76
Affine2D () \
76
- .scale (1 , self ._longitude_cap * 2 ) \
77
+ .scale (1 , self ._longitude_cap * 2.0 ) \
77
78
.translate (0 , - self ._longitude_cap )
78
79
self ._xaxis_transform = \
79
80
self ._xaxis_pretransform + \
@@ -88,7 +89,7 @@ def _set_lim_and_transforms(self):
88
89
Affine2D ().translate (0 , - 4 )
89
90
90
91
# This is the transform for latitude ticks.
91
- yaxis_stretch = Affine2D ().scale (np .pi * 2 , 1 ).translate (- np .pi , 0 )
92
+ yaxis_stretch = Affine2D ().scale (np .pi * 2.0 , 1 ).translate (- np .pi , 0 )
92
93
yaxis_space = Affine2D ().scale (1 , 1.1 )
93
94
self ._yaxis_transform = \
94
95
yaxis_stretch + \
@@ -109,7 +110,7 @@ def _set_lim_and_transforms(self):
109
110
def _get_affine_transform (self ):
110
111
transform = self ._get_core_transform (1 )
111
112
xscale , _ = transform .transform ((np .pi , 0 ))
112
- _ , yscale = transform .transform ((0 , np .pi / 2 ))
113
+ _ , yscale = transform .transform ((0 , 0.5 * np .pi ))
113
114
return Affine2D () \
114
115
.scale (0.5 / xscale , 0.5 / yscale ) \
115
116
.translate (0.5 , 0.5 )
@@ -261,14 +262,16 @@ def transform_non_affine(self, ll):
261
262
longitude , latitude = ll .T
262
263
263
264
# Pre-compute some values
264
- half_long = longitude / 2.0
265
- cos_latitude = np .cos (latitude )
265
+ half_long = 0.5 * longitude
266
+ cos_half = np .cos (half_long )
267
+ sin_half = np .cos (half_long )
268
+ cos_latitude = cos_half * cos_half - sin_half * sin_half
266
269
267
- alpha = np .arccos (cos_latitude * np . cos ( half_long ) )
270
+ alpha = np .arccos (cos_latitude * cos_half )
268
271
sinc_alpha = np .sinc (alpha / np .pi ) # np.sinc is sin(pi*x)/(pi*x).
269
272
270
- x = (cos_latitude * np . sin ( half_long ) ) / sinc_alpha
271
- y = np . sin (latitude ) / sinc_alpha
273
+ x = (cos_latitude * sin_half ) / sinc_alpha
274
+ y = 2.0 * sin_half * cos_half / sinc_alpha # sin(lat ) / sinc_alpha
272
275
return np .column_stack ([x , y ])
273
276
274
277
def inverted (self ):
@@ -287,7 +290,7 @@ def inverted(self):
287
290
return AitoffAxes .AitoffTransform (self ._resolution )
288
291
289
292
def __init__ (self , * args , ** kwargs ):
290
- self ._longitude_cap = np . pi / 2.0
293
+ self ._longitude_cap = 0.5 * np . pi
291
294
super ().__init__ (* args , ** kwargs )
292
295
self .set_aspect (0.5 , adjustable = 'box' , anchor = 'C' )
293
296
self .cla ()
@@ -305,12 +308,14 @@ class HammerTransform(_GeoTransform):
305
308
def transform_non_affine (self , ll ):
306
309
# docstring inherited
307
310
longitude , latitude = ll .T
308
- half_long = longitude / 2.0
309
- cos_latitude = np .cos (latitude )
310
- sqrt2 = np .sqrt (2.0 )
311
- alpha = np .sqrt (1.0 + cos_latitude * np .cos (half_long ))
312
- x = (2.0 * sqrt2 ) * (cos_latitude * np .sin (half_long )) / alpha
313
- y = (sqrt2 * np .sin (latitude )) / alpha
311
+ half_long = 0.5 * longitude
312
+ cos_half = np .cos (half_long )
313
+ sin_half = np .cos (half_long )
314
+ cos_latitude = cos_half * cos_half - sin_half * sin_half
315
+ sqrt2 = math .sqrt (2.0 )
316
+ alpha = np .sqrt (1.0 + cos_latitude * cos_half )
317
+ x = (2.0 * sqrt2 * cos_latitude * sin_half ) / alpha
318
+ y = (2.0 * sqrt2 * cos_half * sin_half ) / alpha # sin(lat)
314
319
return np .column_stack ([x , y ])
315
320
316
321
def inverted (self ):
@@ -323,16 +328,16 @@ def transform_non_affine(self, xy):
323
328
# docstring inherited
324
329
x , y = xy .T
325
330
z = np .sqrt (1 - (x / 4 ) ** 2 - (y / 2 ) ** 2 )
326
- longitude = 2 * np .arctan ((z * x ) / (2 * (2 * z ** 2 - 1 )))
327
- latitude = np .arcsin (y * z )
331
+ longitude = 2.0 * np .arctan ((z * x ) / (2 * (2 * z ** 2 - 1 )))
332
+ latitude = np .arcsin (y * z )
328
333
return np .column_stack ([longitude , latitude ])
329
334
330
335
def inverted (self ):
331
336
# docstring inherited
332
337
return HammerAxes .HammerTransform (self ._resolution )
333
338
334
339
def __init__ (self , * args , ** kwargs ):
335
- self ._longitude_cap = np . pi / 2.0
340
+ self ._longitude_cap = 0.5 * np . pi
336
341
super ().__init__ (* args , ** kwargs )
337
342
self .set_aspect (0.5 , adjustable = 'box' , anchor = 'C' )
338
343
self .cla ()
@@ -351,12 +356,12 @@ def transform_non_affine(self, ll):
351
356
# docstring inherited
352
357
def d (theta ):
353
358
delta = (- (theta + np .sin (theta ) - pi_sin_l )
354
- / (1 + np .cos (theta )))
359
+ / (1.0 + np .cos (theta )))
355
360
return delta , np .abs (delta ) > 0.001
356
361
357
362
longitude , latitude = ll .T
358
363
359
- clat = np .pi / 2 - np .abs (latitude )
364
+ clat = 0.5 * np .pi - np .abs (latitude )
360
365
ihigh = clat < 0.087 # within 5 degrees of the poles
361
366
ilow = ~ ihigh
362
367
aux = np .empty (latitude .shape , dtype = float )
@@ -368,16 +373,17 @@ def d(theta):
368
373
while np .any (large_delta ):
369
374
theta [large_delta ] += delta [large_delta ]
370
375
delta , large_delta = d (theta )
371
- aux [ilow ] = theta / 2
376
+ aux [ilow ] = 0.5 * theta
372
377
373
378
if ihigh .any (): # Taylor series-based approx. solution
374
379
e = clat [ihigh ]
375
- d = 0.5 * ( 3 * np .pi * e ** 2 ) ** ( 1.0 / 3 )
376
- aux [ihigh ] = (np .pi / 2 - d ) * np .sign (latitude [ihigh ])
380
+ d = 0.5 * np . cbrt ( 3.0 * np .pi * e ** 2 )
381
+ aux [ihigh ] = (0.5 * np .pi - d ) * np .sign (latitude [ihigh ])
377
382
378
383
xy = np .empty (ll .shape , dtype = float )
379
- xy [:, 0 ] = (2.0 * np .sqrt (2.0 ) / np .pi ) * longitude * np .cos (aux )
380
- xy [:, 1 ] = np .sqrt (2.0 ) * np .sin (aux )
384
+ sqrt2 = math .sqrt (2 )
385
+ xy [:, 0 ] = (2.0 * sqrt2 / np .pi ) * longitude * np .cos (aux )
386
+ xy [:, 1 ] = sqrt2 * np .sin (aux )
381
387
382
388
return xy
383
389
@@ -392,9 +398,10 @@ def transform_non_affine(self, xy):
392
398
x , y = xy .T
393
399
# from Equations (7, 8) of
394
400
# https://mathworld.wolfram.com/MollweideProjection.html
395
- theta = np .arcsin (y / np .sqrt (2 ))
396
- longitude = (np .pi / (2 * np .sqrt (2 ))) * x / np .cos (theta )
397
- latitude = np .arcsin ((2 * theta + np .sin (2 * theta )) / np .pi )
401
+ sqrt2 = math .sqrt (2.0 )
402
+ theta = np .arcsin (y / sqrt2 )
403
+ longitude = (np .pi / (2.0 * sqrt2 )) * x / np .cos (theta )
404
+ latitude = np .arcsin ((2.0 * theta + np .sin (2.0 * theta )) / np .pi )
398
405
return np .column_stack ([longitude , latitude ])
399
406
400
407
def inverted (self ):
@@ -434,15 +441,17 @@ def transform_non_affine(self, ll):
434
441
clat = self ._center_latitude
435
442
cos_lat = np .cos (latitude )
436
443
sin_lat = np .sin (latitude )
444
+ cos_clat = np .cos (clat )
445
+ sin_clat = np .sin (clat )
437
446
diff_long = longitude - clong
438
447
cos_diff_long = np .cos (diff_long )
439
448
440
449
inner_k = np .maximum ( # Prevent divide-by-zero problems
441
- 1 + np . sin ( clat ) * sin_lat + np . cos ( clat ) * cos_lat * cos_diff_long ,
450
+ 1.0 + sin_clat * sin_lat + cos_clat * cos_lat * cos_diff_long ,
442
451
1e-15 )
443
- k = np .sqrt (2 / inner_k )
452
+ k = np .sqrt (2.0 / inner_k )
444
453
x = k * cos_lat * np .sin (diff_long )
445
- y = k * (np . cos ( clat ) * sin_lat - np . sin ( clat ) * cos_lat * cos_diff_long )
454
+ y = k * (cos_clat * sin_lat - sin_clat * cos_lat * cos_diff_long )
446
455
447
456
return np .column_stack ([x , y ])
448
457
@@ -466,7 +475,7 @@ def transform_non_affine(self, xy):
466
475
clong = self ._center_longitude
467
476
clat = self ._center_latitude
468
477
p = np .maximum (np .hypot (x , y ), 1e-9 )
469
- c = 2 * np .arcsin (0.5 * p )
478
+ c = 2.0 * np .arcsin (0.5 * p )
470
479
sin_c = np .sin (c )
471
480
cos_c = np .cos (c )
472
481
@@ -485,7 +494,7 @@ def inverted(self):
485
494
self ._resolution )
486
495
487
496
def __init__ (self , * args , center_longitude = 0 , center_latitude = 0 , ** kwargs ):
488
- self ._longitude_cap = np . pi / 2
497
+ self ._longitude_cap = 0.5 * np . pi
489
498
self ._center_longitude = center_longitude
490
499
self ._center_latitude = center_latitude
491
500
super ().__init__ (* args , ** kwargs )
0 commit comments