// Boost.Geometry (aka GGL, Generic Geometry Library) // Example: Affine Transformation (translate, scale, rotate) // // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // // 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) #include // for std::time #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_SVG) # include #endif #include #include #include using namespace boost::geometry; struct random_style { random_style() : rng(static_cast(std::time(0))), dist(0, 255), colour(rng, dist) {} std::string fill(double opacity = 1) { std::ostringstream oss; oss << "fill:rgba(" << colour() << "," << colour() << "," << colour() << "," << opacity << ");"; return oss.str(); } std::string stroke(int width, double opacity = 1) { std::ostringstream oss; oss << "stroke:rgba(" << colour() << "," << colour() << "," << colour() << "," << opacity << ");"; oss << "stroke-width:" << width << ";"; return oss.str(); } template std::string text(T x, T y, std::string const& text) { std::ostringstream oss; oss << "(x) - 90 << "\" y=\"" << static_cast(y) << "\" font-family=\"Verdana\">" << text << ""; return oss.str(); } boost::mt19937 rng; boost::uniform_int<> dist; boost::variate_generator > colour; }; template struct svg_output { svg_output(OutputStream& os, double opacity = 1) : os(os), opacity(opacity) { os << "\n" << "\n" << "" << std::endl; } ~svg_output() { os << "" << std::endl; } template void put(G const& g, std::string const& label) { std::string style_str(style.fill(opacity) + style.stroke(5, opacity)); #if defined(HAVE_SVG) os << boost::geometry::svg(g, style_str) << std::endl; #endif if (!label.empty()) { typename point_type::type c; centroid(g, c); os << style.text(static_cast(get<0>(c)), static_cast(get<1>(c)), label); } } private: OutputStream& os; double opacity; random_style style; }; int main() { using namespace boost::geometry::strategy::transform; typedef boost::geometry::model::d2::point_xy point_2d; try { std::string file("06_b_transformation_example.svg"); std::ofstream ofs(file.c_str()); svg_output svg(ofs, 0.5); // G1 - create subject for affine transformations model::polygon g1; read_wkt("POLYGON((50 250, 400 250, 150 50, 50 250))", g1); std::clog << "source box:\t" << boost::geometry::dsv(g1) << std::endl; svg.put(g1, "g1"); // G1 - Translate -> G2 translate_transformer translate(0, 250); model::polygon g2; transform(g1, g2, translate); std::clog << "translated:\t" << boost::geometry::dsv(g2) << std::endl; svg.put(g2, "g2=g1.translate(0,250)"); // G2 - Scale -> G3 scale_transformer scale(0.5, 0.5); model::polygon g3; transform(g2, g3, scale); std::clog << "scaled:\t" << boost::geometry::dsv(g3) << std::endl; svg.put(g3, "g3=g2.scale(0.5,0.5)"); // G3 - Combine rotate and translate -> G4 rotate_transformer rotate(45); // Compose matrix for the two transformation // Create transformer attached to the transformation matrix matrix_transformer combined(rotate.matrix() * translate.matrix()); // Apply transformation to subject geometry point-by-point model::polygon g4; transform(g3, g4, combined); std::clog << "rotated & translated:\t" << boost::geometry::dsv(g4) << std::endl; svg.put(g4, "g4 = g3.(rotate(45) * translate(0,250))"); std::clog << "Saved SVG file:\t" << file << std::endl; } catch (std::exception const& e) { std::cerr << e.what() << std::endl; } catch (...) { std::cerr << "unknown error" << std::endl; } return 0; }