1

我按照 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)
4

2 回答 2

1

通常,您会将地图连接到 PostGIS 或 SQLite 数据库等数据源,并让 mapnik 填充所述数据库中的点,类似于这样。在 python 脚本中或从 xml 生成。

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

以下是使用此处找到的地图文件的脚本的简单片段

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

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 格式的点几何:

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

您可以在此处查看整个脚本。

于 2015-05-28T18:25:07.203 回答
0

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

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);
};
于 2013-08-22T14:22:46.117 回答