Пример #1
0
    def update(self, feature, fields=None):
        """
    Updates a :class:`Feature <geoscript.feature.Feature>` of the layer.

    *feature* is the feature to update. *fields* is an optional ``list`` of 
    field names (as ``str`` objects) to update.
    
    >>> from geoscript import geom
    >>> l = Layer()
    >>> l.add([geom.Point(0,0)])
    >>> f = l.first()
    >>> f.geom
    POINT (0 0)
    >>> f.geom = geom.Point(1,1)
    >>> l.update(f)
    >>> f = l.first()
    >>> f.geom
    POINT (1 1)
    """
        if self.readonly:
            raise Exception('Layer is read-only')

        f = Filter("IN ('%s')" % feature.id)
        if not fields:
            fields = feature.schema.keys()

        vals = [feature._feature.getAttribute('%s' % fld) for fld in fields]
        self._source.modifyFeatures(fields, vals, f._filter)
Пример #2
0
    def histogram(self, field, nbins=10, low=None, high=None, filter=None):
        if low is None or high is None:
            minmax = self.extrema(field)
            low = minmax[0] if low is None else low
            high = minmax[1] if high is None else high

        rnge = high - low
        dx = rnge / float(nbins)
        values = [0] * nbins

        # should optimize this, we don't need a filter if a low,high is not
        # specified
        fil = Filter('%s BETWEEN %s AND %s' % (field, low, high))

        # concatenate with one specified
        fil += self._filter(filter)

        fit = self.layer._source.getFeatures(fil._filter).features()
        try:
            while fit.hasNext():
                f = fit.next()
                val = f.getAttribute(field)
                values[min(nbins - 1, int(
                    (val - low) / float(rnge) * nbins))] += 1
        finally:
            fit.close()

        keys = [round(low + x * dx, 2) for x in range(0, nbins + 1)]
        return zip([(keys[i - 1], keys[i]) for i in range(1, len(keys))],
                   values)
Пример #3
0
    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 = Query(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)
Пример #4
0
    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
Пример #5
0
    def testFilter(self):
        s = (Fill('red') + Stroke('blue')
             ).where("FOO = 'foo'") + Fill('green').where("BAR = 'bar'")
        st = s._style()

        rules = st.featureTypeStyles()[0].rules()
        assert 2 == len(rules)

        rule = rules[0]
        assert Filter("FOO = 'foo'") == Filter(rule.getFilter())
        syms = rule.symbolizers()
        assert 2 == len(syms)
        assert isinstance(syms[0], PolygonSymbolizer)
        assert isinstance(syms[1], LineSymbolizer)

        rule = rules[1]
Пример #6
0
    def cursor(self, filter=None, sort=None, hints=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

        if hints is not None:
            q.setHints(Hints(hints))

        fcol = self._source.getFeatures(q)
        #r = self._source.dataStore.getFeatureReader(q,Transaction.AUTO_COMMIT)
        return Cursor(fcol, self)
Пример #7
0
    def _filter(self, filter):
        if filter is None:
            return self.filter

        if self.filter is None:
            return filter

        return self.filter + Filter(filter)
Пример #8
0
    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
Пример #9
0
    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()
Пример #10
0
    def delete(self, filter):
        """
    Deletes features from the layer which match the specified constraint.

    *filter* is a :class:`Filter <geoscript.filter.Filter>` that specifies which features are to be deleted.

    >>> l = Layer()
    >>> from geoscript import geom
    >>> l.add([geom.Point(1,2)])
    >>> l.add([geom.Point(3,4)])
    >>> l.count()
    2
    >>> l.delete('INTERSECTS(geom, POINT(3 4))')
    >>> l.count()
    1
    """

        f = Filter(filter) if filter else Filter.FAIL
        self._source.removeFeatures(f._filter)
Пример #11
0
    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)
Пример #12
0
    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)
Пример #13
0
 def __init__(self, layer, filter=None):
     self.layer = layer
     self.filter = None if filter is None else Filter(filter)