Esempio n. 1
0
bool push_explicit_style(Attr const& src, Attr & dst, markers_symbolizer const& sym)
{
    boost::optional<stroke> const& strk = sym.get_stroke();
    boost::optional<color> const& fill = sym.get_fill();
    if (strk || fill)
    {
        for(unsigned i = 0; i < src.size(); ++i)
        {
            mapnik::svg::path_attributes attr = src[i];

            if (strk)
            {
                attr.stroke_flag = true;
                attr.stroke_width = strk->get_width();
                color const& s_color = strk->get_color();
                attr.stroke_color = agg::rgba(s_color.red()/255.0,s_color.green()/255.0,
                                              s_color.blue()/255.0,(s_color.alpha()*strk->get_opacity())/255.0);
            }
            if (fill)
            {

                attr.fill_flag = true;
                color const& f_color = *fill;
                attr.fill_color = agg::rgba(f_color.red()/255.0,f_color.green()/255.0,
                                            f_color.blue()/255.0,(f_color.alpha()*sym.get_opacity())/255.0);
            }
            dst.push_back(attr);
        }
        return true;
    }
    return false;
}
Esempio n. 2
0
 void operator () (markers_symbolizer const& sym)
 {
     expression_ptr const& height_expr = sym.get_height();
     if (height_expr)
     {
         boost::apply_visitor(f_attr,*height_expr);
     }
     expression_ptr const& width_expr = sym.get_width();
     if (width_expr)
     {
         boost::apply_visitor(f_attr,*width_expr);
     }
     collect_transform(sym.get_image_transform());
     collect_transform(sym.get_transform());
 }
Esempio n. 3
0
bool push_explicit_style(Attr const& src, Attr & dst, markers_symbolizer const& sym)
{
    boost::optional<stroke> const& strk = sym.get_stroke();
    boost::optional<color> const& fill = sym.get_fill();
    boost::optional<float> const& fill_opacity = sym.get_fill_opacity();
    if (strk || fill || fill_opacity)
    {
        bool success = false;
        for(unsigned i = 0; i < src.size(); ++i)
        {
            success = true;
            dst.push_back(src[i]);
            mapnik::svg::path_attributes & attr = dst.last();
            if (attr.stroke_flag)
            {
                // TODO - stroke attributes need to be boost::optional
                // for this to work properly
                if (strk)
                {
                    attr.stroke_width = strk->get_width();
                    color const& s_color = strk->get_color();
                    attr.stroke_color = agg::rgba(s_color.red()/255.0,
                                                  s_color.green()/255.0,
                                                  s_color.blue()/255.0,
                                                  s_color.alpha()/255.0);
                    attr.stroke_opacity = strk->get_opacity();
                }
            }
            if (attr.fill_flag)
            {
                if (fill)
                {
                    color const& f_color = *fill;
                    attr.fill_color = agg::rgba(f_color.red()/255.0,
                                                f_color.green()/255.0,
                                                f_color.blue()/255.0,
                                                f_color.alpha()/255.0);
                }
                if (fill_opacity)
                {
                    attr.fill_opacity = *fill_opacity;
                }
            }
        }
        return success;
    }
    return false;
}
Esempio n. 4
0
    static void
    setstate (markers_symbolizer& p, boost::python::tuple state)
    {
        using namespace boost::python;
        if (len(state) != 2)
        {
            PyErr_SetObject(PyExc_ValueError,
                            ("expected 2-item tuple in call to __setstate__; got %s"
                             % state).ptr()
                );
            throw_error_already_set();
        }

        p.set_allow_overlap(extract<bool>(state[0]));
        p.set_ignore_placement(extract<bool>(state[1]));
        //p.set_opacity(extract<float>(state[2]));

    }
 void operator () (markers_symbolizer const& sym)
 {
     expression_ptr const& height_expr = sym.get_height();
     if (height_expr)
     {
         boost::apply_visitor(f_attr,*height_expr);
     }
     expression_ptr const& width_expr = sym.get_width();
     if (width_expr)
     {
         boost::apply_visitor(f_attr,*width_expr);
     }
     path_expression_ptr const& filename_expr = sym.get_filename();
     if (filename_expr)
     {
         path_processor_type::collect_attributes(*filename_expr,names_);
     }
     collect_transform(sym.get_image_transform());
     collect_transform(sym.get_transform());
 }
void grid_renderer<T>::process(markers_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    typedef grid_rendering_buffer buf_type;
    typedef typename grid_renderer_base_type::pixfmt_type pixfmt_type;
    typedef typename grid_renderer_base_type::pixfmt_type::color_type color_type;
    typedef agg::renderer_scanline_bin_solid<grid_renderer_base_type> renderer_type;
    typedef label_collision_detector4 detector_type;
    typedef boost::mpl::vector<clip_line_tag,clip_poly_tag,transform_tag,smooth_tag> conv_types;

    std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature);

    if (!filename.empty())
    {
        boost::optional<marker_ptr> mark = mapnik::marker_cache::instance().find(filename, true);
        if (mark && *mark)
        {
            ras_ptr->reset();
            agg::trans_affine geom_tr;
            evaluate_transform(geom_tr, feature, sym.get_transform());
            agg::trans_affine tr = agg::trans_affine_scaling(scale_factor_*(1.0/pixmap_.get_resolution()));

            if ((*mark)->is_vector())
            {
                using namespace mapnik::svg;
                typedef agg::pod_bvector<path_attributes> svg_attribute_type;
                typedef svg_renderer_agg<svg_path_adapter,
                                     svg_attribute_type,
                                     renderer_type,
                                     pixfmt_type > svg_renderer_type;
                typedef vector_markers_rasterizer_dispatch_grid<buf_type,
                                     svg_renderer_type,
                                     grid_rasterizer,
                                     detector_type,
                                     mapnik::grid > dispatch_type;
                boost::optional<svg_path_ptr> const& stock_vector_marker = (*mark)->get_vector_data();
                expression_ptr const& width_expr = sym.get_width();
                expression_ptr const& height_expr = sym.get_height();

                // special case for simple ellipse markers
                // to allow for full control over rx/ry dimensions
                if (filename == "shape://ellipse"
                   && (width_expr || height_expr))
                {
                    svg_storage_type marker_ellipse;
                    vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse.source());
                    svg_path_adapter svg_path(stl_storage);
                    // TODO - clamping to >= 4 pixels
                    build_ellipse(sym, feature, marker_ellipse, svg_path);
                    svg_attribute_type attributes;
                    bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
                    svg_renderer_type svg_renderer(svg_path, result ? attributes : (*stock_vector_marker)->attributes());
                    evaluate_transform(tr, feature, sym.get_image_transform());
                    box2d<double> bbox = marker_ellipse.bounding_box();
                    coord2d center = bbox.center();
                    agg::trans_affine_translation recenter(-center.x, -center.y);
                    agg::trans_affine marker_trans = recenter * tr;
                    buf_type render_buf(pixmap_.raw_data(), width_, height_, width_);
                    dispatch_type rasterizer_dispatch(render_buf,
                                                      svg_renderer,
                                                      *ras_ptr,
                                                      bbox,
                                                      marker_trans,
                                                      sym,
                                                      *detector_,
                                                      scale_factor_,
                                                      feature,
                                                      pixmap_);
                    vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
                                     CoordTransform, proj_transform, agg::trans_affine, conv_types>
                        converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_);
                    if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
                    {
                        eGeomType type = feature.paths()[0].type();
                        if (type == Polygon)
                            converter.template set<clip_poly_tag>();
                        // line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
                        //else if (type == LineString)
                        //    converter.template set<clip_line_tag>();
                        // don't clip if type==Point
                    }
                    converter.template set<transform_tag>(); //always transform
                    if (sym.smooth() > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
                    apply_markers_multi(feature, converter, sym);
                }
                else
                {
                    box2d<double> const& bbox = (*mark)->bounding_box();
                    setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym);
                    evaluate_transform(tr, feature, sym.get_image_transform());
                    // TODO - clamping to >= 4 pixels
                    coord2d center = bbox.center();
                    agg::trans_affine_translation recenter(-center.x, -center.y);
                    agg::trans_affine marker_trans = recenter * tr;
                    vertex_stl_adapter<svg_path_storage> stl_storage((*stock_vector_marker)->source());
                    svg_path_adapter svg_path(stl_storage);
                    svg_attribute_type attributes;
                    bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
                    svg_renderer_type svg_renderer(svg_path, result ? attributes : (*stock_vector_marker)->attributes());
                    buf_type render_buf(pixmap_.raw_data(), width_, height_, width_);
                    dispatch_type rasterizer_dispatch(render_buf,
                                                      svg_renderer,
                                                      *ras_ptr,
                                                      bbox,
                                                      marker_trans,
                                                      sym,
                                                      *detector_,
                                                      scale_factor_,
                                                      feature,
                                                      pixmap_);
                    vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
                                     CoordTransform, proj_transform, agg::trans_affine, conv_types>
                        converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_);
                    if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
                    {
                        eGeomType type = feature.paths()[0].type();
                        if (type == Polygon)
                            converter.template set<clip_poly_tag>();
                        // line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
                        //else if (type == LineString)
                        //    converter.template set<clip_line_tag>();
                        // don't clip if type==Point
                    }
                    converter.template set<transform_tag>(); //always transform
                    if (sym.smooth() > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
                    apply_markers_multi(feature, converter, sym);
                }
            }
            else // raster markers
            {
                setup_transform_scaling(tr, (*mark)->width(), (*mark)->height(), feature, sym);
                evaluate_transform(tr, feature, sym.get_image_transform());
                box2d<double> const& bbox = (*mark)->bounding_box();
                // - clamp sizes to > 4 pixels of interactivity
                coord2d center = bbox.center();
                agg::trans_affine_translation recenter(-center.x, -center.y);
                agg::trans_affine marker_trans = recenter * tr;
                boost::optional<mapnik::image_ptr> marker = (*mark)->get_bitmap_data();
                typedef raster_markers_rasterizer_dispatch_grid<buf_type,
                                                            grid_rasterizer,
                                                            pixfmt_type,
                                                            grid_renderer_base_type,
                                                            renderer_type,
                                                            detector_type,
                                                            mapnik::grid > dispatch_type;
                buf_type render_buf(pixmap_.raw_data(), width_, height_, width_);
                dispatch_type rasterizer_dispatch(render_buf,
                                                  *ras_ptr,
                                                  **marker,
                                                  marker_trans,
                                                  sym,
                                                  *detector_,
                                                  scale_factor_,
                                                  feature,
                                                  pixmap_);
                vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
                                 CoordTransform, proj_transform, agg::trans_affine, conv_types>
                    converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_);
                if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
                {
                    eGeomType type = feature.paths()[0].type();
                    if (type == Polygon)
                        converter.template set<clip_poly_tag>();
                    // line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
                    //else if (type == LineString)
                    //    converter.template set<clip_line_tag>();
                    // don't clip if type==Point
                }
                converter.template set<transform_tag>(); //always transform
                if (sym.smooth() > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
                apply_markers_multi(feature, converter, sym);
            }
        }
    }
}
Esempio n. 7
0
 static  boost::python::tuple
 getstate(markers_symbolizer const& p)
 {
     return boost::python::make_tuple(p.get_allow_overlap(),
                                      p.get_ignore_placement());//,p.get_opacity());
 }
Esempio n. 8
0
 static boost::python::tuple
 getinitargs(markers_symbolizer const& p)
 {
     std::string filename = path_processor_type::to_string(*p.get_filename());
     return boost::python::make_tuple(filename,mapnik::guess_type(filename));
 }
void grid_renderer<T>::process(markers_symbolizer const& sym,
                               mapnik::feature_ptr const& feature,
                               proj_transform const& prj_trans)
{
    typedef coord_transform2<CoordTransform,geometry_type> path_type;
    typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
    typedef agg::renderer_scanline_bin_solid<ren_base> renderer;
    agg::scanline_bin sl;

    grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
    mapnik::pixfmt_gray16 pixf(buf);

    ren_base renb(pixf);
    renderer ren(renb);

    ras_ptr->reset();

    agg::trans_affine tr;
    boost::array<double,6> const& m = sym.get_transform();
    tr.load_from(&m[0]);
    tr = agg::trans_affine_scaling(scale_factor_*(1.0/pixmap_.get_resolution())) * tr;
    std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
    marker_placement_e placement_method = sym.get_marker_placement();
    marker_type_e marker_type = sym.get_marker_type();

    if (!filename.empty())
    {
        boost::optional<marker_ptr> mark = mapnik::marker_cache::instance()->find(filename, true);
        if (mark && *mark && (*mark)->is_vector())
        {
            boost::optional<path_ptr> marker = (*mark)->get_vector_data();
            box2d<double> const& bbox = (*marker)->bounding_box();
            double x1 = bbox.minx();
            double y1 = bbox.miny();
            double x2 = bbox.maxx();
            double y2 = bbox.maxy();

            agg::trans_affine recenter = agg::trans_affine_translation(-0.5*(x1+x2),-0.5*(y1+y2));
            tr.transform(&x1,&y1);
            tr.transform(&x2,&y2);
            box2d<double> extent(x1,y1,x2,y2);
            using namespace mapnik::svg;
            vertex_stl_adapter<svg_path_storage> stl_storage((*marker)->source());
            svg_path_adapter svg_path(stl_storage);
            svg_renderer<svg_path_adapter,
                agg::pod_bvector<path_attributes>,
                renderer,
                mapnik::pixfmt_gray16 > svg_renderer(svg_path,(*marker)->attributes());

            bool placed = false;
            for (unsigned i=0; i<feature->num_geometries(); ++i)
            {
                geometry_type & geom = feature->get_geometry(i);
                if (geom.num_points() <= 1)
                {
                    std::clog << "### Warning svg markers not supported yet for points within markers_symbolizer\n";
                    continue;
                }

                path_type path(t_,geom,prj_trans);
                markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
                                                                                  sym.get_spacing() * scale_factor_,
                                                                                  sym.get_max_error(),
                                                                                  sym.get_allow_overlap());
                double x, y, angle;

                while (placement.get_point(&x, &y, &angle))
                {
                    placed = true;
                    agg::trans_affine matrix = recenter * tr *agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y);
                    svg_renderer.render_id(*ras_ptr, sl, renb, feature->id(), matrix, sym.get_opacity(),bbox);
                }
            }
            if (placed)
                pixmap_.add_feature(feature);
        }
    }
    else
    {
        stroke const& stroke_ = sym.get_stroke();
        double strk_width = stroke_.get_width();

        double w;
        double h;
        unsigned int res = pixmap_.get_resolution();
        if (res != 1) {
            // clamp to at least 4 px otherwise interactive pixels can be too small
            double min = static_cast<double>(4/pixmap_.get_resolution());
            w = std::max(sym.get_width()/res,min);
            h = std::max(sym.get_height()/res,min);
        } else {
            w = sym.get_width()/res;
            h = sym.get_height()/res;
        }

        arrow arrow_;
        box2d<double> extent;

        double dx = w + (2*strk_width);
        double dy = h + (2*strk_width);

        if (marker_type == ARROW)
        {
            extent = arrow_.extent();
            double x1 = extent.minx();
            double y1 = extent.miny();
            double x2 = extent.maxx();
            double y2 = extent.maxy();
            tr.transform(&x1,&y1);
            tr.transform(&x2,&y2);
            extent.init(x1,y1,x2,y2);
        }
        else
        {
            double x1 = -1 *(dx);
            double y1 = -1 *(dy);
            double x2 = dx;
            double y2 = dy;
            tr.transform(&x1,&y1);
            tr.transform(&x2,&y2);
            extent.init(x1,y1,x2,y2);
        }

        double x;
        double y;
        double z=0;

        for (unsigned i=0; i<feature->num_geometries(); ++i)
        {
            geometry_type & geom = feature->get_geometry(i);
            if (placement_method == MARKER_POINT_PLACEMENT || geom.num_points() <= 1)
            {
                geom.label_position(&x,&y);
                prj_trans.backward(x,y,z);
                t_.forward(&x,&y);
                int px = int(floor(x - 0.5 * dx));
                int py = int(floor(y - 0.5 * dy));
                box2d<double> label_ext (px, py, px + dx +1, py + dy +1);

                if (sym.get_allow_overlap() ||
                    detector_.has_placement(label_ext))
                {
                    agg::ellipse c(x, y, w, h);
                    agg::path_storage marker;
                    marker.concat_path(c);
                    ras_ptr->add_path(marker);

                    // outline
                    if (strk_width)
                    {
                        agg::conv_stroke<agg::path_storage>  outline(marker);
                        outline.generator().width(strk_width * scale_factor_);
                        ras_ptr->add_path(outline);
                    }

                    detector_.insert(label_ext);
                }
            }
            else
            {

                agg::path_storage marker;
                if (marker_type == ARROW)
                    marker.concat_path(arrow_);

                path_type path(t_,geom,prj_trans);
                markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
                                                                                  sym.get_spacing() * scale_factor_,
                                                                                  sym.get_max_error(),
                                                                                  sym.get_allow_overlap());
                double x_t, y_t, angle;

                while (placement.get_point(&x_t, &y_t, &angle))
                {
                    agg::trans_affine matrix;

                    if (marker_type == ELLIPSE)
                    {
                        // todo proper bbox - this is buggy
                        agg::ellipse c(x_t, y_t, w, h);
                        marker.concat_path(c);
                        agg::trans_affine matrix;
                        matrix *= agg::trans_affine_translation(-x_t,-y_t);
                        matrix *= agg::trans_affine_rotation(angle);
                        matrix *= agg::trans_affine_translation(x_t,y_t);
                        marker.transform(matrix);
                    }
                    else
                    {
                        matrix = tr * agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x_t, y_t);
                    }

                    agg::conv_transform<agg::path_storage, agg::trans_affine> trans(marker, matrix);

                    // fill
                    ras_ptr->add_path(trans);

                    // outline
                    if (strk_width)
                    {
                        agg::conv_stroke<agg::conv_transform<agg::path_storage, agg::trans_affine> >  outline(trans);
                        outline.generator().width(strk_width * scale_factor_);
                        ras_ptr->add_path(outline);
                    }
                }
            }

        }
        ren.color(mapnik::gray16(feature->id()));
        agg::render_scanlines(*ras_ptr, sl, ren);
        pixmap_.add_feature(feature);
    }
}