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
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)

View File

@ -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)

View File

@ -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",
),