Ejemplo n.º 1
0
 const_iterator query(const box2d<double>& box)
 {
     if (box.intersects(info_.envelope()))
     {
         return begin();
     }
     return end();
 }
Ejemplo n.º 2
0
 void query_node(box2d<double> const& box, result_t & result, node * node_) const
 {
     if (node_)
     {
         box2d<double> const& node_extent = node_->extent();
         if (box.intersects(node_extent))
         {
             for (auto & n : *node_)
             {
                 result.push_back(std::ref(n));
             }
             for (int k = 0; k < 4; ++k)
             {
                 query_node(box,result,node_->children_[k]);
             }
         }
     }
 }
Ejemplo n.º 3
0
 void query_node(box2d<double> const& box, result_t & result, node * node_) const
 {
     if (node_)
     {
         box2d<double> const& node_extent = node_->extent();
         if (box.intersects(node_extent))
         {
             node_data_iterator i=node_->begin();
             node_data_iterator end=node_->end();
             while ( i!=end)
             {
                 result.push_back(&(*i));
                 ++i;
             }
             for (int k = 0; k < 4; ++k)
             {
                 query_node(box,result,node_->children_[k]);
             }
         }
     }
 }
Ejemplo n.º 4
0
 bool pass(const box2d<double>& extent) const
 {
     return extent.intersects(box_);
 }
void feature_style_processor<Processor>::prepare_layer(layer_rendering_material & mat,
                                                       feature_style_context_map & ctx_map,
                                                       Processor & p,
                                                       double scale,
                                                       double scale_denom,
                                                       unsigned width,
                                                       unsigned height,
                                                       box2d<double> const& extent,
                                                       int buffer_size,
                                                       std::set<std::string>& names)
{
    layer const& lay = mat.lay_;

    std::vector<std::string> const& style_names = lay.styles();

    std::size_t num_styles = style_names.size();
    if (num_styles == 0)
    {
        MAPNIK_LOG_DEBUG(feature_style_processor)
            << "feature_style_processor: No style for layer=" << lay.name();
        return;
    }

    mapnik::datasource_ptr ds = lay.datasource();
    if (!ds)
    {
        MAPNIK_LOG_DEBUG(feature_style_processor)
            << "feature_style_processor: No datasource for layer=" << lay.name();
        return;
    }

    processor_context_ptr current_ctx = ds->get_context(ctx_map);
    proj_transform prj_trans(mat.proj0_,mat.proj1_);

    box2d<double> query_ext = extent; // unbuffered
    box2d<double> buffered_query_ext(query_ext);  // buffered

    double buffer_padding = 2.0 * scale;
    boost::optional<int> layer_buffer_size = lay.buffer_size();
    if (layer_buffer_size) // if layer overrides buffer size, use this value to compute buffered extent
    {
        buffer_padding *= *layer_buffer_size;
    }
    else
    {
        buffer_padding *= buffer_size;
    }
    buffered_query_ext.width(query_ext.width() + buffer_padding);
    buffered_query_ext.height(query_ext.height() + buffer_padding);

    // clip buffered extent by maximum extent, if supplied
    boost::optional<box2d<double> > const& maximum_extent = m_.maximum_extent();
    if (maximum_extent)
    {
        buffered_query_ext.clip(*maximum_extent);
    }

    box2d<double> layer_ext = lay.envelope();
    const box2d<double> buffered_query_ext_map_srs = buffered_query_ext;
    bool fw_success = false;
    bool early_return = false;

    // first, try intersection of map extent forward projected into layer srs
    if (prj_trans.forward(buffered_query_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext.intersects(layer_ext))
    {
        fw_success = true;
        layer_ext.clip(buffered_query_ext);
    }
    // if no intersection and projections are also equal, early return
    else if (prj_trans.equal())
    {
        early_return = true;
    }
    // next try intersection of layer extent back projected into map srs
    else if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext_map_srs.intersects(layer_ext))
    {
        layer_ext.clip(buffered_query_ext_map_srs);
        // forward project layer extent back into native projection
        if (! prj_trans.forward(layer_ext, PROJ_ENVELOPE_POINTS))
        {
            MAPNIK_LOG_ERROR(feature_style_processor)
                << "feature_style_processor: Layer=" << lay.name()
                << " extent=" << layer_ext << " in map projection "
                << " did not reproject properly back to layer projection";
        }
    }
    else
    {
        // if no intersection then nothing to do for layer
        early_return = true;
    }

    std::vector<feature_type_style const*> & active_styles = mat.active_styles_;

    if (early_return)
    {
        // check for styles needing compositing operations applied
        // https://github.com/mapnik/mapnik/issues/1477
        for (std::string const& style_name : style_names)
        {
            boost::optional<feature_type_style const&> style=m_.find_style(style_name);
            if (!style)
            {
                continue;
            }

            if (style->comp_op() || style->image_filters().size() > 0)
            {
                if (style->active(scale_denom))
                {
                    // we'll have to handle compositing ops
                    active_styles.push_back(&(*style));
                }
            }
        }
        return;
    }

    // if we've got this far, now prepare the unbuffered extent
    // which is used as a bbox for clipping geometries
    if (maximum_extent)
    {
        query_ext.clip(*maximum_extent);
    }

    box2d<double> & layer_ext2 = mat.layer_ext2_;

    layer_ext2 = lay.envelope();
    if (fw_success)
    {
        if (prj_trans.forward(query_ext, PROJ_ENVELOPE_POINTS))
        {
            layer_ext2.clip(query_ext);
        }
    }
    else
    {
        if (prj_trans.backward(layer_ext2, PROJ_ENVELOPE_POINTS))
        {
            layer_ext2.clip(query_ext);
            prj_trans.forward(layer_ext2, PROJ_ENVELOPE_POINTS);
        }
    }

    std::vector<rule_cache> & rule_caches = mat.rule_caches_;
    attribute_collector collector(names);

    // iterate through all named styles collecting active styles and attribute names
    for (std::string const& style_name : style_names)
    {
        boost::optional<feature_type_style const&> style=m_.find_style(style_name);
        if (!style)
        {
            MAPNIK_LOG_ERROR(feature_style_processor)
                << "feature_style_processor: Style=" << style_name
                << " required for layer=" << lay.name() << " does not exist.";

            continue;
        }

        std::vector<rule> const& style_rules = style->get_rules();
        bool active_rules = false;
        rule_cache rc;
        for(rule const& r : style_rules)
        {
            if (r.active(scale_denom))
            {
                rc.add_rule(r);
                active_rules = true;
                collector(r);
            }
        }
        if (active_rules)
        {
            rule_caches.push_back(std::move(rc));
            active_styles.push_back(&(*style));
        }
    }

    // Don't even try to do more work if there are no active styles.
    if (active_styles.empty())
    {
        return;
    }

    double qw = query_ext.width()>0 ? query_ext.width() : 1;
    double qh = query_ext.height()>0 ? query_ext.height() : 1;
    query::resolution_type res(width/qw,
                               height/qh);

    query q(layer_ext,res,scale_denom,extent);
    q.set_variables(p.variables());

    if (p.attribute_collection_policy() == COLLECT_ALL)
    {
        layer_descriptor lay_desc = ds->get_descriptor();
        for (attribute_descriptor const& desc : lay_desc.get_descriptors())
        {
            q.add_property_name(desc.get_name());
        }
    }
    else
    {
        for (std::string const& name : names)
        {
            q.add_property_name(name);
        }
    }
    q.set_filter_factor(collector.get_filter_factor());

    // Also query the group by attribute
    std::string const& group_by = lay.group_by();
    if (!group_by.empty())
    {
        q.add_property_name(group_by);
    }

    bool cache_features = lay.cache_features() && active_styles.size() > 1;

    std::vector<featureset_ptr> & featureset_ptr_list = mat.featureset_ptr_list_;
    if (!group_by.empty() || cache_features)
    {
        featureset_ptr_list.push_back(ds->features_with_context(q,current_ctx));
    }
    else
    {
        for(std::size_t i = 0; i < active_styles.size(); ++i)
        {
            featureset_ptr_list.push_back(ds->features_with_context(q,current_ctx));
        }
    }
}