3232import itertools
3333import logging
3434
35+ from shapely import box , Point
36+
3537from pygeoapi .provider .base import (BaseProvider , ProviderInvalidQueryError ,
3638 ProviderItemNotFoundError ,
3739 ProviderQueryError )
@@ -99,6 +101,7 @@ def _load(self, offset=0, limit=10, resulttype='results',
99101 :param limit: number of records to return (default 10)
100102 :param datetime_: temporal (datestamp or extent)
101103 :param resulttype: return results or hit limit (default results)
104+ :param bbox: bounding box [minx,miny,maxx,maxy]
102105 :param properties: list of tuples (name, value)
103106 :param select_properties: list of property names
104107 :param skip_geometry: bool of whether to skip geometry (default False)
@@ -120,6 +123,7 @@ def _load(self, offset=0, limit=10, resulttype='results',
120123 with open (self .data ) as ff :
121124 LOGGER .debug ('Serializing DictReader' )
122125 data_ = csv .DictReader (ff )
126+
123127 if properties :
124128 for prop in properties :
125129 if prop [0 ] not in data_ .fieldnames :
@@ -131,10 +135,17 @@ def _load(self, offset=0, limit=10, resulttype='results',
131135 lambda p : all (
132136 [p [prop [0 ]] == prop [1 ] for prop in properties ]), data_ )
133137
138+ if bbox :
139+ LOGGER .debug ('processing bbox parameter' )
140+ data_ = filter (
141+ lambda f : all (
142+ [self ._intersects (f , bbox )]), data_ )
143+
134144 if resulttype == 'hits' :
135145 LOGGER .debug ('Returning hits only' )
136146 feature_collection ['numberMatched' ] = len (list (data_ ))
137147 return feature_collection
148+
138149 LOGGER .debug ('Slicing CSV rows' )
139150 for row in itertools .islice (data_ , 0 , None ):
140151 try :
@@ -193,6 +204,24 @@ def _load(self, offset=0, limit=10, resulttype='results',
193204
194205 return feature_collection
195206
207+ def _intersects (self , data , bbox ):
208+ """
209+ Helper function to evaluate point geometry intersection with a bbox
210+
211+ :param geometry: `dict` of CSV row
212+ :param bbox: `list` of bbox
213+
214+ :returns: `bool` of whether point geometry intersects with bbox
215+ """
216+
217+ if None in [data .get (self .geometry_x ), data .get (self .geometry_y )]:
218+ return True
219+
220+ point = Point (data [self .geometry_x ], data [self .geometry_y ])
221+ bbox2 = box (* bbox )
222+
223+ return bbox2 .intersects (point )
224+
196225 @crs_transform
197226 def query (self , offset = 0 , limit = 10 , resulttype = 'results' ,
198227 bbox = [], datetime_ = None , properties = [], sortby = [],
@@ -215,7 +244,7 @@ def query(self, offset=0, limit=10, resulttype='results',
215244 """
216245
217246 return self ._load (offset , limit , resulttype ,
218- properties = properties ,
247+ bbox = bbox , properties = properties ,
219248 select_properties = select_properties ,
220249 skip_geometry = skip_geometry )
221250
0 commit comments