1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 import logging
31 import numpy.linalg
32
33 from django.contrib.gis.geos import GEOSGeometry, Polygon, LineString
34
35 from eoxserver.core.exceptions import InternalError
36 from eoxserver.core.util.timetools import getDateTime
37 from eoxserver.services.exceptions import (
38 InvalidAxisLabelException, InvalidSubsettingException
39 )
40
41
42 logger = logging.getLogger(__name__)
43
45 - def __init__(self,
46 dim=2,
47 spatial_dim=2,
48 low=(0,0),
49 high=(0,0),
50 axis_labels=('lon','lat'),
51 srid=4326,
52 origin=(0,0),
53 offsets=((1,0),(0,1))
54 ):
55 super(RectifiedGrid, self).__init__()
56 self.dim = dim
57 self.spatial_dim = spatial_dim
58 self.low = low
59 self.high = high
60 self.axis_labels = axis_labels
61 self.srid = srid
62 self.origin = origin
63 self.offsets = offsets
64
65
66
67 - def getExtent2D(self):
68 if self.spatial_dim >= 2:
69 lowx = self.origin[0] + self.low[0] * self.offsets[0][0] + self.low[1] * self.offsets[1][0]
70 lowy = self.origin[1] + self.low[0] * self.offsets[0][1] + self.low[1] * self.offsets[1][1]
71 highx = self.origin[0] + self.high[0] * self.offsets[0][0] + self.high[1] * self.offsets[1][0]
72 highy = self.origin[1] + self.high[0] * self.offsets[0][1] + self.high[1] * self.offsets[1][1]
73
74 return (min(lowx, highx), min(lowy, highy), max(lowx, highx), max(lowy, highy))
75 else:
76 raise Exception("Cannot compute 2D extent of grid with less than 2 spatial dimensions")
77
83
85 this_minx, this_miny, this_maxx, this_maxy = self.getExtent2D()
86 that_minx, that_miny, that_maxx, that_maxy = grid.getExtent2D()
87
88 return this_minx <= that_minx and this_miny <= that_miny and \
89 this_maxx >= that_maxx and this_maxy >= that_maxy
90
92 logger.debug("EOxSRectifiedGrid.isSubGrid: Own Extent: (%f,%f,%f,%f)" % self.getExtent2D())
93 logger.debug("EOxSRectifiedGrid.isSubGrid: Containing Extent: (%f,%f,%f,%f)" % grid.getExtent2D())
94
95 if grid.contains(self):
96 this_offsets = numpy.array([self.offsets[i][0:2] for i in range(0, 2)])
97 that_offsets = numpy.array([grid.offsets[i][0:2] for i in range(0, 2)])
98
99 if not numpy.all(numpy.equal(numpy.abs(this_offsets), numpy.abs(that_offsets))):
100 return False
101 else:
102 v = numpy.linalg.solve(this_offsets, numpy.array(self.origin[0:2]) - numpy.array(grid.origin[0:2]))
103
104 logger.debug("EOxSRectifiedGrid.isSubGrid: v=(%f,%f)" % (v[0], v[1]))
105
106 EPSILON = 1e-10
107
108 if numpy.all(numpy.less(numpy.absolute((numpy.rint(v) - v) / numpy.maximum(v, 1)), EPSILON)):
109 return True
110 else:
111 return False
112 else:
113 return False
114
146
148 - def __init__(self, dimension, crs, slice_point):
152
162
164 srid, env_minx, env_miny, env_maxx, env_maxy = self._getDataFromFootprint(footprint)
165
166 if self.dimension in ("long", "Long"):
167 line = LineString((self.slice_point, env_miny), (self.slice_point, env_maxy), srid=srid)
168 elif self.dimension in ("lat", "Lat"):
169 line = LineString((env_minx, self.slice_point), (env_maxx, self.slice_point), srid=srid)
170 else:
171 raise InternalError("Can handle 2D coverages only.")
172
173
174
175 raise InternalError("BBOX not defined")
176
177 -class Trim(Subsetting):
178 - def __init__(self, dimension, crs, trim_low, trim_high):
183
185 if self.trim_low is not None and self.trim_high is not None and self.trim_high < self.trim_low:
186 raise InvalidSubsettingException("Lower bound of trim greater than upper bound")
187
188
189
190
191
192 if self.dimension not in ("phenomenonTime", "time", "t", "Long", "long", "Lat", "lat"):
193 raise InvalidAxisLabelException("Invalid axis label '%s'. Use 'phenomenonTime', 'Long' and 'Lat'." % self.dimension)
194
195 return True
196
198 srid, env_minx, env_miny, env_maxx, env_maxy = self._getDataFromFootprint(footprint)
199
200 EPSILON = 1e-10
201
202 if self.dimension in ("long", "Long"):
203 miny = env_miny
204 maxy = env_maxy
205
206 if self.trim_low is None:
207 minx = env_minx
208 else:
209 minx = max(env_minx, self.trim_low)
210
211 if self.trim_high is None:
212 maxx = env_maxx
213 else:
214 maxx = min(env_maxx, self.trim_high)
215
216 elif self.dimension in ("lat", "Lat"):
217 minx = env_minx
218 maxx = env_maxx
219
220 if self.trim_low is None:
221 miny = env_miny
222 else:
223 miny = max(env_miny, self.trim_low)
224
225 if self.trim_high is None:
226 maxy = env_maxy
227 else:
228 maxy = min(env_maxy, self.trim_high)
229
230 if maxx <= minx or maxy <= miny:
231 return GEOSGeometry("POLYGON EMPTY", srid=srid)
232 else:
233
234
235 minx = minx * (1 - EPSILON)
236 miny = miny * (1 - EPSILON)
237 maxx = maxx * (1 + EPSILON)
238 maxy = maxy * (1 + EPSILON)
239
240 poly = Polygon.from_bbox((minx, miny, maxx, maxy))
241 poly.srid = srid
242
243 return poly
244
249
254
255
256
257
258
259
260
261
262
263
264
265
266
267