2222)
2323from tipg .filter .evaluate import to_filter
2424from tipg .filter .filters import bbox_to_wkt
25- from tipg .model import Extent , Spatial , Temporal
25+ from tipg .model import Extent
2626from tipg .settings import TableSettings , TileSettings
2727
2828tile_settings = TileSettings ()
@@ -135,9 +135,7 @@ def json_type(self) -> str:
135135 @property
136136 def is_geometry (self ) -> bool :
137137 """Returns true if this property is a geometry column."""
138- if self .geometry_type :
139- return True
140- return False
138+ return self .type in ("geometry" , "geography" )
141139
142140 @property
143141 def is_datetime (self ) -> bool :
@@ -170,26 +168,63 @@ class Collection(BaseModel):
170168 default_tms : str = tile_settings .default_tms
171169
172170 @property
173- def geometry_columns (self ):
174- """Return geometry columns."""
175- return [c for c in self .properties if c .is_geometry ]
171+ def extent (self ) -> Optional [Extent ]:
172+ """Return extent."""
173+ extent = {}
174+ if cols := self .geometry_columns :
175+ if len (cols ) == 1 :
176+ bbox = [cols [0 ].bounds ]
177+ else :
178+ minx , miny , maxx , maxy = zip (* [col .bounds for col in cols ])
179+ bbox = [
180+ [min (minx ), min (miny ), max (maxx ), max (maxy )],
181+ * [col .bounds for col in cols ],
182+ ]
183+
184+ extent ["spatial" ] = {
185+ "bbox" : bbox ,
186+ "crs" : f"http://www.opengis.net/def/crs/EPSG/0/{ cols [0 ].srid } " ,
187+ }
188+
189+ if cols := self .datetime_columns :
190+ cols = [col for col in cols if col .mindt or col .maxdt ]
191+
192+ intervals = []
193+ if len (cols ) == 1 :
194+ if cols [0 ].mindt or cols [0 ].maxdt :
195+ intervals = [[cols [0 ].mindt , cols [0 ].maxdt ]]
196+
197+ else :
198+ mindt = [col .mindt for col in cols if col .mindt ]
199+ maxdt = [col .maxdt for col in cols if col .maxdt ]
200+ intervals = [
201+ [min (mindt ), max (maxdt )],
202+ * [[col .mindt , col .maxdt ] for col in cols if col .mindt or col .maxdt ],
203+ ]
204+
205+ if intervals :
206+ extent ["temporal" ] = {"interval" : intervals }
207+
208+ if extent :
209+ return Extent (** extent )
210+
211+ return None
176212
177213 @property
178- def extent (self ):
179- """Return extent."""
180- spatial = None
181- temporal = None
182- if self .geometry_column and self .geometry_column .bounds :
183- spatial = Spatial (bbox = [self .geometry_column .bounds ], crs = self .crs )
184- if (
185- self .datetime_column
186- and self .datetime_column .mindt
187- and self .datetime_column .maxdt
188- ):
189- temporal = Temporal (
190- interval = [[self .datetime_column .mindt , self .datetime_column .maxdt ]]
191- )
192- return Extent (spatial = spatial , temporal = temporal )
214+ def bounds (self ) -> Optional [List [float ]]:
215+ """Return spatial bounds from collection extent."""
216+ if self .extent and self .extent .spatial :
217+ return self .extent .spatial .bbox [0 ]
218+
219+ return None
220+
221+ @property
222+ def dt_bounds (self ) -> Optional [List [str ]]:
223+ """Return temporal bounds from collection extent."""
224+ if self .extent and self .extent .temporal :
225+ return self .extent .temporal .interval [0 ]
226+
227+ return None
193228
194229 @property
195230 def crs (self ):
@@ -198,46 +233,43 @@ def crs(self):
198233 return f"http://www.opengis.net/def/crs/EPSG/0/{ self .geometry_column .srid } "
199234
200235 @property
201- def datetime_columns (self ):
236+ def geometry_columns (self ) -> List [Column ]:
237+ """Return geometry columns."""
238+ return [c for c in self .properties if c .is_geometry ]
239+
240+ @property
241+ def datetime_columns (self ) -> List [Column ]:
202242 """Return datetime columns."""
203243 return [c for c in self .properties if c .is_datetime ]
204244
205- def get_datetime_column (self , name : Optional [str ] = None ) -> Optional [Column ]:
206- """Return the Column for either the passed in tstz column or the first tstz column."""
207- if not self .datetime_columns :
245+ def get_geometry_column (self , name : Optional [str ] = None ) -> Optional [Column ]:
246+ """Return the name of the first geometry column."""
247+ if ( not self .geometry_columns ) or ( name and name . lower () == "none" ) :
208248 return None
209249
210250 if name is None :
211- return self .datetime_column
251+ return self .geometry_column
212252
213- for col in self .datetime_columns :
253+ for col in self .geometry_columns :
214254 if col .name == name :
215255 return col
216256
217257 return None
218258
219- def get_geometry_column (self , name : Optional [str ] = None ) -> Optional [Column ]:
220- """Return the name of the first geometry column."""
221- if ( not self .geometry_columns ) or ( name and name . lower () == "none" ) :
259+ def get_datetime_column (self , name : Optional [str ] = None ) -> Optional [Column ]:
260+ """Return the Column for either the passed in tstz column or the first tstz column."""
261+ if not self .datetime_columns :
222262 return None
223263
224264 if name is None :
225- return self .geometry_column
265+ return self .datetime_column
226266
227- for col in self .geometry_columns :
267+ for col in self .datetime_columns :
228268 if col .name == name :
229269 return col
230270
231271 return None
232272
233- @property
234- def bounds (self ) -> Optional [List [float ]]:
235- """Return bounds from collection extent."""
236- if self .extent and self .extent .spatial :
237- return self .extent .spatial .bbox [0 ]
238-
239- return None
240-
241273 @property
242274 def id_column_info (self ) -> Column : # type: ignore
243275 """Return Column for a unique identifier."""
@@ -913,6 +945,7 @@ async def get_collection_index( # noqa: C901
913945 or datetime_column is None
914946 ):
915947 datetime_column = c
948+
916949 if c .get ("type" ) in ("geometry" , "geography" ):
917950 if (
918951 table_conf .get ("geomcol" ) == c ["name" ]
0 commit comments