Merge branch 'text-extend' of https://github.com/mapycz/mapnik into mapycz-text-extend
This commit is contained in:
commit
c1053181f5
12 changed files with 490 additions and 100 deletions
232
include/mapnik/extend_converter.hpp
Normal file
232
include/mapnik/extend_converter.hpp
Normal file
|
@ -0,0 +1,232 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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_EXTEND_CONVERTER_HPP
|
||||
#define MAPNIK_EXTEND_CONVERTER_HPP
|
||||
|
||||
#include <mapnik/vertex.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/msm/back/state_machine.hpp>
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
#include <boost/msm/front/functor_row.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// stl
|
||||
#include <cmath>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
namespace msm = boost::msm;
|
||||
namespace mpl = boost::mpl;
|
||||
using namespace msm::front;
|
||||
|
||||
template <typename T>
|
||||
T extend(T const & v1, T const & v2, double length)
|
||||
{
|
||||
double dx = v2.x - v1.x;
|
||||
double dy = v2.y - v1.y;
|
||||
double l12 = std::sqrt(dx * dx + dy * dy);
|
||||
double coef = 1.0 + length / l12;
|
||||
return vertex2d(v1.x + dx * coef,
|
||||
v1.y + dy * coef, v2.cmd);
|
||||
}
|
||||
|
||||
namespace events
|
||||
{
|
||||
struct vertex_event
|
||||
{
|
||||
vertex_event(vertex2d const & vertex) : vertex(vertex) { }
|
||||
vertex2d const & vertex;
|
||||
};
|
||||
|
||||
struct move_to : vertex_event { using vertex_event::vertex_event; };
|
||||
struct line_to : vertex_event { using vertex_event::vertex_event; };
|
||||
struct close : vertex_event { using vertex_event::vertex_event; };
|
||||
struct end : vertex_event { using vertex_event::vertex_event; };
|
||||
}
|
||||
|
||||
namespace actions
|
||||
{
|
||||
struct store
|
||||
{
|
||||
template <class FSM, class EVT, class SourceState, class TargetState>
|
||||
void operator()(EVT const & e, FSM & m, SourceState&, TargetState&)
|
||||
{
|
||||
m.v2 = m.v1;
|
||||
m.v1 = e.vertex;
|
||||
m.output = boost::none;
|
||||
}
|
||||
};
|
||||
|
||||
struct output
|
||||
{
|
||||
template <class FSM, class EVT, class SourceState, class TargetState>
|
||||
void operator()(EVT const & e, FSM & m, SourceState&, TargetState&)
|
||||
{
|
||||
m.output = e.vertex;
|
||||
}
|
||||
};
|
||||
|
||||
struct store_and_output
|
||||
{
|
||||
template <class FSM, class EVT, class SourceState, class TargetState>
|
||||
void operator()(EVT const & e, FSM & m, SourceState&, TargetState&)
|
||||
{
|
||||
m.v2 = m.v1;
|
||||
m.v1 = e.vertex;
|
||||
m.output = m.v2;
|
||||
}
|
||||
};
|
||||
|
||||
struct output_begin
|
||||
{
|
||||
template <class FSM, class EVT, class SourceState, class TargetState>
|
||||
void operator()(EVT const & e, FSM & m, SourceState&, TargetState&)
|
||||
{
|
||||
m.v2 = m.v1;
|
||||
m.v1 = e.vertex;
|
||||
m.output = extend(m.v1, m.v2, m.extend_length);
|
||||
}
|
||||
};
|
||||
|
||||
struct output_end
|
||||
{
|
||||
template <class FSM, class EVT, class SourceState, class TargetState>
|
||||
void operator()(EVT const & e, FSM & m, SourceState&, TargetState&)
|
||||
{
|
||||
m.output = extend(m.v2, m.v1, m.extend_length);
|
||||
m.v1 = e.vertex;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct extender_def : public msm::front::state_machine_def<extender_def>
|
||||
{
|
||||
using no_exception_thrown = int;
|
||||
using no_message_queue = int;
|
||||
|
||||
struct initial : public msm::front::state<> { };
|
||||
struct vertex_one : public msm::front::state<> { };
|
||||
struct vertex_two : public msm::front::state<> { };
|
||||
struct end : public msm::front::state<> { };
|
||||
|
||||
using initial_state = initial;
|
||||
|
||||
struct transition_table : mpl::vector<
|
||||
// Start Event Next Action Guard
|
||||
// +------------+-----------------+------------+--------------------+------+
|
||||
Row < initial , events::move_to , vertex_one , actions::store >,
|
||||
Row < initial , events::line_to , vertex_one , actions::store >,
|
||||
Row < initial , events::close , initial >,
|
||||
Row < initial , events::end , end , actions::output >,
|
||||
Row < vertex_one , events::move_to , vertex_one , actions::store_and_output >,
|
||||
Row < vertex_one , events::line_to , vertex_two , actions::output_begin >,
|
||||
Row < vertex_one , events::close , initial , actions::store_and_output >,
|
||||
Row < vertex_one , events::end , end , actions::store_and_output >,
|
||||
Row < vertex_two , events::move_to , vertex_one , actions::output_end >,
|
||||
Row < vertex_two , events::line_to , vertex_two , actions::store_and_output >,
|
||||
Row < vertex_two , events::close , initial , actions::output_end >,
|
||||
Row < vertex_two , events::end , end , actions::output_end >,
|
||||
Row < end , events::end , end , actions::output >
|
||||
> {};
|
||||
|
||||
extender_def(double extend_length)
|
||||
: extend_length(extend_length)
|
||||
{
|
||||
}
|
||||
|
||||
boost::optional<vertex2d> output;
|
||||
vertex2d v1, v2;
|
||||
double extend_length;
|
||||
};
|
||||
|
||||
using extender = msm::back::state_machine<extender_def>;
|
||||
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct extend_converter
|
||||
{
|
||||
extend_converter(Geometry & geom)
|
||||
: extend_converter(geom, 0)
|
||||
{}
|
||||
|
||||
extend_converter(Geometry & geom, double extend)
|
||||
: geom_(geom), extender_(extend)
|
||||
{}
|
||||
|
||||
void set_extend(double extend)
|
||||
{
|
||||
extender_.extend_length = extend;
|
||||
}
|
||||
|
||||
unsigned vertex(double * x, double * y)
|
||||
{
|
||||
using namespace detail;
|
||||
vertex2d v;
|
||||
do
|
||||
{
|
||||
v.cmd = geom_.vertex(&v.x, &v.y);
|
||||
switch (v.cmd)
|
||||
{
|
||||
case SEG_MOVETO:
|
||||
extender_.process_event(events::move_to(v));
|
||||
break;
|
||||
case SEG_LINETO:
|
||||
extender_.process_event(events::line_to(v));
|
||||
break;
|
||||
case SEG_CLOSE:
|
||||
extender_.process_event(events::close(v));
|
||||
break;
|
||||
case SEG_END:
|
||||
extender_.process_event(events::end(v));
|
||||
break;
|
||||
}
|
||||
} while(!extender_.output);
|
||||
|
||||
vertex2d const & output = *extender_.output;
|
||||
*x = output.x;
|
||||
*y = output.y;
|
||||
return output.cmd;
|
||||
}
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
geom_.rewind(0);
|
||||
extender_.start();
|
||||
}
|
||||
|
||||
private:
|
||||
Geometry & geom_;
|
||||
detail::extender extender_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_EXTEND_CONVERTER_HPP
|
|
@ -369,6 +369,13 @@ struct symbolizer_default<value_bool, keys::avoid_edges>
|
|||
|
||||
// font-feature-settings
|
||||
|
||||
// extend
|
||||
template <>
|
||||
struct symbolizer_default<value_double, keys::extend>
|
||||
{
|
||||
static value_double value() { return 0.0; }
|
||||
};
|
||||
|
||||
} // namespace mapnik
|
||||
|
||||
#endif // MAPNIK_SYMBOLIZER_DEFAULT_VALUES_HPP
|
||||
|
|
|
@ -92,6 +92,7 @@ enum class keys : std::uint8_t
|
|||
direction,
|
||||
avoid_edges,
|
||||
ff_settings,
|
||||
extend,
|
||||
MAX_SYMBOLIZER_KEY
|
||||
};
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ struct placement_finder_adapter
|
|||
|
||||
};
|
||||
|
||||
using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag, affine_transform_tag, simplify_tag, smooth_tag>;
|
||||
using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag, affine_transform_tag, extend_tag, simplify_tag, smooth_tag>;
|
||||
|
||||
class base_symbolizer_helper
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <mapnik/symbolizer_enumerations.hpp>
|
||||
#include <mapnik/symbolizer_keys.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/extend_converter.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore_agg.hpp>
|
||||
|
@ -65,6 +66,7 @@ struct stroke_tag {};
|
|||
struct dash_tag {};
|
||||
struct affine_transform_tag {};
|
||||
struct offset_transform_tag {};
|
||||
struct extend_tag {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
@ -254,6 +256,23 @@ struct converter_traits<T,mapnik::offset_transform_tag>
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct converter_traits<T, mapnik::extend_tag>
|
||||
{
|
||||
using geometry_type = T;
|
||||
using conv_type = extend_converter<geometry_type>;
|
||||
|
||||
template <typename Args>
|
||||
static void setup(geometry_type & geom, Args const& args)
|
||||
{
|
||||
auto const& sym = args.sym;
|
||||
auto const& feat = args.feature;
|
||||
auto const& vars = args.vars;
|
||||
double extend = get<value_double, keys::extend>(sym, feat, vars);
|
||||
geom.set_extend(extend * args.scale_factor);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T0, typename T1>
|
||||
struct is_switchable
|
||||
|
|
|
@ -895,6 +895,7 @@ void map_parser::parse_symbolizer_base(symbolizer_base &sym, xml_node const& nod
|
|||
set_symbolizer_property<symbolizer_base,composite_mode_e>(sym, keys::comp_op, node);
|
||||
set_symbolizer_property<symbolizer_base,transform_type>(sym, keys::geometry_transform, node);
|
||||
set_symbolizer_property<symbolizer_base,simplify_algorithm_e>(sym, keys::simplify_algorithm, node);
|
||||
set_symbolizer_property<symbolizer_base,double>(sym, keys::extend, node);
|
||||
}
|
||||
|
||||
void map_parser::parse_point_symbolizer(rule & rule, xml_node const & node)
|
||||
|
|
|
@ -158,6 +158,7 @@ static const property_meta_type key_meta[const_max_key] =
|
|||
property_types::target_direction},
|
||||
property_meta_type{ "avoid-edges",nullptr, property_types::target_bool },
|
||||
property_meta_type{ "font-feature-settings", nullptr, property_types::target_font_feature_settings },
|
||||
property_meta_type{ "extend", nullptr, property_types::target_double},
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -327,10 +327,12 @@ text_symbolizer_helper::text_symbolizer_helper(
|
|||
value_bool clip = mapnik::get<value_bool, keys::clip>(sym_, feature_, vars_);
|
||||
value_double simplify_tolerance = mapnik::get<value_double, keys::simplify_tolerance>(sym_, feature_, vars_);
|
||||
value_double smooth = mapnik::get<value_double, keys::smooth>(sym_, feature_, vars_);
|
||||
value_double extend = mapnik::get<value_double, keys::extend>(sym_, feature_, vars_);
|
||||
|
||||
if (clip) converter_.template set<clip_line_tag>();
|
||||
converter_.template set<transform_tag>(); //always transform
|
||||
converter_.template set<affine_transform_tag>();
|
||||
if (extend > 0.0) converter_.template set<extend_tag>();
|
||||
if (simplify_tolerance > 0.0) converter_.template set<simplify_tag>(); // optional simplify converter
|
||||
if (smooth > 0.0) converter_.template set<smooth_tag>(); // optional smooth converter
|
||||
|
||||
|
@ -452,12 +454,15 @@ text_symbolizer_helper::text_symbolizer_helper(
|
|||
value_bool clip = mapnik::get<value_bool, keys::clip>(sym_, feature_, vars_);
|
||||
value_double simplify_tolerance = mapnik::get<value_double, keys::simplify_tolerance>(sym_, feature_, vars_);
|
||||
value_double smooth = mapnik::get<value_double, keys::smooth>(sym_, feature_, vars_);
|
||||
value_double extend = mapnik::get<value_double, keys::extend>(sym_, feature_, vars_);
|
||||
|
||||
if (clip) converter_.template set<clip_line_tag>();
|
||||
converter_.template set<transform_tag>(); //always transform
|
||||
converter_.template set<affine_transform_tag>();
|
||||
if (extend > 0.0) converter_.template set<extend_tag>();
|
||||
if (simplify_tolerance > 0.0) converter_.template set<simplify_tag>(); // optional simplify converter
|
||||
if (smooth > 0.0) converter_.template set<smooth_tag>(); // optional smooth converter
|
||||
|
||||
if (geometries_to_process_.size())
|
||||
{
|
||||
init_marker();
|
||||
|
|
128
test/unit/vertex_adapter/extend_converter.cpp
Normal file
128
test/unit/vertex_adapter/extend_converter.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
#include "catch.hpp"
|
||||
#include "fake_path.hpp"
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/extend_converter.hpp>
|
||||
|
||||
// stl
|
||||
#include <iostream>
|
||||
|
||||
namespace offset_test {
|
||||
|
||||
TEST_CASE("extend converter") {
|
||||
|
||||
SECTION("empty") {
|
||||
try
|
||||
{
|
||||
fake_path path = {};
|
||||
mapnik::extend_converter<fake_path> c(path, 1000);
|
||||
double x, y;
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
std::cerr << ex.what() << "\n";
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("one point") {
|
||||
try
|
||||
{
|
||||
fake_path path = { 0, 0 };
|
||||
mapnik::extend_converter<fake_path> c(path, 1000);
|
||||
double x, y;
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
|
||||
REQUIRE(x == 0);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
std::cerr << ex.what() << "\n";
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("two points") {
|
||||
try
|
||||
{
|
||||
fake_path path = { 0, 0 , 1, 0};
|
||||
mapnik::extend_converter<fake_path> c(path, 1000);
|
||||
double x, y;
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
|
||||
REQUIRE(x == -1000);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 1001);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
std::cerr << ex.what() << "\n";
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("three points") {
|
||||
try
|
||||
{
|
||||
fake_path path = { 0, 0, 1, 0, 2, 0 };
|
||||
mapnik::extend_converter<fake_path> c(path, 1000);
|
||||
double x, y;
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
|
||||
REQUIRE(x == -1000);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 1);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 1002);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
std::cerr << ex.what() << "\n";
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("more points") {
|
||||
try
|
||||
{
|
||||
fake_path path = { 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0 };
|
||||
mapnik::extend_converter<fake_path> c(path, 1000);
|
||||
double x, y;
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
|
||||
REQUIRE(x == -1000);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 1);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 2);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 3);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 4);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
|
||||
REQUIRE(x == 1005);
|
||||
REQUIRE(y == 0);
|
||||
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
std::cerr << ex.what() << "\n";
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
93
test/unit/vertex_adapter/fake_path.hpp
Normal file
93
test/unit/vertex_adapter/fake_path.hpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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
|
||||
#include <mapnik/vertex.hpp>
|
||||
|
||||
// stl
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct fake_path
|
||||
{
|
||||
using coord_type = std::tuple<T, T, unsigned>;
|
||||
using cont_type = std::vector<coord_type>;
|
||||
cont_type vertices_;
|
||||
typename cont_type::iterator itr_;
|
||||
|
||||
fake_path(std::initializer_list<T> l)
|
||||
: fake_path(l.begin(), l.size())
|
||||
{
|
||||
}
|
||||
|
||||
fake_path(std::vector<T> const &v, bool make_invalid = false)
|
||||
: fake_path(v.begin(), v.size(), make_invalid)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Itr>
|
||||
fake_path(Itr itr, size_t sz, bool make_invalid = false)
|
||||
{
|
||||
size_t num_coords = sz >> 1;
|
||||
vertices_.reserve(num_coords + (make_invalid ? 1 : 0));
|
||||
if (make_invalid)
|
||||
{
|
||||
vertices_.push_back(std::make_tuple(0,0,mapnik::SEG_END));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_coords; ++i)
|
||||
{
|
||||
T x = *itr++;
|
||||
T y = *itr++;
|
||||
unsigned cmd = (i == 0) ? mapnik::SEG_MOVETO : mapnik::SEG_LINETO;
|
||||
vertices_.push_back(std::make_tuple(x, y, cmd));
|
||||
}
|
||||
itr_ = vertices_.begin();
|
||||
}
|
||||
|
||||
unsigned vertex(T *x, T *y)
|
||||
{
|
||||
if (itr_ == vertices_.end())
|
||||
{
|
||||
return mapnik::SEG_END;
|
||||
}
|
||||
*x = std::get<0>(*itr_);
|
||||
*y = std::get<1>(*itr_);
|
||||
unsigned cmd = std::get<2>(*itr_);
|
||||
++itr_;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
itr_ = vertices_.begin();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using fake_path = detail::fake_path<double>;
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "catch.hpp"
|
||||
#include "fake_path.hpp"
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/vertex_cache.hpp>
|
||||
|
@ -7,53 +8,6 @@
|
|||
|
||||
// stl
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
struct fake_path
|
||||
{
|
||||
using coord_type = std::tuple<double, double, unsigned>;
|
||||
using cont_type = std::vector<coord_type>;
|
||||
cont_type vertices_;
|
||||
cont_type::iterator itr_;
|
||||
|
||||
fake_path(std::initializer_list<double> l)
|
||||
: fake_path(l.begin(), l.size()) {
|
||||
}
|
||||
|
||||
fake_path(std::vector<double> const &v)
|
||||
: fake_path(v.begin(), v.size()) {
|
||||
}
|
||||
|
||||
template <typename Itr>
|
||||
fake_path(Itr itr, size_t sz) {
|
||||
size_t num_coords = sz >> 1;
|
||||
vertices_.reserve(num_coords);
|
||||
|
||||
for (size_t i = 0; i < num_coords; ++i) {
|
||||
double x = *itr++;
|
||||
double y = *itr++;
|
||||
unsigned cmd = (i == 0) ? agg::path_cmd_move_to : agg::path_cmd_line_to;
|
||||
vertices_.push_back(std::make_tuple(x, y, cmd));
|
||||
}
|
||||
itr_ = vertices_.begin();
|
||||
}
|
||||
|
||||
unsigned vertex(double *x, double *y) {
|
||||
if (itr_ == vertices_.end()) {
|
||||
return agg::path_cmd_stop;
|
||||
}
|
||||
*x = std::get<0>(*itr_);
|
||||
*y = std::get<1>(*itr_);
|
||||
unsigned cmd = std::get<2>(*itr_);
|
||||
++itr_;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void rewind(unsigned) {
|
||||
itr_ = vertices_.begin();
|
||||
}
|
||||
};
|
||||
|
||||
double dist(mapnik::pixel_position const &a,
|
||||
mapnik::pixel_position const &b)
|
||||
|
|
|
@ -1,66 +1,15 @@
|
|||
|
||||
#include "catch.hpp"
|
||||
#include "fake_path.hpp"
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/vertex.hpp>
|
||||
#include <mapnik/offset_converter.hpp>
|
||||
|
||||
// stl
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
namespace offset_test {
|
||||
|
||||
struct fake_path
|
||||
{
|
||||
using coord_type = std::tuple<double, double, unsigned>;
|
||||
using cont_type = std::vector<coord_type>;
|
||||
cont_type vertices_;
|
||||
cont_type::iterator itr_;
|
||||
|
||||
fake_path(std::initializer_list<double> l)
|
||||
: fake_path(l.begin(), l.size()) {
|
||||
}
|
||||
|
||||
fake_path(std::vector<double> const &v, bool make_invalid = false)
|
||||
: fake_path(v.begin(), v.size(), make_invalid) {
|
||||
}
|
||||
|
||||
template <typename Itr>
|
||||
fake_path(Itr itr, size_t sz, bool make_invalid = false) {
|
||||
size_t num_coords = sz >> 1;
|
||||
vertices_.reserve(num_coords + (make_invalid ? 1 : 0));
|
||||
if (make_invalid)
|
||||
{
|
||||
vertices_.push_back(std::make_tuple(0,0,mapnik::SEG_END));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_coords; ++i) {
|
||||
double x = *itr++;
|
||||
double y = *itr++;
|
||||
unsigned cmd = (i == 0) ? mapnik::SEG_MOVETO : mapnik::SEG_LINETO;
|
||||
vertices_.push_back(std::make_tuple(x, y, cmd));
|
||||
}
|
||||
itr_ = vertices_.begin();
|
||||
}
|
||||
|
||||
unsigned vertex(double *x, double *y) {
|
||||
if (itr_ == vertices_.end()) {
|
||||
return mapnik::SEG_END;
|
||||
}
|
||||
*x = std::get<0>(*itr_);
|
||||
*y = std::get<1>(*itr_);
|
||||
unsigned cmd = std::get<2>(*itr_);
|
||||
++itr_;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void rewind(unsigned) {
|
||||
itr_ = vertices_.begin();
|
||||
}
|
||||
};
|
||||
|
||||
static double DELTA_BUFF = 0.5;
|
||||
|
||||
double dist(double x0, double y0, double x1, double y1)
|
||||
|
|
Loading…
Reference in a new issue