Пример #1
0
    def test_insert_one(self):
        ix = GeoIndex('./test_indices', 'test_insert_one', int, int)
        ix.insert(1L, poly1)

        x = ix.within(cover)
        x = list(x)
        self.assertEqual(len(x), 1)
        self.assertEqual(x[0], 1L, "Geom in index doesn't overlap")

        x = ix.equals(poly1)
        x = list(x)
        self.assertEqual(len(x), 1)
        self.assertEqual(x[0], 1L, "Geom in index isn't exact")

        ix.drop()
Пример #2
0
    def test_uniquity(self):
        ix = GeoIndex('./test_indices', 'test_unique', int, int)

        ix.insert(1L, poly1)
        self.assertTrue(ix.exists(1))

        try:
            self.assertRaises(IntegrityError, ix.insert(1, poly1))
        except IntegrityError:
            pass

        try:
            self.assertRaises(IntegrityError, ix.bulk_insert([(1,poly1), (1,poly1)]))
        except IntegrityError:
            pass

        ix.drop()
Пример #3
0
    def test_delete_id(self):
        ix = GeoIndex('./test_indices', 'test_delete_id', int, int)

        ix.insert(1L, poly1)
        ix.insert(2L, poly2)
        ix.insert(3L, poly3)

        ix.delete(1)


        x = ix.within(cover)
        x = list(x)
        self.assertEqual(len(x), 2, "didn't drop one like we should have")
        self.assertEqual(sorted(x), [2,3], "Didn't pull back all ids")

        ix.bulk_delete([2,3])
        x = ix.within(cover)
        x = list(x)
        self.assertEqual(len(x) ,0)

        ix.drop()
Пример #4
0
    def test_multiple_indexes(self):
        ix1 = GeoIndex('./test_indices', 'test_multiple_indexes', int, int)
        ix2 = GeoIndex('./test_indices', 'test_multiple_indexes', int, int)

        ix1.insert(1L, poly1)
        ix2.insert(2L, poly2)
        ix1.insert(3L, poly3)

        x = ix1.intersects(cover)
        x = list(x)
        y = ix2.intersects(cover)
        y = list(y)

        self.assertEqual(len(x), 3, "Didn't pull back all ids with first index")
        self.assertEqual(sorted(x), [1,2,3], "Didn't pull back all ids with first index")
        self.assertEqual(len(y), 3, "didn't pull back all ids with second index")
        self.assertEqual(sorted(y), [1,2,3], "Didn't pull back all ids with second index")

        ix1.drop()
        ix2.drop()
Пример #5
0
class GeoJSONCollection(object, UserDict.DictMixin):
    def _normalize_srs(self, fcrs):
        # untested, but finished

        crs = None
        reproject = False # assume we're not going to reproject unless proven otherwise

        try: # look for a CRS in the feature or featurecollection
            if (isinstance(fcrs, str) or isinstance(fcrs, unicode)) :  # if it's a string, we can check to see if it matches the original.
                crs = SpatialReference(str(fcrs))                                                              # if it doesn't, set a new one
                reproject = True                                                                          # and reproject
            elif isinstance(fcrs, int) and fcrs == self.srid:
                reproject = False
            elif not isinstance(fcrs, SpatialReference):                                                  # if it's not a string, make sure it's a SpatialReference object.
                raise ValidationError("feature's 'crs' cannot be interpreted as a SpatialReference by OGR") # otherwise whine.
            else:
                crs = fcrs
        except OGRException as e:
            raise ValidationError("feature's 'crs' cannot be interpreted as a SpatialReference by OGR:\n"+ str(e) + "\n" + fcrs)

        return reproject, crs

    def _get_real_geometry(self, feature):
        # untested, but finished
        # start by assuming we're just using our own CRS.
        fc = feature['type'] == 'FeatureCollection' # if we have a feature collection we have to iterate over all the features
        crs, reproject = self._normalize_srs(feature['crs']) if 'crs' in feature else (self.srid, False)

        if fc: # if we have a feature collection, collect the geometry
            if reproject:                                        # if we have to reproject
                for i, f in enumerate(feature['features']):      # iterate over all the features
                    geometry = f['geometry'] if isinstance(f['geometry'], GEOSGeometry) else GEOSGeometry(json.dumps(f['geometry']))
                    geometry.transform(self.srid)              # transform their geometry in place
                    f['geometry'] = json.loads(geometry.json) # and change the geometry itself in the data
                feature['crs'] = self.srid
            geometry = (GEOSGeometry(json.dumps(fs['geometry']), srid=crs) for fs in feature['features'])
        else: # we have only a single feature
            geometry = feature['geometry'] if isinstance(feature['geometry'], GEOSGeometry) else GEOSGeometry(json.dumps(feature['geometry']))
            if reproject:
                geometry.transform(self.srid)                    # reproject the feature if necessary
                feature['geometry'] = json.loads(geometry.json) # and change the geometry itself in the data.
                feature['crs'] = self.srid

        return fc, feature, geometry                            # return a tuple of featurecollection:bool, the original dict, and the GEOS geometry.

    def __init__(self, db, collection, index_path=None, srid=None, fc=None, clear=False):
        # pull collection metadata from the database if it exists
        if clear:
            GeoIndex(index_path, collection, _from_objectid, _to_objectid, srid=srid if srid else 4326).drop()
            db[collection].drop()
            db.geojson__meta.remove(collection)

        self.collection_metadata = db.geojson__meta
        self.meta = db.geojson__meta.find_one(collection) or {
            'srid' : srid,
            'index_path' : index_path,
            '_id' : collection,
            'properties' : {}
        }
        self.collection_metadata.save(self.meta)
        if collection not in db.collection_names():
            db.create_collection(collection)


        if fc and not self.meta['srid'] and 'crs' in fc:
            self.srid = fc['crs'] # however this means crs must conform to an integer srid.  This is not preferred by the spec but necessary here.

        # instantiate GeoIndex for collection
        self.index = GeoIndex(index_path, collection, _from_objectid, _to_objectid, srid=srid if srid else 4326)
        self.coll = db[collection]

        if fc:
            self.insert_features(fc, replace=True)

    @property
    def srid(self):
        return self.meta['srid']

    @srid.setter
    def srid(self, srid):
        self.meta['srid'] = srid
        self.collection_metadata.save(self.meta)

    def __setitem__(self, key, value):
        self.meta['properties'][key] = value
        self.collection_metadata.save(self.meta)

    def __getitem__(self, key):
        return self.meta['properties'][key]

    def __delitem__(self, key):
        del self.meta['properties'][key]
        self.collection_metadata.save(self.meta)

    def keys(self):
        return self.meta['properties'].keys()

    def drop(self):
        if hasattr(self, 'index'):
            self.index.drop()

        if hasattr(self, 'coll'):
            self.coll.drop()

        if hasattr(self, 'meta'):
            self.collection_metadata.remove(self.meta['_id'])

    def insert_features(self, fc, replace=False, **kwargs):

        if(hasattr(fc, 'keys')):
            is_fc, fc, geometry = self._get_real_geometry(fc)

            if is_fc:
                features = fc['features']
                del fc['features']

                if 'crs' in fc:
                    del fc['crs']
                fc['crs'] = self.srid

                if replace:
                    self.meta['properties'] = fc
                    self.collection_metadata.save(self.meta)
                else:
                    for k, v in filter(lambda (x,y): x not in ('crs','type'), fc.items()):
                        if k not in self:
                            self[k] = v
                        elif v != self[k]:
                            raise KeyError("{k} already in feature collection and is not equal")

                fcid = self.meta['_id']
                for f in features:
                    f['_parent'] = fcid

                try:
                    ids = self.coll.insert(features)
                except AutoReconnect:
                    ids = []
                    for feature in features:
                        try:
                            i = self.coll.insert(feature)
                            ids.append(i)
                        except AutoReconnect:
                            log.error('feature {f} wouldnt insert'.format(f=len(ids)))


                self.index.bulk_insert(zip(ids, geometry))
            else:
                oid = self.coll.insert(fc, **kwargs)
                self.index.insert(oid, geometry)
        else: