Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot read context in shapefile with mapnik #4451

Open
Wingong opened this issue May 6, 2024 · 5 comments
Open

Cannot read context in shapefile with mapnik #4451

Wingong opened this issue May 6, 2024 · 5 comments
Assignees

Comments

@Wingong
Copy link

Wingong commented May 6, 2024

I tried using C++ with Mapnik to read a shapefile located in path/to/shapefile. The shapefile includes .shp, .shx, .prj, .dbf, etc. files. The shapefile can be read and rendered successfully, including its features. However, the context within each feature contains nothing (it should contain a map with descriptors and attributes).

I have successfully read the DBF file in the shapefile folder using other tools (like QGIS), and the attributes were displayed. I also tried another shapefile in mapnik demo, but the result was the same.

What could be causing this problem? What steps should I take to fix it?

Environment: Win10; Mapnik 2023-06-12#3 built by vcpkg; VS 2022.

The code is as following:

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;
    }
}
@artemp
Copy link
Member

artemp commented May 9, 2024

@Wingong - I'm assuming you're trying to access Feature attributes. If so, you can use feature_kv_iterator

#include <mapnik/feature_kv_iterator.hpp>
.....

while (auto feature = features->next())
{
   feature_kv_iterator itr(*feature, true);
   feature_kv_iterator end(*feature); 
   for (; itr != end; ++itr)
   {
      std::cerr << std::get<0>(*itr) << ":" << std::get<1>(*itr).to_string() << std::endl;
   }
}

or

auto itr = feature->begin();
auto end = feature->end();
for (; itr != end; ++itr) { ... }

or

for (auto const& kv : feature)
{
        std::cerr << std::get<0>(kv) << ":" << std::get<1>(kv).to_string();
}

HTH

@artemp artemp self-assigned this May 9, 2024
@Wingong
Copy link
Author

Wingong commented May 15, 2024

@artemp I tried feature_kv_iterator, but it seems not working. itr is equal to end, so nothing was iterate. Besides, I read the code of the input file shape.input, exactly dbf.hpp and dbf.cpp in it. When reading dBase file, it doesn't load records, but only the header (using read_header() function). I thought if it could cause the problem?

@artemp
Copy link
Member

artemp commented May 15, 2024

@Wingong Could you share your shapefile if it's not too large?

@Wingong
Copy link
Author

Wingong commented May 16, 2024

@artemp Of course, but i don't know how to upload file - however, it is just the demo shapefile in mapnik source code, like src/demo/data/boundaries and others. Thanks very much!

@Wingong
Copy link
Author

Wingong commented May 16, 2024

@artemp update: using mapnik::rule and add rules to style can filter the write shape (like r.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));). I tried using map.query_point(index, x, y), and features in it contain correct context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants