def extrema(self, field, low=None, high=None, filter=None): # build a filter based on specified min/max values fil = ['%s >= %s' % (field, low)] if low != None else [] fil += ['%s <= %s' % (field, high)] if high != None else [] fil = ' AND '.join(fil) fil = Filter(fil) if len(fil) > 0 else Filter.PASS # concatenate with one passed in fil += self._filter(filter) q = DefaultQuery(self.layer.name) q.setFilter(fil._filter) min, max = None, None fit = self.layer._source.getFeatures(q).features() try: while fit.hasNext(): f = fit.next() val = f.getAttribute(field) min = val if min == None or val < min else min max = val if max == None or val > max else max finally: fit.close() return (min, max)
def extrema(self, field, low=None, high=None, filter=None): # build a filter based on specified min/max values fil = ['%s >= %s' % (field, low)] if low != None else [] fil += ['%s <= %s' % (field, high)] if high != None else [] fil = ' AND '.join(fil) fil = Filter(fil) if len(fil) > 0 else Filter.PASS # concatenate with one passed in fil += self._filter(filter) q = DefaultQuery(self.layer.name) q.setFilter(fil._filter) min, max = None, None fit = self.layer._source.getFeatures(q).features() try: while fit.hasNext(): f = fit.next() val = f.getAttribute(field) min = val if min == None or val < min else min max = val if max == None or val > max else max finally: fit.close() return (min,max)
def minmax(self, att, low=None, high=None): """ Calculates the minimum and maximum values for an attribute of the layer. *att* specifies the attribute. *low* and *high* are used to constrain the value space. """ # build a filter based on specified min/max values fil = ['%s >= %s' % (att, low)] if low != None else [] fil += ['%s <= %s' % (att, high)] if high != None else [] fil = ' AND '.join(fil) q = DefaultQuery(self.name) if len(fil) > 0: q.setFilter(Filter(fil)._filter) min, max = None, None fit = self._source.getFeatures(q).features() try: while fit.hasNext(): f = fit.next() val = f.getAttribute(att) min = val if min == None or val < min else min max = val if max == None or val > max else max finally: fit.close() return (min,max)
def cursor(self, filter=None, sort=None): """ Returns a :class:`Cursor <geoscript.layer.cursor.Cursor>` over the features of the layer. *filter* is a optional :class:`Filter <geoscript.filter.Filter>` to constrain the features iterated over. *sort* is an optional tuple or ``list`` of tuples that defined the order in which features are iterated over. The first value of each tuple is the name of a field to sort on. The second value is one of the strings 'ASC' or 'DESC', representing ascending and decending sort order respectively. >>> l = Layer() >>> from geoscript import geom >>> l.add([geom.Point(1,2)]) >>> l.add([geom.Point(3,4)]) >>> l.add([geom.Point(5,6)]) >>> l.add([geom.Point(7,8)]) >>> l.add([geom.Point(9,10)]) >>> c = l.cursor() >>> f = c.next() >>> f.geom POINT (1 2) >>> f = c.next() >>> f.geom POINT (3 4) >>> features = c.read(2) >>> len(features) 2 >>> features[0].geom POINT (5 6) >>> features[1].geom POINT (7 8) >>> features = c.read(2) >>> len(features) 1 >>> features[0].geom POINT (9 10) >>> c.close() """ f = Filter(filter) if filter else Filter.PASS q = DefaultQuery(self.name, f._filter) if sort: sort = sort if isinstance(sort, list) else [sort] sortBy = [] ff = _filterFactory for s in sort: s = s if isinstance(s, tuple) else [s, 'ASC'] sortBy.append(ff.sort(s[0], SortOrder.valueOf(s[1]))) q.setSortBy(sortBy) if self.proj: q.coordinateSystem = self.proj._crs fcol = self._source.getFeatures(q) #r = self._source.dataStore.getFeatureReader(q,Transaction.AUTO_COMMIT) return Cursor(fcol, self)
def reproject(self, prj, name=None, chunk=1000): """ Reprojects a layer. *prj* is the destination :class:`Projection <geoscript.proj.Projection>` *name* is the optional name as a ``str`` to assign to the resulting reprojected layer. This method returns a newly reprojected layer. The new layer is create within the containing workspace of the original layer. >>> from geoscript import geom >>> l = Layer() >>> l.proj = 'epsg:4326' >>> l.add([geom.Point(-111, 45.7)]) >>> >>> l2 = l.reproject('epsg:26912') >>> l2.proj.id 'EPSG:26912' >>> [f.geom.round() for f in l2.features()] [POINT (500000 5060716)] """ prj = proj.Projection(prj) name = name or Layer._newname() # reproject the schema rschema = self.schema.reproject(prj, name) # create the reprojected layer rlayer = self.workspace.create(schema=rschema) # create a query specifying that feautres should be reprojected q = DefaultQuery(self.name, Filter.PASS._filter) if self.proj: q.coordinateSystem = self.proj._crs q.coordinateSystemReproject = prj._crs # loop through features and add to new reprojeced layer fit = self._source.getFeatures(q).features() try: while True: features = readFeatures(fit, self._source.getSchema(), chunk) if features.isEmpty(): break rlayer._source.addFeatures(features) finally: fit.close() return rlayer
def reproject(self, prj, name=None): """ Reprojects a layer. *prj* is the destination :class:`Projection <geoscript.proj.Projection>` *name* is the optional name as a ``str`` to assign to the resulting reprojected layer. This method returns a newly reprojected layer. The new layer is create within the containing workspace of the original layer. >>> from geoscript import geom >>> l = Layer() >>> l.proj = 'epsg:4326' >>> l.add([geom.Point(-111, 45.7)]) >>> >>> l2 = l.reproject('epsg:26912') >>> l2.proj.id 'EPSG:26912' >>> [f.geom for f in l2.features()] [POINT (499999.42501775385 5060716.092032814)] """ prj = proj.Projection(prj) name = name or Layer._newname() # reproject the schema rschema = self.schema.reproject(prj, name) # create the reprojected layer rlayer = self.workspace.create(schema=rschema) # create a query specifying that feautres should be reproje`cted q = DefaultQuery(self.name, Filter.PASS._filter) if self.proj: q.coordinateSystem = self.proj._crs q.coordinateSystemReproject = prj._crs fc = self._source.getFeatures(q) i = fc.features() # loop through features and add to new reprojeced layer while i.hasNext(): f = feature.Feature(schema=rschema, f=i.next()) rlayer.add(f) fc.close(i) return rlayer
def count(self, filter=None): """ The number of features in the layer as an ``int``. *filter* is an optional :class:`Filter <geoscript.filter.Filter>` to constrains the counted set of features. >>> l = Layer() >>> l.count() 0 >>> from geoscript import geom >>> l.add([geom.Point(1,2)]) >>> l.add([geom.Point(3,4)]) >>> l.count() 2 >>> l.count('INTERSECTS(geom,POINT(3 4))') 1 """ f = Filter(filter) if filter else Filter.PASS count = self._source.getCount(DefaultQuery(self.name, f._filter)) if count == -1: count = 0 # calculate manually for f in self.features(filter): count += 1 return count
def cursor(self, filter=None): """ Returns a :class:`Cursor <geoscript.layer.cursor.Cursor>` over the features of the layer. *filter* is a optional :class:`Filter <geoscript.filter.Filter>` to constrain the features iterated over. >>> l = Layer() >>> from geoscript import geom >>> l.add([geom.Point(1,2)]) >>> l.add([geom.Point(3,4)]) >>> l.add([geom.Point(5,6)]) >>> l.add([geom.Point(7,8)]) >>> l.add([geom.Point(9,10)]) >>> c = l.cursor() >>> f = c.next() >>> f.geom POINT (1 2) >>> f = c.next() >>> f.geom POINT (3 4) >>> features = c.read(2) >>> len(features) 2 >>> features[0].geom POINT (5 6) >>> features[1].geom POINT (7 8) >>> features = c.read(2) >>> len(features) 1 >>> features[0].geom POINT (9 10) >>> c.close() """ f = Filter(filter) if filter else Filter.PASS q = DefaultQuery(self.name, f._filter) if self.proj: q.coordinateSystem = self.proj._crs r = self._source.dataStore.getFeatureReader(q, Transaction.AUTO_COMMIT) return Cursor(r, self)
def filter(self, fil, name=None): """ Filters the layer. *fil* is the :class:`Filter <geoscript.filter.Filter>` to apply. *name* is the optional name to assign to the new filtered layer. This method returns a newly filtered layer. The new layer is create within the containing workspace of the original layer. >>> from geoscript.feature import Schema >>> l = Layer(schema=Schema('original', [('name', str)])) >>> l.add(['foo']) >>> l.add(['bar']) >>> l.add(['baz']) >>> >>> l2 = l.filter("name = 'foo'", "filtered") >>> l2.count() 1 >>> l3 = l.filter("name LIKE 'b%'", "filtered2") >>> l3.count() 2 """ f = Filter(fil) name = name or Layer._newname() fschema = feature.Schema(name, self.schema.fields) # create the filtered layer flayer = self.workspace.create(schema=fschema) q = DefaultQuery(self.name, f._filter) # loop through features and add to new filtered layer fit = self._source.getFeatures(q).features() try: while fit.hasNext(): f = feature.Feature(schema=fschema, f=fit.next()) flayer.add(f) finally: fit.close() return flayer
def bounds(self, filter=None): """ The :class:`Bounds <geoscript.geom.Bounds>` of the layer. *filter* is an optional :class:`Filter <geoscript.filter.Filter>` to constrains the returned bounds. >>> l = Layer() >>> from geoscript import geom >>> l.add([geom.Point(1.0, 2.0)]) >>> l.add([geom.Point(3.0, 4.0)]) >>> l.bounds() (1.0, 2.0, 3.0, 4.0, EPSG:4326) >>> l.bounds('INTERSECTS(geom,POINT(3 4))') (3.0, 4.0, 3.0, 4.0, EPSG:4326) """ f = Filter(filter) if filter else Filter.PASS q = DefaultQuery(self.name, f._filter) e = self._source.getBounds(q) if not e: # try through feature collection fc = self._source.getFeatures(q) e = fc.getBounds() if e: if e.crs(): return geom.Bounds(env=e) else: return geom.Bounds(env=e, prj=self.proj) else: # calculate manually fit = self._source.getFeatures(q).features() try: bounds = geom.Bounds(prj=self.proj) if fit.hasNext(): bounds.init(fit.next().getBounds()) while fit.hasNext(): bounds.expland(fit.next().getBounds()) return bounds finally: fit.close()
def bounds(self, filter=None): """ The :class:`Bounds <geoscript.geom.Bounds>` of the layer. *filter* is an optional :class:`Filter <geoscript.filter.Filter>` to constrains the returned bounds. >>> l = Layer() >>> from geoscript import geom >>> l.add([geom.Point(1.0, 2.0)]) >>> l.add([geom.Point(3.0, 4.0)]) >>> l.bounds() (1.0, 2.0, 3.0, 4.0) >>> l.bounds('INTERSECTS(geom,POINT(3 4))') (3.0, 4.0, 3.0, 4.0) """ f = Filter(filter) if filter else Filter.PASS e = self._source.getBounds(DefaultQuery(self.name, f._filter)) if e: return geom.Bounds(env=e)