Merge pull request #2388 from mapycz/3.x-refactor-markers-placement

refactor marker placements
This commit is contained in:
Dane Springmeyer 2014-08-24 12:09:23 -07:00
commit 4ebf1ae114
9 changed files with 68 additions and 167 deletions

View file

@ -83,15 +83,9 @@ struct raster_markers_rasterizer_dispatch_grid : mapnik::noncopyable
box2d<double> bbox(0,0, src_.width(), src_.height());
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
markers_placement_finder<T, label_collision_detector4> placement_finder(
placement_method,
path,
bbox,
marker_trans_,
detector_,
spacing * scale_factor_,
max_error,
allow_overlap);
placement_method, path, detector_, params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
{
@ -200,15 +194,9 @@ struct vector_markers_rasterizer_dispatch_grid : mapnik::noncopyable
agg::trans_affine_translation recenter(-center.x, -center.y);
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
markers_placement_finder<T, Detector> placement_finder(
placement_method,
path,
bbox_,
marker_trans_,
detector_,
spacing * scale_factor_,
max_error,
allow_overlap);
placement_method, path, detector_, params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
{

View file

@ -117,15 +117,9 @@ struct vector_markers_rasterizer_dispatch : mapnik::noncopyable
coord2d center = bbox_.center();
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine tr = recenter * marker_trans_;
markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap };
markers_placement_finder<T, Detector> placement_finder(
placement_method,
path,
bbox_,
tr,
detector_,
spacing * scale_factor_,
max_error,
allow_overlap);
placement_method, path, detector_, params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
{
@ -206,15 +200,9 @@ struct raster_markers_rasterizer_dispatch : mapnik::noncopyable
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
markers_placement_finder<T, label_collision_detector4> placement_finder(
placement_method,
path,
bbox_,
marker_trans_,
detector_,
spacing * scale_factor_,
max_error,
allow_overlap);
placement_method, path, detector_, params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
{

View file

@ -67,13 +67,9 @@ public:
markers_placement_finder(marker_placement_e placement_type,
Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)
: placement_(create(placement_type, locator, size, tr, detector, spacing, max_error, allow_overlap))
markers_placement_params const& params)
: placement_(create(placement_type, locator, detector, params))
{
}
@ -87,21 +83,13 @@ private:
// Factory function for particular placement implementations.
static markers_placement create(marker_placement_e placement_type,
Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)
markers_placement_params const& params)
{
static const std::map<marker_placement_e, boost::function<markers_placement(
Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)>> factories =
markers_placement_params const& params)>> factories =
{
{ MARKER_POINT_PLACEMENT, boost::value_factory<markers_point_placement<Locator, Detector>>() },
{ MARKER_INTERIOR_PLACEMENT, boost::value_factory<markers_interior_placement<Locator, Detector>>() },
@ -109,7 +97,7 @@ private:
{ MARKER_VERTEX_FIRST_PLACEMENT, boost::value_factory<markers_vertex_first_placement<Locator, Detector>>() },
{ MARKER_VERTEX_LAST_PLACEMENT, boost::value_factory<markers_vertex_last_placement<Locator, Detector>>() }
};
return factories.at(placement_type)(locator, size, tr, detector, spacing, max_error, allow_overlap);
return factories.at(placement_type)(locator, detector, params);
}
markers_placement placement_;

View file

@ -32,17 +32,8 @@ template <typename Locator, typename Detector>
class markers_interior_placement : public markers_point_placement<Locator, Detector>
{
public:
markers_interior_placement(
Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)
: markers_point_placement<Locator, Detector>(
locator, size, tr, detector,
spacing, max_error, allow_overlap)
markers_interior_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
: markers_point_placement<Locator, Detector>(locator, detector, params)
{
}
@ -79,7 +70,7 @@ public:
box2d<double> box = this->perform_transform(angle, x, y);
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
{
return false;
}

View file

@ -36,32 +36,18 @@ template <typename Locator, typename Detector>
class markers_line_placement : public markers_point_placement<Locator, Detector>
{
public:
markers_line_placement(Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)
: markers_point_placement<Locator, Detector>(
locator, size, tr, detector,
spacing, max_error, allow_overlap),
last_x(0.0),
last_y(0.0),
next_x(0.0),
next_y(0.0),
error_(0.0),
spacing_left_(0.0),
marker_nr_(0)
markers_line_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
: markers_point_placement<Locator, Detector>(locator, detector, params),
marker_width_((params.size * params.tr).width()),
last_x(0.0),
last_y(0.0),
next_x(0.0),
next_y(0.0),
error_(0.0),
spacing_left_(0.0),
marker_nr_(0)
{
if (spacing >= 1)
{
this->spacing_ = spacing;
}
else
{
this->spacing_ = 100;
}
spacing_ = params.spacing < 1 ? 100 : params.spacing;
rewind();
}
@ -103,31 +89,31 @@ public:
{
//First marker
marker_nr_++;
this->spacing_left_ = this->spacing_ / 2;
spacing_left_ = spacing_ / 2;
}
else
{
this->spacing_left_ = this->spacing_;
spacing_left_ = spacing_;
}
spacing_left_ -= error_;
error_ = 0.0;
double max_err_allowed = this->max_error_ * this->spacing_;
double max_err_allowed = this->params_.max_error * spacing_;
//Loop exits when a position is found or when no more segments are available
while (true)
{
//Do not place markers too close to the beginning of a segment
if (spacing_left_ < this->marker_width_/2)
if (spacing_left_ < this->marker_width_ / 2)
{
set_spacing_left(this->marker_width_/2); //Only moves forward
set_spacing_left(this->marker_width_ / 2); //Only moves forward
}
//Error for this marker is too large. Skip to the next position.
if (std::fabs(error_) > max_err_allowed)
{
while (this->error_ > this->spacing_)
while (this->error_ > spacing_)
{
error_ -= this->spacing_; //Avoid moving backwards
error_ -= spacing_; //Avoid moving backwards
}
spacing_left_ += this->spacing_ - this->error_;
spacing_left_ += spacing_ - this->error_;
error_ = 0.0;
}
double dx = next_x - last_x;
@ -185,10 +171,10 @@ public:
x = last_x + dx * (spacing_left_ / segment_length);
y = last_y + dy * (spacing_left_ / segment_length);
box2d<double> box = this->perform_transform(angle, x, y);
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
{
//10.0 is the approxmiate number of positions tried and choosen arbitrarily
set_spacing_left(spacing_left_ + this->spacing_ * this->max_error_ / 10.0); //Only moves forward
set_spacing_left(spacing_left_ + spacing_ * this->params_.max_error / 10.0); //Only moves forward
continue;
}
if (!ignore_placement)
@ -206,6 +192,8 @@ private:
double last_y;
double next_x;
double next_y;
double spacing_;
double marker_width_;
// If a marker could not be placed at the exact point where it should
// go the next marker's distance will be a bit lower.
double error_;

View file

@ -23,7 +23,6 @@
#ifndef MAPNIK_MARKERS_PLACEMENTS_POINT_HPP
#define MAPNIK_MARKERS_PLACEMENTS_POINT_HPP
#include <mapnik/markers_placements/point.hpp>
#include <mapnik/geom_util.hpp>
#include "agg_basics.h"
@ -31,26 +30,23 @@
namespace mapnik {
struct markers_placement_params
{
box2d<double> const& size;
agg::trans_affine const& tr;
double spacing;
double max_error;
bool allow_overlap;
};
template <typename Locator, typename Detector>
class markers_point_placement
{
public:
markers_point_placement(
Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)
markers_point_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
: locator_(locator),
size_(size),
tr_(tr),
detector_(detector),
spacing_(spacing),
max_error_(max_error),
allow_overlap_(allow_overlap),
marker_width_((size_ * tr_).width()),
params_(params),
done_(false)
{
rewind();
@ -89,11 +85,9 @@ public:
}
angle = 0;
agg::trans_affine matrix = tr_;
matrix.translate(x,y);
box2d<double> box = size_ * matrix;
box2d<double> box = perform_transform(angle, x, y);
if (!allow_overlap_ && !detector_.has_placement(box))
if (!params_.allow_overlap && !detector_.has_placement(box))
{
return false;
}
@ -109,24 +103,18 @@ public:
protected:
Locator &locator_;
box2d<double> size_;
agg::trans_affine tr_;
Detector &detector_;
double spacing_;
double max_error_;
bool allow_overlap_;
double marker_width_;
markers_placement_params const& params_;
bool done_;
// Rotates the size_ box and translates the position.
box2d<double> perform_transform(double angle, double dx, double dy)
{
double x1 = size_.minx();
double x2 = size_.maxx();
double y1 = size_.miny();
double y2 = size_.maxy();
agg::trans_affine tr = tr_ * agg::trans_affine_rotation(angle)
.translate(dx, dy);
double x1 = params_.size.minx();
double x2 = params_.size.maxx();
double y1 = params_.size.miny();
double y2 = params_.size.maxy();
agg::trans_affine tr = params_.tr * agg::trans_affine_rotation(angle).translate(dx, dy);
double xA = x1, yA = y1,
xB = x2, yB = y1,
xC = x2, yC = y2,

View file

@ -31,17 +31,8 @@ template <typename Locator, typename Detector>
class markers_vertex_first_placement : public markers_point_placement<Locator, Detector>
{
public:
markers_vertex_first_placement(
Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)
: markers_point_placement<Locator, Detector>(
locator, size, tr, detector,
spacing, max_error, allow_overlap)
markers_vertex_first_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
: markers_point_placement<Locator, Detector>(locator, detector, params)
{
}
@ -78,7 +69,7 @@ public:
box2d<double> box = this->perform_transform(angle, x, y);
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
{
return false;
}

View file

@ -31,17 +31,8 @@ template <typename Locator, typename Detector>
class markers_vertex_last_placement : public markers_point_placement<Locator, Detector>
{
public:
markers_vertex_last_placement(
Locator &locator,
box2d<double> const& size,
agg::trans_affine const& tr,
Detector &detector,
double spacing,
double max_error,
bool allow_overlap)
: markers_point_placement<Locator, Detector>(
locator, size, tr, detector,
spacing, max_error, allow_overlap)
markers_vertex_last_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
: markers_point_placement<Locator, Detector>(locator, detector, params)
{
}
@ -83,7 +74,7 @@ public:
box2d<double> box = this->perform_transform(angle, x, y);
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
{
return false;
}

View file

@ -87,15 +87,9 @@ struct markers_dispatch : mapnik::noncopyable
coord2d center = bbox_.center();
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine tr = recenter * marker_trans_;
markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap };
markers_placement_finder<T, label_collision_detector4> placement_finder(
placement_method,
path,
bbox_,
tr,
detector_,
spacing * scale_factor_,
max_error,
allow_overlap);
placement_method, path, detector_, params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
{
@ -156,15 +150,9 @@ struct raster_markers_dispatch : mapnik::noncopyable
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
box2d<double> bbox_(0,0, src_.width(),src_.height());
markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
markers_placement_finder<T, label_collision_detector4> placement_finder(
placement_method,
path,
bbox_,
marker_trans_,
detector_,
spacing * scale_factor_,
max_error,
allow_overlap);
placement_method, path, detector_, params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
{