在Mapnik上绘制点

时间:2013-07-31 14:38:57

标签: python-2.7 plot mapnik

我在mapnik github wiki中按照本教程制作了一张世界地图:https://github.com/mapnik/mapnik/wiki/GettingStartedInPython

我修改了这个例子,现在已经将代码嵌入到Pyside Qt Widget中。我现在的问题是,如何使用x和y坐标或纬度和经度点在此地图上绘制点?

以下是我用于生成地图并将其嵌入窗口小部件的代码:

    import mapnik
    m = mapnik.Map(1200,600)
    m.background = mapnik.Color('steelblue')
    s = mapnik.Style()
    r = mapnik.Rule()
    polygon_symbolizer = mapnik.PolygonSymbolizer(mapnik.Color('#f2eff9'))
    r.symbols.append(polygon_symbolizer)
    line_symbolizer = mapnik.LineSymbolizer(mapnik.Color('rgb(50%,50%,50%)'),0.1)
    r.symbols.append(line_symbolizer)
    s.rules.append(r)
    m.append_style('My Style',s)
    ds = mapnik.Shapefile(file='/home/lee/shapefiles/ne_110m_admin_0_countries.shp')
    layer = mapnik.Layer('world')
    layer.datasource = ds
    layer.styles.append('My Style')
    m.layers.append(layer)
    m.zoom_all()


    im = mapnik.Image(1200,600)
    mapnik.render(m, im)

    qim = QImage()
    qim.loadFromData(QByteArray(im.tostring('png')))

    label = QLabel(self)

    label.setPixmap(QPixmap.fromImage(qim))

    self.layout.addWidget(label)

2 个答案:

答案 0 :(得分:0)

如果您需要从像素坐标获取地理坐标(即:lat / lon),则可能需要添加转换器功能。

Google Maps JS代码如下可能有所帮助: https://developers.google.com/maps/documentation/javascript/examples/map-coordinates

var TILE_SIZE = 256;

function bound(value, opt_min, opt_max) {
  if (opt_min != null) value = Math.max(value, opt_min);
  if (opt_max != null) value = Math.min(value, opt_max);
  return value;
}

function degreesToRadians(deg) {
  return deg * (Math.PI / 180);
}

function radiansToDegrees(rad) {
  return rad / (Math.PI / 180);
}

/** @constructor */
function MercatorProjection() {
  this.pixelOrigin_ = new google.maps.Point(TILE_SIZE / 2,
      TILE_SIZE / 2);
  this.pixelsPerLonDegree_ = TILE_SIZE / 360;
  this.pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
}

MercatorProjection.prototype.fromLatLngToPoint = function(latLng,
    opt_point) {
  var me = this;
  var point = opt_point || new google.maps.Point(0, 0);
  var origin = me.pixelOrigin_;

  point.x = origin.x + latLng.lng() * me.pixelsPerLonDegree_;

  // Truncating to 0.9999 effectively limits latitude to 89.189. This is
  // about a third of a tile past the edge of the world tile.
  var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999,
      0.9999);
  point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) *
      -me.pixelsPerLonRadian_;
  return point;
};

MercatorProjection.prototype.fromPointToLatLng = function(point) {
  var me = this;
  var origin = me.pixelOrigin_;
  var lng = (point.x - origin.x) / me.pixelsPerLonDegree_;
  var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
  var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) -
      Math.PI / 2);
  return new google.maps.LatLng(lat, lng);
};

答案 1 :(得分:0)

通常,您可以将地图连接到数据源(例如PostGIS或SQLite数据库),并让mapnik填充来自所述数据库的点,类似于this。无论是在python脚本中还是从xml生成。

但是,在回答您的问题时,您可以通过从WKT字符串创建新功能并将该功能添加到mapnik.MemoryDatasource()来绘制Lat / Lon点。

以下是使用找到here

的地图文件的脚本中的简单代码段

首先,我们创建我们的样式并将其添加到我们的地图中:

s = mapnik.Style() # style object to hold rules
r = mapnik.Rule() # rule object to hold symbolizers
point_sym = mapnik.PointSymbolizer()
point_sym.filename = './symbols/airport.p.16.png' 
r.symbols.append(point_sym) # add the symbolizer to the rule object
s.rules.append(r) 
m.append_style('airport point', s)

现在我们创建数据源并以WKT格式添加Point几何体:

ds = mapnik.MemoryDatasource()
f = mapnik.Feature(mapnik.Context(), 1)
f.add_geometries_from_wkt("POINT(-92.289595 34.746481)")
ds.add_feature(f)

现在我们必须创建一个新图层,添加我们创建的样式,并将图层添加到地图中:

player = mapnik.Layer('airport_layer')
#since our map is mercator but you wanted to add lat lon points 
#we must make sure our layer projection is set to lat lon
player.srs = longlat.params() 
player.datasource = ds
player.styles.append('airport point')
m.layers.append(player)
m.zoom_all()

您可以查看整个脚本here