@@ -271,16 +271,16 @@ def transform(self, ll):
271271 cos_latitude = np .cos (latitude )
272272
273273 alpha = np .arccos (cos_latitude * np .cos (half_long ))
274- # Mask this array, or we'll get divide-by-zero errors
274+ # Mask this array or we'll get divide-by-zero errors
275275 alpha = ma .masked_where (alpha == 0.0 , alpha )
276+ # The numerators also need to be masked so that masked
277+ # division will be invoked.
276278 # We want unnormalized sinc. numpy.sinc gives us normalized
277279 sinc_alpha = ma .sin (alpha ) / alpha
278280
279- x = (cos_latitude * np .sin (half_long )) / sinc_alpha
280- y = (np .sin (latitude ) / sinc_alpha )
281- x .set_fill_value (0.0 )
282- y .set_fill_value (0.0 )
283- return np .concatenate ((x .filled (), y .filled ()), 1 )
281+ x = (cos_latitude * ma .sin (half_long )) / sinc_alpha
282+ y = (ma .sin (latitude ) / sinc_alpha )
283+ return np .concatenate ((x .filled (0 ), y .filled (0 )), 1 )
284284 transform .__doc__ = Transform .transform .__doc__
285285
286286 transform_non_affine = transform
@@ -436,23 +436,35 @@ def __init__(self, resolution):
436436 def transform (self , ll ):
437437 def d (theta ):
438438 delta = - (theta + np .sin (theta ) - pi_sin_l ) / (1 + np .cos (theta ))
439- return delta , abs (delta ) > 0.001
439+ return delta , np . abs (delta ) > 0.001
440440
441- longitude = ll [:, 0 :1 ]
442- latitude = ll [:, 1 :2 ]
441+ longitude = ll [:, 0 ]
442+ latitude = ll [:, 1 ]
443+
444+ clat = np .pi / 2 - np .abs (latitude )
445+ ihigh = clat < 0.087 # within 5 degrees of the poles
446+ ilow = ~ ihigh
447+ aux = np .empty (latitude .shape , dtype = np .float )
443448
444- pi_sin_l = np .pi * np .sin (latitude )
445- theta = 2.0 * latitude
446- delta , large_delta = d (theta )
447- while np .any (large_delta ):
448- theta += np .where (large_delta , delta , 0 )
449+ if ilow .any (): # Newton-Raphson iteration
450+ pi_sin_l = np .pi * np .sin (latitude [ilow ])
451+ theta = 2.0 * latitude [ilow ]
449452 delta , large_delta = d (theta )
450- aux = theta / 2
453+ while np .any (large_delta ):
454+ theta [large_delta ] += delta [large_delta ]
455+ delta , large_delta = d (theta )
456+ aux [ilow ] = theta / 2
451457
452- x = (2.0 * np .sqrt (2.0 ) * longitude * np .cos (aux )) / np .pi
453- y = (np .sqrt (2.0 ) * np .sin (aux ))
458+ if ihigh .any (): # Taylor series-based approx. solution
459+ e = clat [ihigh ]
460+ d = 0.5 * (3 * np .pi * e ** 2 ) ** (1.0 / 3 )
461+ aux [ihigh ] = (np .pi / 2 - d ) * np .sign (latitude [ihigh ])
454462
455- return np .concatenate ((x , y ), 1 )
463+ xy = np .empty (ll .shape , dtype = np .float )
464+ xy [:,0 ] = (2.0 * np .sqrt (2.0 ) / np .pi ) * longitude * np .cos (aux )
465+ xy [:,1 ] = np .sqrt (2.0 ) * np .sin (aux )
466+
467+ return xy
456468 transform .__doc__ = Transform .transform .__doc__
457469
458470 transform_non_affine = transform
0 commit comments