From fa0b97fff7390eb8ac9a2295c1931088b2b71fe6 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Mon, 28 Jul 2014 15:36:10 +0000 Subject: [PATCH] add markers placement methods vertex-first and vertex-last --- include/mapnik/markers_placement.hpp | 10 +- .../markers_placements/vertext_first.hpp | 98 +++++++++++++++++ .../markers_placements/vertext_last.hpp | 103 ++++++++++++++++++ include/mapnik/symbolizer_enumerations.hpp | 2 + src/symbolizer_enumerations.cpp | 2 + 5 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 include/mapnik/markers_placements/vertext_first.hpp create mode 100644 include/mapnik/markers_placements/vertext_last.hpp diff --git a/include/mapnik/markers_placement.hpp b/include/mapnik/markers_placement.hpp index 6a784a790..bbc15b85e 100644 --- a/include/mapnik/markers_placement.hpp +++ b/include/mapnik/markers_placement.hpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -41,7 +43,9 @@ class markers_placement_finder : mapnik::noncopyable public: using markers_placement = boost::variant, markers_line_placement, - markers_interior_placement>; + markers_interior_placement, + markers_vertex_first_placement, + markers_vertex_last_placement>; class get_point_visitor : public boost::static_visitor { @@ -110,7 +114,9 @@ private: { { MARKER_POINT_PLACEMENT, boost::value_factory>() }, { MARKER_INTERIOR_PLACEMENT, boost::value_factory>() }, - { MARKER_LINE_PLACEMENT, boost::value_factory>() } + { MARKER_LINE_PLACEMENT, boost::value_factory>() }, + { MARKER_VERTEX_FIRST_PLACEMENT, boost::value_factory>() }, + { MARKER_VERTEX_LAST_PLACEMENT, boost::value_factory>() } }; return factories.at(placement_type)(locator, size, tr, detector, spacing, max_error, allow_overlap); } diff --git a/include/mapnik/markers_placements/vertext_first.hpp b/include/mapnik/markers_placements/vertext_first.hpp new file mode 100644 index 000000000..57608fbdd --- /dev/null +++ b/include/mapnik/markers_placements/vertext_first.hpp @@ -0,0 +1,98 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#ifndef MAPNIK_MARKERS_PLACEMENTS_VERTEXT_FIRST_HPP +#define MAPNIK_MARKERS_PLACEMENTS_VERTEXT_FIRST_HPP + +#include + +namespace mapnik { + +template +class markers_vertex_first_placement : public markers_point_placement +{ +public: + markers_vertex_first_placement( + Locator &locator, + box2d const& size, + agg::trans_affine const& tr, + Detector &detector, + double spacing, + double max_error, + bool allow_overlap) + : markers_point_placement( + locator, size, tr, detector, + spacing, max_error, allow_overlap) + { + } + + bool get_point(double &x, double &y, double &angle, bool ignore_placement) + { + if (this->done_) + { + return false; + } + + if (this->locator_.type() == mapnik::geometry_type::types::Point) + { + return markers_point_placement::get_point(x, y, angle, ignore_placement); + } + + double x0, y0; + + if (agg::is_stop(this->locator_.vertex(&x0, &y0))) + { + this->done_ = true; + return false; + } + + x = x0; + y = y0; + angle = 0; + + double x1, y1; + + if (agg::is_line_to(this->locator_.vertex(&x1, &y1))) + { + angle = std::atan2(y1 - y0, x1 - x0); + } + + box2d box = this->perform_transform(angle, x, y); + + if (!this->allow_overlap_ && !this->detector_.has_placement(box)) + { + return false; + } + + if (!ignore_placement) + { + this->detector_.insert(box); + } + + this->done_ = true; + return true; + } +}; + +} + +#endif // MAPNIK_MARKERS_PLACEMENTS_VERTEXT_FIRST_HPP diff --git a/include/mapnik/markers_placements/vertext_last.hpp b/include/mapnik/markers_placements/vertext_last.hpp new file mode 100644 index 000000000..2ff1f740a --- /dev/null +++ b/include/mapnik/markers_placements/vertext_last.hpp @@ -0,0 +1,103 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#ifndef MAPNIK_MARKERS_PLACEMENTS_VERTEXT_LAST_HPP +#define MAPNIK_MARKERS_PLACEMENTS_VERTEXT_LAST_HPP + +#include + +namespace mapnik { + +template +class markers_vertex_last_placement : public markers_point_placement +{ +public: + markers_vertex_last_placement( + Locator &locator, + box2d const& size, + agg::trans_affine const& tr, + Detector &detector, + double spacing, + double max_error, + bool allow_overlap) + : markers_point_placement( + locator, size, tr, detector, + spacing, max_error, allow_overlap) + { + } + + bool get_point(double &x, double &y, double &angle, bool ignore_placement) + { + if (this->done_) + { + return false; + } + + double next_x, next_y; + double x0, y0; + double x1, y1; + unsigned command0, command1 = agg::path_cmd_stop; + + while (!agg::is_stop(command0 = this->locator_.vertex(&next_x, &next_y))) + { + command1 = command0; + x1 = x0; + y1 = y0; + x0 = next_x; + y0 = next_y; + } + + // If path stopped on the very firts vertex. + if (agg::is_stop(command1)) + { + this->done_ = true; + return false; + } + + x = x0; + y = y0; + + if (agg::is_line_to(command1)) + { + angle = std::atan2(y0 - y1, x0 - x1); + } + + box2d box = this->perform_transform(angle, x, y); + + if (!this->allow_overlap_ && !this->detector_.has_placement(box)) + { + return false; + } + + if (!ignore_placement) + { + this->detector_.insert(box); + } + + this->done_ = true; + return true; + } +}; + +} + +#endif // MAPNIK_MARKERS_PLACEMENTS_VERTEXT_LAST_HPP diff --git a/include/mapnik/symbolizer_enumerations.hpp b/include/mapnik/symbolizer_enumerations.hpp index 0b3179815..b4b81c1de 100644 --- a/include/mapnik/symbolizer_enumerations.hpp +++ b/include/mapnik/symbolizer_enumerations.hpp @@ -102,6 +102,8 @@ enum marker_placement_enum MARKER_POINT_PLACEMENT, MARKER_INTERIOR_PLACEMENT, MARKER_LINE_PLACEMENT, + MARKER_VERTEX_FIRST_PLACEMENT, + MARKER_VERTEX_LAST_PLACEMENT, marker_placement_enum_MAX }; diff --git a/src/symbolizer_enumerations.cpp b/src/symbolizer_enumerations.cpp index 27e3f9b14..257de804d 100644 --- a/src/symbolizer_enumerations.cpp +++ b/src/symbolizer_enumerations.cpp @@ -65,6 +65,8 @@ static const char * marker_placement_strings[] = { "point", "interior", "line", + "vertex-first", + "vertex-last", "" };