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