From b062af211a38a9f3b84c6a1de48b68cd1fa25b4f Mon Sep 17 00:00:00 2001 From: Hermann Kraus Date: Thu, 2 Aug 2012 17:53:02 +0200 Subject: [PATCH] Implement find_points_on_line(). --- include/mapnik/path_processor.hpp | 61 +++++++++++++++++++++ include/mapnik/text/placement_finder_ng.hpp | 8 ++- src/text/placement_finder_ng.cpp | 41 +++++++++++--- 3 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 include/mapnik/path_processor.hpp diff --git a/include/mapnik/path_processor.hpp b/include/mapnik/path_processor.hpp new file mode 100644 index 000000000..54028aef1 --- /dev/null +++ b/include/mapnik/path_processor.hpp @@ -0,0 +1,61 @@ +#ifndef MAPNIK_PATH_PROCESSOR_HPP +#define MAPNIK_PATH_PROCESSOR_HPP + +//mapnik +#include "pixel_position.hpp" + +// agg +#include "agg_path_length.h" +namespace mapnik +{ +template +class path_processor +{ +public: + path_processor(T &path) + : path_(path), length_(agg::path_length(path_)), valid_(true) + { + rewind(); + } + + double length() const { return length_ ;} + + bool next() + { + if (!valid_) return false; + valid_ = path_.vertex(¤t_point_.x, ¤t_point_.y); + return valid_; + } + + pixel_position const& current_point() const + { + return current_point_; + } + + void rewind() + { + path_.rewind(0); + valid_ = true; + } + + bool valid() const { return valid_; } + + /** Skip a certain amount of space. + * + * This function automatically calculates new points if the position is not exactly + * on a point on the path. + */ + bool skip(double length) + { + //TODO + return valid_; + } + +private: + T &path_; + double length_; + bool valid_; + pixel_position current_point_; +}; +} +#endif // PATH_PROCESSOR_HPP diff --git a/include/mapnik/text/placement_finder_ng.hpp b/include/mapnik/text/placement_finder_ng.hpp index 59b5e23d4..51b9aff7e 100644 --- a/include/mapnik/text/placement_finder_ng.hpp +++ b/include/mapnik/text/placement_finder_ng.hpp @@ -32,6 +32,7 @@ //stl #include +#include //boost #include @@ -85,7 +86,8 @@ private: }; typedef boost::shared_ptr glyph_positions_ptr; -struct text_symbolizer_properties; +typedef std::list placements_list; +typedef boost::shared_ptr placements_list_ptr; class placement_finder_ng : boost::noncopyable { @@ -101,10 +103,10 @@ public: glyph_positions_ptr find_point_placement(pixel_position pos); /** Iterate over the given path, placing line-following labels with respect to label_spacing. */ template - glyph_positions_ptr find_line_placements(T & path); + placements_list_ptr find_line_placements(T & path); /** Iterate over the given path, placing point labels with respect to label_spacing. */ template - glyph_positions_ptr find_point_on_line_placements(T & path); + placements_list_ptr find_point_on_line_placements(T & path); /** Try next position alternative from placement_info. */ bool next_position(); private: diff --git a/src/text/placement_finder_ng.cpp b/src/text/placement_finder_ng.cpp index 0cbbeaae5..debe588ab 100644 --- a/src/text/placement_finder_ng.cpp +++ b/src/text/placement_finder_ng.cpp @@ -26,6 +26,7 @@ #include #include #include +#include //boost #include @@ -222,15 +223,39 @@ glyph_positions_ptr placement_finder_ng::find_point_placement(pixel_position pos template -glyph_positions_ptr placement_finder_ng::find_point_on_line_placements(T & path) +placements_list_ptr placement_finder_ng::find_point_on_line_placements(T & path) { - return glyph_positions_ptr(); + path_processor pp(path); + placements_list_ptr list = boost::make_shared(); + if (!pp.valid() || !layout_.size()) return list; + if (pp.length() == 0.0) + { + list->push_back(find_point_placement(pp.current_point())); + return list; + } + + int num_labels = 1; + if (info_->properties.label_spacing > 0) + num_labels = static_cast (floor(pp.length() / info_->properties.label_spacing * scale_factor_)); + + if (info_->properties.force_odd_labels && num_labels % 2 == 0) + num_labels--; + if (num_labels <= 0) + num_labels = 1; + + double spacing = pp.length() / num_labels; + pp.skip(spacing/2.); // first label should be placed at half the spacing + do + { + list->push_back(find_point_placement(pp.current_point())); + } while (pp.skip(spacing)); + return list; } template -glyph_positions_ptr placement_finder_ng::find_line_placements(T & path) +placements_list_ptr placement_finder_ng::find_line_placements(T & path) { - return glyph_positions_ptr(); + return placements_list_ptr(); } @@ -291,10 +316,10 @@ void glyph_positions::set_base_point(pixel_position base_point) typedef agg::conv_clip_polyline clipped_geometry_type; typedef coord_transform ClippedPathType; typedef coord_transform PathType; -template glyph_positions_ptr placement_finder_ng::find_point_on_line_placements(ClippedPathType &); -template glyph_positions_ptr placement_finder_ng::find_line_placements(ClippedPathType &); -template glyph_positions_ptr placement_finder_ng::find_point_on_line_placements(PathType &); -template glyph_positions_ptr placement_finder_ng::find_line_placements(PathType &); +template placements_list_ptr placement_finder_ng::find_point_on_line_placements(ClippedPathType &); +template placements_list_ptr placement_finder_ng::find_line_placements(ClippedPathType &); +template placements_list_ptr placement_finder_ng::find_point_on_line_placements(PathType &); +template placements_list_ptr placement_finder_ng::find_line_placements(PathType &); }// ns mapnik