############################################################################### ## ## ## ALEXANDRIA DIGITAL LIBRARY ## ## University of California at Santa Barbara ## ## ## ## ------------------------------------------------------------------------- ## ## ## ## Copyright (c) 2008 by the Regents of the University of California ## ## All rights reserved ## ## ## ## Redistribution and use in source and binary forms, with or without ## ## modification, are permitted provided that the following conditions are ## ## met: ## ## ## ## 1. Redistributions of source code must retain the above copyright ## ## notice, this list of conditions, and the following disclaimer. ## ## ## ## 2. Redistributions in binary form must reproduce the above copyright ## ## notice, this list of conditions, and the following disclaimer in ## ## the documentation and/or other materials provided with the ## ## distribution. ## ## ## ## 3. All advertising materials mentioning features or use of this ## ## software must display the following acknowledgement: This product ## ## includes software developed by the Alexandria Digital Library, ## ## University of California at Santa Barbara, and its contributors. ## ## ## ## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY ## ## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ## ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE ## ## DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ## ## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ## ## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ## ## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ## ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ## ## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ## ## ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ## ## POSSIBILITY OF SUCH DAMAGE. ## ## ## ############################################################################### # $Header: /export/home/gjanee/bucket99/paradigms/RCS/Spatial_OracleSpatial.py,v 1.1 2008/04/16 20:07:14 gjanee Exp $ # SYNOPSIS # # Spatial_OracleSpatial (table, idColumn, geometryColumn, cardinality, # srid=None) # # table # A table to query, e.g., "holding". # # idColumn # The table's object identifier column (i.e., the column # to be selected), e.g., "holding_id". # # geometryColumn # The table's geometry column (i.e., the column against # which the constraint is to be placed), e.g., # "footprint". # # cardinality # A Cardinality object representing the cardinality of # 'table' with respect to 'geometryColumn'. # # srid # The ID of the spatial reference system used by # 'geometryColumn'. Defaults to None. # # DESCRIPTION # # Translates a spatial constraint to an Oracle Spatial SDO_RELATE # function call of the form: # # SELECT idColumn FROM table WHERE # SDO_RELATE(geometryColumn, target, # 'mask=operator querytype=WINDOW') = 'TRUE' # # where 'target' is the constraint region and 'operator' is(are) # the nine-intersection-model predicate(s) corresponding to the # constraint operator. # # For more information, see: Oracle Spatial User's Guide and # Reference, version 10g Release 2 (March 2006), # . # # This paradigm assumes that 'geometryColumn' coordinates are # two-dimensional, and it further assumes that the first (X) # coordinate is longitude in degrees east of the Greenwich # meridian and in the range [-180,180] and the second (Y) # coordinate is latitude in degrees north of the equator and in # the range [-90,90]. This assumption is compatible with spatial # reference systems 8307 ("Longitude / Latitude (WGS 84)"), 8192 # ("Longitude / Latitude"), and 4326 ("WGS 84"). # # Footprints and query regions that cross the +/-180 meridian are # allowed and are handled correctly only if a geodetic spatial # reference system such as one of those mentioned above is used. # # The semantics of the "contains" and "is-contained-in" operators # will generally be correct only if the cardinality is "1" or # "1?". The "0+" and "1+" cardinalities should be used with this # paradigm only if objects truly have multiple, equivalent # footprints. In particular, this paradigm does not support # footprints that are unions of multiple disjoint regions. # # Exceptions thrown: # # none # # AUTHOR # # Greg Janee # gjanee@alexandria.ucsb.edu # # HISTORY # # $Log: Spatial_OracleSpatial.py,v $ # Revision 1.1 2008/04/16 20:07:14 gjanee # Initial revision # import operator import types import edu.ucsb.adl.middleware M = edu.ucsb.adl.middleware import UniversalTranslator UT = UniversalTranslator _operatorMapping = { "contains" : "CONTAINS+COVERS", "is-contained-in" : "INSIDE+COVEREDBY", "overlaps" : "ANYINTERACT" } def _formatGeometry (coords, srid, code): if srid != None: srid = str(srid) else: srid = "NULL" # Magic numbers: # 2003: 2-dimensional polygon # 1: starting at ordinate array position 1 # 1003: exterior polygon ring, counterclockwise vertex order # code=1: simple polygon, straight edges, first vertex repeated # code=3: rectangle, LL and UR opposing corners, dateline crossing allowed return ("SDO_GEOMETRY(2003, %s, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, %d), " +\ "SDO_ORDINATE_ARRAY(%s))") % (srid, code, ", ".join([str(c) for c in coords])) class Spatial_OracleSpatial (UT.Paradigm): def __init__ (self, table, idColumn, geometryColumn, cardinality, srid=None): UT.assertType(table, types.StringType) UT.assertType(idColumn, types.StringType) UT.assertType(geometryColumn, types.StringType) UT.assertType(cardinality, UT.Cardinality) UT.assertPolytype(srid, [types.IntType, types.NoneType]) self.table = table self.idColumn = idColumn self.geometryColumn = geometryColumn self.cardinality = cardinality self.srid = srid def translateBucketAtomic (self, constraint, vocabularies): UT.assertType(constraint, M.Query.SpatialConstraint) assert constraint.getOperator() in UT.standardSpatialOperators,\ "unsupported operator: " + constraint.getOperator() if constraint.getType() == M.Query.SpatialConstraint.BOX: north = constraint.getNorthBoundary() south = constraint.getSouthBoundary() east = constraint.getEastBoundary() west = constraint.getWestBoundary() if west > east: if west == 180.0: west = -180.0 elif east == -180.0: east = 180.0 target = _formatGeometry([west, south, east, north], self.srid, 3) else: vertices = [[v.longitude, v.latitude] for v in constraint.getVertices()] vertices.append(vertices[0]) target = _formatGeometry(reduce(operator.add, vertices, []), self.srid, 1) table = UT.TableRef(self.table) clause = UT.Expression(["SDO_RELATE(", table, "." +\ self.geometryColumn + ", " + target + ", '" +\ "mask=" + _operatorMapping[constraint.getOperator()] +\ " querytype=WINDOW') = 'TRUE'"]) return UT.Select([UT.MainFrom(table, self.idColumn, self.cardinality)], clause)