From 57631a8931c434bf8f27cb18e94aff3b6005a14c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Mercader?= Date: Fri, 18 Mar 2011 17:42:43 +0000 Subject: [PATCH] Use the projection from harvested documents. Add a configure option to define the database projection --- ckanext/harvest/controllers/api.py | 49 +++++----------- ckanext/harvest/lib/__init__.py | 93 ++++++++++++++++++++++++------ ckanext/harvest/model/__init__.py | 2 +- 3 files changed, 91 insertions(+), 53 deletions(-) diff --git a/ckanext/harvest/controllers/api.py b/ckanext/harvest/controllers/api.py index cee5b73..a0d119d 100644 --- a/ckanext/harvest/controllers/api.py +++ b/ckanext/harvest/controllers/api.py @@ -4,27 +4,14 @@ from ckan.lib.base import c, g, request, \ response, session, render, config, abort, redirect from ckan.controllers.rest import BaseApiController - from ckan.model import Session +from ckanext.harvest.lib import get_srid + class ApiController(BaseApiController): - def _get_srid(self,crs): - """Returns the SRID for the provided CRS definition - The CRS can be defined in the following formats - - urn:ogc:def:crs:EPSG::4258 - - EPSG:4258 - - 4258 - """ - - if ':' in crs: - crs = crs.split(':') - srid = crs[len(crs)-1] - else: - srid = crs - - return int(srid) - + + db_srid = int(config.get('ckan.harvesting.srid', '4258')) def spatial_query(self): if not 'bbox' in request.params: @@ -39,13 +26,12 @@ class ApiController(BaseApiController): maxx = float(bbox[2]) maxy = float(bbox[3]) - params = {'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy} - - if 'crs' in request.params: + params = {'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy,'db_srid':self.db_srid} + + srid = get_srid(request.params.get('crs')) if 'crs' in request.params else None + if srid and srid != self.db_srid: # The input bounding box is defined in another projection, we need # to transform it - srid = self._get_srid(request.params['crs']) - statement = """SELECT package_id FROM package_extent WHERE ST_Intersects( ST_Transform( @@ -54,7 +40,7 @@ class ApiController(BaseApiController): %(maxx)s %(maxy)s, %(minx)s %(maxy)s, %(minx)s %(miny)s))',%(srid)s), - 4258) + %(db_srid)s) ,the_geom)""" params.update({'srid': srid}) else: @@ -64,17 +50,14 @@ class ApiController(BaseApiController): %(maxx)s %(miny)s, %(maxx)s %(maxy)s, %(minx)s %(maxy)s, - %(minx)s %(miny)s))',4258), + %(minx)s %(miny)s))',%(db_srid)s), the_geom)""" - try: - conn = Session.connection() - rows = conn.execute(statement,params) - ids = [row['package_id'] for row in rows] - - output = dict(count=len(ids),results=ids) + conn = Session.connection() + rows = conn.execute(statement,params) + ids = [row['package_id'] for row in rows] + + output = dict(count=len(ids),results=ids) - return self._finish_ok(output) - except: - abort(500) + return self._finish_ok(output) diff --git a/ckanext/harvest/lib/__init__.py b/ckanext/harvest/lib/__init__.py index 596579a..7fda58d 100644 --- a/ckanext/harvest/lib/__init__.py +++ b/ckanext/harvest/lib/__init__.py @@ -1,53 +1,108 @@ from ckan.model import Session +from ckan.lib.base import config + log = __import__("logging").getLogger(__name__) +def get_srid(crs): + """Returns the SRID for the provided CRS definition + The CRS can be defined in the following formats + - urn:ogc:def:crs:EPSG::4258 + - EPSG:4258 + - 4258 + """ + + if ':' in crs: + crs = crs.split(':') + srid = crs[len(crs)-1] + else: + srid = crs + + return int(srid) + def save_extent(package,extent=False): '''Updates the package extent in the package_extent geometry column If no extent provided (as a dict with minx,miny,maxx,maxy and srid keys), the values stored in the package extras are used''' - #TODO: configure SRID + + db_srid = int(config.get('ckan.harvesting.srid', '4258')) conn = Session.connection() + + srid = None if extent: minx = extent['minx'] miny = extent['miny'] maxx = extent['maxx'] maxy = extent['maxy'] + if 'srid' in extent: + srid = extent['srid'] else: minx = float(package.extras.get('bbox-east-long')) miny = float(package.extras.get('bbox-south-lat')) maxx = float(package.extras.get('bbox-west-long')) maxy = float(package.extras.get('bbox-north-lat')) - + crs = package.extras.get('spatial-reference-system') + if crs: + srid = get_srid(crs) try: # Check if extent already exists rows = conn.execute('SELECT package_id FROM package_extent WHERE package_id = %s',package.id).fetchall() update =(len(rows) > 0) - + + params = {'id':package.id, 'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy, 'db_srid': db_srid} + if update: # Update - statement = """UPDATE package_extent SET - the_geom = ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, - %(maxx)s %(miny)s, - %(maxx)s %(maxy)s, - %(minx)s %(maxy)s, - %(minx)s %(miny)s))',4258) - WHERE package_id = %(id)s - """ + if srid and srid != db_srid: + # We need to reproject the input geometry + statement = """UPDATE package_extent SET + the_geom = ST_Transform( + ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, + %(maxx)s %(miny)s, + %(maxx)s %(maxy)s, + %(minx)s %(maxy)s, + %(minx)s %(miny)s))',%(srid)s), + %(db_srid)s) + WHERE package_id = %(id)s + """ + params.update({'srid': srid}) + else: + statement = """UPDATE package_extent SET + the_geom = ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, + %(maxx)s %(miny)s, + %(maxx)s %(maxy)s, + %(minx)s %(maxy)s, + %(minx)s %(miny)s))',%(db_srid)s) + WHERE package_id = %(id)s + """ msg = 'Updated extent for package %s' else: # Insert - statement = """INSERT INTO package_extent (package_id,the_geom) VALUES ( - %(id)s, - ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, - %(maxx)s %(miny)s, - %(maxx)s %(maxy)s, - %(minx)s %(maxy)s, - %(minx)s %(miny)s))',4258))""" + if srid and srid != db_srid: + # We need to reproject the input geometry + statement = """INSERT INTO package_extent (package_id,the_geom) VALUES ( + %(id)s, + ST_Transform( + ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, + %(maxx)s %(miny)s, + %(maxx)s %(maxy)s, + %(minx)s %(maxy)s, + %(minx)s %(miny)s))',%(srid)s), + %(db_srid)) + )""" + params.update({'srid': srid}) + else: + statement = """INSERT INTO package_extent (package_id,the_geom) VALUES ( + %(id)s, + ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, + %(maxx)s %(miny)s, + %(maxx)s %(maxy)s, + %(minx)s %(maxy)s, + %(minx)s %(miny)s))',%(db_srid)s))""" msg = 'Created new extent for package %s' - conn.execute(statement,{'id':package.id, 'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy}) + conn.execute(statement,params) Session.commit() log.info(msg, package.id) diff --git a/ckanext/harvest/model/__init__.py b/ckanext/harvest/model/__init__.py index c4e8929..ba13a52 100644 --- a/ckanext/harvest/model/__init__.py +++ b/ckanext/harvest/model/__init__.py @@ -356,7 +356,7 @@ class GeminiDocument(MappedXmlDocument): GeminiElement( name="spatial-reference-system", search_paths=[ - "gmd:referenceSystemInfo/gmd:MD_ReferenceSystem", + "gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:code/gco:CharacterString/text()", ], multiplicity="0..1", ),