Changeset 456

Show
Ignore:
Timestamp:
10/16/05 20:59:34 (3 years ago)
Author:
zool
Message:

passing more options about on create and update, mostly.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • bbox/bbox/spatialStore.py

    Revision 448 Revision 456
    1"""provides the unified data store between redland RDF and spatial (for now PostGIS) index""" 1"""provides the unified data store between redland RDF and spatial (for now PostGIS) index""" 
    2import pgdb 2import pgdb 
    3import re 3import re 
    4from warnings import warn 4from warnings import warn 
    5 5 
    6# Spatial Reference ID for WGS84 lat/long is 4326 6# Spatial Reference ID for WGS84 lat/long is 4326 
    7 7 
    8_srid = str(4326) 8_srid = str(4326) 
    9 9 
    10class SpatialStore: 10class SpatialStore: 
    11 11 
    12    def __init__(self,database,vars=None,model=None): 12    def __init__(self,database,vars=None,model=None): 
    13        """Create a new store interface to a database name.""" 13        """Create a new store interface to a database name.""" 
    14        self.vars = vars 14        self.vars = vars 
    15        self.model = model 15        self.model = model 
    16 16 
    17        if database is None: 17        if database is None: 
    18            return AttributeError 18            return AttributeError 
    19             19             
    20        db = pgdb.connect(database=database) 20        db = pgdb.connect(database=database) 
    21        self.db = db 21        self.db = db 
    22 22 
    23    def parse_points(self,line): 23    def parse_points(self,line): 
    24        """Given a string of space and comma separated points, 24        """Given a string of space and comma separated points, 
    25        got usually from GeoRDF, return a list of lists. 25        got usually from GeoRDF, return a list of lists. 
    26 26 
    27        This could optionally support different line formats. 27        This could optionally support different line formats. 
    28        (e.g. WKT, or http://brainoff.com/worldkit/doc/polygon.php ) 28        (e.g. WKT, or http://brainoff.com/worldkit/doc/polygon.php ) 
    29        """ 29        """ 
    30        sets = line.split(',') 30        sets = line.split(',') 
    31        points = [] 31        points = [] 
    32        for s in sets: 32        for s in sets: 
    33            s = re.sub('^ ','',s) 33            s = re.sub('^ ','',s) 
    34            p = s.split(' ') 34            p = s.split(' ') 
    35            points.append(p) 35            points.append(p) 
    36             36             
    37        return points 37        return points 
      38 
      39    def wkt_from_points(self,points): 
      40        sets = [] 
      41        for p in points: 
      42            set = ' '.join(p) 
      43            sets.append(set) 
      44        return ','.join(sets) 
    38 45 
    39    def geom(self,uri): 46    def geom(self,uri): 
    40        """Passed the uri of an object, or an rdfobj Object, returns geometry for it as a dict; if the geom is a point, {'x':x,'y':y}; if the geom is a line, x1,y1,x2,y2; polygon geom isn't really supported yet.""" 47        """Passed the uri of an object, or an rdfobj Object, returns geometry for it as a dict; if the geom is a point, {'x':x,'y':y}; if the geom is a line, x1,y1,x2,y2; polygon geom isn't really supported yet.""" 
    41        # again we have an issue of what kind of geom this is 48        # again we have an issue of what kind of geom this is 
    42        select = "select GeometryType(geom) from nodes where node='"+uri+"'" 49        select = "select GeometryType(geom) from nodes where node='"+uri+"'" 
    43        db = self.db.cursor() 50        db = self.db.cursor() 
    44        db.execute(select) 51        db.execute(select) 
    45        g = db.fetchone() 52        g = db.fetchone() 
    46        geom = {} 53        geom = {} 
    47        if g[0] == 'LINESTRING': 54        if g[0] == 'LINESTRING': 
    48            select = "SELECT name, type, X(StartPoint(geom)) as x, Y(StartPoint(geom)), GeomFromText(geom) as y, X(EndPoint(geom)), Y(EndPoint(geom)) from nodes where node='"+str(uri)+"'" 55            select = "SELECT name, type, X(StartPoint(geom)) as x, Y(StartPoint(geom)), GeomFromText(geom) as y, X(EndPoint(geom)), Y(EndPoint(geom)) from nodes where node='"+str(uri)+"'" 
    49            db.execute(select) 56            db.execute(select) 
    50            c = db.fetchone() 57            c = db.fetchone() 
    51            geom['x1'] = c[2] 58            geom['x1'] = c[2] 
    52            geom['x2'] = c[4] 59            geom['x2'] = c[4] 
    53            geom['y1'] = c[3] 60            geom['y1'] = c[3] 
    54            geom['y2'] = c[5] 61            geom['y2'] = c[5] 
    55 62 
    56        elif g[0] == 'POINT': 63        elif g[0] == 'POINT': 
    57            select = "SELECT name,type,X(geom),Y(geom) from nodes where node='"+uri+"'" 64            select = "SELECT name,type,X(geom),Y(geom) from nodes where node='"+uri+"'" 
    58            db.execute(select) 65            db.execute(select) 
    59            c = db.fetchone() 66            c = db.fetchone() 
    60            geom['x'] = c[2] 67            geom['x'] = c[2] 
    61            geom['y'] = c[3] 68            geom['y'] = c[3] 
    62 69 
    63        elif g[0] == 'POLYGON': 70        elif g[0] == 'POLYGON': 
    64            #@@TODO support this properly, as vectors, whatever 71            #@@TODO support this properly, as vectors, whatever 
    65            select = 'SELECT GeomAsText(geom) where node = \''+uri+"'"   72            select = 'SELECT GeomAsText(geom) where node = \''+uri+"'"   
    66         73         
    67        return geom 74        return geom 
    68 75 
    69     76     
    70 77 
    71    def find_near(self,node=None,x=None,y=None,r=None,type=None,terse=None): 78    def find_near(self,node=None,x=None,y=None,r=None,type=None,terse=None): 
    72        if r is None: 79        if r is None: 
    73            r = 0.1  80            r = 0.1  
    74        found = self.within_box(minx=x-r,miny=y-r,maxx=x+r,maxy=y+r,type=type) 81        found = self.within_box(minx=x-r,miny=y-r,maxx=x+r,maxy=y+r,type=type) 
    75        return found 82        return found 
    76     83     
    77    def within_box(self,minx=None,miny=None,maxx=None,maxy=None,type=None): 84    def within_box(self,minx=None,miny=None,maxx=None,maxy=None,type=None): 
    78        """Accepts a minx,miny,maxx,maxy bounding box. 85        """Accepts a minx,miny,maxx,maxy bounding box. 
    79        Returns a list of rdfobj Objects.""" 86        Returns a list of rdfobj Objects.""" 
    80        points=[(minx,miny),(minx,maxy),(maxx,maxy),(maxx,miny),(minx,miny)] 87        points=[(minx,miny),(minx,maxy),(maxx,maxy),(maxx,miny),(minx,miny)] 
    81        return self.within_shape(points=points,type=type) 88        return self.within_shape(points=points,type=type) 
    82 89 
    83    def within_shape(self,points=[],type=None): 90    def within_shape(self,points=[],type=None): 
    84        """Finds all the nodes in the shape made up by the points. 91        """Finds all the nodes in the shape made up by the points. 
    85        In future this may be filterable differently or we might post-filter it. 92        In future this may be filterable differently or we might post-filter it. 
    86        Returns a list of rdfobj objects which can be explored for connections. 93        Returns a list of rdfobj objects which can be explored for connections. 
    87        """ 94        """ 
    88        poly = [] 95        poly = [] 
    89        points = self.join_into_shape(points) 96        points = self.join_into_shape(points) 
    90         97         
    91        for p in points: 98        for p in points: 
    92            poly.append(str(p[0])+' '+str(p[1])) 99            poly.append(str(p[0])+' '+str(p[1])) 
    93        polystring = ','.join(poly) 100        polystring = ','.join(poly) 
    94 101 
    95        select = "SELECT node FROM nodes where Within( geom , GeomFromText('POLYGON(("+polystring+"))',4326) )" 102        select = "SELECT node FROM nodes where Within( geom , GeomFromText('POLYGON(("+polystring+"))',4326) )" 
    96 103 
    97        warn( select ) 104        warn( select ) 
    98        """Also optionally filter by type""" 105        """Also optionally filter by type""" 
    99        if type is not None: 106        if type is not None: 
    100            select = select+' AND type=\''+str(type)+'\'' 107            select = select+' AND type=\''+str(type)+'\'' 
    101             108             
    102        db = self.db 109        db = self.db 
    103        c = db.cursor() 110        c = db.cursor() 
    104        c.execute(select) 111        c.execute(select) 
    105        geoms = c.fetchall() 112        geoms = c.fetchall() 
    106        things = [] 113        things = [] 
    107        for g in geoms: 114        for g in geoms: 
    108            thing = self.model.fetch(g[0]) 115            thing = self.model.fetch(g[0]) 
    109            if thing is not None: 116            if thing is not None: 
    110                things.append(thing) 117                things.append(thing) 
    111         118         
    112        """Return a rdfobj node/object for each geometry.""" 119        """Return a rdfobj node/object for each geometry.""" 
    113        return things 120        return things 
    114 121 
    115    def join_into_shape(self,points): 122    def join_into_shape(self,points): 
    116        first = points[0] 123        first = points[0] 
    117        last = points.pop() 124        last = points.pop() 
    118        if first[0] == last[0]: 125        if first[0] == last[0]: 
    119            if first[1] == last[1]: 126            if first[1] == last[1]: 
    120                points.append(last) 127                points.append(last) 
    121                return points 128                return points 
    122        points.append(last) 129        points.append(last) 
    123        points.append(first) 130        points.append(first) 
    124        return points 131        return points 
    125 132 
    126    def recent(self,days=None,type=None,object=None): 133    def recent(self,days=None,type=None,object=None): 
    127        if days is None: days = 30 134        if days is None: days = 30 
    128         135         
    129        if type is None:  136        if type is None:  
    130            if object is not None: 137            if object is not None: 
    131                type = object.rdf_type 138                type = object.rdf_type 
    132 139 
    133        query = "SELECT node from nodes where (now() - interval '"+str(days)+" days') <= created" 140        query = "SELECT node from nodes where (now() - interval '"+str(days)+" days') <= created" 
    134        if type is not None: 141        if type is not None: 
    135            query = query+" and rdf_type = '"+type+"'" 142            query = query+" and rdf_type = '"+type+"'" 
    136 143 
    137        db = self.db 144        db = self.db 
    138        c = db.cursor() 145        c = db.cursor() 
    139        c.execute(query) 146        c.execute(query) 
    140        nodes = c.fetchall() 147        nodes = c.fetchall() 
    141        things = [] 148        things = [] 
    142        for n in nodes: 149        for n in nodes: 
    143            thing = self.model.fetch(n[0]) 150            thing = self.model.fetch(n[0]) 
    144            if thing is not None: things.append(thing) 151            if thing is not None: things.append(thing) 
    145        return things 152        return things 
    146 153 
    147     154     
    148    def add_geom(self,geom,uri,type=None,owner=None,points=[],object=None,date=None,name=None): 155    def add_geom(self,geom,uri,type=None,owner=None,points=[],object=None,date=None,name=None): 
    149        """ Add geometry for a Uri or rdfobj Object into a spatial index. name=[name] REALLY SHOULD be supplied.""" 156        """ Add geometry for a Uri or rdfobj Object into a spatial index. name=[name] REALLY SHOULD be supplied.""" 
    150        warn(geom) 157        warn(geom) 
    151        if type is None:  158        if type is None:  
    152            if object is not None: 159            if object is not None: 
    153                if object.rdf_type is not None: 160                if object.rdf_type is not None: 
    154                    type = str(object.rdf_type)  161                    type = str(object.rdf_type)  
    155 162 
    156        if type is None: 163        if type is None: 
    157            type = 'http://www.w3.org/2003/01/geo/wgs84_pos#SpatialThing' 164            type = 'http://www.w3.org/2003/01/geo/wgs84_pos#SpatialThing' 
    158 165 
    159        if owner is None: owner = 'wl@frot.org' 166        if owner is None: owner = 'wl@frot.org' 
    160 167 
    161        if date is None: 168        if date is None: 
    162            date = 'now()' 169            date = 'now()' 
    163        else: 170        else: 
    164            date = "'"+str(date)+"'" 171            date = "'"+str(date)+"'" 
    165     172     
    166        geomtext = None 173        geomtext = None 
    167        if geom == 'POINT': 174        if geom == 'POINT': 
    168            geomtext = "GeomFromText('POINT("+str(points[0][0])+' '+str(points[0][1])+")',4326)" 175            geomtext = "GeomFromText('POINT("+str(points[0][0])+' '+str(points[0][1])+")',4326)" 
    169        elif geom == 'LINESTRING': 176        elif geom == 'LINESTRING': 
    170            geomtext = "GeomFromText('LINESTRING("+str(points[0][0])+' '+str(points[0][1])+','+str(points[1][0])+' '+str(points[1][1])+")',4326)" 177            geomtext = "GeomFromText('LINESTRING("+str(points[0][0])+' '+str(points[0][1])+','+str(points[1][0])+' '+str(points[1][1])+")',4326)" 
    171        elif geom == 'POLYGON': 178        elif geom == 'POLYGON': 
    172            poly = [] 179            poly = [] 
    173            for p in points: 180            for p in points: 
    174                poly.append(str(p[0])+' '+str(p[1])) 181                poly.append(str(p[0])+' '+str(p[1])) 
    175            polystring = ','.join(poly) 182            polystring = ','.join(poly) 
    176            geomtext = "GeomFromText('POLYGON(("+polystring+"))',4326)"  183            geomtext = "GeomFromText('POLYGON(("+polystring+"))',4326)"  
    177 184 
    178        db = self.db 185        db = self.db 
    179        db.cursor().execute("INSERT INTO nodes (node,name,geom,type,created) values (%s,%s,"+geomtext+",%s,"+date+")", (str(uri),str(name),str(type))) 186        db.cursor().execute("INSERT INTO nodes (node,name,geom,type,created) values (%s,%s,"+geomtext+",%s,"+date+")", (str(uri),str(name),str(type))) 
    180        db.commit() 187        db.commit() 
    181 188 
    182     189     
    183    def update_geom(self,geom,uri,points=None,object=None,type=None,owner=None): 190    def update_geom(self,geom,uri,points=None,object=None,type=None,owner=None,name=None): 
    184         191         
    185        """Given a geometry type ('POINT','LINESTRING' or 'POLYGON'), and a uri, replace  192        """Given a geometry type ('POINT','LINESTRING' or 'POLYGON'), and a uri, replace  
    186        the geometry for that URI with the new one contained in the points list.""" 193        the geometry for that URI with the new one contained in the points list.""" 
    187        if geom is None: return 194        if geom is None: return 
    188        if uri is None: 195        if uri is None: 
    189            if object is not None: 196            if object is not None: 
    190                uri = str(object) 197                uri = str(object) 
    191            else: 198            else: 
    192                return 199                return 
    193        uri = uri.replace("'","\\'") 200        uri = uri.replace("'","\\'") 
    194        db = self.db 201        db = self.db 
    195        c = db.cursor() 202        c = db.cursor() 
    196        if geom == 'POINT': 203        if geom == 'POINT': 
    197            c.execute("UPDATE nodes SET geom = GeomFromText('POINT("+str(points[0][0])+' '+str(points[0][1])+")',4326) where node = '"+str(uri)+"'") 204            c.execute("UPDATE nodes SET geom = GeomFromText('POINT("+str(points[0][0])+' '+str(points[0][1])+")',4326) where node = '"+str(uri)+"'") 
    198        elif geom == 'LINESTRING': 205        elif geom == 'LINESTRING': 
    199            pass 206            pass 
    200        elif geom == 'POLYGON': 207        elif geom == 'POLYGON': 
    201            pass 208            pass 
    202  209         if name is not None: 
       210             c.execute("UPDATE nodes SET name = %s",(str(name),))         
    203        db.commit() 211        db.commit() 
    204 212 
    205    def geom_exists(self,uri): 213    def geom_exists(self,uri): 
    206        if uri is None: return 214        if uri is None: return 
    207        uri = str(uri) 215        uri = str(uri) 
    208        uri = re.sub("'","\\'",uri) 216        uri = re.sub("'","\\'",uri) 
    209        db = self.db 217        db = self.db 
    210        c = db.cursor() 218        c = db.cursor() 
    211        c.execute("SELECT X(geom) as x, Y(geom) as y from nodes WHERE node = '"+uri+"'") 219        c.execute("SELECT X(geom) as x, Y(geom) as y from nodes WHERE node = '"+uri+"'") 
    212        node = c.fetchone() 220        node = c.fetchone() 
    213        if node is not None: 221        if node is not None: 
    214            return True 222            return True 
    215        else: 223        else: 
    216            return False 224            return False 
    217         225         
    218 226 
    219    def add_or_update_geom(self,geom,uri,points=None,type=None,owner=None,object=None,name=None): 227    def add_or_update_geom(self,geom,uri,points=None,type=None,owner=None,object=None,name=None): 
    220        exists = self.geom_exists(uri) 228        exists = self.geom_exists(uri) 
    221        if exists is True: 229        if exists is True: 
    222            warn(uri) 230            warn(uri) 
    223            warn(geom) 231            warn(geom) 
    224            self.update_geom(geom,uri,points=points,type=type,owner=owner,object=object232            self.update_geom(geom,uri,points=points,type=type,owner=owner,object=object,name=name
    225        else: 233        else: 
    226            warn(uri) 234            warn(uri) 
    227            warn(geom) 235            warn(geom) 
    228            self.add_geom(geom,uri,points=points,type=type,owner=owner,object=object236            self.add_geom(geom,uri,points=points,type=type,owner=owner,object=object,name=name
    229 237 
    230    def add_or_update_point(self,uri,points=[],x=None,y=None,type=None,owner=None,object=None,name=None): 238    def add_or_update_point(self,uri,points=[],x=None,y=None,type=None,owner=None,object=None,name=None): 
    231        if x is not None: 239        if x is not None: 
    232            points = [(x,y)] 240            points = [(x,y)] 
    233        return self.add_or_update_geom('POINT',uri,points=points,type=type,owner=owner,object=object,name=name) 241        return self.add_or_update_geom('POINT',uri,points=points,type=type,owner=owner,object=object,name=name) 
    234 242 
    235    def add_or_update_line(self,uri,points=[],type=None,owner=None,object=None,name=None): 243    def add_or_update_line(self,uri,points=[],type=None,owner=None,object=None,name=None): 
    236        warn("update line") 244        warn("update line") 
    237        return self.add_or_update_geom('LINESTRING',uri,points=points,type=type,owner=owner,object=object,name=name)     245        return self.add_or_update_geom('LINESTRING',uri,points=points,type=type,owner=owner,object=object,name=name)     
    238 246 
    239    def add_or_update_polygon(self,uri,points=[],type=None,owner=None,object=None,name=None): 247    def add_or_update_polygon(self,uri,points=[],type=None,owner=None,object=None,name=None): 
    240        points = self.join_into_shape(points) 248        points = self.join_into_shape(points) 
    241        return self.add_or_update_geom('POLYGON',uri,points=points,type=type,owner=owner,object=object,name=name)  249        return self.add_or_update_geom('POLYGON',uri,points=points,type=type,owner=owner,object=object,name=name)