Use the projection from harvested documents. Add a configure option to define the database projection

This commit is contained in:
Adrià Mercader 2011-03-18 17:42:43 +00:00
parent 35537bbbcb
commit 57631a8931
3 changed files with 91 additions and 53 deletions

View File

@ -4,27 +4,14 @@ from ckan.lib.base import c, g, request, \
response, session, render, config, abort, redirect response, session, render, config, abort, redirect
from ckan.controllers.rest import BaseApiController from ckan.controllers.rest import BaseApiController
from ckan.model import Session from ckan.model import Session
from ckanext.harvest.lib import get_srid
class ApiController(BaseApiController): 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): def spatial_query(self):
if not 'bbox' in request.params: if not 'bbox' in request.params:
@ -39,13 +26,12 @@ class ApiController(BaseApiController):
maxx = float(bbox[2]) maxx = float(bbox[2])
maxy = float(bbox[3]) maxy = float(bbox[3])
params = {'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy} params = {'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy,'db_srid':self.db_srid}
if 'crs' in request.params: 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 # The input bounding box is defined in another projection, we need
# to transform it # to transform it
srid = self._get_srid(request.params['crs'])
statement = """SELECT package_id FROM package_extent WHERE statement = """SELECT package_id FROM package_extent WHERE
ST_Intersects( ST_Intersects(
ST_Transform( ST_Transform(
@ -54,7 +40,7 @@ class ApiController(BaseApiController):
%(maxx)s %(maxy)s, %(maxx)s %(maxy)s,
%(minx)s %(maxy)s, %(minx)s %(maxy)s,
%(minx)s %(miny)s))',%(srid)s), %(minx)s %(miny)s))',%(srid)s),
4258) %(db_srid)s)
,the_geom)""" ,the_geom)"""
params.update({'srid': srid}) params.update({'srid': srid})
else: else:
@ -64,9 +50,8 @@ class ApiController(BaseApiController):
%(maxx)s %(miny)s, %(maxx)s %(miny)s,
%(maxx)s %(maxy)s, %(maxx)s %(maxy)s,
%(minx)s %(maxy)s, %(minx)s %(maxy)s,
%(minx)s %(miny)s))',4258), %(minx)s %(miny)s))',%(db_srid)s),
the_geom)""" the_geom)"""
try:
conn = Session.connection() conn = Session.connection()
rows = conn.execute(statement,params) rows = conn.execute(statement,params)
ids = [row['package_id'] for row in rows] ids = [row['package_id'] for row in rows]
@ -74,7 +59,5 @@ class ApiController(BaseApiController):
output = dict(count=len(ids),results=ids) output = dict(count=len(ids),results=ids)
return self._finish_ok(output) return self._finish_ok(output)
except:
abort(500)

View File

@ -1,53 +1,108 @@
from ckan.model import Session from ckan.model import Session
from ckan.lib.base import config
log = __import__("logging").getLogger(__name__) 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): def save_extent(package,extent=False):
'''Updates the package extent in the package_extent geometry column '''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), If no extent provided (as a dict with minx,miny,maxx,maxy and srid keys),
the values stored in the package extras are used''' the values stored in the package extras are used'''
#TODO: configure SRID
db_srid = int(config.get('ckan.harvesting.srid', '4258'))
conn = Session.connection() conn = Session.connection()
srid = None
if extent: if extent:
minx = extent['minx'] minx = extent['minx']
miny = extent['miny'] miny = extent['miny']
maxx = extent['maxx'] maxx = extent['maxx']
maxy = extent['maxy'] maxy = extent['maxy']
if 'srid' in extent:
srid = extent['srid']
else: else:
minx = float(package.extras.get('bbox-east-long')) minx = float(package.extras.get('bbox-east-long'))
miny = float(package.extras.get('bbox-south-lat')) miny = float(package.extras.get('bbox-south-lat'))
maxx = float(package.extras.get('bbox-west-long')) maxx = float(package.extras.get('bbox-west-long'))
maxy = float(package.extras.get('bbox-north-lat')) maxy = float(package.extras.get('bbox-north-lat'))
crs = package.extras.get('spatial-reference-system')
if crs:
srid = get_srid(crs)
try: try:
# Check if extent already exists # Check if extent already exists
rows = conn.execute('SELECT package_id FROM package_extent WHERE package_id = %s',package.id).fetchall() rows = conn.execute('SELECT package_id FROM package_extent WHERE package_id = %s',package.id).fetchall()
update =(len(rows) > 0) update =(len(rows) > 0)
params = {'id':package.id, 'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy, 'db_srid': db_srid}
if update: if update:
# Update # Update
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 statement = """UPDATE package_extent SET
the_geom = ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, the_geom = ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
%(maxx)s %(miny)s, %(maxx)s %(miny)s,
%(maxx)s %(maxy)s, %(maxx)s %(maxy)s,
%(minx)s %(maxy)s, %(minx)s %(maxy)s,
%(minx)s %(miny)s))',4258) %(minx)s %(miny)s))',%(db_srid)s)
WHERE package_id = %(id)s WHERE package_id = %(id)s
""" """
msg = 'Updated extent for package %s' msg = 'Updated extent for package %s'
else: else:
# Insert # Insert
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 ( statement = """INSERT INTO package_extent (package_id,the_geom) VALUES (
%(id)s, %(id)s,
ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, ST_GeomFromText('POLYGON ((%(minx)s %(miny)s,
%(maxx)s %(miny)s, %(maxx)s %(miny)s,
%(maxx)s %(maxy)s, %(maxx)s %(maxy)s,
%(minx)s %(maxy)s, %(minx)s %(maxy)s,
%(minx)s %(miny)s))',4258))""" %(minx)s %(miny)s))',%(db_srid)s))"""
msg = 'Created new extent for package %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() Session.commit()
log.info(msg, package.id) log.info(msg, package.id)

View File

@ -356,7 +356,7 @@ class GeminiDocument(MappedXmlDocument):
GeminiElement( GeminiElement(
name="spatial-reference-system", name="spatial-reference-system",
search_paths=[ 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", multiplicity="0..1",
), ),