使用Mapnik读取Shapefile时无法获取要素Context的问题排查
问题
使用C++结合Mapnik读取位于path/to/shapefile的Shapefile(包含.shp、.shx、.prj、.dbf等配套文件),可以成功读取并渲染要素,但每个要素的context为空(本应包含属性描述映射)。已通过QGIS等工具验证DBF文件可正常读取属性,更换其他Shapefile后问题仍存在。
环境:Win10;vcpkg构建的Mapnik 2023-06-12#3;VS 2022。
代码如下:
int main(int argc, char** argv) { mapnik::setup(); try { mapnik::datasource_cache::instance().register_datasources("path/to/input"); const std::string srs_lcc = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"; const std::string srs_merc = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 " "+units=m +nadgrids=@null +wktext +no_defs +over"; mapnik::Map map(3840, 2160); map.set_background(mapnik::color(255, 255, 255)); map.set_srs(srs_merc); mapnik::parameters params; params["type"] = "shape"; params["file"] = "path/to/shapefile"; mapnik::layer lyr("Provinces", srs_lcc); lyr.set_datasource(mapnik::datasource_cache::instance().create(params)); map.add_layer(lyr); mapnik::query q(lyr.envelope()); auto features = lyr.datasource()->features(q); while (auto feature = features->next()) { auto context = feature->context(); // Problem here } } catch (...) { std::cout << "### Unknown exception." << std::endl; } }
成因分析
核心原因是Mapnik的查询默认不加载属性字段——为了性能优化,Mapnik仅在查询对象明确指定需要获取的字段时,才会读取DBF文件中的属性信息。当前代码没有配置查询的字段需求,所以返回的要素context为空。
修复方案
在创建mapnik::query对象后,通过add_all_fields()方法加载所有属性字段,或者用add_field()方法指定需要的特定字段。
方式1:加载所有属性字段
mapnik::query q(lyr.envelope()); // 显式添加所有属性字段 q.add_all_fields(); auto features = lyr.datasource()->features(q); while (auto feature = features->next()) { auto context = feature->context(); // 遍历输出属性名示例 for (auto const& field_name : context->names()) { std::cout << "属性名称: " << field_name << std::endl; // 可通过feature->get(field_name)获取对应属性值 } }
方式2:加载指定属性字段
如果只需要部分属性,可以逐个添加:
mapnik::query q(lyr.envelope()); q.add_field("NAME"); q.add_field("POPULATION"); // 后续获取要素逻辑同上
内容的提问来源于stack exchange,提问作者L. Drail
相关产品推荐
相关产品推荐

