2012-02-18 14:03:21 +01:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
|
|
|
* This file is part of Mapnik (c++ mapping toolkit)
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Artem Pavlenko
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
// mapnik
|
2012-01-29 04:49:02 +01:00
|
|
|
#include <mapnik/symbolizer_helpers.hpp>
|
2012-02-12 03:55:13 +01:00
|
|
|
#include <mapnik/label_collision_detector.hpp>
|
2012-02-18 14:03:21 +01:00
|
|
|
#include <mapnik/placement_finder.hpp>
|
2012-03-07 13:48:51 +01:00
|
|
|
#include "agg_conv_clip_polyline.h"
|
2012-01-29 04:49:02 +01:00
|
|
|
|
|
|
|
namespace mapnik {
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-03-03 20:15:24 +01:00
|
|
|
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next()
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-03-03 20:15:24 +01:00
|
|
|
if (!placement_valid_) return false;
|
2012-01-29 04:49:02 +01:00
|
|
|
if (point_placement_)
|
2012-03-03 20:15:24 +01:00
|
|
|
return next_point_placement();
|
2012-07-11 15:47:39 +02:00
|
|
|
else if (sym_.clip())
|
|
|
|
return next_line_placement_clipped();
|
2012-01-29 04:49:02 +01:00
|
|
|
else
|
2012-03-03 20:15:24 +01:00
|
|
|
return next_line_placement();
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-03-03 20:15:24 +01:00
|
|
|
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-02-28 00:52:02 +01:00
|
|
|
while (!geometries_to_process_.empty())
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
if (geo_itr_ == geometries_to_process_.end())
|
|
|
|
{
|
|
|
|
//Just processed the last geometry. Try next placement.
|
2012-03-03 20:15:24 +01:00
|
|
|
if (!next_placement()) return false; //No more placements
|
2012-01-29 04:49:02 +01:00
|
|
|
//Start again from begin of list
|
|
|
|
geo_itr_ = geometries_to_process_.begin();
|
|
|
|
continue; //Reexecute size check
|
|
|
|
}
|
2012-03-13 15:56:11 +01:00
|
|
|
|
2012-07-11 15:47:39 +02:00
|
|
|
typedef coord_transform<CoordTransform,geometry_type> path_type;
|
|
|
|
path_type path(t_, **geo_itr_, prj_trans_);
|
|
|
|
|
|
|
|
finder_->clear_placements();
|
|
|
|
if (points_on_line_) {
|
|
|
|
finder_->find_point_placements(path);
|
|
|
|
} else {
|
|
|
|
finder_->find_line_placements(path);
|
|
|
|
}
|
|
|
|
if (!finder_->get_results().empty())
|
|
|
|
{
|
|
|
|
//Found a placement
|
|
|
|
if (points_on_line_)
|
|
|
|
{
|
|
|
|
finder_->update_detector();
|
|
|
|
}
|
|
|
|
geo_itr_ = geometries_to_process_.erase(geo_itr_);
|
|
|
|
if (writer_.first) writer_.first->add_text(
|
|
|
|
finder_->get_results(), finder_->get_extents(),
|
|
|
|
feature_, t_, writer_.second);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//No placement for this geometry. Keep it in geometries_to_process_ for next try.
|
|
|
|
geo_itr_++;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
|
|
|
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement_clipped()
|
|
|
|
{
|
|
|
|
while (!geometries_to_process_.empty())
|
|
|
|
{
|
|
|
|
if (geo_itr_ == geometries_to_process_.end())
|
|
|
|
{
|
|
|
|
//Just processed the last geometry. Try next placement.
|
|
|
|
if (!next_placement()) return false; //No more placements
|
|
|
|
//Start again from begin of list
|
|
|
|
geo_itr_ = geometries_to_process_.begin();
|
|
|
|
continue; //Reexecute size check
|
|
|
|
}
|
|
|
|
|
2012-03-07 13:48:51 +01:00
|
|
|
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
|
2012-05-31 13:13:09 +02:00
|
|
|
typedef coord_transform<CoordTransform,clipped_geometry_type> path_type;
|
2012-03-07 13:48:51 +01:00
|
|
|
clipped_geometry_type clipped(**geo_itr_);
|
|
|
|
clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy());
|
|
|
|
path_type path(t_, clipped, prj_trans_);
|
2012-07-11 15:47:39 +02:00
|
|
|
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->clear_placements();
|
2012-02-21 00:01:54 +01:00
|
|
|
if (points_on_line_) {
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->find_point_placements(path);
|
2012-02-21 00:01:54 +01:00
|
|
|
} else {
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->find_line_placements(path);
|
2012-02-21 00:01:54 +01:00
|
|
|
}
|
2012-03-03 20:15:24 +01:00
|
|
|
if (!finder_->get_results().empty())
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
//Found a placement
|
2012-03-02 12:38:38 +01:00
|
|
|
if (points_on_line_)
|
|
|
|
{
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->update_detector();
|
2012-03-02 12:38:38 +01:00
|
|
|
}
|
2012-02-28 00:52:02 +01:00
|
|
|
geo_itr_ = geometries_to_process_.erase(geo_itr_);
|
2012-01-29 04:49:02 +01:00
|
|
|
if (writer_.first) writer_.first->add_text(
|
2012-03-04 23:25:13 +01:00
|
|
|
finder_->get_results(), finder_->get_extents(),
|
2012-02-02 02:53:35 +01:00
|
|
|
feature_, t_, writer_.second);
|
2012-03-03 20:15:24 +01:00
|
|
|
return true;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
//No placement for this geometry. Keep it in geometries_to_process_ for next try.
|
2012-02-28 00:52:02 +01:00
|
|
|
geo_itr_++;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
2012-03-03 20:15:24 +01:00
|
|
|
return false;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-03-03 20:15:24 +01:00
|
|
|
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-02-28 00:52:02 +01:00
|
|
|
while (!points_.empty())
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
if (point_itr_ == points_.end())
|
|
|
|
{
|
|
|
|
//Just processed the last point. Try next placement.
|
2012-03-03 20:15:24 +01:00
|
|
|
if (!next_placement()) return false; //No more placements
|
2012-01-29 04:49:02 +01:00
|
|
|
//Start again from begin of list
|
|
|
|
point_itr_ = points_.begin();
|
|
|
|
continue; //Reexecute size check
|
|
|
|
}
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->clear_placements();
|
|
|
|
finder_->find_point_placement(point_itr_->first, point_itr_->second, angle_);
|
|
|
|
if (!finder_->get_results().empty())
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
//Found a placement
|
2012-02-28 00:52:02 +01:00
|
|
|
point_itr_ = points_.erase(point_itr_);
|
2012-01-29 04:49:02 +01:00
|
|
|
if (writer_.first) writer_.first->add_text(
|
2012-03-04 23:25:13 +01:00
|
|
|
finder_->get_results(), finder_->get_extents(),
|
2012-02-02 02:53:35 +01:00
|
|
|
feature_, t_, writer_.second);
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->update_detector();
|
|
|
|
return true;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
//No placement for this point. Keep it in points_ for next try.
|
2012-02-28 00:52:02 +01:00
|
|
|
point_itr_++;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
2012-03-03 20:15:24 +01:00
|
|
|
return false;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
|
2012-01-31 12:52:43 +01:00
|
|
|
struct largest_bbox_first
|
|
|
|
{
|
|
|
|
bool operator() (geometry_type const* g0, geometry_type const* g1) const
|
|
|
|
{
|
|
|
|
box2d<double> b0 = g0->envelope();
|
|
|
|
box2d<double> b1 = g1->envelope();
|
|
|
|
return b0.width()*b0.height() > b1.width()*b1.height();
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
2012-01-29 04:49:02 +01:00
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
|
|
|
void text_symbolizer_helper<FaceManagerT, DetectorT>::initialize_geometries()
|
|
|
|
{
|
2012-01-31 12:52:43 +01:00
|
|
|
bool largest_box_only = false;
|
2012-01-29 04:49:02 +01:00
|
|
|
unsigned num_geom = feature_.num_geometries();
|
|
|
|
for (unsigned i=0; i<num_geom; ++i)
|
|
|
|
{
|
|
|
|
geometry_type const& geom = feature_.get_geometry(i);
|
|
|
|
|
|
|
|
// don't bother with empty geometries
|
2012-07-19 17:36:44 +02:00
|
|
|
if (geom.size() == 0) continue;
|
2012-01-31 12:52:43 +01:00
|
|
|
eGeomType type = geom.type();
|
2012-02-02 02:53:35 +01:00
|
|
|
if (type == Polygon)
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-06-25 16:00:53 +02:00
|
|
|
largest_box_only = sym_.largest_bbox_only();
|
2012-01-31 12:52:43 +01:00
|
|
|
if (sym_.get_minimum_path_length() > 0)
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-01-31 12:52:43 +01:00
|
|
|
box2d<double> gbox = t_.forward(geom.envelope(), prj_trans_);
|
|
|
|
if (gbox.width() < sym_.get_minimum_path_length())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO - calculate length here as well
|
|
|
|
geometries_to_process_.push_back(const_cast<geometry_type*>(&geom));
|
|
|
|
}
|
2012-02-02 02:53:35 +01:00
|
|
|
|
2012-01-31 12:52:43 +01:00
|
|
|
if (largest_box_only)
|
|
|
|
{
|
|
|
|
geometries_to_process_.sort(largest_bbox_first());
|
|
|
|
geo_itr_ = geometries_to_process_.begin();
|
|
|
|
geometries_to_process_.erase(++geo_itr_,geometries_to_process_.end());
|
|
|
|
}
|
2012-01-29 04:49:02 +01:00
|
|
|
geo_itr_ = geometries_to_process_.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
|
|
|
void text_symbolizer_helper<FaceManagerT, DetectorT>::initialize_points()
|
|
|
|
{
|
|
|
|
label_placement_enum how_placed = placement_->properties.label_placement;
|
2012-03-06 03:00:45 +01:00
|
|
|
if (how_placed == LINE_PLACEMENT)
|
|
|
|
{
|
2012-01-29 04:49:02 +01:00
|
|
|
point_placement_ = false;
|
|
|
|
return;
|
2012-03-06 03:00:45 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-29 04:49:02 +01:00
|
|
|
point_placement_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
double label_x=0.0;
|
|
|
|
double label_y=0.0;
|
|
|
|
double z=0.0;
|
|
|
|
|
|
|
|
std::list<geometry_type*>::const_iterator itr = geometries_to_process_.begin();
|
|
|
|
std::list<geometry_type*>::const_iterator end = geometries_to_process_.end();
|
|
|
|
for (; itr != end; itr++)
|
|
|
|
{
|
|
|
|
geometry_type const& geom = **itr;
|
|
|
|
if (how_placed == VERTEX_PLACEMENT)
|
|
|
|
{
|
|
|
|
geom.rewind(0);
|
2012-07-19 17:36:44 +02:00
|
|
|
for(unsigned i = 0; i < geom.size(); i++)
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
geom.vertex(&label_x, &label_y);
|
|
|
|
prj_trans_.backward(label_x, label_y, z);
|
|
|
|
t_.forward(&label_x, &label_y);
|
|
|
|
points_.push_back(std::make_pair(label_x, label_y));
|
|
|
|
}
|
2012-03-06 03:00:45 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-31 03:29:26 +02:00
|
|
|
if (geom.type() == LineString)
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-07-31 03:29:26 +02:00
|
|
|
label::middle_point(geom, label_x,label_y);
|
|
|
|
}
|
|
|
|
else if (how_placed == POINT_PLACEMENT)
|
|
|
|
{
|
|
|
|
label::centroid(geom, label_x, label_y);
|
2012-03-06 03:00:45 +01:00
|
|
|
}
|
|
|
|
else if (how_placed == INTERIOR_PLACEMENT)
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-07-20 18:32:38 +02:00
|
|
|
label::interior_position(geom, label_x, label_y);
|
2012-03-06 03:00:45 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-04-10 00:51:04 +02:00
|
|
|
MAPNIK_LOG_ERROR(symbolizer_helpers) << "ERROR: Unknown placement type in initialize_points()";
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
prj_trans_.backward(label_x, label_y, z);
|
|
|
|
t_.forward(&label_x, &label_y);
|
|
|
|
points_.push_back(std::make_pair(label_x, label_y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
point_itr_ = points_.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
|
|
|
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
|
|
|
|
{
|
|
|
|
if (!placement_->next()) {
|
|
|
|
placement_valid_ = false;
|
|
|
|
return false;
|
|
|
|
}
|
2012-01-31 16:24:58 +01:00
|
|
|
placement_->properties.process(text_, feature_);
|
2012-01-29 04:49:02 +01:00
|
|
|
info_ = &(text_.get_string_info());
|
|
|
|
if (placement_->properties.orientation)
|
|
|
|
{
|
2012-08-04 02:13:09 +02:00
|
|
|
// https://github.com/mapnik/mapnik/issues/1352
|
|
|
|
mapnik::evaluate<Feature, value_type> evaluator(feature_);
|
2012-01-29 04:49:02 +01:00
|
|
|
angle_ = boost::apply_visitor(
|
2012-08-04 02:13:09 +02:00
|
|
|
evaluator,
|
2012-02-02 02:53:35 +01:00
|
|
|
*(placement_->properties.orientation)).to_double();
|
2012-01-29 04:49:02 +01:00
|
|
|
} else {
|
|
|
|
angle_ = 0.0;
|
|
|
|
}
|
2012-03-04 13:32:10 +01:00
|
|
|
|
|
|
|
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_ = boost::shared_ptr<placement_finder<DetectorT> >(new placement_finder<DetectorT>(feature_, *placement_, *info_, detector_, dims_));
|
|
|
|
// boost::make_shared<placement_finder<DetectorT> >(feature_, *placement_, *info_, detector_, dims_);
|
2012-03-04 13:32:10 +01:00
|
|
|
|
|
|
|
if (writer_.first) finder_->set_collect_extents(true);
|
|
|
|
|
2012-03-03 20:15:24 +01:00
|
|
|
placement_valid_ = true;
|
2012-01-29 04:49:02 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-03 20:15:24 +01:00
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-07-11 11:32:08 +02:00
|
|
|
placements_type const& text_symbolizer_helper<FaceManagerT, DetectorT>::placements() const
|
2012-03-03 20:15:24 +01:00
|
|
|
{
|
|
|
|
return finder_->get_results();
|
|
|
|
}
|
|
|
|
|
2012-01-29 04:49:02 +01:00
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-03-03 20:15:24 +01:00
|
|
|
bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next()
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-03-03 20:15:24 +01:00
|
|
|
if (!placement_valid_ || !marker_) return false;
|
2012-01-29 04:49:02 +01:00
|
|
|
if (point_placement_)
|
2012-03-03 20:15:24 +01:00
|
|
|
return next_point_placement();
|
2012-01-29 04:49:02 +01:00
|
|
|
else
|
2012-03-03 20:15:24 +01:00
|
|
|
return next_line_placement();
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-03-03 20:15:24 +01:00
|
|
|
bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
position const& shield_pos = sym_.get_shield_displacement();
|
2012-02-28 00:52:02 +01:00
|
|
|
while (!points_.empty())
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
if (point_itr_ == points_.end())
|
|
|
|
{
|
|
|
|
//Just processed the last point. Try next placement.
|
2012-03-03 20:15:24 +01:00
|
|
|
if (!next_placement()) return false; //No more placements
|
2012-01-29 04:49:02 +01:00
|
|
|
//Start again from begin of list
|
|
|
|
point_itr_ = points_.begin();
|
|
|
|
continue; //Reexecute size check
|
|
|
|
}
|
2012-02-18 13:07:23 +01:00
|
|
|
position const& text_disp = placement_->properties.displacement;
|
2012-01-29 17:33:43 +01:00
|
|
|
double label_x = point_itr_->first + shield_pos.first;
|
|
|
|
double label_y = point_itr_->second + shield_pos.second;
|
2012-01-29 04:49:02 +01:00
|
|
|
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->clear_placements();
|
|
|
|
finder_->find_point_placement(label_x, label_y, angle_);
|
|
|
|
if (finder_->get_results().empty())
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
//No placement for this point. Keep it in points_ for next try.
|
2012-02-28 02:05:44 +01:00
|
|
|
point_itr_++;
|
2012-01-29 04:49:02 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
//Found a label placement but not necessarily also a marker placement
|
|
|
|
// check to see if image overlaps anything too, there is only ever 1 placement found for points and verticies
|
|
|
|
if (!sym_.get_unlock_image())
|
|
|
|
{
|
|
|
|
// center image at text center position
|
|
|
|
// remove displacement from image label
|
2012-03-03 20:15:24 +01:00
|
|
|
placements_type const& p = finder_->get_results();
|
|
|
|
double lx = p[0].center.x - text_disp.first;
|
|
|
|
double ly = p[0].center.y - text_disp.second;
|
2012-02-17 00:03:46 +01:00
|
|
|
marker_x_ = lx - 0.5 * marker_w_;
|
|
|
|
marker_y_ = ly - 0.5 * marker_h_;
|
2012-01-29 04:49:02 +01:00
|
|
|
marker_ext_.re_center(lx, ly);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // center image at reference location
|
2012-02-17 00:03:46 +01:00
|
|
|
marker_x_ = label_x - 0.5 * marker_w_;
|
|
|
|
marker_y_ = label_y - 0.5 * marker_h_;
|
2012-01-29 04:49:02 +01:00
|
|
|
marker_ext_.re_center(label_x, label_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (placement_->properties.allow_overlap || detector_.has_placement(marker_ext_))
|
|
|
|
{
|
|
|
|
detector_.insert(marker_ext_);
|
2012-03-03 20:15:24 +01:00
|
|
|
finder_->update_detector();
|
2012-01-29 04:49:02 +01:00
|
|
|
if (writer_.first) {
|
|
|
|
writer_.first->add_box(marker_ext_, feature_, t_, writer_.second);
|
2012-03-04 23:25:13 +01:00
|
|
|
writer_.first->add_text(finder_->get_results(), finder_->get_extents(),
|
|
|
|
feature_, t_, writer_.second);
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
2012-02-28 00:52:02 +01:00
|
|
|
point_itr_ = points_.erase(point_itr_);
|
2012-03-03 20:15:24 +01:00
|
|
|
return true;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
2012-02-28 00:52:02 +01:00
|
|
|
//No placement found. Try again
|
|
|
|
point_itr_++;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
2012-03-03 20:15:24 +01:00
|
|
|
return false;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-03-03 20:15:24 +01:00
|
|
|
bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
position const& pos = placement_->properties.displacement;
|
2012-07-13 11:25:12 +02:00
|
|
|
finder_->additional_boxes().clear();
|
2012-02-28 00:52:02 +01:00
|
|
|
//Markers are automatically centered
|
2012-07-13 11:25:12 +02:00
|
|
|
finder_->additional_boxes().push_back(
|
2012-02-02 02:53:35 +01:00
|
|
|
box2d<double>(-0.5 * marker_ext_.width() - pos.first,
|
|
|
|
-0.5 * marker_ext_.height() - pos.second,
|
|
|
|
0.5 * marker_ext_.width() - pos.first,
|
|
|
|
0.5 * marker_ext_.height() - pos.second));
|
2012-07-11 15:47:39 +02:00
|
|
|
if ( sym_.clip())
|
|
|
|
return text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement_clipped();
|
|
|
|
else
|
|
|
|
return text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement();
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
|
|
|
void shield_symbolizer_helper<FaceManagerT, DetectorT>::init_marker()
|
|
|
|
{
|
|
|
|
std::string filename = path_processor_type::evaluate(*sym_.get_filename(), this->feature_);
|
2012-05-27 23:50:09 +02:00
|
|
|
evaluate_transform(image_transform_, feature_, sym_.get_image_transform());
|
2012-01-29 04:49:02 +01:00
|
|
|
marker_.reset();
|
|
|
|
if (!filename.empty())
|
|
|
|
{
|
|
|
|
marker_ = marker_cache::instance()->find(filename, true);
|
|
|
|
}
|
|
|
|
if (!marker_) {
|
|
|
|
marker_w_ = 0;
|
|
|
|
marker_h_ = 0;
|
|
|
|
marker_ext_.init(0, 0, 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
marker_w_ = (*marker_)->width();
|
|
|
|
marker_h_ = (*marker_)->height();
|
|
|
|
double px0 = - 0.5 * marker_w_;
|
|
|
|
double py0 = - 0.5 * marker_h_;
|
|
|
|
double px1 = 0.5 * marker_w_;
|
|
|
|
double py1 = 0.5 * marker_h_;
|
|
|
|
double px2 = px1;
|
|
|
|
double py2 = py0;
|
|
|
|
double px3 = px0;
|
|
|
|
double py3 = py1;
|
2012-05-10 03:15:34 +02:00
|
|
|
image_transform_.transform(&px0,&py0);
|
|
|
|
image_transform_.transform(&px1,&py1);
|
|
|
|
image_transform_.transform(&px2,&py2);
|
|
|
|
image_transform_.transform(&px3,&py3);
|
2012-01-29 04:49:02 +01:00
|
|
|
marker_ext_.init(px0, py0, px1, py1);
|
|
|
|
marker_ext_.expand_to_include(px2, py2);
|
|
|
|
marker_ext_.expand_to_include(px3, py3);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-02-20 19:32:34 +01:00
|
|
|
pixel_position shield_symbolizer_helper<FaceManagerT, DetectorT>::get_marker_position(text_path const& p)
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
|
|
|
position const& pos = placement_->properties.displacement;
|
|
|
|
if (placement_->properties.label_placement == LINE_PLACEMENT) {
|
2012-02-18 13:07:23 +01:00
|
|
|
double lx = p.center.x - pos.first;
|
|
|
|
double ly = p.center.y - pos.second;
|
2012-02-20 19:32:34 +01:00
|
|
|
double px = lx - 0.5*marker_w_;
|
|
|
|
double py = ly - 0.5*marker_h_;
|
2012-01-29 04:49:02 +01:00
|
|
|
marker_ext_.re_center(lx, ly);
|
2012-02-28 01:23:25 +01:00
|
|
|
//label is added to detector by get_line_placement(), but marker isn't
|
|
|
|
detector_.insert(marker_ext_);
|
2012-01-29 04:49:02 +01:00
|
|
|
if (writer_.first) writer_.first->add_box(marker_ext_, feature_, t_, writer_.second);
|
2012-02-20 19:32:34 +01:00
|
|
|
return pixel_position(px, py);
|
2012-01-29 04:49:02 +01:00
|
|
|
} else {
|
2012-02-28 01:23:25 +01:00
|
|
|
//collision_detector is already updated for point placement in get_point_placement()
|
2012-02-20 19:32:34 +01:00
|
|
|
return pixel_position(marker_x_, marker_y_);
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
|
|
|
marker& shield_symbolizer_helper<FaceManagerT, DetectorT>::get_marker() const
|
|
|
|
{
|
|
|
|
return **marker_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FaceManagerT, typename DetectorT>
|
2012-05-01 17:47:33 +02:00
|
|
|
agg::trans_affine const& shield_symbolizer_helper<FaceManagerT, DetectorT>::get_image_transform() const
|
2012-01-29 04:49:02 +01:00
|
|
|
{
|
2012-05-10 03:15:34 +02:00
|
|
|
return image_transform_;
|
2012-01-29 04:49:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template class text_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>;
|
|
|
|
template class shield_symbolizer_helper<face_manager<freetype_engine>, label_collision_detector4>;
|
|
|
|
} //namespace
|