예제 #1
0
    def test_insert_multiple(self):
        ix = GeoIndex('./test_indices', 'test_insert_multiple', int, int)
        ix.bulk_insert([(1, poly1), (2, poly2), (3, poly3)])

        x = ix.equals(poly1)
        x = list(x)
        self.assertEqual(len(x), 1)
        self.assertEqual(x[0], 1, "Geom in index for poly 1 isn't exact")
        x = ix.equals(poly2)
        x = list(x)
        self.assertEqual(len(x), 1)
        self.assertEqual(x[0], 2, "Geom in index for poly 2 isn't exact")
        x = ix.equals(poly3)
        x = list(x)
        self.assertEqual(len(x), 1)
        self.assertEqual(x[0], 3, "Geom in index for poly 3 isn't exact")

        x = ix.within(cover)
        x = list(x)
        self.assertEqual(len(x), 3)
        self.assertEqual(sorted(x), [1,2,3], "Didn't pull back all ids")

        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
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:
예제 #4
0
파일: query.py 프로젝트: JeffHeard/cera
def read_bathymetry_file():
    log.info('Building irregular-grid index from bathymetry file.  This will take awhile.')
    then = datetime.now()
    def take(k, source):
        while k>0:
            yield re.split(r'\s*', source.readline().strip())
            k -= 1

    src = open(settings.BATHYMETRY_SOURCE_FILE)
    version = src.readline().strip()
    num_edges, num_nodes = [int(k) for k in re.split(r'\s*', src.readline().strip())]

    log.info("Reading {num_edges} triangles from {num_nodes} total nodes".format(num_edges=num_edges, num_nodes=num_nodes))

    zvalues = np.empty(num_nodes+1, dtype=np.float_)
    nodes_arr = np.empty((num_nodes+1, 2), dtype=np.float_)
    triangle_arr = np.empty((num_edges+1, 3), dtype=np.int_)
    triangle_coords_arr = np.empty((num_edges+1, 3, 2), dtype=np.float_)
    #triangle_coords_arr = {}

    for node, x, y, z in take(num_nodes, src):
        node = int(node)
        nodes_arr[node][0] = float(x)
        nodes_arr[node][1] = float(y)
        zvalues[node] = z

    log.info('Built node array')

    for triangle, dim, node1, node2, node3 in take(num_edges, src):
        node1 = int(node1)
        node2 = int(node2)
        node3 = int(node3)
        triangle = int(triangle)

        triangle_arr[triangle][0] = node1
        triangle_arr[triangle][1] = node2
        triangle_arr[triangle][2] = node3

        triangle_coords_arr[triangle][0] = nodes_arr[node1]
        triangle_coords_arr[triangle][1] = nodes_arr[node2]
        triangle_coords_arr[triangle][2] = nodes_arr[node3]

        #triangle_coords_arr[triangle] = Polygon(( tuple(nodes_arr[node1]), tuple(nodes_arr[node2]), tuple(nodes_arr[node3]), tuple(nodes_arr[node1]) ), srid=4326)

    log.info('Built triangle array')

    obj = StaticArray.objects.filter(name='bathymetry', long_name='bathymetry').first() or StaticArray(name='bathymetry', long_name='bathymetry')
    obj.data = pickle.dumps(zvalues)
    obj.save()

    log.info('Saved bathymetry data')

    if os.path.exists(settings.BATHYMETRY_INDEX_FILE + '.idx'):
        os.unlink(settings.BATHYMETRY_INDEX_FILE + '.idx')
        os.unlink(settings.BATHYMETRY_INDEX_FILE + '.dat')

    index = GeoIndex(settings.BATHYMETRY_INDEX_FILE, 'bathymetry', str, int, clear=True) # bulk load

    cs = ((i, triangle_arr[i]) for i in range(1, triangle_arr.shape[0]))
    triangles = ((i, Polygon(( tuple(nodes_arr[c1]), tuple(nodes_arr[c2]), tuple(nodes_arr[c3]), tuple(nodes_arr[c1]) ), srid=4326) ) for i, (c1, c2, c3) in cs)
    index.bulk_insert(triangles)

    log.info('saved geometry index')

    np.save(settings.BATHYMETRY_INDEX_FILE + "bathymetry.nodes.npy", triangle_arr)
    log.info('saved nodes')
    np.save(settings.BATHYMETRY_INDEX_FILE + 'bathymetry.coords.npy', triangle_coords_arr)
    log.info('saved coordinates')

    index.close()
    delta = datetime.now() - then
    log.info('Finished building index in {secs} seconds.'.format(secs=delta.seconds))