1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 // Unit Test Helper 3 4 // Copyright (c) 2010-2019 Barend Gehrels, Amsterdam, the Netherlands. 5 // Use, modification and distribution is subject to the Boost Software License, 6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 9 10 #ifndef BOOST_GEOMETRY_TEST_BUFFER_SVG_PER_TURN_HPP 11 #define BOOST_GEOMETRY_TEST_BUFFER_SVG_PER_TURN_HPP 12 13 #include <fstream> 14 #include <vector> 15 16 #include "test_buffer_svg.hpp" 17 #include <boost/ptr_container/ptr_vector.hpp> 18 19 template <typename Point> 20 class save_turns_visitor 21 { 22 public : 23 typedef std::vector<std::pair<Point, int> > vector_type; 24 25 template <typename Turns> get_turns(Turns const & turns)26 inline void get_turns(Turns const& turns) 27 { 28 for (typename boost::range_iterator<Turns const>::type it = 29 boost::begin(turns); it != boost::end(turns); ++it) 30 { 31 m_points.push_back(std::make_pair(it->point, it->turn_index)); 32 } 33 } 34 35 template <typename PieceCollection> apply(PieceCollection const & collection,int phase)36 inline void apply(PieceCollection const& collection, int phase) 37 { 38 if (phase == 0) 39 { 40 get_turns(collection.m_turns); 41 } 42 } 43 get_points()44 vector_type const& get_points() { return m_points; } 45 46 private : 47 vector_type m_points; 48 }; 49 50 51 52 template <typename Point> 53 class mapper_visitor 54 { 55 public : mapper_visitor(std::string const & complete,int index,Point const & point)56 mapper_visitor(std::string const& complete, int index, Point const& point) 57 : m_filename(get_filename(complete, index)) 58 , m_svg(m_filename.c_str()) 59 , m_mapper(m_svg, 1000, 800) 60 , m_visitor(m_mapper) 61 , m_buffer_mapper(m_filename) 62 { 63 box_type box; 64 double half_size = 75.0; // specific for multi_point buffer 65 bg::set<bg::min_corner, 0>(box, bg::get<0>(point) - half_size); 66 bg::set<bg::min_corner, 1>(box, bg::get<1>(point) - half_size); 67 bg::set<bg::max_corner, 0>(box, bg::get<0>(point) + half_size); 68 bg::set<bg::max_corner, 1>(box, bg::get<1>(point) + half_size); 69 70 m_mapper.add(box); 71 m_visitor.set_alternate_box(box); 72 m_buffer_mapper.set_alternate_box(box); 73 } 74 75 // It is used in a ptr vector ~mapper_visitor()76 virtual ~mapper_visitor() 77 { 78 } 79 80 template <typename PieceCollection> apply(PieceCollection const & collection,int phase)81 inline void apply(PieceCollection const& collection, int phase) 82 { 83 m_visitor.apply(collection, phase); 84 } 85 86 template <typename Geometry, typename GeometryBuffer> map_input_output(Geometry const & geometry,GeometryBuffer const & buffered,bool negative)87 void map_input_output(Geometry const& geometry, 88 GeometryBuffer const& buffered, bool negative) 89 { 90 m_buffer_mapper.map_input_output(m_mapper, geometry, buffered, negative); 91 } 92 93 private : get_filename(std::string const & complete,int index)94 std::string get_filename(std::string const& complete, int index) 95 { 96 std::ostringstream filename; 97 filename << "buffer_per_turn_" << complete << "_" << index << ".svg"; 98 return filename.str(); 99 } 100 101 typedef bg::svg_mapper<Point> mapper_type; 102 typedef bg::model::box<Point> box_type; 103 104 std::string m_filename; 105 std::ofstream m_svg; 106 mapper_type m_mapper; 107 svg_visitor<mapper_type, box_type> m_visitor; 108 buffer_svg_mapper<Point> m_buffer_mapper; 109 }; 110 111 template <typename Point> 112 class per_turn_visitor 113 { 114 // Both fstreams and svg mappers are non-copyable, 115 // therefore we need to use dynamic memory 116 typedef boost::ptr_vector<mapper_visitor<Point> > container_type; 117 container_type mappers; 118 119 public : 120 121 typedef std::pair<Point, int> pair_type; 122 typedef std::vector<pair_type> vector_type; 123 per_turn_visitor(std::string const & complete_caseid,vector_type const & points)124 per_turn_visitor(std::string const& complete_caseid, 125 vector_type const& points) 126 { 127 namespace bg = boost::geometry; 128 129 if (points.size() > 100u) 130 { 131 // Defensive check. Too much intersections. Don't create anything 132 return; 133 } 134 135 BOOST_FOREACH(pair_type const& p, points) 136 { 137 mappers.push_back(new mapper_visitor<Point>(complete_caseid, p.second, p.first)); 138 } 139 } 140 141 template <typename PieceCollection> apply(PieceCollection const & collection,int phase)142 inline void apply(PieceCollection const& collection, int phase) 143 { 144 for(typename container_type::iterator it = mappers.begin(); 145 it != mappers.end(); ++it) 146 { 147 it->apply(collection, phase); 148 } 149 } 150 151 template <typename Geometry, typename GeometryBuffer> map_input_output(Geometry const & geometry,GeometryBuffer const & buffered,bool negative)152 void map_input_output(Geometry const& geometry, 153 GeometryBuffer const& buffered, bool negative) 154 { 155 for(typename container_type::iterator it = mappers.begin(); 156 it != mappers.end(); ++it) 157 { 158 it->map_input_output(geometry, buffered, negative); 159 } 160 } 161 }; 162 163 164 #endif // BOOST_GEOMETRY_TEST_BUFFER_SVG_PER_TURN_HPP 165