// Boost.Geometry (aka GGL, Generic Geometry Library) // Tool reporting Implementation Status in QBK format // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2011-2012 Bruno Lalande, Paris, France. // 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 #include #include #include #include #include #include #include #include #include static const int point = 0; static const int segment = 1; static const int box = 2; static const int linestring = 3; static const int ring = 4; static const int polygon = 5; static const int multi_point = 6; static const int multi_linestring = 7; static const int multi_polygon = 8; static const int geometry_count = 9; struct compile_bjam { static inline bool apply(int type1, int type2) { std::ostringstream command; // For debugging: command << "bjam -a tmp > tmp/t" << type1 << "_" << type2 << ".out"; //command << "bjam -a tmp > tmp/t.out"; int failed = system(command.str().c_str()); return failed == 0; } }; struct compile_msvc { bool first; int count; compile_msvc() : first(true) , count(0) {} inline bool apply(int type1, int type2) { std::ostringstream command; command << "cl /nologo -I. -I/_svn/boost/trunk /EHsc /Y"; if (first) { std::cout << " (creating PCH)"; command << "c"; first = false; } else { command << "u"; } command << "implementation_status.hpp tmp/t.cpp > tmp/t" //.out"; // For debugging: << type1 << "_" << type2 << ".out"; int failed = system(command.str().c_str()); return failed == 0; } }; struct algorithm { std::string name; int arity; explicit algorithm(std::string const& n, int a = 1) : name(n) , arity(a) {} }; inline std::string bool_string(bool v) { return v ? "true" : "false"; } inline std::string typedef_string(int type, bool clockwise, bool open) { std::ostringstream out; switch(type) { case point : return "P"; case linestring : return "bg::model::linestring

"; case box : return "bg::model::box

"; case segment : return "bg::model::segment

"; case ring : out << "bg::model::ring"; break; case polygon : out << "bg::model::polygon"; break; case multi_point : return "bg::model::multi_point

"; case multi_linestring : out << "bg::model::multi_linestring >"; break; case multi_polygon : out << "bg::model::multi_polygon >"; break; } return out.str(); } inline std::string wkt_string(int type) { switch(type) { case point : return "POINT(1 1)"; case linestring : return "LINESTRING(1 1,2 2)"; case segment : return "LINESTRING(1 1,2 2)"; case box : return "POLYGON((1 1,2 2)"; case polygon : case ring : return "POLYGON((0 0,0 1,1 1,0 0))"; case multi_point : return "MULTIPOINT((1 1),(2 2))"; case multi_linestring : return "MULTILINESTRING((1 1,2 2))"; case multi_polygon : return "MULTIPOLYGON(((0 0,0 1,1 1,0 0)))"; } return ""; } inline std::string geometry_string(int type) { switch(type) { case point : return "Point"; case linestring : return "Linestring"; case box : return "Box"; case polygon : return "Polygon"; case ring : return "Ring"; case segment : return "Segment"; case multi_point : return "MultiPoint"; case multi_linestring : return "MultiLinestring"; case multi_polygon : return "MultiPolygon"; } return ""; } template int report_library(CompilePolicy& compile_policy, int type, algorithm const& algo, bool clockwise, bool open, int dimensions, std::string const& cs, int type2 = -1) { std::string lit; { std::ostringstream out; out << geometry_string(type); if (type2 != -1) { out << "_" << geometry_string(type2); } out << "_" << algo.name << "_" << bool_string(clockwise) << "_" << bool_string(open) << "_" << boost::replace_all_copy ( boost::replace_all_copy ( boost::replace_all_copy(cs, "bg::", "") , "<", "_" ) , ">", "_" ); lit = out.str(); } std::cout << lit; { std::ofstream out("tmp/t.cpp"); out << "#include " << std::endl << "template " << std::endl << "inline void test()" << std::endl << "{" << std::endl << " namespace bg = boost::geometry;" << std::endl << " " << typedef_string(type, clockwise, open) << " geometry;" << std::endl << " bg::read_wkt(\"" << wkt_string(type) << "\", geometry);" << std::endl; if (algo.arity > 1) { out << " " << typedef_string(type2, clockwise, open) << " geometry2;" << std::endl << " bg::read_wkt(\"" << wkt_string(type2) << "\", geometry2);" << std::endl; } switch(algo.arity) { case 1 : out << " bg::" << algo.name << "(geometry);" << std::endl; break; case 2 : out << " bg::" << algo.name << "(geometry, geometry2);" << std::endl; break; } out << "}" << std::endl << std::endl ; out << "int main()" << std::endl << "{" << std::endl << " namespace bg = boost::geometry;" << std::endl << " test >();" << std::endl << " return 0;" << std::endl << "}" << std::endl << std::endl ; } bool result = compile_policy.apply(type, type2); if (! result) { std::cout << " ERROR"; } std::cout << std::endl; return result; } template std::vector report(CompilePolicy& compile_policy, int type, algorithm const& algo, bool clockwise, bool open, int dimensions, std::string const& cs) { std::vector result; switch(algo.arity) { case 1 : result.push_back(report_library(compile_policy, type, algo, clockwise, open, dimensions, cs)); break; case 2 : for (int type2 = point; type2 < geometry_count; ++type2) { result.push_back(report_library(compile_policy, type, algo, clockwise, open, dimensions, cs, type2)); } break; } return result; } struct cs { std::string name; cs(std::string const& n) : name(n) {} }; int main(int argc, char** argv) { #if defined(_MSC_VER) compile_msvc compile_policy; #else compile_bjam compile_policy; #endif typedef std::vector v_a_type; v_a_type algorithms; algorithms.push_back(algorithm("area")); algorithms.push_back(algorithm("length")); algorithms.push_back(algorithm("perimeter")); algorithms.push_back(algorithm("correct")); algorithms.push_back(algorithm("distance", 2)); algorithms.push_back(algorithm("centroid", 2)); algorithms.push_back(algorithm("intersects", 2)); algorithms.push_back(algorithm("within", 2)); algorithms.push_back(algorithm("equals", 2)); typedef std::vector cs_type; cs_type css; css.push_back(cs("cartesian")); // css.push_back(cs("spherical")); // css.push_back(cs("spherical")); boost::timer timer; for (v_a_type::const_iterator it = algorithms.begin(); it != algorithms.end(); ++it) { /*([heading Behavior] [table [[Case] [Behavior] ] [[__2dim__][All combinations of: box, ring, polygon, multi_polygon]] [[__other__][__nyiversion__]] [[__sph__][__nyiversion__]] [[Three dimensional][__nyiversion__]] ]*/ std::ostringstream name; name << "../../../../generated/" << it->name << "_status.qbk"; std::ofstream out(name.str().c_str()); out << "[heading Supported geometries]" << std::endl; cs_type::const_iterator cit = css.begin(); { // Construct the table std::vector > table; for (int type = point; type < geometry_count; type++) { table.push_back(report(compile_policy, type, *it, true, true, 2, cit->name)); } // Detect red rows/columns std::vector lines_status(table.size(), false); std::vector columns_status(table[0].size(), false); for (unsigned int i = 0; i != table.size(); ++i) { for (unsigned int j = 0; j != table[i].size(); ++j) { lines_status[i] |= table[i][j]; columns_status[j] |= table[i][j]; } } // Display the table out << "[table" << std::endl << "["; if (it->arity > 1) { out << "[ ]"; for (int type = point; type < geometry_count; type++) { if (!columns_status[type]) continue; out << "[" << geometry_string(type) << "]"; } } else { out << "[Geometry][Status]"; } out << "]" << std::endl; for (unsigned int i = 0; i != table.size(); ++i) { if (!lines_status[i]) continue; out << "["; out << "[" << geometry_string(i) << "]"; for (unsigned int j = 0; j != table[i].size(); ++j) { if (!columns_status[j]) continue; out << "[[$img/" << (table[i][j] ? "ok" : "nyi") << ".png]]"; } out << "]" << std::endl; } out << "]" << std::endl; } } std::cout << "TIME: " << timer.elapsed() << std::endl; return 0; }