############################################################################### ## ## ## ALEXANDRIA DIGITAL LIBRARY ## ## University of California at Santa Barbara ## ## ## ## ------------------------------------------------------------------------- ## ## ## ## Copyright (c) 2002 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_InformixGeodetic.py,v 1.1 2002/10/22 20:24:02 gjanee Exp $ # SYNOPSIS # # Spatial_InformixGeodetic (table, idColumn, footprintColumn, # cardinality) # # 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". # # footprintColumn # The table's footprint 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 'footprintColumn'. # # DESCRIPTION # # Translates a spatial constraint to an Informix Geodetic # DataBlade function call of one of the forms # # SELECT idColumn FROM table # WHERE Inside(footprintColumn, targetExpression) # # SELECT idColumn FROM table # WHERE Inside(targetExpression, footprintColumn) # # SELECT idColumn FROM table # WHERE Intersect(footprintColumn, targetExpression) # # depending on the constraint operator. # # 'targetExpression' is a string that can take any of several # forms: depending on the query region, it may describe a # GeoPoint, a GeoLineseg, a GeoString, a GeoRing, a GeoBox, or a # GeoPolyon. The altitude and time constraints in the expression # are unspecified (i.e., are "ANY"). # # In certain cases this paradigm constructs a parallel (i.e., a # line of constant latitude) out of multiple great circle # segments. The size of the segments in degrees is governed by # '_step', below. # # Exceptions thrown: # # unsupported spatial predicate # (Thrown when the target region needs to have an # interior and it doesn't.) # # AUTHOR # # Greg Janee # gjanee@alexandria.ucsb.edu # # HISTORY # # $Log: Spatial_InformixGeodetic.py,v $ # Revision 1.1 2002/10/22 20:24:02 gjanee # Initial revision # import types import edu.ucsb.adl.middleware M = edu.ucsb.adl.middleware import UniversalTranslator UT = UniversalTranslator _step = 0.5 def _makeParallel (latitude, west, east, increment): p = "" if increment > 0.0: longitude = west if west < east: limit = east else: limit = east + 360.0 else: longitude = east if west < east: limit = west else: limit = west - 360.0 while 1: if p != "": p = p + ", " l = longitude if l > 180.0: l = l - 360.0 elif l < -180.0: l = l + 360.0 p = p + "(" + str(latitude) + ", " + str(l) + ")" if longitude == limit: break longitude = longitude + increment if increment > 0.0: if longitude > limit: longitude = limit else: if longitude < limit: longitude = limit return p class Spatial_InformixGeodetic (UT.Paradigm): def __init__ (self, table, idColumn, footprintColumn, cardinality): UT.assertType(table, types.StringType) UT.assertType(idColumn, types.StringType) UT.assertType(footprintColumn, types.StringType) UT.assertType(cardinality, UT.Cardinality) self.table = table self.idColumn = idColumn self.footprintColumn = footprintColumn self.cardinality = cardinality 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 or (west == 180.0 and east == -180.0): if north == south: target = "GeoPoint((" + str(north) + ", " + str(west) +\ "), ANY, ANY)" else: if north == 90.0 and south == -90.0: target = "GeoString(((90.0, " + str(west) +\ "), (0.0, " + str(west) + "), (-90.0, " +\ str(west) + ")), ANY, ANY)" else: target = "GeoLineseg((" + str(north) + ", " +\ str(west) + "), (" + str(south) + ", " +\ str(west) + "), ANY, ANY)" elif west == -180.0 and east == 180.0: if north == south: if abs(north) == 90.0: target = "GeoPoint((" + str(north) +\ ", 0.0), ANY, ANY)" else: target = "GeoRing((" +\ _makeParallel(north, -180.0, 180.0-_step, _step) +\ "), ANY, ANY)" elif north == 90.0 and south == -90.0: target = "GeoBox((-90.0, -180.0), (90.0, 180.0), ANY, ANY)" elif north == 90.0: target = "GeoPolygon(((" +\ _makeParallel(south, -180.0, 180.0-_step, _step) +\ ")), ANY, ANY)" elif south == -90.0: target = "GeoPolygon(((" +\ _makeParallel(north, -180.0, 180.0-_step, -_step) +\ ")), ANY, ANY)" else: target = "GeoPolygon(((" +\ _makeParallel(south, -180.0, 180.0-_step, _step) +\ "), (" +\ _makeParallel(north, -180.0, 180.0-_step, -_step) +\ ")), ANY, ANY)" else: if north == south: if abs(north) == 90.0: target = "GeoPoint((" + str(north) +\ ", 0.0), ANY, ANY)" else: target = "GeoString((" +\ _makeParallel(north, west, east, _step) +\ "), ANY, ANY)" elif north == 90.0 and south == -90.0: target = "GeoPolygon((((90.0, 0.0), (0.0, " + str(west) +\ "), (-90.0, 0.0), (0.0, " + str(east) +\ "))), ANY, ANY)" elif north == 90.0: target = "GeoPolygon((((90.0, 0.0), " +\ _makeParallel(south, west, east, _step) +\ ")), ANY, ANY)" elif south == -90.0: target = "GeoPolygon((((-90.0, 0.0), " +\ _makeParallel(north, west, east, -_step) +\ ")), ANY, ANY)" else: target = "GeoBox((" + str(south) + ", " + str(west) +\ "), (" +\ str(north) + ", " + str(east) + "), ANY, ANY)" else: target = "" for vertex in constraint.getVertices(): if target != "": target = target + ", " target = target + "(" + str(vertex.latitude) + ", " +\ str(vertex.longitude) + ")" target = "GeoPolygon(((" + target + ")), ANY, ANY)" table = UT.TableRef(self.table) if constraint.getOperator() == "contains": expression = UT.Expression(["Inside('" + target + "', ", table, "." + self.footprintColumn + ")"]) elif constraint.getOperator() == "is-contained-in": if target[:6] != "GeoBox" and target[:10] != "GeoPolygon": raise UT.QueryError, "unsupported spatial predicate: " +\ "target region has no interior" expression = UT.Expression(["Inside(", table, "." +\ self.footprintColumn + ", '" + target + "')"]) elif constraint.getOperator() == "overlaps": expression = UT.Expression(["Intersect(", table, "." +\ self.footprintColumn + ", '" + target + "')"]) else: UT.unhandledCase() return UT.Select( [UT.MainFrom(table, self.idColumn, self.cardinality)], expression)