From b18db001b813f486b014744e9dd920e894bc3523 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 10 Aug 2022 14:24:05 +0200 Subject: [PATCH] [test] add optional csv output to view buffer test cases in qgis --- test/algorithms/buffer/debug_buffer_info.hpp | 35 +++++ test/algorithms/buffer/test_buffer.hpp | 16 ++- test/algorithms/buffer/test_buffer_csv.hpp | 129 +++++++++++++++++++ test/algorithms/buffer/test_buffer_svg.hpp | 17 +-- 4 files changed, 179 insertions(+), 18 deletions(-) create mode 100644 test/algorithms/buffer/debug_buffer_info.hpp create mode 100644 test/algorithms/buffer/test_buffer_csv.hpp diff --git a/test/algorithms/buffer/debug_buffer_info.hpp b/test/algorithms/buffer/debug_buffer_info.hpp new file mode 100644 index 000000000..af8bd5f33 --- /dev/null +++ b/test/algorithms/buffer/debug_buffer_info.hpp @@ -0,0 +1,35 @@ +// Boost.Geometry +// Unit Test Helper + +// Copyright (c) 2022 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_GEOMETRY_TEST_ALGORITHMS_BUFFER_DEBUG_BUFFER_INFO_HPP +#define BOOST_GEOMETRY_TEST_ALGORITHMS_BUFFER_DEBUG_BUFFER_INFO_HPP + +namespace boost { namespace geometry { namespace debug +{ + +// Helper method to translate enumeration to character +inline char piece_type_char(strategy::buffer::piece_type const& type) +{ + using namespace strategy::buffer; + switch(type) + { + case buffered_segment : return 's'; + case buffered_join : return 'j'; + case buffered_round_end : return 'r'; + case buffered_flat_end : return 'f'; + case buffered_point : return 'p'; + case buffered_concave : return 'c'; + default : return '?'; + } +} + +}}} + +#endif diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index efedacd5d..ec6d6962e 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -58,6 +58,10 @@ const double same_distance = -999; # include "test_buffer_svg_per_turn.hpp" #endif +#if defined(TEST_WITH_CSV) +# include "test_buffer_csv.hpp" +#endif + //----------------------------------------------------------------------------- template struct JoinTestProperties @@ -213,7 +217,10 @@ void test_buffer(std::string const& caseid, //std::cout << complete.str() << std::endl; -#if defined(TEST_WITH_SVG_PER_TURN) +#if defined(TEST_WITH_CSV) + detail::buffer_visitor_csv visitor("/tmp/csv/" + caseid + "_"); + +#elif defined(TEST_WITH_SVG_PER_TURN) save_turns_visitor visitor; #elif defined(TEST_WITH_SVG) @@ -268,7 +275,8 @@ void test_buffer(std::string const& caseid, rescale_policy, visitor); -#if defined(TEST_WITH_SVG) +#if defined(TEST_WITH_CSV) +#elif defined(TEST_WITH_SVG) buffer_mapper.map_input_output(mapper, geometry, buffered, distance_strategy.negative()); #endif @@ -340,7 +348,9 @@ void test_buffer(std::string const& caseid, BOOST_CHECK_MESSAGE(bg::is_valid(buffered), complete.str() << " is not valid"); } -#if defined(TEST_WITH_SVG_PER_TURN) +#if defined(TEST_WITH_CSV) + visitor.write_input_output(geometry, buffered); +#elif defined(TEST_WITH_SVG_PER_TURN) { // Create a per turn visitor to map per turn, and buffer again with it per_turn_visitor ptv(complete.str(), visitor.get_points()); diff --git a/test/algorithms/buffer/test_buffer_csv.hpp b/test/algorithms/buffer/test_buffer_csv.hpp new file mode 100644 index 000000000..8a1692659 --- /dev/null +++ b/test/algorithms/buffer/test_buffer_csv.hpp @@ -0,0 +1,129 @@ +// Boost.Geometry +// Unit Test Helper + +// Copyright (c) 2022 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_BUFFER_CSV_HPP +#define BOOST_GEOMETRY_TEST_BUFFER_CSV_HPP + +#include +#include + +#include "debug_buffer_info.hpp" +#include +#include + + +namespace detail +{ + +class buffer_visitor_csv +{ +public: + buffer_visitor_csv(const std::string &path) + : m_path(path) + { + } + + template + inline void apply(PieceCollection const& collection, int phase) + { + if (phase == 0) + { + write_pieces(collection.m_pieces, collection.offsetted_rings); + } + if (phase == 1) + { + write_turns(collection.m_turns); + } + } + + template + inline void write_input_output(Geometry const& input, GeometryBuffer const& buffer) + { + std::ofstream stream(m_path + "_geometries.csv"); + if (! stream.good()) + { + return; + } + + stream << std::setprecision(16) + << "id;role;wkt" << std::endl + << "1;input;" << bg::wkt(input) << std::endl + << "2;output;" << bg::wkt(buffer) << std::endl; + } + +private: + + template + inline void write_turns(Turns const& turns) + { + std::ofstream stream(m_path + "_turns.csv"); + if (! stream.good()) + { + return; + } + std::size_t id = 1; + stream << std::setprecision(16) << "id;wkt;piece_indices;method;operations;cluster_id;traversable;blocked" << std::endl; + for (const auto &turn : turns) + { + stream << id++ << ";" + << bg::wkt(turn.point) << ";" + << turn.operations[0].piece_index << "/" << turn.operations[1].piece_index << ";" + << bg::method_char(turn.method) << ";" + << bg::operation_char(turn.operations[0].operation) << "/" << bg::operation_char(turn.operations[1].operation) << ";" + << turn.cluster_id << ";" + << turn.is_turn_traversable << ";" + << turn.blocked() << ";" + << std::endl; + } + } + + template + inline void write_pieces(Pieces const& pieces, OffsettedRings const& offsetted_rings) + { + std::ofstream stream(m_path + "_pieces.csv"); + if (! stream.good()) + { + return; + } + + std::size_t id = 1; + stream << std::setprecision(16) << "id;wkt;index;start;end;type;segment_indices" << std::endl; + for (auto const& piece : pieces) + { + bg::segment_identifier const& seg_id = piece.first_seg_id; + if (seg_id.segment_index < 0) + { + continue; + } + // NOTE: ring is returned by copy here + auto const corner = piece.m_piece_border.get_full_ring(); + if (corner.empty()) + { + continue; + } + + auto const& ring = offsetted_rings[seg_id.multi_index]; + + stream << id++ << ";" + << bg::wkt(corner) << ";" + << piece.index << ";" + << piece.is_flat_start << ";" + << piece.is_flat_end << ";" + << bg::debug::piece_type_char(piece.type) << ";" + << piece.first_seg_id.segment_index << ".." << piece.beyond_last_segment_index - 1 + << std::endl; + } + } + + std::string m_path; +}; + +} + +#endif diff --git a/test/algorithms/buffer/test_buffer_svg.hpp b/test/algorithms/buffer/test_buffer_svg.hpp index dccb44915..34c8da494 100644 --- a/test/algorithms/buffer/test_buffer_svg.hpp +++ b/test/algorithms/buffer/test_buffer_svg.hpp @@ -28,6 +28,7 @@ # endif #endif +#include "debug_buffer_info.hpp" #include #include #include @@ -85,20 +86,6 @@ get_labelpoint(Ring const& ring, Piece const& piece) } } -inline char piece_type_char(bg::strategy::buffer::piece_type const& type) -{ - using namespace bg::strategy::buffer; - switch(type) - { - case buffered_segment : return 's'; - case buffered_join : return 'j'; - case buffered_round_end : return 'r'; - case buffered_flat_end : return 'f'; - case buffered_point : return 'p'; - case buffered_concave : return 'c'; - default : return '?'; - } -} template class svg_visitor @@ -297,7 +284,7 @@ private : out << piece.index << (piece.is_flat_start ? " FS" : "") << (piece.is_flat_end ? " FE" : "") - << " (" << piece_type_char(piece.type) << ") " + << " (" << bg::debug::piece_type_char(piece.type) << ") " << piece.first_seg_id.segment_index << ".." << piece.beyond_last_segment_index - 1 ;