Ejemplo n.º 1
0
def build_geometries(diff, srid):
    srid_txt = "EPSG:{}".format(srid)
    geom = {'line': [], 'point': [], 'polygon': []}
    for osm_id, node in diff['add']['node'].iteritems():
        x, y = projections.from4326(node["geom"], srid_txt)
        geom["point"].append({"geom": "SRID={};POINT({} {})".format(srid, x, y), "osm_id": osm_id, "tags": node["tags"]})
    for osm_id, way in diff['add']['way'].iteritems():
        line = projections.from4326(way["geom"], srid_txt)
        polygonize = check_tags_if_polygon(way["tags"])
        if polygonize:
            result, dangles, cuts, invalids = polygonize_full([line])
            #print result, dangles, cuts, invalids
            for poly in result:
                geom["polygon"].append({"geom": "SRID={};{}".format(srid, poly.wkt), "osm_id": osm_id, "way_area":poly.area, "tags": way["tags"]})
            for line in dangles:
                geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": osm_id, "tags": way["tags"]})
            for line in cuts:
                geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": osm_id, "tags": way["tags"]})
            for line in invalids:
                geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": osm_id, "tags": way["tags"]})
        else:
            ll = ",".join([a[0] + a[1] for a in line])
            geom["line"].append({"geom": "SRID={};LINESTRING({})".format(srid, ll), "osm_id": osm_id, "tags": way["tags"]})
    for osm_id, relation in diff['add']['relation'].iteritems():
        lines = [projections.from4326(way, srid_txt) for way in relation["geom"]]
        polygonize = check_tags_if_polygon(relation["tags"])
        if polygonize:
            merged = linemerge(lines)
            polys = []
            lines = []
            for line in merged:
                if line.is_ring:
                    polys.append(line)
                else:
                    lines.append(line)
            if polys:
                # TODO: repair geometry
                poly = Polygon(polys[0], polys[1:])
                geom["polygon"].append({"geom": "SRID={};{}".format(srid, poly.wkt), "osm_id": -osm_id, "way_area":0, "tags": relation["tags"]})
            for line in lines:
                geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": -osm_id, "tags": relation["tags"]})

            #result, dangles, cuts, invalids = polygonize_full(lines)
            ##print result, dangles, cuts, invalids
            #result = list(result)
            #sd = result[0]
            #for poly in result[1:]:
                #sd = sd.symmetric_difference(poly)
            #geom["polygon"].append({"geom": "SRID={};{}".format(srid, sd.wkt), "osm_id": -osm_id, "way_area":sd.area, "tags": relation["tags"]})
            #for line in dangles:
                #geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": -osm_id, "tags": relation["tags"]})
            #for line in cuts:
                #geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": -osm_id, "tags": relation["tags"]})

        else:
            ll = ",".join([a[0] + a[1] for a in line])
            geom["line"].append({"geom": "SRID={};LINESTRING({})".format(srid, ll), "osm_id": osm_id, "tags": relation["tags"]})
    return geom
Ejemplo n.º 2
0
  def expose_ev(self, widget, event):
    if(widget.allocation.width != self.width or widget.allocation.height != self.height ):
      #debug("Rrresize!")
      self.width = widget.allocation.width
      self.height = widget.allocation.height

    cr = widget.window.cairo_create()
    if self.old_center_coord != self.center_coord or self.old_zoom != self.zoom:
      #print "Recentered!"
      xy = projections.from4326(self.center_coord,"EPSG:3857")
      xy1 = projections.to4326((xy[0]-40075016.*(0.5**(self.zoom))/self.tiles.tilewidth*self.width, xy[1]-40075016.*(0.5**(self.zoom))/self.tiles.tileheight*self.height), "EPSG:3857")
      xy2 = projections.to4326((xy[0]+40075016.*(0.5**(self.zoom))/self.tiles.tilewidth*self.width, xy[1]+40075016.*(0.5**(self.zoom))/self.tiles.tileheight*self.height), "EPSG:3857")
      self.bbox = (xy1[0],xy1[1],xy2[0],xy2[1])
      self.tilebox = projections.tile_by_bbox(self.bbox, self.zoom, "EPSG:3857")
      self.old_center_coord = self.center_coord
      self.old_zoom = self.zoom
    from_tile_x, from_tile_y, to_tile_x, to_tile_y = self.tilebox
    dx = 1.*(from_tile_x - int(from_tile_x))*self.tiles.tilewidth
    dy = 1.*(from_tile_y - int(from_tile_y))*self.tiles.tileheight
    print dx,dy
    #print self.dx, self.dy
    onscreen_tiles = set()
    for x in range (int(from_tile_x), int(to_tile_x)+1):
      for y in range (int(to_tile_y), int(from_tile_y)+1):
        onscreen_tiles.add((self.zoom,x,y))
    self.tiles.onscreen = onscreen_tiles
    for z,x,y in onscreen_tiles:
      tile = self.tiles[(self.zoom,x,y)]
      #print dx+(x-from_tile_x)*self.tiles.tilewidth-self.width
      #print dy+(y-from_tile_y)*self.tiles.tileheight-self.height
      #cr.set_source_surface(tile, int(self.dx-dx+(x-int(from_tile_x))*self.tiles.tilewidth-self.width), int(self.dy-dy-(int(from_tile_y)-y)*self.tiles.tileheight+self.height))
      cr.set_source_surface(tile, int(self.dx-dx+(x-int(from_tile_x))*self.tiles.tilewidth), int(self.dy-dy-(int(from_tile_y)-y)*self.tiles.tileheight+self.height))
      cr.paint()
Ejemplo n.º 3
0
 def update_surface_by_center(self, lonlat, zoom, style):
   self.zoom = zoom
   xy = projections.from4326(lonlat, self.proj)
   xy1 = projections.to4326((xy[0]-40075016*0.5**self.zoom/256*self.w, xy[1]-40075016*0.5**self.zoom/256*self.h), self.proj)
   xy2 = projections.to4326((xy[0]+40075016*0.5**self.zoom/256*self.w, xy[1]+40075016*0.5**self.zoom/256*self.h), self.proj)
   bbox = (xy1[0],xy1[1],xy2[0],xy2[1])
   debug (bbox)
   return self.update_surface(bbox, zoom, style)
Ejemplo n.º 4
0
 def update_surface_by_center(self, lonlat, zoom, style):
     self.zoom = zoom
     xy = projections.from4326(lonlat, self.proj)
     xy1 = projections.to4326(
         (xy[0] - 40075016 * 0.5**self.zoom / 256 * self.w,
          xy[1] - 40075016 * 0.5**self.zoom / 256 * self.h), self.proj)
     xy2 = projections.to4326(
         (xy[0] + 40075016 * 0.5**self.zoom / 256 * self.w,
          xy[1] + 40075016 * 0.5**self.zoom / 256 * self.h), self.proj)
     bbox = (xy1[0], xy1[1], xy2[0], xy2[1])
     debug(bbox)
     return self.update_surface(bbox, zoom, style)
Ejemplo n.º 5
0
    def expose_ev(self, widget, event):
        if (widget.allocation.width != self.width
                or widget.allocation.height != self.height):
            # debug("Rrresize!")
            self.width = widget.allocation.width
            self.height = widget.allocation.height

        cr = widget.window.cairo_create()
        if self.old_center_coord != self.center_coord or self.old_zoom != self.zoom:
            # print "Recentered!"
            xy = projections.from4326(self.center_coord, "EPSG:3857")
            xy1 = projections.to4326(
                (xy[0] - 40075016. *
                 (0.5**(self.zoom)) / self.tiles.tilewidth * self.width,
                 xy[1] - 40075016. *
                 (0.5**(self.zoom)) / self.tiles.tileheight * self.height),
                "EPSG:3857")
            xy2 = projections.to4326(
                (xy[0] + 40075016. *
                 (0.5**(self.zoom)) / self.tiles.tilewidth * self.width,
                 xy[1] + 40075016. *
                 (0.5**(self.zoom)) / self.tiles.tileheight * self.height),
                "EPSG:3857")
            self.bbox = (xy1[0], xy1[1], xy2[0], xy2[1])
            self.tilebox = projections.tile_by_bbox(self.bbox, self.zoom,
                                                    "EPSG:3857")
            self.old_center_coord = self.center_coord
            self.old_zoom = self.zoom
        from_tile_x, from_tile_y, to_tile_x, to_tile_y = self.tilebox
        dx = 1. * (from_tile_x - int(from_tile_x)) * self.tiles.tilewidth
        dy = 1. * (from_tile_y - int(from_tile_y)) * self.tiles.tileheight
        print dx, dy
        # print self.dx, self.dy
        onscreen_tiles = set()
        for x in range(int(from_tile_x), int(to_tile_x) + 1):
            for y in range(int(to_tile_y), int(from_tile_y) + 1):
                onscreen_tiles.add((self.zoom, x, y))
        self.tiles.onscreen = onscreen_tiles
        for z, x, y in onscreen_tiles:
            tile = self.tiles[(self.zoom, x, y)]
            # print dx+(x-from_tile_x)*self.tiles.tilewidth-self.width
            # print dy+(y-from_tile_y)*self.tiles.tileheight-self.height
            # cr.set_source_surface(tile, int(self.dx-dx+(x-int(from_tile_x))*self.tiles.tilewidth-self.width), int(self.dy-dy-(int(from_tile_y)-y)*self.tiles.tileheight+self.height))
            cr.set_source_surface(
                tile,
                int(self.dx - dx +
                    (x - int(from_tile_x)) * self.tiles.tilewidth),
                int(self.dy - dy -
                    (int(from_tile_y) - y) * self.tiles.tileheight +
                    self.height))
            cr.paint()
Ejemplo n.º 6
0
  def release_ev(self, widget, event):
    if event.button == 1:
      #debug("Stop drag")
      self.drag = False
      self.timer.stop()
      #debug("dd: %s,%s "%(self.dx, self.dy))
      x = event.x
      y = event.y
      lo1, la1, lo2, la2 = projections.from4326(self.bbox, "EPSG:3857")
      print lo1, la1, lo2, la2
      #self.center_coord = projections.to4326((0.5*(self.width+self.dx)/self.width*(lo1-lo2)+lo2, la1+(0.5*(self.height+self.dy)/self.height*(la2-la1))),"EPSG:3857")

      self.center_coord = projections.to4326((0.5*(self.width+2*self.dx)/self.width*(lo1-lo2)+lo2, la1+(0.5*(self.height+2*self.dy)/self.height*(la2-la1))),"EPSG:3857")
      #self.rastertile.screen2lonlat(self.rastertile.w/2 - self.dx, self.rastertile.h/2 - self.dy);
      self.dx = 0
      self.dy = 0
      self.redraw()
Ejemplo n.º 7
0
    def release_ev(self, widget, event):
        if event.button == 1:
            # debug("Stop drag")
            self.drag = False
            self.timer.stop()
            # debug("dd: %s,%s "%(self.dx, self.dy))
            x = event.x
            y = event.y
            lo1, la1, lo2, la2 = projections.from4326(self.bbox, "EPSG:3857")
            print lo1, la1, lo2, la2
            # self.center_coord = projections.to4326((0.5*(self.width+self.dx)/self.width*(lo1-lo2)+lo2, la1+(0.5*(self.height+self.dy)/self.height*(la2-la1))),"EPSG:3857")

            self.center_coord = projections.to4326(
                (0.5 * (self.width + 2 * self.dx) / self.width *
                 (lo1 - lo2) + lo2, la1 +
                 (0.5 * (self.height + 2 * self.dy) / self.height *
                  (la2 - la1))), "EPSG:3857")
            # self.rastertile.screen2lonlat(self.rastertile.w/2 - self.dx, self.rastertile.h/2 - self.dy);
            self.dx = 0
            self.dy = 0
            self.redraw()
Ejemplo n.º 8
0
def get_vectors(bbox, zoom, style, vec="polygon"):
    bbox_p = projections.from4326(bbox, "EPSG:3857")
    geomcolumn = "way"

    database = "dbname=gis user=gis"
    pxtolerance = 1.8
    intscalefactor = 10000
    ignore_columns = set(["way_area", "osm_id", geomcolumn, "tags", "z_order"])
    table = {"polygon": "planet_osm_polygon", "line": "planet_osm_line", "point": "planet_osm_point", "coastline": "coastlines"}

    a = psycopg2.connect(database)
    b = a.cursor()
    if vec != "coastline":
        b.execute("SELECT * FROM %s LIMIT 1;" % table[vec])
        names = [q[0] for q in b.description]
        for i in ignore_columns:
            if i in names:
                names.remove(i)
        names = ",".join(['"' + i + '"' for i in names])

        taghint = "*"
        types = {"line": "line", "polygon": "area", "point": "node"}
        adp = ""
        if "get_sql_hints" in dir(style):
            sql_hint = style.get_sql_hints(types[vec], zoom)
            adp = []
            for tp in sql_hint:
                add = []
                for j in tp[0]:
                    if j not in names:
                        break
                else:
                    add.append(tp[1])
                if add:
                    add = " OR ".join(add)
                    add = "(" + add + ")"
                    adp.append(add)
            adp = " OR ".join(adp)
            if adp:
                adp = adp.replace("&lt;", "<")
                adp = adp.replace("&gt;", ">")

    if vec == "polygon":
        query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s,
                          ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_PointOnSurface(way)),%s,%s,%s,%s),0) as reprpoint, %s from
                  (select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s, %s from
                    (select ST_Union(way) as %s, %s from
                      (select ST_Buffer(way, %s) as %s, %s from
                         %s
                         where (%s)
                           and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
                           and way_area > %s
                      ) p
                     group by %s
                    ) p
                    where ST_Area(way) > %s
                    order by ST_Area(way)
                  ) p
          """ % (bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],
                 -bbox_p[0], -bbox_p[1], intscalefactor / (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
                 geomcolumn,
                 -bbox_p[0], -bbox_p[1], intscalefactor / (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
                 names,
                 pixel_size_at_zoom(zoom, pxtolerance), pixel_size_at_zoom(zoom, pxtolerance),
                 geomcolumn, names,
                 geomcolumn, names,
                 pixel_size_at_zoom(zoom, pxtolerance),
                 geomcolumn, names,
                 table[vec],
                 adp,
                 bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],
                 (pixel_size_at_zoom(zoom, pxtolerance) ** 2) / pxtolerance,
                 names,
                 pixel_size_at_zoom(zoom, pxtolerance) ** 2
                 )
    elif vec == "line":
        query = """select ST_AsGeoJSON(ST_TransScale(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)),%s,%s,%s,%s),0) as %s, %s from
                  (select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_LineMerge(way),%s)))).geom as %s, %s from
                    (select ST_Union(way) as %s, %s from
                         %s
                         where (%s)
                           and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)

                     group by %s
                    ) p

                  ) p
          """ % (bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],
                 -bbox_p[0], -bbox_p[1], intscalefactor / (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
                 geomcolumn, names,
                 pixel_size_at_zoom(zoom, pxtolerance),
                 geomcolumn, names,
                 geomcolumn, names,
                 table[vec],
                 adp,
                 bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],

                 names,

                 )
    elif vec == "point":
        query = """select ST_AsGeoJSON(ST_TransScale(way,%s,%s,%s,%s),0) as %s, %s
                    from %s where
                    (%s)
                    and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
                   limit 10000
                 """ % (
            -bbox_p[0], -bbox_p[1], intscalefactor / (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
            geomcolumn, names,
            table[vec],
            adp,
            bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],

        )
    elif vec == "coastline":
        query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s, 'coastline' as "natural" from
                  (select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s from
                    (select ST_Union(way) as %s from
                      (select ST_Buffer(SetSRID(the_geom,900913), %s) as %s from
                         %s
                         where
                            SetSRID(the_geom,900913) && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
                      ) p
                    ) p
                    where ST_Area(way) > %s
                  ) p
          """ % (bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],
                 -bbox_p[0], -bbox_p[1], intscalefactor / (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
                 geomcolumn,
                 pixel_size_at_zoom(zoom, pxtolerance), pixel_size_at_zoom(zoom, pxtolerance),
                 geomcolumn,
                 geomcolumn,
                 pixel_size_at_zoom(zoom, pxtolerance),
                 geomcolumn,
                 table[vec],
                 bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],
                 pixel_size_at_zoom(zoom, pxtolerance) ** 2
                 )
    # print query
    a = psycopg2.connect(database)
    b = a.cursor()
    b.execute(query)
    names = [q[0] for q in b.description]

    ROWS_FETCHED = 0
    polygons = []

    for row in b.fetchall():
        ROWS_FETCHED += 1
        geom = dict(map(None, names, row))
        for t in geom.keys():
            if not geom[t]:
                del geom[t]
        geojson = json.loads(geom[geomcolumn])
        del geom[geomcolumn]
        if geojson["type"] == "GeometryCollection":
            continue
        if "reprpoint" in geom:
            geojson["reprpoint"] = json.loads(geom["reprpoint"])["coordinates"]
            del geom["reprpoint"]
        prop = {}
        for k, v in geom.iteritems():
            prop[k] = v
            try:
                if int(v) == float(v):
                    prop[k] = int(v)
                else:
                    prop[k] = float(v)
                if str(prop[k]) != v:  # leading zeros etc.. should be saved
                    prop[k] = v
            except:
                pass
        geojson["properties"] = prop
        polygons.append(geojson)
    return {"bbox": bbox, "granularity": intscalefactor, "features": polygons}
Ejemplo n.º 9
0
def get_vectors(bbox, zoom, style, vec="polygon"):
    bbox_p = projections.from4326(bbox, "EPSG:3857")
    geomcolumn = "way"

    database = "dbname=gis user=gis"
    pxtolerance = 1.8
    intscalefactor = 10000
    ignore_columns = set(["way_area", "osm_id", geomcolumn, "tags", "z_order"])
    table = {
        "polygon": "planet_osm_polygon",
        "line": "planet_osm_line",
        "point": "planet_osm_point",
        "coastline": "coastlines"
    }

    a = psycopg2.connect(database)
    b = a.cursor()
    if vec != "coastline":
        b.execute("SELECT * FROM %s LIMIT 1;" % table[vec])
        names = [q[0] for q in b.description]
        for i in ignore_columns:
            if i in names:
                names.remove(i)
        names = ",".join(['"' + i + '"' for i in names])

        taghint = "*"
        types = {"line": "line", "polygon": "area", "point": "node"}
        adp = ""
        if "get_sql_hints" in dir(style):
            sql_hint = style.get_sql_hints(types[vec], zoom)
            adp = []
            for tp in sql_hint:
                add = []
                for j in tp[0]:
                    if j not in names:
                        break
                else:
                    add.append(tp[1])
                if add:
                    add = " OR ".join(add)
                    add = "(" + add + ")"
                    adp.append(add)
            adp = " OR ".join(adp)
            if adp:
                adp = adp.replace("&lt;", "<")
                adp = adp.replace("&gt;", ">")

    if vec == "polygon":
        query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s,
                      ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_PointOnSurface(way)),%s,%s,%s,%s),0) as reprpoint, %s from
              (select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s, %s from
                (select ST_Union(way) as %s, %s from
                  (select ST_Buffer(way, %s) as %s, %s from
                     %s
                     where (%s)
                       and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
                       and way_area > %s
                  ) p
                 group by %s
                ) p
                where ST_Area(way) > %s
                order by ST_Area(way)
              ) p
      """ % (bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3], -bbox_p[0],
             -bbox_p[1], intscalefactor /
             (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
             geomcolumn, -bbox_p[0], -bbox_p[1], intscalefactor /
             (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
             names, pixel_size_at_zoom(
                 zoom, pxtolerance), pixel_size_at_zoom(
                     zoom, pxtolerance), geomcolumn, names, geomcolumn, names,
             pixel_size_at_zoom(zoom, pxtolerance), geomcolumn, names,
             table[vec], adp, bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],
             (pixel_size_at_zoom(zoom, pxtolerance)**2) / pxtolerance, names,
             pixel_size_at_zoom(zoom, pxtolerance)**2)
    elif vec == "line":
        query = """select ST_AsGeoJSON(ST_TransScale(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)),%s,%s,%s,%s),0) as %s, %s from
              (select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_LineMerge(way),%s)))).geom as %s, %s from
                (select ST_Union(way) as %s, %s from
                     %s
                     where (%s)
                       and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)

                 group by %s
                ) p

              ) p
      """ % (
            bbox_p[0],
            bbox_p[1],
            bbox_p[2],
            bbox_p[3],
            -bbox_p[0],
            -bbox_p[1],
            intscalefactor / (bbox_p[2] - bbox_p[0]),
            intscalefactor / (bbox_p[3] - bbox_p[1]),
            geomcolumn,
            names,
            pixel_size_at_zoom(zoom, pxtolerance),
            geomcolumn,
            names,
            geomcolumn,
            names,
            table[vec],
            adp,
            bbox_p[0],
            bbox_p[1],
            bbox_p[2],
            bbox_p[3],
            names,
        )
    elif vec == "point":
        query = """select ST_AsGeoJSON(ST_TransScale(way,%s,%s,%s,%s),0) as %s, %s
                from %s where
                (%s)
                and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
               limit 10000
             """ % (
            -bbox_p[0],
            -bbox_p[1],
            intscalefactor / (bbox_p[2] - bbox_p[0]),
            intscalefactor / (bbox_p[3] - bbox_p[1]),
            geomcolumn,
            names,
            table[vec],
            adp,
            bbox_p[0],
            bbox_p[1],
            bbox_p[2],
            bbox_p[3],
        )
    elif vec == "coastline":
        query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s, 'coastline' as "natural" from
              (select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s from
                (select ST_Union(way) as %s from
                  (select ST_Buffer(SetSRID(the_geom,900913), %s) as %s from
                     %s
                     where
                        SetSRID(the_geom,900913) && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
                  ) p
                ) p
                where ST_Area(way) > %s
              ) p
      """ % (bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3], -bbox_p[0],
             -bbox_p[1], intscalefactor /
             (bbox_p[2] - bbox_p[0]), intscalefactor / (bbox_p[3] - bbox_p[1]),
             geomcolumn, pixel_size_at_zoom(zoom, pxtolerance),
             pixel_size_at_zoom(zoom, pxtolerance), geomcolumn, geomcolumn,
             pixel_size_at_zoom(zoom, pxtolerance), geomcolumn, table[vec],
             bbox_p[0], bbox_p[1], bbox_p[2], bbox_p[3],
             pixel_size_at_zoom(zoom, pxtolerance)**2)
    #print query
    a = psycopg2.connect(database)
    b = a.cursor()
    b.execute(query)
    names = [q[0] for q in b.description]

    ROWS_FETCHED = 0
    polygons = []

    for row in b.fetchall():
        ROWS_FETCHED += 1
        geom = dict(map(None, names, row))
        for t in geom.keys():
            if not geom[t]:
                del geom[t]
        geojson = json.loads(geom[geomcolumn])
        del geom[geomcolumn]
        if geojson["type"] == "GeometryCollection":
            continue
        if "reprpoint" in geom:
            geojson["reprpoint"] = json.loads(geom["reprpoint"])["coordinates"]
            del geom["reprpoint"]
        prop = {}
        for k, v in geom.iteritems():
            prop[k] = v
            try:
                if int(v) == float(v):
                    prop[k] = int(v)
                else:
                    prop[k] = float(v)
                if str(prop[k]) != v:  # leading zeros etc.. should be saved
                    prop[k] = v
            except:
                pass
        geojson["properties"] = prop
        polygons.append(geojson)
    return {"bbox": bbox, "granularity": intscalefactor, "features": polygons}
Ejemplo n.º 10
0
def build_geometries(diff, srid):
    srid_txt = "EPSG:{}".format(srid)
    geom = {'line': [], 'point': [], 'polygon': []}
    for osm_id, node in diff['add']['node'].iteritems():
        x, y = projections.from4326(node["geom"], srid_txt)
        geom["point"].append({
            "geom": "SRID={};POINT({} {})".format(srid, x, y),
            "osm_id": osm_id,
            "tags": node["tags"]
        })
    for osm_id, way in diff['add']['way'].iteritems():
        line = projections.from4326(way["geom"], srid_txt)
        polygonize = check_tags_if_polygon(way["tags"])
        if polygonize:
            result, dangles, cuts, invalids = polygonize_full([line])
            #print result, dangles, cuts, invalids
            for poly in result:
                geom["polygon"].append({
                    "geom":
                    "SRID={};{}".format(srid, poly.wkt),
                    "osm_id":
                    osm_id,
                    "way_area":
                    poly.area,
                    "tags":
                    way["tags"]
                })
            for line in dangles:
                geom["line"].append({
                    "geom": "SRID={};{}".format(srid, line.wkt),
                    "osm_id": osm_id,
                    "tags": way["tags"]
                })
            for line in cuts:
                geom["line"].append({
                    "geom": "SRID={};{}".format(srid, line.wkt),
                    "osm_id": osm_id,
                    "tags": way["tags"]
                })
            for line in invalids:
                geom["line"].append({
                    "geom": "SRID={};{}".format(srid, line.wkt),
                    "osm_id": osm_id,
                    "tags": way["tags"]
                })
        else:
            ll = ",".join([a[0] + a[1] for a in line])
            geom["line"].append({
                "geom":
                "SRID={};LINESTRING({})".format(srid, ll),
                "osm_id":
                osm_id,
                "tags":
                way["tags"]
            })
    for osm_id, relation in diff['add']['relation'].iteritems():
        lines = [
            projections.from4326(way, srid_txt) for way in relation["geom"]
        ]
        polygonize = check_tags_if_polygon(relation["tags"])
        if polygonize:
            merged = linemerge(lines)
            polys = []
            lines = []
            for line in merged:
                if line.is_ring:
                    polys.append(line)
                else:
                    lines.append(line)
            if polys:
                # TODO: repair geometry
                poly = Polygon(polys[0], polys[1:])
                geom["polygon"].append({
                    "geom":
                    "SRID={};{}".format(srid, poly.wkt),
                    "osm_id":
                    -osm_id,
                    "way_area":
                    0,
                    "tags":
                    relation["tags"]
                })
            for line in lines:
                geom["line"].append({
                    "geom": "SRID={};{}".format(srid, line.wkt),
                    "osm_id": -osm_id,
                    "tags": relation["tags"]
                })

            #result, dangles, cuts, invalids = polygonize_full(lines)
            ##print result, dangles, cuts, invalids
            #result = list(result)
            #sd = result[0]
            #for poly in result[1:]:
            #sd = sd.symmetric_difference(poly)
            #geom["polygon"].append({"geom": "SRID={};{}".format(srid, sd.wkt), "osm_id": -osm_id, "way_area":sd.area, "tags": relation["tags"]})
            #for line in dangles:
            #geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": -osm_id, "tags": relation["tags"]})
            #for line in cuts:
            #geom["line"].append({"geom": "SRID={};{}".format(srid, line.wkt), "osm_id": -osm_id, "tags": relation["tags"]})

        else:
            ll = ",".join([a[0] + a[1] for a in line])
            geom["line"].append({
                "geom":
                "SRID={};LINESTRING({})".format(srid, ll),
                "osm_id":
                osm_id,
                "tags":
                relation["tags"]
            })
    return geom
Ejemplo n.º 11
0
    def get_vectors(self, bbox, zoom, sql_hint=None, tags_hint=None):
        """
        Fetches vectors for given bbox.
        sql_hint is a list of sets of (key, sql_for_key)
        """
        a = psycopg2.connect(self.database)
        b = a.cursor()
        bbox = tuple(projections.from4326(bbox, self.proj))
        ### FIXME: hardcoded EPSG:3857 in database
        tables = ("planet_osm_line", "planet_osm_polygon")  # FIXME: points
        resp = {}
        for table in tables:
            add = ""
            taghint = "*"
            if sql_hint:
                adp = []

                for tp in sql_hint:
                    add = []
                    b.execute("SELECT * FROM %s LIMIT 1;" % table)
                    names = [q[0] for q in b.description]

                    for j in tp[0]:
                        if j not in names:
                            break
                    else:
                        add.append(tp[1])
                    if add:
                        add = " OR ".join(add)
                        add = "(" + add + ")"
                        adp.append(add)

                    if tags_hint:
                        taghint = ", ".join([
                            '"' + j + '"' for j in tags_hint if j in names
                        ]) + ", way, osm_id"

                adp = " OR ".join(adp)

            req = "SELECT %s FROM %s WHERE (%s) and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913);" % (
                taghint, table, adp, bbox[0], bbox[1], bbox[2], bbox[3])
            print req
            b.execute(req)
            names = [q[0] for q in b.description]

            for row in b.fetchall():

                row_dict = dict(map(None, names, row))
                for k, v in row_dict.items():
                    if not v:
                        del row_dict[k]
                geom = shapely.wkb.loads(row_dict["way"].decode('hex'))
                ### FIXME: a dirty hack to basically support polygons, needs lots of rewrite
                try:
                    geom = list(geom.coords)
                except NotImplementedError:
                    "trying polygons"
                    try:
                        geom = geom.boundary
                        geom = list(geom.coords)
                        row_dict[":area"] = "yes"
                    except NotImplementedError:
                        "multipolygon"
                        continue
                        ### FIXME

                # geom = projections.to4326(geom, self.proj)
                del row_dict["way"]
                oid = row_dict["osm_id"]
                del row_dict["osm_id"]
                w = Way(row_dict, geom)
                # print row_dict
                resp[oid] = w
        a.close()
        del a

        return resp
Ejemplo n.º 12
0
    def update_surface(self, bbox, zoom, style, callback=lambda x=None: None):
        rendertimer = Timer("Rendering image")
        if "image" not in style.cache:
            style.cache["image"] = ImageLoader()

        timer = Timer("Getting data")
        self.zoom = zoom
        self.bbox = bbox
        self.bbox_p = projections.from4326(bbox, self.proj)

        print self.bbox_p
        scale = abs(self.w / (self.bbox_p[0] - self.bbox_p[2]) /
                    math.cos(math.pi *
                             (self.bbox[1] + self.bbox[3]) / 2 / 180))
        zscale = 0.5 * scale
        cr = cairo.Context(self.surface)
        # getting and setting canvas properties
        bgs = style.get_style("canvas", {}, self.zoom, scale, zscale)
        if not bgs:
            bgs = [{}]
        bgs = bgs[0]
        cr.rectangle(0, 0, self.w, self.h)
        # canvas color and opcity
        color = bgs.get("fill-color", (0.7, 0.7, 0.7))
        cr.set_source_rgba(color[0], color[1], color[2],
                           bgs.get("fill-opacity", 1))
        cr.fill()
        callback()

        # canvas antialiasing
        antialias = bgs.get("antialias", "full")
        if antialias == "none":
            "no antialiasing enabled"
            cr.set_antialias(1)
            #cr.font_options_set_antialias(1)
        elif antialias == "text":
            "only text antialiased"
            cr.set_antialias(1)
            #cr.font_options_set_antialias(2)
        else:
            "full antialias"
            cr.set_antialias(2)
            #cr.font_options_set_antialias(2)

        datatimer = Timer("Asking backend")
        if "get_sql_hints" in dir(style):
            hints = style.get_sql_hints('way', self.zoom)
        else:
            hints = None
        if "get_interesting_tags" in dir(style):
            itags = style.get_interesting_tags(zoom=self.zoom)
        else:
            itags = None

        # enlarge bbox by 20% to each side. results in more vectors, but makes less artifaces.
        span_x, span_y = bbox[2] - bbox[0], bbox[3] - bbox[1]
        bbox_expand = [
            bbox[0] - 0.2 * span_x, bbox[1] - 0.2 * span_y,
            bbox[2] + 0.2 * span_x, bbox[3] + 0.2 * span_y
        ]
        vectors = self.data.get_vectors(bbox_expand, self.zoom, hints,
                                        itags).values()
        datatimer.stop()
        datatimer = Timer("Applying styles")
        ww = []

        for way in vectors:
            type = "line"
            if way.coords[0] == way.coords[-1]:
                type == "area"
            st = style.get_style("area", way.tags, self.zoom, scale, zscale)
            if st:
                for fpt in st:
                    #debug(fpt)
                    ww.append([way.copy(), fpt])

        datatimer.stop()
        debug("%s objects on screen (%s in dataset)" % (len(ww), len(vectors)))

        er = Timer("Projecing data")
        if self.data.proj != self.proj:
            for w in ww:
                w[0].cs = [
                    self.lonlat2screen(coord)
                    for coord in projections.transform(
                        w[0].coords, self.data.proj, self.proj)
                ]
        else:
            for w in ww:
                w[0].cs = [self.lonlat2screen(coord) for coord in w[0].coords]
        for w in ww:
            if "offset" in w[1]:
                offset = float(w[1]["offset"])
                w[0] = w[0].copy()
                w[0].cs = offset_line(w[0].cs, offset)
            if "raise" in w[1] and not "extrude" in w[1]:
                w[0] = w[0].copy()
                offset = float(w[1]["raise"])
                w[0].cs_real = w[0].cs
                w[0].cs = [(x, y - offset) for x, y in w[0].cs]
            if "extrude" in w[1]:
                if w[1]["extrude"] < 2:
                    del w[1]["extrude"]
            if "extrude" in w[1] and "fill-color" not in w[1] and "width" in w[
                    1]:
                w[1]["fill-color"] = w[1].get("color", (0, 0, 0))
                w[1]["fill-opacity"] = w[1].get("opacity", 1)
                w[0] = w[0].copy()
                #print w[0].cs
                w[0].cs = offset_line(w[0].cs, w[1]["width"] / 2)
                #print w[0].cs
                aa = offset_line(w[0].cs, -w[1]["width"])
                del w[1]["width"]
                aa.reverse()
                w[0].cs.extend(aa)

        er.stop()

        ww.sort(key=lambda x: x[1]["layer"])
        layers = list(set([int(x[1]["layer"] / 100.) for x in ww]))
        layers.sort()
        objs_by_layers = {}
        for layer in layers:
            objs_by_layers[layer] = []
        for obj in ww:
            objs_by_layers[int(obj[1]["layer"] / 100.)].append(obj)

        del ww
        timer.stop()
        timer = Timer("Rasterizing image")
        linecaps = {"butt": 0, "round": 1, "square": 2}
        linejoin = {"miter": 0, "round": 1, "bevel": 2}

        text_rendered_at = set([(-100, -100)])
        for layer in layers:
            data = objs_by_layers[layer]
            #data.sort(lambda x,y:cmp(max([x1[1] for x1 in x[0].cs]), max([x1[1] for x1 in y[0].cs])))

            # - fill polygons
            for obj in data:
                if ("fill-color" in obj[1] or "fill-image" in obj[1]
                    ) and not "extrude" in obj[1]:  ## TODO: fill-image
                    color = obj[1].get("fill-color", (0, 0, 0))
                    cr.set_source_rgba(color[0], color[1], color[2],
                                       obj[1].get("fill-opacity", 1))

                    if "fill-image" in obj[1]:
                        image = style.cache["image"][obj[1]["fill-image"]]
                        if image:
                            pattern = cairo.SurfacePattern(image)
                            pattern.set_extend(cairo.EXTEND_REPEAT)
                            cr.set_source(pattern)
                    poly(cr, obj[0].cs)

            # - draw casings on layer
            for obj in data:
                ### Extras: casing-linecap, casing-linejoin
                if "casing-width" in obj[1] or "casing-color" in obj[
                        1] and "extrude" not in obj[1]:
                    cr.set_dash(obj[1].get("casing-dashes",
                                           obj[1].get("dashes", [])))
                    cr.set_line_join(
                        linejoin.get(
                            obj[1].get("casing-linejoin",
                                       obj[1].get("linejoin", "round")), 1))
                    color = obj[1].get("casing-color", (0, 0, 0))
                    cr.set_source_rgba(color[0], color[1], color[2],
                                       obj[1].get("casing-opacity", 1))
                    ## TODO: good combining of transparent lines and casing
                    ## Probable solution: render casing, render way as mask and put casing with mask chopped out onto image

                    cr.set_line_width(obj[1].get("width", 0) +
                                      obj[1].get("casing-width", 1))
                    cr.set_line_cap(
                        linecaps.get(
                            obj[1].get("casing-linecap",
                                       obj[1].get("linecap", "butt")), 0))
                    line(cr, obj[0].cs)

            # - draw line centers
            for obj in data:
                if ("width" in obj[1] or "color" in obj[1]
                        or "image" in obj[1]) and "extrude" not in obj[1]:
                    cr.set_dash(obj[1].get("dashes", []))
                    cr.set_line_join(
                        linejoin.get(obj[1].get("linejoin", "round"), 1))
                    color = obj[1].get("color", (0, 0, 0))
                    cr.set_source_rgba(color[0], color[1], color[2],
                                       obj[1].get("opacity", 1))
                    ## TODO: better overlapping of transparent lines.
                    ## Probable solution: render them (while they're of the same opacity and layer) on a temporary canvas that's merged into main later
                    cr.set_line_width(obj[1].get("width", 1))
                    cr.set_line_cap(
                        linecaps.get(obj[1].get("linecap", "butt"), 0))
                    if "image" in obj[1]:
                        image = style.cache["image"][obj[1]["image"]]
                        if image:
                            pattern = cairo.SurfacePattern(image)
                            pattern.set_extend(cairo.EXTEND_REPEAT)
                            cr.set_source(pattern)
                    line(cr, obj[0].cs)

            callback()

            # - extruding polygons
            #data.sort(lambda x,y:cmp(max([x1[1] for x1 in x[0].cs]), max([x1[1] for x1 in y[0].cs])))
            # Pass 1. Creating list of extruded polygons
            extlist = []
            # fromat: (coords, ("h"/"v", y,z), real_obj)
            for obj in data:
                if "extrude" in obj[1]:

                    def face_to_poly(face, hgt):
                        """
            Converts a line into height-up extruded poly
            """
                        return [
                            face[0], face[1], (face[1][0], face[1][1] - hgt),
                            (face[0][0], face[0][1] - hgt), face[0]
                        ]

                    hgt = obj[1]["extrude"]
                    raised = float(obj[1].get("raise", 0))
                    excoords = [(a[0], a[1] - hgt - raised) for a in obj[0].cs]

                    faces = []
                    coord = obj[0].cs[-1]
                    #p_coord = (coord[0],coord[1]-raised)
                    p_coord = False
                    for coord in obj[0].cs:
                        c = (coord[0], coord[1] - raised)
                        if p_coord:
                            extlist.append((face_to_poly([c, p_coord], hgt),
                                            ("v", min(coord[1],
                                                      p_coord[1]), hgt), obj))
                        p_coord = c

                    extlist.append(
                        (excoords, ("h", min(coord[1], p_coord[1]), hgt), obj))
                    #faces.sort(lambda x,y:cmp(max([x1[1] for x1 in x]), max([x1[1] for x1 in y])))

            # Pass 2. Sorting
            def compare_things(a, b):
                """
        Custom comparator for extlist sorting.
        Sorts back-to-front, bottom-to-top, | > \ > _, horizontal-to-vertical.
        """
                t1, t2 = a[1], b[1]  #
                if t1[1] > t2[1]:  # back-to-front
                    return 1
                if t1[1] < t2[1]:
                    return -1
                if t1[2] > t2[2]:  # bottom-to-top
                    return 1
                if t1[2] < t2[2]:
                    return -1
                if t1[0] < t2[0]:  # h-to-v
                    return 1
                if t1[0] > t2[0]:
                    return -1

                return cmp(
                    math.sin(
                        math.atan2(a[0][0][0] - a[0][1][0],
                                   a[0][0][0] - a[0][1][0])),
                    math.sin(
                        math.atan2(b[0][0][0] - b[0][1][0],
                                   b[0][0][0] - b[0][1][0])))
                print t1
                print t2

            extlist.sort(compare_things)

            # Pass 3. Rendering using painter's algorythm
            cr.set_dash([])
            for ply, prop, obj in extlist:
                if prop[0] == "v":
                    color = obj[1].get("extrude-face-color",
                                       obj[1].get("color", (0, 0, 0)))
                    cr.set_source_rgba(
                        color[0], color[1], color[2],
                        obj[1].get("extrude-face-opacity",
                                   obj[1].get("opacity", 1)))
                    poly(cr, ply)
                    color = obj[1].get("extrude-edge-color",
                                       obj[1].get("color", (0, 0, 0)))
                    cr.set_source_rgba(
                        color[0], color[1], color[2],
                        obj[1].get("extrude-edge-opacity",
                                   obj[1].get("opacity", 1)))
                    cr.set_line_width(.5)
                    line(cr, ply)
                if prop[0] == "h":
                    if "fill-color" in obj[1]:
                        color = obj[1]["fill-color"]
                        cr.set_source_rgba(
                            color[0], color[1], color[2],
                            obj[1].get("fill-opacity",
                                       obj[1].get("opacity", 1)))
                        poly(cr, ply)
                    color = obj[1].get("extrude-edge-color",
                                       obj[1].get("color", (0, 0, 0)))
                    cr.set_source_rgba(
                        color[0], color[1], color[2],
                        obj[1].get("extrude-edge-opacity",
                                   obj[1].get("opacity", 1)))
                    cr.set_line_width(1)
                    line(cr, ply)

                #cr.set_line_width (obj[1].get("width", 1))
                #color = obj[1].get("color", (0,0,0) )
                #cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("extrude-edge-opacity", obj[1].get("opacity", 1)))
                #line(cr,excoords)
                #if "fill-color" in obj[1]:
                #color = obj[1]["fill-color"]
                #cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("fill-opacity", 1))
                #poly(cr,excoords)
            for obj in data:
                if "icon-image" in obj[1]:
                    image = style.cache["image"][obj[1]["icon-image"]]
                    if image:
                        dy = image.get_height() / 2
                        dx = image.get_width() / 2

                        where = self.lonlat2screen(
                            projections.transform(obj[0].center,
                                                  self.data.proj, self.proj))
                        cr.set_source_surface(image, where[0] - dx,
                                              where[1] - dy)
                        cr.paint()

            callback()
            # - render text labels
            texttimer = Timer("Text rendering")
            cr.set_line_join(
                1
            )  # setting linejoin to "round" to get less artifacts on halo render
            for obj in data:
                if "text" in obj[1]:

                    text = obj[1]["text"]
                    #cr.set_line_width (obj[1].get("width", 1))
                    #cr.set_font_size(float(obj[1].get("font-size", 9)))
                    ft_desc = pango.FontDescription()

                    ft_desc.set_family(obj[1].get('font-family', 'sans'))
                    ft_desc.set_size(pango.SCALE *
                                     int(obj[1].get('font-size', 9)))
                    fontstyle = obj[1].get('font-style', 'normal')
                    if fontstyle == 'italic':
                        fontstyle = pango.STYLE_ITALIC
                    else:
                        fontstyle = pango.STYLE_NORMAL
                    ft_desc.set_style(fontstyle)
                    fontweight = obj[1].get('font-weight', 400)
                    try:
                        fontweight = int(fontweight)
                    except ValueError:
                        if fontweight == 'bold':
                            fontweight = 700
                        else:
                            fontweight = 400
                    ft_desc.set_weight(fontweight)
                    if obj[1].get('text-transform', None) == 'uppercase':
                        text = text.upper()
                    p_ctx = pangocairo.CairoContext(cr)
                    p_layout = p_ctx.create_layout()
                    p_layout.set_font_description(ft_desc)
                    p_layout.set_text(text)
                    p_attrs = pango.AttrList()
                    decoration = obj[1].get('text-decoration', 'none')
                    if decoration == 'underline':
                        p_attrs.insert(
                            pango.AttrUnderline(pango.UNDERLINE_SINGLE,
                                                end_index=-1))
                    decoration = obj[1].get('font-variant', 'none')
                    if decoration == 'small-caps':
                        p_attrs.insert(
                            pango.AttrVariant(pango.VARIANT_SMALL_CAPS,
                                              start_index=0,
                                              end_index=-1))

                    p_layout.set_attributes(p_attrs)

                    if obj[1].get("text-position", "center") == "center":
                        where = self.lonlat2screen(
                            projections.transform(obj[0].center,
                                                  self.data.proj, self.proj))
                        for t in text_rendered_at:
                            if ((t[0] - where[0])**2 +
                                (t[1] - where[1])**2) < 15 * 15:
                                break
                        else:
                            text_rendered_at.add(where)
                            #debug ("drawing text: %s at %s"%(text, where))
                            if "text-halo-color" in obj[
                                    1] or "text-halo-radius" in obj[1]:
                                cr.new_path()
                                cr.move_to(where[0], where[1])
                                cr.set_line_width(obj[1].get(
                                    "text-halo-radius", 1))
                                color = obj[1].get("text-halo-color",
                                                   (1., 1., 1.))
                                cr.set_source_rgb(color[0], color[1], color[2])
                                cr.text_path(text)
                                cr.stroke()
                            cr.new_path()
                            cr.move_to(where[0], where[1])
                            cr.set_line_width(obj[1].get(
                                "text-halo-radius", 1))
                            color = obj[1].get("text-color", (0., 0., 0.))
                            cr.set_source_rgb(color[0], color[1], color[2])
                            cr.text_path(text)
                            cr.fill()
                    else:  ### render text along line
                        c = obj[0].cs
                        text = unicode(text, "utf-8")
                        # - calculate line length
                        length = reduce(
                            lambda x, y: (x[0] +
                                          ((y[0] - x[1])**2 +
                                           (y[1] - x[2])**2)**0.5, y[0], y[1]),
                            c, (0, c[0][0], c[0][1]))[0]
                        #print length, text, cr.text_extents(text)
                        if length > cr.text_extents(text)[2]:

                            # - function to get (x, y, normale) from (c, length_along_c)
                            def get_xy_from_len(c, length_along_c):
                                x0, y0 = c[0]

                                for x, y in c:
                                    seg_len = ((x - x0)**2 + (y - y0)**2)**0.5
                                    if length_along_c < seg_len:
                                        normed = length_along_c / seg_len
                                        return (x - x0) * normed + x0, (
                                            y - y0) * normed + y0, math.atan2(
                                                y - y0, x - x0)
                                    else:
                                        length_along_c -= seg_len
                                        x0, y0 = x, y
                                else:
                                    return None

                            da = 0
                            os = 1
                            z = length / 2 - cr.text_extents(text)[2] / 2
                            #  print get_xy_from_len(c,z)
                            if c[0][0] < c[1][0] and get_xy_from_len(
                                    c, z)[2] < math.pi / 2 and get_xy_from_len(
                                        c, z)[2] > -math.pi / 2:
                                da = 0
                                os = 1
                                z = length / 2 - cr.text_extents(text)[2] / 2
                            else:
                                da = math.pi
                                os = -1
                                z = length / 2 + cr.text_extents(text)[2] / 2
                            z1 = z
                            if "text-halo-color" in obj[
                                    1] or "text-halo-radius" in obj[1]:
                                cr.set_line_width(
                                    obj[1].get("text-halo-radius", 1.5) * 2)
                                color = obj[1].get("text-halo-color",
                                                   (1., 1., 1.))
                                cr.set_source_rgb(color[0], color[1], color[2])
                                xy = get_xy_from_len(c, z)
                                cr.save()
                                #cr.move_to(xy[0],xy[1])
                                p_ctx.translate(xy[0], xy[1])
                                cr.rotate(xy[2] + da)
                                #p_ctx.translate(x,y)
                                #p_ctx.show_layout(p_layout)
                                p_ctx.layout_path(p_layout)

                                cr.restore()
                                cr.stroke()
                                #for letter in text:
                                #cr.new_path()
                                #xy = get_xy_from_len(c,z)
                                ##print letter, cr.text_extents(letter)
                                #cr.move_to(xy[0],xy[1])
                                #cr.save()
                                #cr.rotate(xy[2]+da)
                                #cr.text_path(letter)
                                #cr.restore()
                                #cr.stroke()
                                #z += os*cr.text_extents(letter)[4]

                            color = obj[1].get("text-color", (0., 0., 0.))
                            cr.set_source_rgb(color[0], color[1], color[2])
                            z = z1
                            xy = get_xy_from_len(c, z)
                            cr.save()
                            #cr.move_to(xy[0],xy[1])
                            p_ctx.translate(xy[0], xy[1])
                            cr.rotate(xy[2] + da)
                            #p_ctx.translate(x,y)
                            p_ctx.show_layout(p_layout)
                            cr.restore()

                            #for letter in text:
                            #cr.new_path()
                            #xy = get_xy_from_len(c,z)
                            ##print letter, cr.text_extents(letter)
                            #cr.move_to(xy[0],xy[1])
                            #cr.save()
                            #cr.rotate(xy[2]+da)
                            #cr.text_path(letter)
                            #cr.restore()
                            #cr.fill()
                            #z += os*cr.text_extents(letter)[4]

            texttimer.stop()
            del data
        del layers

        timer.stop()
        rendertimer.stop()
        debug(self.bbox)
        callback(True)
Ejemplo n.º 13
0
    def __del__(self):
        del self.surface

    def screen2lonlat(self, x, y):
        lo1, la1, lo2, la2 = self.bbox_p
        debug("%s %s - %s %s" % (x, y, self.w, self.h))
        debug(self.bbox_p)
        return projections.to4326((1. * x / self.w * (lo2 - lo1) + lo1, la2 +
                                   (1. * y / (self.h) * (la1 - la2))),
                                  self.proj)

    #  return (x - self.w/2)/(math.cos(self.center_coord[1]*math.pi/180)*self.zoom) + self.center_coord[0], -(y - self.h/2)/self.zoom + self.center_coord[1]
    def lonlat2screen(self, (lon, lat), epsg4326=False):
        if epsg4326:
            lon, lat = projections.from4326((lon, lat), self.proj)
        lo1, la1, lo2, la2 = self.bbox_p
        return ((lon - lo1) * (self.w - 1) / abs(lo2 - lo1),
                ((la2 - lat) * (self.h - 1) / (la2 - la1)))

    #  return (lon - self.center_coord[0])*self.lcc*self.zoom + self.w/2, -(lat - self.center_coord[1])*self.zoom + self.h/2
    def update_surface_by_center(self, lonlat, zoom, style):
        self.zoom = zoom
        xy = projections.from4326(lonlat, self.proj)
        xy1 = projections.to4326(
            (xy[0] - 40075016 * 0.5**self.zoom / 256 * self.w,
             xy[1] - 40075016 * 0.5**self.zoom / 256 * self.h), self.proj)
        xy2 = projections.to4326(
            (xy[0] + 40075016 * 0.5**self.zoom / 256 * self.w,
             xy[1] + 40075016 * 0.5**self.zoom / 256 * self.h), self.proj)
        bbox = (xy1[0], xy1[1], xy2[0], xy2[1])
Ejemplo n.º 14
0
  def update_surface(self, bbox, zoom, style, callback = lambda x=None: None):
    rendertimer = Timer("Rendering image")
    if "image" not in style.cache:
      style.cache["image"] = ImageLoader()

    
    timer = Timer("Getting data")
    self.zoom = zoom
    self.bbox = bbox
    self.bbox_p = projections.from4326(bbox,self.proj)
    
    print self.bbox_p
    scale = abs(self.w/(self.bbox_p[0] - self.bbox_p[2])/math.cos(math.pi*(self.bbox[1]+self.bbox[3])/2/180))
    zscale = 0.5*scale
    cr = cairo.Context(self.surface)
    # getting and setting canvas properties
    bgs = style.get_style("canvas", {}, self.zoom, scale, zscale)
    if not bgs:
      bgs = [{}]
    bgs = bgs[0]
    cr.rectangle(0, 0, self.w, self.h)
    # canvas color and opcity
    color = bgs.get("fill-color",(0.7, 0.7, 0.7))
    cr.set_source_rgba(color[0], color[1], color[2], bgs.get("fill-opacity", 1))
    cr.fill()
    callback()

    # canvas antialiasing
    antialias = bgs.get("antialias", "full")
    if   antialias == "none":
      "no antialiasing enabled"
      cr.set_antialias(1)
      #cr.font_options_set_antialias(1)
    elif antialias == "text":
      "only text antialiased"
      cr.set_antialias(1)
      #cr.font_options_set_antialias(2)
    else:
      "full antialias"
      cr.set_antialias(2)
      #cr.font_options_set_antialias(2)


    
    datatimer = Timer("Asking backend")
    if "get_sql_hints" in dir(style):
      hints = style.get_sql_hints('way', self.zoom)
    else:
      hints = None
    if "get_interesting_tags" in dir(style):
      itags = style.get_interesting_tags(zoom=self.zoom)
    else:
      itags = None

    # enlarge bbox by 20% to each side. results in more vectors, but makes less artifaces.
    span_x, span_y = bbox[2]-bbox[0], bbox[3]-bbox[1]
    bbox_expand = [bbox[0]-0.2*span_x,bbox[1]-0.2*span_y,bbox[2]+0.2*span_x,bbox[3]+0.2*span_y]
    vectors = self.data.get_vectors(bbox_expand,self.zoom,hints,itags).values()
    datatimer.stop()
    datatimer = Timer("Applying styles")
    ww = []

    for way in vectors:
      type = "line"
      if way.coords[0] == way.coords[-1]:
        type == "area"
      st = style.get_style("area", way.tags, self.zoom, scale, zscale)
      if st:
       for fpt in st:
        #debug(fpt)
        ww.append([way.copy(), fpt])
    
    datatimer.stop()
    debug( "%s objects on screen (%s in dataset)"%(len(ww),len(vectors)) )

    er = Timer("Projecing data")
    if self.data.proj != self.proj:
      for w in ww:
        w[0].cs = [self.lonlat2screen(coord) for coord in projections.transform(w[0].coords, self.data.proj, self.proj)]
    else:
      for w in ww:
        w[0].cs = [self.lonlat2screen(coord) for coord in w[0].coords]
    for w in ww:
      if "offset" in w[1]:
        offset = float(w[1]["offset"])
        w[0] = w[0].copy()
        w[0].cs = offset_line(w[0].cs, offset)
      if "raise" in w[1] and not "extrude" in w[1]:
        w[0] = w[0].copy()
        offset = float(w[1]["raise"])
        w[0].cs_real = w[0].cs
        w[0].cs = [(x,y-offset) for x,y in w[0].cs]
      if "extrude" in w[1]:
        if w[1]["extrude"]<2:
          del w[1]["extrude"]
      if "extrude" in w[1] and "fill-color" not in w[1] and "width" in w[1]:
        w[1]["fill-color"] = w[1].get("color", (0,0,0))
        w[1]["fill-opacity"] = w[1].get("opacity", 1)
        w[0] = w[0].copy()
        #print w[0].cs
        w[0].cs = offset_line(w[0].cs, w[1]["width"]/2)
        #print w[0].cs
        aa = offset_line(w[0].cs, -w[1]["width"])
        del w[1]["width"] 
        aa.reverse()
        w[0].cs.extend(aa)


    er.stop()


    ww.sort(key=lambda x: x[1]["layer"])
    layers = list(set([int(x[1]["layer"]/100.) for x in ww]))
    layers.sort()
    objs_by_layers = {}
    for layer in layers:
      objs_by_layers[layer] = []
    for obj in ww:
      objs_by_layers[int(obj[1]["layer"]/100.)].append(obj)

    del ww
    timer.stop()
    timer = Timer("Rasterizing image")
    linecaps = {"butt":0, "round":1, "square":2}
    linejoin = {"miter":0, "round":1, "bevel":2}

    text_rendered_at = set([(-100,-100)])
    for layer in layers:
      data = objs_by_layers[layer]
      #data.sort(lambda x,y:cmp(max([x1[1] for x1 in x[0].cs]), max([x1[1] for x1 in y[0].cs])))
      



      # - fill polygons
      for obj in data:
        if ("fill-color" in obj[1] or "fill-image"  in obj[1]) and not "extrude" in obj[1]:   ## TODO: fill-image
          color = obj[1].get("fill-color", (0,0,0))
          cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("fill-opacity", 1))

          if "fill-image" in obj[1]:
            image = style.cache["image"][obj[1]["fill-image"]]
            if image:
              pattern = cairo.SurfacePattern(image)
              pattern.set_extend(cairo.EXTEND_REPEAT)
              cr.set_source(pattern)
          poly(cr, obj[0].cs)

      # - draw casings on layer
      for obj in data:
        ### Extras: casing-linecap, casing-linejoin
        if "casing-width" in obj[1] or "casing-color" in obj[1] and "extrude" not in obj[1]:
          cr.set_dash(obj[1].get("casing-dashes",obj[1].get("dashes", [])))
          cr.set_line_join(linejoin.get(obj[1].get("casing-linejoin",obj[1].get("linejoin", "round")),1))
          color = obj[1].get("casing-color", (0,0,0))
          cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("casing-opacity", 1))
                ## TODO: good combining of transparent lines and casing
                ## Probable solution: render casing, render way as mask and put casing with mask chopped out onto image


          cr.set_line_width (obj[1].get("width",0)+obj[1].get("casing-width", 1 ))
          cr.set_line_cap(linecaps.get(obj[1].get("casing-linecap", obj[1].get("linecap", "butt")),0))
          line(cr, obj[0].cs)

      # - draw line centers
      for obj in data:
        if ("width" in obj[1] or "color" in obj[1] or "image" in obj[1]) and "extrude" not in obj[1]:
          cr.set_dash(obj[1].get("dashes", []))
          cr.set_line_join(linejoin.get(obj[1].get("linejoin", "round"),1))
          color = obj[1].get("color", (0,0,0))
          cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("opacity", 1))
                ## TODO: better overlapping of transparent lines.
                ## Probable solution: render them (while they're of the same opacity and layer) on a temporary canvas that's merged into main later
          cr.set_line_width (obj[1].get("width", 1))
          cr.set_line_cap(linecaps.get(obj[1].get("linecap", "butt"),0))
          if "image" in obj[1]:
            image = style.cache["image"][obj[1]["image"]]
            if image:
              pattern = cairo.SurfacePattern(image)
              pattern.set_extend(cairo.EXTEND_REPEAT)
              cr.set_source(pattern)
          line(cr, obj[0].cs)


      callback()

      # - extruding polygons
      #data.sort(lambda x,y:cmp(max([x1[1] for x1 in x[0].cs]), max([x1[1] for x1 in y[0].cs])))
      # Pass 1. Creating list of extruded polygons
      extlist = []
      # fromat: (coords, ("h"/"v", y,z), real_obj)
      for obj in data:
        if "extrude" in obj[1]:
          def face_to_poly(face, hgt):
            """
            Converts a line into height-up extruded poly
            """
            return [face[0], face[1], (face[1][0], face[1][1]-hgt), (face[0][0], face[0][1]-hgt), face[0]]
          hgt = obj[1]["extrude"]
          raised = float(obj[1].get("raise",0))
          excoords = [(a[0],a[1]-hgt-raised) for a in obj[0].cs]

          faces = []
          coord = obj[0].cs[-1]
          #p_coord = (coord[0],coord[1]-raised)
          p_coord = False
          for coord in obj[0].cs:
            c = (coord[0],coord[1]-raised)
            if p_coord:
              extlist.append( (face_to_poly([c, p_coord],hgt), ("v", min(coord[1],p_coord[1]), hgt), obj ))
            p_coord = c
          
          extlist.append( (excoords, ("h", min(coord[1],p_coord[1]), hgt), obj ))
          #faces.sort(lambda x,y:cmp(max([x1[1] for x1 in x]), max([x1[1] for x1 in y])))


      # Pass 2. Sorting 
      def compare_things(a,b):
        """
        Custom comparator for extlist sorting.
        Sorts back-to-front, bottom-to-top, | > \ > _, horizontal-to-vertical.
        """
        t1,t2 = a[1],b[1] # 
        if t1[1] > t2[1]: # back-to-front
          return 1
        if t1[1] < t2[1]:
          return -1
        if t1[2] > t2[2]: # bottom-to-top
          return 1
        if t1[2] < t2[2]:
          return -1
        if t1[0] < t2[0]: # h-to-v
          return 1
        if t1[0] > t2[0]:
          return -1
          
        return cmp(math.sin(math.atan2(a[0][0][0]-a[0][1][0],a[0][0][0]-a[0][1][0])),math.sin(math.atan2(b[0][0][0]-b[0][1][0],b[0][0][0]-b[0][1][0])))
        print t1
        print t2

      extlist.sort(compare_things)
      
      # Pass 3. Rendering using painter's algorythm
      cr.set_dash([])
      for ply, prop, obj in extlist:
        if prop[0] == "v":
          color = obj[1].get("extrude-face-color", obj[1].get("color", (0,0,0) ))
          cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("extrude-face-opacity", obj[1].get("opacity", 1)))
          poly(cr, ply)
          color = obj[1].get("extrude-edge-color", obj[1].get("color", (0,0,0) ))
          cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("extrude-edge-opacity", obj[1].get("opacity", 1)))
          cr.set_line_width (.5)
          line(cr, ply)
        if prop[0] == "h":
          if "fill-color" in obj[1]:
            color = obj[1]["fill-color"]
            cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("fill-opacity", obj[1].get("opacity", 1)))
            poly(cr,ply)
          color = obj[1].get("extrude-edge-color", obj[1].get("color", (0,0,0) ))
          cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("extrude-edge-opacity", obj[1].get("opacity", 1)))
          cr.set_line_width (1)
          line(cr, ply)

        #cr.set_line_width (obj[1].get("width", 1))
        #color = obj[1].get("color", (0,0,0) )
        #cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("extrude-edge-opacity", obj[1].get("opacity", 1)))
        #line(cr,excoords)
        #if "fill-color" in obj[1]:
          #color = obj[1]["fill-color"]
          #cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("fill-opacity", 1))
          #poly(cr,excoords)
      for obj in data:
        if "icon-image" in obj[1]:
          image = style.cache["image"][obj[1]["icon-image"]]
          if image:
            dy = image.get_height()/2
            dx = image.get_width()/2

            where = self.lonlat2screen(projections.transform(obj[0].center,self.data.proj,self.proj))
            cr.set_source_surface(image, where[0]-dx, where[1]-dy)
            cr.paint()


      callback()
      # - render text labels
      texttimer = Timer("Text rendering")
      cr.set_line_join(1)  # setting linejoin to "round" to get less artifacts on halo render
      for obj in data:
        if "text" in obj[1]:
          
          text = obj[1]["text"]
          #cr.set_line_width (obj[1].get("width", 1))
          #cr.set_font_size(float(obj[1].get("font-size", 9)))
          ft_desc = pango.FontDescription()
          
          ft_desc.set_family(obj[1].get('font-family', 'sans'))
          ft_desc.set_size(pango.SCALE*int(obj[1].get('font-size',9)))
          fontstyle = obj[1].get('font-style', 'normal')
          if fontstyle == 'italic':
            fontstyle = pango.STYLE_ITALIC
          else:
            fontstyle = pango.STYLE_NORMAL
          ft_desc.set_style(fontstyle)
          fontweight = obj[1].get('font-weight', 400)
          try:
            fontweight = int(fontweight)
          except ValueError:
            if fontweight == 'bold':
              fontweight = 700
            else:
              fontweight = 400
          ft_desc.set_weight(fontweight)
          if obj[1].get('text-transform', None) == 'uppercase':
            text = text.upper()
          p_ctx = pangocairo.CairoContext(cr)
          p_layout = p_ctx.create_layout()
          p_layout.set_font_description(ft_desc)
          p_layout.set_text(text)
          p_attrs = pango.AttrList()
          decoration = obj[1].get('text-decoration', 'none')
          if decoration == 'underline':
            p_attrs.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE,end_index=-1))
          decoration = obj[1].get('font-variant', 'none')
          if decoration == 'small-caps':
              p_attrs.insert(pango.AttrVariant(pango.VARIANT_SMALL_CAPS, start_index=0, end_index=-1))

          p_layout.set_attributes(p_attrs)
          
          
          if obj[1].get("text-position", "center") == "center":
            where = self.lonlat2screen(projections.transform(obj[0].center,self.data.proj,self.proj))
            for t in text_rendered_at:
              if ((t[0]-where[0])**2+(t[1]-where[1])**2) < 15*15:
                break
            else:
                text_rendered_at.add(where)
            #debug ("drawing text: %s at %s"%(text, where))
                if "text-halo-color" in obj[1] or "text-halo-radius" in obj[1]:
                  cr.new_path()
                  cr.move_to(where[0], where[1])
                  cr.set_line_width (obj[1].get("text-halo-radius", 1))
                  color = obj[1].get("text-halo-color", (1.,1.,1.))
                  cr.set_source_rgb(color[0], color[1], color[2])
                  cr.text_path(text)
                  cr.stroke()
                cr.new_path()
                cr.move_to(where[0], where[1])
                cr.set_line_width (obj[1].get("text-halo-radius", 1))
                color = obj[1].get("text-color", (0.,0.,0.))
                cr.set_source_rgb(color[0], color[1], color[2])
                cr.text_path(text)
                cr.fill()
          else:  ### render text along line
            c = obj[0].cs
            text = unicode(text,"utf-8")
            # - calculate line length
            length = reduce(lambda x,y: (x[0]+((y[0]-x[1])**2 + (y[1]-x[2])**2 )**0.5, y[0], y[1]), c, (0,c[0][0],c[0][1]))[0]
            #print length, text, cr.text_extents(text)
            if length > cr.text_extents(text)[2]:

              # - function to get (x, y, normale) from (c, length_along_c)
              def get_xy_from_len(c,length_along_c):
                x0, y0 = c[0]
                
                for x,y in c:
                  seg_len = ((x-x0)**2+(y-y0)**2)**0.5
                  if length_along_c < seg_len:
                    normed =  length_along_c /seg_len
                    return (x-x0)*normed+x0, (y-y0)*normed+y0, math.atan2(y-y0,x-x0)
                  else:
                    length_along_c -= seg_len
                    x0,y0 = x,y
                else:
                  return None
              da = 0
              os = 1
              z = length/2-cr.text_extents(text)[2]/2
           #  print get_xy_from_len(c,z)
              if c[0][0] < c[1][0] and get_xy_from_len(c,z)[2]<math.pi/2 and get_xy_from_len(c,z)[2] > -math.pi/2:
                da = 0
                os = 1
                z = length/2-cr.text_extents(text)[2]/2
              else:
                da = math.pi
                os = -1
                z = length/2+cr.text_extents(text)[2]/2
              z1=z
              if "text-halo-color" in obj[1] or "text-halo-radius" in obj[1]:
                cr.set_line_width (obj[1].get("text-halo-radius", 1.5)*2)
                color = obj[1].get("text-halo-color", (1.,1.,1.))
                cr.set_source_rgb(color[0], color[1], color[2])
                xy = get_xy_from_len(c,z)
                cr.save()
                #cr.move_to(xy[0],xy[1])
                p_ctx.translate(xy[0],xy[1])
                cr.rotate(xy[2]+da)
                #p_ctx.translate(x,y)
                #p_ctx.show_layout(p_layout)
                p_ctx.layout_path(p_layout)
                
                cr.restore()
                cr.stroke()
                #for letter in text:
                  #cr.new_path()
                  #xy = get_xy_from_len(c,z)
                  ##print letter, cr.text_extents(letter)
                  #cr.move_to(xy[0],xy[1])
                  #cr.save()
                  #cr.rotate(xy[2]+da)
                  #cr.text_path(letter)
                  #cr.restore()
                  #cr.stroke()
                  #z += os*cr.text_extents(letter)[4]

              color = obj[1].get("text-color", (0.,0.,0.))
              cr.set_source_rgb(color[0], color[1], color[2])
              z = z1
              xy = get_xy_from_len(c,z)
              cr.save()
              #cr.move_to(xy[0],xy[1])
              p_ctx.translate(xy[0],xy[1])
              cr.rotate(xy[2]+da)
              #p_ctx.translate(x,y)
              p_ctx.show_layout(p_layout)
              cr.restore()
              
              #for letter in text:
                #cr.new_path()
                #xy = get_xy_from_len(c,z)
                ##print letter, cr.text_extents(letter)
                #cr.move_to(xy[0],xy[1])
                #cr.save()
                #cr.rotate(xy[2]+da)
                #cr.text_path(letter)
                #cr.restore()
                #cr.fill()
                #z += os*cr.text_extents(letter)[4]

      texttimer.stop()
      del data
    del layers

    timer.stop()
    rendertimer.stop()
    debug(self.bbox)
    callback(True)
Ejemplo n.º 15
0
    self.bbox_p = (0.,0.,0.,0.)
    self.zoomlevel = zoomlevel
    self.zoom = None
    self.data = data_backend
    self.proj = raster_proj
  def __del__(self):
    del self.surface
  def screen2lonlat(self, x, y):
    lo1, la1, lo2, la2 = self.bbox_p
    debug ("%s %s - %s %s"%(x,y,self.w, self.h))
    debug(self.bbox_p)
    return projections.to4326( (1.*x/self.w*(lo2-lo1)+lo1, la2+(1.*y/(self.h)*(la1-la2))),self.proj)
  #  return (x - self.w/2)/(math.cos(self.center_coord[1]*math.pi/180)*self.zoom) + self.center_coord[0], -(y - self.h/2)/self.zoom + self.center_coord[1]
  def lonlat2screen(self, (lon, lat), epsg4326=False):
    if epsg4326:
      lon, lat = projections.from4326((lon,lat),self.proj)
    lo1, la1, lo2, la2 = self.bbox_p
    return ((lon-lo1)*(self.w-1)/abs(lo2-lo1), ((la2-lat)*(self.h-1)/(la2-la1)))
  #  return (lon - self.center_coord[0])*self.lcc*self.zoom + self.w/2, -(lat - self.center_coord[1])*self.zoom + self.h/2
  def update_surface_by_center(self, lonlat, zoom, style):
    self.zoom = zoom
    xy = projections.from4326(lonlat, self.proj)
    xy1 = projections.to4326((xy[0]-40075016*0.5**self.zoom/256*self.w, xy[1]-40075016*0.5**self.zoom/256*self.h), self.proj)
    xy2 = projections.to4326((xy[0]+40075016*0.5**self.zoom/256*self.w, xy[1]+40075016*0.5**self.zoom/256*self.h), self.proj)
    bbox = (xy1[0],xy1[1],xy2[0],xy2[1])
    debug (bbox)
    return self.update_surface(bbox, zoom, style)

    
  def update_surface(self, bbox, zoom, style, callback = lambda x=None: None):
    rendertimer = Timer("Rendering image")
Ejemplo n.º 16
0
    def get_vectors (self, bbox, zoom, sql_hint = None, tags_hint = None):
        """
        Fetches vectors for given bbox.
        sql_hint is a list of sets of (key, sql_for_key)
        """
        a = psycopg2.connect(self.database)
        b = a.cursor()
        bbox = tuple(projections.from4326(bbox,self.proj))
        ### FIXME: hardcoded EPSG:3857 in database
        tables = ("planet_osm_line","planet_osm_polygon")  # FIXME: points
        resp = {}
        for table in tables:
            add = ""
            taghint = "*"
            if sql_hint:
                adp = []

                for tp in sql_hint:
                    add = []
                    b.execute("SELECT * FROM %s LIMIT 1;"%table)
                    names = [q[0] for q in b.description]

                    for j in tp[0]:
                        if j not in names:
                            break
                    else:
                        add.append(tp[1])
                    if add:
                        add = " OR ".join(add)
                        add = "("+add+")"
                        adp.append(add)

                    if tags_hint:
                        taghint = ", ".join(['"'+j+'"' for j in tags_hint if j in names])+ ", way, osm_id"


                adp = " OR ".join(adp)


            req = "SELECT %s FROM %s WHERE (%s) and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913);"%(taghint,table,adp,bbox[0],bbox[1],bbox[2],bbox[3])
            print req
            b.execute(req)
            names = [q[0] for q in b.description]

            for row in b.fetchall():

                row_dict = dict(map(None,names,row))
                for k,v in row_dict.items():
                    if not v:
                        del row_dict[k]
                geom = shapely.wkb.loads(row_dict["way"].decode('hex'))
                ### FIXME: a dirty hack to basically support polygons, needs lots of rewrite
                try:
                    geom = list(geom.coords)
                except NotImplementedError:
                    "trying polygons"
                    try:
                        geom = geom.boundary
                        geom = list(geom.coords)
                        row_dict[":area"] = "yes"
                    except NotImplementedError:
                        "multipolygon"
                        continue
                        ### FIXME

                #geom = projections.to4326(geom, self.proj)
                del row_dict["way"]
                oid = row_dict["osm_id"]
                del row_dict["osm_id"]
                w = Way(row_dict, geom)
                #print row_dict
                resp[oid] = w
        a.close()
        del a

        return resp