Beispiel #1
0
featureset_ptr geos_datasource::features(query const& q) const
{
    if (!is_bound_) bind();

    const mapnik::box2d<double> extent = q.get_bbox();

    std::ostringstream s;
    s << "POLYGON(("
      << extent.minx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.miny()
      << "))";

#ifdef MAPNIK_DEBUG
    clog << "GEOS Plugin: using extent: " << s.str() << endl;
#endif

    return boost::make_shared<geos_featureset>(*geometry_,
                                               GEOSGeomFromWKT(s.str().c_str()),
                                               geometry_id_,
                                               geometry_data_,
                                               geometry_data_name_,
                                               desc_.get_encoding(),
                                               multiple_geometries_);
}
 void operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     for (unsigned i=0;i<iterations_;++i)
     {
         for (mapnik::geometry_type & geom : paths)
         {
             poly_clipper clipped(geom,ps,
                                  agg::clipper_and,
                                  agg::clipper_non_zero,
                                  agg::clipper_non_zero,
                                  1);
             clipped.rewind(0);
             unsigned cmd;
             double x,y;
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {}
         }
     }
 }
Beispiel #3
0
featureset_ptr geos_datasource::features(query const& q) const
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "geos_datasource::features");
#endif

    const mapnik::box2d<double> extent = q.get_bbox();

    std::ostringstream s;
    s << "POLYGON(("
      << extent.minx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.miny()
      << "))";

    MAPNIK_LOG_DEBUG(geos) << "geos_datasource: Using extent=" << s.str();

    return boost::make_shared<geos_featureset>(*geometry_,
                                               GEOSGeomFromWKT(s.str().c_str()),
                                               geometry_id_,
                                               geometry_data_,
                                               geometry_data_name_,
                                               desc_.get_encoding());
}
    bool operator()() const
    {
        mapnik::geometry::geometry<double> geom;
        if (!mapnik::from_wkt(wkt_in_, geom))
        {
            throw std::runtime_error("Failed to parse WKT");
        }
        if (mapnik::geometry::is_empty(geom))
        {
            std::clog << "empty geom!\n";
            return false;
        }
        if (!geom.is<mapnik::geometry::polygon<double> >())
        {
            std::clog << "not a polygon!\n";
            return false;
        }
        mapnik::geometry::polygon<double> & poly = mapnik::util::get<mapnik::geometry::polygon<double> >(geom);
        mapnik::geometry::correct(poly);

        mapnik::geometry::linear_ring<double> bbox;
        bbox.emplace_back(extent_.minx(), extent_.miny());
        bbox.emplace_back(extent_.minx(), extent_.maxy());
        bbox.emplace_back(extent_.maxx(), extent_.maxy());
        bbox.emplace_back(extent_.maxx(), extent_.miny());
        bbox.emplace_back(extent_.minx(), extent_.miny());

        bool valid = true;
        for (unsigned i=0;i<iterations_;++i)
        {
            std::deque<mapnik::geometry::polygon<double> > result;
            boost::geometry::intersection(bbox, poly, result);
            unsigned count = 0;
            for (auto const& _geom : result)
            {
                mapnik::geometry::polygon_vertex_adapter<double> va(_geom);
                unsigned cmd;
                double x,y;
                while ((cmd = va.vertex(&x, &y)) != mapnik::SEG_END) {
                    ++count;
                }
                unsigned expected_count = 29;
                if (count != expected_count) {
                    std::clog << "test3: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
                    valid = false;
                }
            }
        }
        return valid;
    }
    bool validate() const
    {
        mapnik::geometry::geometry<double> geom;
        if (!mapnik::from_wkt(wkt_in_, geom))
        {
            throw std::runtime_error("Failed to parse WKT");
        }
        if (mapnik::geometry::is_empty(geom))
        {
            std::clog << "empty geom!\n";
            return false;
        }
        if (!geom.is<mapnik::geometry::polygon<double> >())
        {
            std::clog << "not a polygon!\n";
            return false;
        }
        mapnik::geometry::polygon<double> & poly = mapnik::util::get<mapnik::geometry::polygon<double> >(geom);
        mapnik::geometry::correct(poly);

        mapnik::geometry::linear_ring<double> bbox;
        bbox.emplace_back(extent_.minx(), extent_.miny());
        bbox.emplace_back(extent_.minx(), extent_.maxy());
        bbox.emplace_back(extent_.maxx(), extent_.maxy());
        bbox.emplace_back(extent_.maxx(), extent_.miny());
        bbox.emplace_back(extent_.minx(), extent_.miny());

        std::deque<mapnik::geometry::polygon<double> > result;
        boost::geometry::intersection(bbox, poly, result);

        std::string expect = expected_+".png";
        std::string actual = expected_+"_actual.png";
        mapnik::geometry::multi_polygon<double> mp;
        for (auto const& _geom: result)
        {
            //std::clog << boost::geometry::dsv(geom) << "\n";
            mp.emplace_back(_geom);
        }
        mapnik::geometry::geometry<double> geom2(mp);
        auto env = mapnik::geometry::envelope(geom2);
        if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
        {
            std::clog << "generating expected image: " << expect << "\n";
            render(mp,env,expect);
        }
        render(mp,env,actual);
        return benchmark::compare_images(actual,expect);
    }
 bool operator()() const
 {
     mapnik::geometry::geometry<double> geom;
     if (!mapnik::from_wkt(wkt_in_, geom))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     if (mapnik::geometry::is_empty(geom))
     {
         std::clog << "empty geom!\n";
         return false;
     }
     if (!geom.is<mapnik::geometry::polygon<double>>())
     {
         std::clog << "not a polygon!\n";
         return false;
     }
     mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         mapnik::geometry::polygon_vertex_adapter<double> va(poly);
         poly_clipper clipped(va,ps,
                              agg::clipper_and,
                              agg::clipper_non_zero,
                              agg::clipper_non_zero,
                              1);
         clipped.rewind(0);
         unsigned cmd;
         double x,y;
         while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
             count++;
         }
         unsigned expected_count = 31;
         if (count != expected_count) {
             std::clog << "test2: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
Beispiel #7
0
 static bool apply_spatial_filter(std::string & query,
                                  mapnik::box2d<double> const& e,
                                  std::string const& table,
                                  std::string const& key_field,
                                  std::string const& index_table,
                                  std::string const& geometry_table,
                                  std::string const& intersects_token)
 {
     std::ostringstream spatial_sql;
     spatial_sql << std::setprecision(16);
     spatial_sql << key_field << " IN (SELECT pkid FROM " << index_table;
     spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
     spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
     if (boost::algorithm::ifind_first(query,  intersects_token))
     {
         boost::algorithm::ireplace_all(query, intersects_token, spatial_sql.str());
         return true;
     }
     // substitute first WHERE found if not using JOIN
     // (because we can't know the WHERE is on the right table)
     else if (boost::algorithm::ifind_first(query, "WHERE")
              && !boost::algorithm::ifind_first(query, "JOIN"))
     {
         std::string replace(" WHERE " + spatial_sql.str() + " AND ");
         boost::algorithm::ireplace_first(query, "WHERE", replace);
         return true;
     }
     // fallback to appending spatial filter at end of query
     else if (boost::algorithm::ifind_first(query, geometry_table))
     {
         query = table + " WHERE " + spatial_sql.str();
         return true;
     }
     return false;
 }
Beispiel #8
0
static jobject box2dFromNative(JNIEnv *env, mapnik::box2d<double> const& box) {
	jobject ret=env->AllocObject(CLASS_BOX2D);
	env->SetDoubleField(ret, FIELD_BOX2D_MINX, box.minx());
	env->SetDoubleField(ret, FIELD_BOX2D_MINY, box.miny());
	env->SetDoubleField(ret, FIELD_BOX2D_MAXX, box.maxx());
	env->SetDoubleField(ret, FIELD_BOX2D_MAXY, box.maxy());
	return ret;
}
Beispiel #9
0
std::string clip_line(mapnik::box2d<double> const& bbox,
                      mapnik::geometry_type & geom)
{
    using line_clipper = agg::conv_clip_polyline<mapnik::geometry_type>;
    line_clipper clipped(geom);
    clipped.clip_box(bbox.minx(),bbox.miny(),bbox.maxx(),bbox.maxy());
    return dump_path(clipped);
}
Beispiel #10
0
std::string clip_line(mapnik::box2d<double> const& bbox,
                      mapnik::path_type const& path)
{
    using line_clipper = agg::conv_clip_polyline<mapnik::vertex_adapter>;
    mapnik::vertex_adapter va(path);
    line_clipper clipped(va);
    clipped.clip_box(bbox.minx(),bbox.miny(),bbox.maxx(),bbox.maxy());
    return dump_path(clipped);
}
 bool validate() const
 {
     std::string expected_wkt("Polygon((212 134,329 138,394 229,528 178,631 234.4,631 321.3,559 466,463 324,421 446,315 340,233 454,181 286.7,181 238.2,200 264,183 228),(313 190,229 191,249 334,343 287,405 378,455 262,553 397,613 263,533 237,510 305,470 248,440 256))");
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     if (paths.size() != 1)
     {
         std::clog << "paths.size() != 1\n";
         return false;
     }
     mapnik::geometry_type const& geom = paths[0];
     mapnik::vertex_adapter va(geom);
     poly_clipper clipped(va,ps,
                          agg::clipper_and,
                          agg::clipper_non_zero,
                          agg::clipper_non_zero,
                          1);
     clipped.rewind(0);
     unsigned cmd;
     double x,y;
     mapnik::geometry_type geom2(mapnik::geometry_type::types::Polygon);
     while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
         geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
     }
     std::string expect = expected_+".png";
     std::string actual = expected_+"_actual.png";
     auto env = mapnik::envelope(geom);
     if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
     {
         std::clog << "generating expected image: " << expect << "\n";
         render(geom2,env,expect);
     }
     render(geom2,env,actual);
     return benchmark::compare_images(actual,expect);
 }
Beispiel #12
0
 void bind(mapnik::box2d<double> const& bbox)
 {
     if ((sqlite3_bind_double(stmt_, 2, bbox.minx()) != SQLITE_OK) ||
         (sqlite3_bind_double(stmt_, 3, bbox.maxx()) != SQLITE_OK) ||
         (sqlite3_bind_double(stmt_, 4, bbox.miny()) != SQLITE_OK) ||
         (sqlite3_bind_double(stmt_, 5, bbox.maxy()) != SQLITE_OK))
     {
         throw mapnik::datasource_exception("SQLite Plugin: invalid value for for extent while generating index");
     }
 }
 bool operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         for (mapnik::geometry_type const& geom : paths)
         {
             mapnik::vertex_adapter va(geom);
             poly_clipper clipped(va,ps,
                                  agg::clipper_and,
                                  agg::clipper_non_zero,
                                  agg::clipper_non_zero,
                                  1);
             clipped.rewind(0);
             unsigned cmd;
             double x,y;
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
                 count++;
             }
         }
         unsigned expected_count = 29;
         if (count != expected_count) {
             std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
 bool validate() const
 {
     mapnik::projection src(src_,defer_proj4_init_);
     mapnik::projection dest(dest_,defer_proj4_init_);
     mapnik::proj_transform tr(src,dest);
     mapnik::box2d<double> bbox = from_;
     if (!tr.forward(bbox)) return false;
     return ((std::fabs(bbox.minx() - to_.minx()) < .5) &&
             (std::fabs(bbox.maxx() - to_.maxx()) < .5) &&
             (std::fabs(bbox.miny() - to_.miny()) < .5) &&
             (std::fabs(bbox.maxy() - to_.maxy()) < .5)
            );
 }
Beispiel #15
0
ogr_featureset::ogr_featureset(mapnik::context_ptr const& ctx,
                               OGRLayer & layer,
                               mapnik::box2d<double> const& extent,
                               std::string const& encoding)
    : ctx_(ctx),
      layer_(layer),
      layerdef_(layer.GetLayerDefn()),
      tr_(new transcoder(encoding)),
      fidcolumn_(layer_.GetFIDColumn()), // TODO - unused
      count_(0)
{
    layer_.SetSpatialFilterRect (extent.minx(),
                                 extent.miny(),
                                 extent.maxx(),
                                 extent.maxy());
}
 bool operator()() const
 {
     mapnik::geometry::geometry<double> geom;
     if (!mapnik::from_wkt(wkt_in_, geom))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     if (mapnik::geometry::is_empty(geom))
     {
         std::clog << "empty geom!\n";
         return false;
     }
     if (!geom.is<mapnik::geometry::polygon<double>>())
     {
         std::clog << "not a polygon!\n";
         return false;
     }
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
         mapnik::geometry::polygon_vertex_adapter<double> va(poly);
         conv_clip clipped(va);
         clipped.clip_box(
                     extent_.minx(),
                     extent_.miny(),
                     extent_.maxx(),
                     extent_.maxy());
         unsigned cmd;
         double x,y;
         // NOTE: this rewind is critical otherwise
         // agg_conv_adapter_vpgen will give garbage
         // values for the first vertex
         clipped.rewind(0);
         while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
             count++;
         }
         unsigned expected_count = 30;
         if (count != expected_count) {
             std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
 bool operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     bool valid = true;
     for (unsigned i=0;i<iterations_;++i)
     {
         unsigned count = 0;
         for (mapnik::geometry_type const& geom : paths)
         {
             mapnik::vertex_adapter va(geom);
             conv_clip clipped(va);
             clipped.clip_box(
                         extent_.minx(),
                         extent_.miny(),
                         extent_.maxx(),
                         extent_.maxy());
             unsigned cmd;
             double x,y;
             // NOTE: this rewind is critical otherwise
             // agg_conv_adapter_vpgen will give garbage
             // values for the first vertex
             clipped.rewind(0);
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
                 count++;
             }
         }
         unsigned expected_count = 31;
         if (count != expected_count) {
             std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
             valid = false;
         }
     }
     return valid;
 }
std::vector<unsigned> bboxToXYZ(mapnik::box2d<double> const& bboxCoords)
{
    double minx = bboxCoords.minx();
    double miny = bboxCoords.miny();
    double maxx = bboxCoords.maxx();
    double maxy = bboxCoords.maxy();
    mapnik::merc2lonlat(&minx,&miny,1);
    mapnik::merc2lonlat(&maxx,&maxy,1);

    std::vector<double> ubbox = {
        minx,
        miny,
        maxx,
        maxy
    };
    unsigned z = getBboxZoom(ubbox);
    if (z == 0) return {0, 0, 0};
    minx = pointToTile(minx, miny, 32)[0];
    miny = pointToTile(minx, miny, 32)[1];
    unsigned x = static_cast<unsigned>(minx);
    unsigned y = static_cast<unsigned>(miny);
    return {x, y, z};
}
 void operator()() const
 {
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     for (unsigned i=0;i<iterations_;++i)
     {
         for (mapnik::geometry_type & geom : paths)
         {
             conv_clip clipped(geom);
             clipped.clip_box(
                         extent_.minx(),
                         extent_.miny(),
                         extent_.maxx(),
                         extent_.maxy());
             unsigned cmd;
             double x,y;
             while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {}
         }
     }
 }
 bool validate() const
 {
     std::string expected_wkt("Polygon((181 286.666667,233 454,315 340,421 446,463 324,559 466,631 321.320755,631 234.386861,528 178,394 229,329 138,212 134,183 228,200 264,181 238.244444),(313 190,440 256,470 248,510 305,533 237,613 263,553 397,455 262,405 378,343 287,249 334,229 191,313 190,313 190))");
     boost::ptr_vector<mapnik::geometry_type> paths;
     if (!mapnik::from_wkt(wkt_in_, paths))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     if (paths.size() != 1)
     {
         std::clog << "paths.size() != 1\n";
         return false;
     }
     mapnik::geometry_type & geom = paths[0];
     conv_clip clipped(geom);
     clipped.clip_box(
                 extent_.minx(),
                 extent_.miny(),
                 extent_.maxx(),
                 extent_.maxy());
     unsigned cmd;
     double x,y;
     mapnik::geometry_type geom2(mapnik::geometry_type::types::Polygon);
     while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
         geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
     }
     std::string expect = expected_+".png";
     std::string actual = expected_+"_actual.png";
     if (!mapnik::util::exists(expect))
     {
         std::clog << "generating expected image: " << expect << "\n";
         render(geom2,geom.envelope(),expect);
     }
     render(geom2,geom.envelope(),actual);
     return benchmark::compare_images(actual,expect);
 }
 static inline ct get(mapnik::box2d<double> const& b) { return b.miny();}
 bool validate() const
 {
     mapnik::geometry::geometry<double> geom;
     if (!mapnik::from_wkt(wkt_in_, geom))
     {
         throw std::runtime_error("Failed to parse WKT");
     }
     if (mapnik::geometry::is_empty(geom))
     {
         std::clog << "empty geom!\n";
         return false;
     }
     if (!geom.is<mapnik::geometry::polygon<double>>())
     {
         std::clog << "not a polygon!\n";
         return false;
     }
     mapnik::geometry::polygon<double> & poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
     agg::path_storage ps;
     ps.move_to(extent_.minx(), extent_.miny());
     ps.line_to(extent_.minx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.maxy());
     ps.line_to(extent_.maxx(), extent_.miny());
     ps.close_polygon();
     mapnik::geometry::polygon_vertex_adapter<double> va(poly);
     poly_clipper clipped(va,ps,
                          agg::clipper_and,
                          agg::clipper_non_zero,
                          agg::clipper_non_zero,
                          1);
     unsigned cmd;
     double x,y;
     clipped.rewind(0);
     mapnik::geometry::polygon<double> poly2;
     mapnik::geometry::linear_ring<double> ring;
     // TODO: handle resulting multipolygon
     // exterior ring
     while (true)
     {
         cmd = clipped.vertex(&x, &y);
         ring.add_coord(x,y);
         if (cmd == mapnik::SEG_CLOSE) break;
     }
     poly2.set_exterior_ring(std::move(ring));
     // interior ring
     ring.clear();
     while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
     {
         ring.add_coord(x,y);
     }
     poly2.add_hole(std::move(ring));
     mapnik::geometry::correct(poly2);
     std::string expect = expected_+".png";
     std::string actual = expected_+"_actual.png";
     mapnik::geometry::multi_polygon<double> mp;
     mp.emplace_back(poly2);
     auto env = mapnik::geometry::envelope(mp);
     if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
     {
         std::clog << "generating expected image: " << expect << "\n";
         render(mp,env,expect);
     }
     render(mp,env,actual);
     return benchmark::compare_images(actual,expect);
 }
    bool validate() const
    {
        mapnik::geometry::geometry<double> geom;
        if (!mapnik::from_wkt(wkt_in_, geom))
        {
            throw std::runtime_error("Failed to parse WKT");
        }
        if (mapnik::geometry::is_empty(geom))
        {
            std::clog << "empty geom!\n";
            return false;
        }
        if (!geom.is<mapnik::geometry::polygon<double> >())
        {
            std::clog << "not a polygon!\n";
            return false;
        }
        mapnik::geometry::polygon<double> & poly = mapnik::util::get<mapnik::geometry::polygon<double> >(geom);
        mapnik::geometry::correct(poly);
        ClipperLib::Clipper clipper;

        mapnik::geometry::line_string<std::int64_t> path;
        for (auto const& pt : poly.exterior_ring)
        {
            double x = pt.x;
            double y = pt.y;
            path.emplace_back(static_cast<ClipperLib::cInt>(x),static_cast<ClipperLib::cInt>(y));
        }
        if (!clipper.AddPath(path, ClipperLib::ptSubject, true))
        {
            std::clog << "ptSubject ext failed!\n";
        }
        for (auto const& ring : poly.interior_rings)
        {
            path.clear();
            for (auto const& pt : ring)
            {
                double x = pt.x;
                double y = pt.y;
                path.emplace_back(static_cast<ClipperLib::cInt>(x),static_cast<ClipperLib::cInt>(y));
            }
            if (!clipper.AddPath(path, ClipperLib::ptSubject, true))
            {
                std::clog << "ptSubject ext failed!\n";
            }
        }
        std::cerr << "path size=" << path.size() << std::endl;
        mapnik::geometry::line_string<std::int64_t> clip_box;
        clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.minx()),static_cast<ClipperLib::cInt>(extent_.miny()));
        clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.maxx()),static_cast<ClipperLib::cInt>(extent_.miny()));
        clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.maxx()),static_cast<ClipperLib::cInt>(extent_.maxy()));
        clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.minx()),static_cast<ClipperLib::cInt>(extent_.maxy()));
        clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.minx()),static_cast<ClipperLib::cInt>(extent_.miny()));

        if (!clipper.AddPath( clip_box, ClipperLib::ptClip, true ))
        {
            std::clog << "ptClip failed!\n";
        }

        ClipperLib::PolyTree polygons;
        clipper.Execute(ClipperLib::ctIntersection, polygons, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
        clipper.Clear();
        ClipperLib::PolyNode* polynode = polygons.GetFirst();
        mapnik::geometry::multi_polygon<double> mp;
        mp.emplace_back();
        bool first = true;
        while (polynode)
        {
            if (!polynode->IsHole())
            {
                if (first) first = false;
                else mp.emplace_back(); // start new polygon
                for (auto const& pt : polynode->Contour)
                {
                    mp.back().exterior_ring.add_coord(pt.x, pt.y);
                }
                // childrens are interior rings
                for (auto const* ring : polynode->Childs)
                {
                    mapnik::geometry::linear_ring<double> hole;
                    for (auto const& pt : ring->Contour)
                    {
                        hole.add_coord(pt.x, pt.y);
                    }
                    mp.back().add_hole(std::move(hole));
                }
            }
            polynode = polynode->GetNext();
        }
        std::string expect = expected_+".png";
        std::string actual = expected_+"_actual.png";
        mapnik::geometry::geometry<double> geom2(mp);
        auto env = mapnik::geometry::envelope(geom2);
        if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
        {
            std::clog << "generating expected image: " << expect << "\n";
            render(mp,env,expect);
        }
        render(mp,env,actual);
        return benchmark::compare_images(actual,expect);
    }
    bool validate() const
    {
        mapnik::geometry::geometry<double> geom;
        if (!mapnik::from_wkt(wkt_in_, geom))
        {
            throw std::runtime_error("Failed to parse WKT");
        }
        if (mapnik::geometry::is_empty(geom))
        {
            std::clog << "empty geom!\n";
            return false;
        }
        if (!geom.is<mapnik::geometry::polygon<double>>())
        {
            std::clog << "not a polygon!\n";
            return false;
        }
        mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
        mapnik::geometry::polygon_vertex_adapter<double> va(poly);


        conv_clip clipped(va);
        clipped.clip_box(
                    extent_.minx(),
                    extent_.miny(),
                    extent_.maxx(),
                    extent_.maxy());


        clipped.rewind(0);
        mapnik::geometry::polygon<double> poly2;
        mapnik::geometry::linear_ring<double> ring;
        // exterior ring
        unsigned cmd;
        double x, y, x0, y0;
        while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
        {
            if (cmd == mapnik::SEG_MOVETO)
            {
                x0 = x; y0 = y;
            }

            if (cmd == mapnik::SEG_CLOSE)
            {
                ring.emplace_back(x0, y0);
                break;
            }
            ring.emplace_back(x,y);
        }
        poly2.push_back(std::move(ring));
        // interior rings
        ring.clear();
        while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
        {
            if (cmd == mapnik::SEG_MOVETO)
            {
                x0 = x; y0 = y;
            }
            else if (cmd == mapnik::SEG_CLOSE)
            {
                ring.emplace_back(x0,y0);
                poly2.push_back(std::move(ring));
                ring.clear();
                continue;
            }
            ring.emplace_back(x,y);
        }

        std::string expect = expected_+".png";
        std::string actual = expected_+"_actual.png";
        mapnik::geometry::multi_polygon<double> mp;
        mp.emplace_back(poly2);
        auto env = mapnik::geometry::envelope(mp);
        if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
        {
            std::clog << "generating expected image: " << expect << "\n";
            render(mp,env,expect);
        }
        render(mp,env,actual);
        return benchmark::compare_images(actual,expect);
    }
Beispiel #25
0
 static inline ct get(mapnik::box2d<CoordinateType> const& b) { return b.miny();}
featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
{
   if (!is_bound_) bind();

   if (dataset_)
   {
        // TODO - need tolerance
        mapnik::box2d<double> const e(pt.x,pt.y,pt.x,pt.y);

        std::ostringstream s;
        s << "SELECT " << geometry_field_ << "," << key_field_;
        std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
        std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
        while (itr != end)
        {
            std::string fld_name = itr->get_name();
            if (fld_name != key_field_)
                s << ",\"" << itr->get_name() << "\"";
            ++itr;
        }
        
        s << " FROM "; 
        
        std::string query (table_); 
        
        if (use_spatial_index_)
        {
           std::ostringstream spatial_sql;
           spatial_sql << std::setprecision(16);
           spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM idx_" << geometry_table_ << "_" << geometry_field_;
           spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
           spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
           if (boost::algorithm::ifind_first(query, "WHERE"))
           {
              boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
           }
           else if (boost::algorithm::ifind_first(query, geometry_table_))  
           {
              boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str());
           }
        }
        
        s << query ;
        
        if (row_limit_ > 0) {
            s << " LIMIT " << row_limit_;
        }

        if (row_offset_ > 0) {
            s << " OFFSET " << row_offset_;
        }

#ifdef MAPNIK_DEBUG
        std::clog << "Sqlite Plugin: " << s.str() << std::endl;
#endif

        boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));

        return boost::make_shared<sqlite_featureset>(rs, desc_.get_encoding(), format_, multiple_geometries_);
   }
      
   return featureset_ptr();
}
    };
    unsigned z = getBboxZoom(ubbox);
    if (z == 0) return {0, 0, 0};
    minx = pointToTile(minx, miny, 32)[0];
    miny = pointToTile(minx, miny, 32)[1];
    unsigned x = static_cast<unsigned>(minx);
    unsigned y = static_cast<unsigned>(miny);
    return {x, y, z};
}

TEST_CASE( "vector tile projection 1", "should support z/x/y to bbox conversion at 0/0/0" ) {
    mapnik::box2d<double> map_extent = mapnik::vector_tile_impl::tile_mercator_bbox(0,0,0);
    mapnik::box2d<double> e(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);
    double epsilon = 0.000001;
    CHECK(std::fabs(map_extent.minx() - e.minx()) < epsilon);
    CHECK(std::fabs(map_extent.miny() - e.miny()) < epsilon);
    CHECK(std::fabs(map_extent.maxx() - e.maxx()) < epsilon);
    CHECK(std::fabs(map_extent.maxy() - e.maxy()) < epsilon);
    auto xyz = bboxToXYZ(map_extent);
    /*
    CHECK(xyz[0] == 0);
    CHECK(xyz[1] == 0);
    CHECK(xyz[2] == 0);
    */
}

TEST_CASE( "vector tile projection 2", "should support z/x/y to bbox conversion up to z33" ) {
    int x = 2145960701;
    int y = 1428172928;
    int z = 32;
    mapnik::box2d<double> map_extent = mapnik::vector_tile_impl::tile_mercator_bbox(x,y,z);