@@ -40,12 +40,47 @@ def _search_time_index(field: Field, time: datetime):
4040 return np .atleast_1d (tau ), np .atleast_1d (ti )
4141
4242
43+ def curvilinear_point_in_cell (grid , y : np .ndarray , x : np .ndarray , yi : np .ndarray , xi : np .ndarray ):
44+ xsi = eta = - 1.0 * np .ones (len (x ), dtype = float )
45+ invA = np .array (
46+ [
47+ [1 , 0 , 0 , 0 ],
48+ [- 1 , 1 , 0 , 0 ],
49+ [- 1 , 0 , 0 , 1 ],
50+ [1 , - 1 , 1 , - 1 ],
51+ ]
52+ )
53+
54+ px = np .array ([grid .lon [yi , xi ], grid .lon [yi , xi + 1 ], grid .lon [yi + 1 , xi + 1 ], grid .lon [yi + 1 , xi ]])
55+ py = np .array ([grid .lat [yi , xi ], grid .lat [yi , xi + 1 ], grid .lat [yi + 1 , xi + 1 ], grid .lat [yi + 1 , xi ]])
56+
57+ a , b = np .dot (invA , px ), np .dot (invA , py )
58+ aa = a [3 ] * b [2 ] - a [2 ] * b [3 ]
59+ bb = a [3 ] * b [0 ] - a [0 ] * b [3 ] + a [1 ] * b [2 ] - a [2 ] * b [1 ] + x * b [3 ] - y * a [3 ]
60+ cc = a [1 ] * b [0 ] - a [0 ] * b [1 ] + x * b [1 ] - y * a [1 ]
61+ det2 = bb * bb - 4 * aa * cc
62+
63+ with np .errstate (divide = "ignore" , invalid = "ignore" ):
64+ det = np .where (det2 > 0 , np .sqrt (det2 ), eta )
65+ eta = np .where (abs (aa ) < 1e-12 , - cc / bb , np .where (det2 > 0 , (- bb + det ) / (2 * aa ), eta ))
66+
67+ xsi = np .where (
68+ abs (a [1 ] + a [3 ] * eta ) < 1e-12 ,
69+ ((y - py [0 ]) / (py [1 ] - py [0 ]) + (y - py [3 ]) / (py [2 ] - py [3 ])) * 0.5 ,
70+ (x - a [0 ] - a [2 ] * eta ) / (a [1 ] + a [3 ] * eta ),
71+ )
72+
73+ is_in_cell = np .where ((xsi >= 0 ) & (xsi <= 1 ) & (eta >= 0 ) & (eta <= 1 ), 1 , 0 )
74+
75+ return is_in_cell
76+
77+
4378def _search_indices_curvilinear_2d (
4479 grid : XGrid , y : float , x : float , yi_guess : int | None = None , xi_guess : int | None = None
4580): # TODO fix typing instructions to make clear that y, x etc need to be ndarrays
4681 yi , xi = yi_guess , xi_guess
4782 if yi is None or xi is None :
48- yi , xi = grid .get_spatial_hash ().query (y , x )
83+ yi , xi = grid .get_spatial_hash ().query (y , x , curvilinear_point_in_cell )
4984
5085 xsi = eta = - 1.0 * np .ones (len (x ), dtype = float )
5186 invA = np .array (
0 commit comments