############################################################################### ## ## ## ALEXANDRIA DIGITAL LIBRARY ## ## University of California at Santa Barbara ## ## ## ## ------------------------------------------------------------------------- ## ## ## ## Copyright (c) 2004 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. ## ## ## ## 4. Neither the name of the University nor the names of its ## ## contributors may be used to endorse or promote products derived ## ## from this software without specific prior written permission. ## ## ## ## 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_OGCSimpleFeatures.py,v 1.1 2004/04/07 23:34:06 gjanee Exp $ # SYNOPSIS # # Spatial_OGCSimpleFeatures (table, idColumn, geometryColumn, # cardinality, srid=-1) # # 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 -1. # # DESCRIPTION # # Translates a spatial constraint to an OpenGIS "Simple Features" # (hereafter, OGC/SF) function call of the form # # SELECT idColumn FROM table # WHERE function(geometryColumn, # GeomFromText(target, srid)) # # where 'function' is the OGC/SF function corresponding to the # spatial constraint operator and 'target' is the constraint # region expressed as an OGC/SF POINT, LINESTRING, or POLYGON. In # certain cases more complex query forms may be returned. # # For more information, see: Open GIS Consortium, Inc., "OpenGIS # Simple Features Specification for SQL" (revision 1.1; 1999), # available at . # # OGC/SF specifies that coordinates are two-dimensional. This # paradigm 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 ESRI spatial reference systems # 53001 ("Sphere Plate Carree") and 54001 ("World Plate Carree") # and EPSG coordinate reference system 4326 ("WGS 84"). # # NOTE: this paradigm assumes that NO object footprint crosses the # +/-180 meridian. However, query regions that cross the +/-180 # meridian are allowed and are handled correctly. Discontinuities # at the poles are NOT handled correctly. # # 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_OGCSimpleFeatures.py,v $ # Revision 1.1 2004/04/07 23:34:06 gjanee # Initial revision # import types import edu.ucsb.adl.middleware M = edu.ucsb.adl.middleware import UniversalTranslator UT = UniversalTranslator _operatorMapping = { "contains" : "Contains", "is-contained-in" : "Within", "overlaps" : "Intersects" } class Spatial_OGCSimpleFeatures (UT.Paradigm): def __init__ (self, table, idColumn, geometryColumn, cardinality, srid=-1): UT.assertType(table, types.StringType) UT.assertType(idColumn, types.StringType) UT.assertType(geometryColumn, types.StringType) UT.assertType(cardinality, UT.Cardinality) UT.assertType(srid, types.IntType) 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() multipleTargets = 0 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 if west < east: if north == south: target = "LINESTRING(" + str(west) + " " + str(north) +\ ", " + str(east) + " " + str(north) + ")" else: target = "POLYGON((" + str(west) + " " + str(south) +\ ", " + str(west) + " " + str(north) + ", " +\ str(east) + " " + str(north) + ", " + str(east) +\ " " + str(south) + ", " + str(west) + " " +\ str(south) + "))" elif west == east: if north == south: target = "POINT(" + str(west) + " " + str(north) + ")" else: target = "LINESTRING(" + str(west) + " " + str(north) +\ ", " + str(west) + " " + str(south) + ")" else: multipleTargets = 1 if north == south: target1 = "LINESTRING(" + str(west) + " " + str(north) +\ ", 180.0 " + str(north) + ")" target2 = "LINESTRING(-180.0 " + str(north) + ", " +\ str(east) + " " + str(north) + ")" else: target1 = "POLYGON((" + str(west) + " " + str(south) +\ ", " + str(west) + " " + str(north) + ", 180.0 " +\ str(north) + ", 180.0 " + str(south) + ", " +\ str(west) + " " + str(south) + "))" target2 = "POLYGON((-180.0 " + str(south) + ", -180.0 " +\ str(north) + ", " + str(east) + " " + str(north) +\ ", " + str(east) + " " + str(south) + ", -180.0 " +\ str(south) + "))" else: target = "" for vertex in constraint.getVertices(): v = str(vertex.longitude) + " " + str(vertex.latitude) if target == "": firstVertex = v target = target + v + ", " target = "POLYGON((" + target + firstVertex + "))" table = UT.TableRef(self.table) if multipleTargets: if constraint.getOperator() == "contains": return UT.constantFalseQuery(self.table, self.idColumn, self.cardinality) else: expression = UT.Expression([ _operatorMapping[constraint.getOperator()] + "(", table, "." + self.geometryColumn + ", GeomFromText('" +\ target1 + "', " + str(self.srid) + "))"]).combine("OR", UT.Expression([ _operatorMapping[constraint.getOperator()] + "(", table, "." + self.geometryColumn + ", GeomFromText('" +\ target2 + "', " + str(self.srid) + "))"])) else: expression = UT.Expression([ _operatorMapping[constraint.getOperator()] + "(", table, "." + self.geometryColumn + ", GeomFromText('" +\ target + "', " + str(self.srid) + "))"]) return UT.Select( [UT.MainFrom(table, self.idColumn, self.cardinality)], expression)