From e7df487fa82ed5c9e122896d75b448b31f9f0f72 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 1 Apr 2011 18:48:43 +0000 Subject: [PATCH 001/135] Added geometry to trunk [SVN r70827] --- .gitattributes | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..3e84d7c704 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain From 030e3c47e18b53dcefb943a5cc4efacdd75dadf0 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 2 Apr 2011 22:17:05 +0000 Subject: [PATCH 002/135] Added index.html to release branche [SVN r70903] --- index.html | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 0000000000..0942ef1ee9 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + + +Automatic redirection failed, please go to +doc/html/index.html + + From 496425a7e810557575c95c6687e4f5a44e0c7623 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 2 Apr 2011 22:22:02 +0000 Subject: [PATCH 003/135] Added geometry.hpp to release branche [SVN r70916] --- include/boost/geometry/geometry.hpp | 93 +++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 include/boost/geometry/geometry.hpp diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp new file mode 100644 index 0000000000..e0acee9657 --- /dev/null +++ b/include/boost/geometry/geometry.hpp @@ -0,0 +1,93 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_GEOMETRY_HPP +#define BOOST_GEOMETRY_GEOMETRY_HPP + +// Shortcut to include all header files + + +#include +#include +#include + +// Core algorithms +#include +#include +#include +#include +#include + + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Include provided geometries +#include +#include +#include +#include +#include +#include + + +// Include multi a.o. because it can give weird effects +// if you don't (e.g. area=0 of a filled multipolygon) +#include + + + +// check includes all concepts +#include + +#include +#include +#include +#include +#include + +#include + + +#endif // BOOST_GEOMETRY_GEOMETRY_HPP From 0f9eb1c664278fb6d308e537d1290cadee9af529 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 2 Apr 2011 23:25:41 +0000 Subject: [PATCH 004/135] Merged files with unit test errors [SVN r70918] --- .../detail/sections/sectionalize.cpp | 1 - test/algorithms/difference.cpp | 32 ++++--------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/test/algorithms/detail/sections/sectionalize.cpp b/test/algorithms/detail/sections/sectionalize.cpp index 0fe0c51385..7071e051e8 100644 --- a/test/algorithms/detail/sections/sectionalize.cpp +++ b/test/algorithms/detail/sections/sectionalize.cpp @@ -27,7 +27,6 @@ #include -#define TEST_WITH_SVG #if defined(TEST_WITH_SVG) # include # include diff --git a/test/algorithms/difference.cpp b/test/algorithms/difference.cpp index 948b79bc94..c1564d20b2 100644 --- a/test/algorithms/difference.cpp +++ b/test/algorithms/difference.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2010 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2011 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 @@ -23,8 +23,8 @@ #include #include -#include -#include +//#include +//#include #include #include @@ -272,7 +272,8 @@ void test_all() ***/ } - +/******* +// To be moved to another file template void test_difference_parcel_precision() { @@ -340,31 +341,10 @@ void test_difference_parcel_precision() } #endif } - - -#include - - -template -void test_copy() -{ - std::vector

first; - first.push_back(P(1,1)); - first.push_back(P(2,2)); - - std::vector

second; - boost::copy(first, std::back_inserter(second)); - boost::reverse(second); - - std::vector

third, fourth; - boost::copy(second, boost::copy(first, std::back_inserter(third))); - -} +*****/ int test_main(int, char* []) { - //test_copy >(); - //test_difference_parcel_precision(); //test_difference_parcel_precision(); From c5b04559ba75e4978fed766e25cbce5c9bfdf013 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 3 Apr 2011 07:55:46 +0000 Subject: [PATCH 005/135] Merged changes with ifdefs for release branch [SVN r70920] --- example/05_a_overlay_polygon_example.cpp | 12 +- ...5_b_overlay_linestring_polygon_example.cpp | 9 +- example/06_b_transformation_example.cpp | 11 +- example/07_a_graph_route_example.cpp | 19 ++- example/07_b_graph_route_example.cpp | 18 ++- example/Jamfile.v2 | 2 +- example/c03_custom_linestring_example.cpp | 88 ----------- example/with_external_libs/x02_gd_example.cpp | 146 ------------------ .../with_external_libs/x03_c_soci_example.cpp | 118 -------------- .../with_external_libs/x03_d_soci_example.cpp | 83 ---------- 10 files changed, 53 insertions(+), 453 deletions(-) delete mode 100644 example/c03_custom_linestring_example.cpp delete mode 100644 example/with_external_libs/x02_gd_example.cpp delete mode 100644 example/with_external_libs/x03_c_soci_example.cpp delete mode 100644 example/with_external_libs/x03_d_soci_example.cpp diff --git a/example/05_a_overlay_polygon_example.cpp b/example/05_a_overlay_polygon_example.cpp index 40d7b46331..9d74b8273d 100644 --- a/example/05_a_overlay_polygon_example.cpp +++ b/example/05_a_overlay_polygon_example.cpp @@ -21,7 +21,9 @@ #include #include -#include +#if defined(HAVE_SVG) +# include +#endif int main(void) @@ -32,8 +34,10 @@ int main(void) typedef bg::model::polygon polygon_2d; +#if defined(HAVE_SVG) std::ofstream stream("05_a_intersection_polygon_example.svg"); bg::svg_mapper svg(stream, 500, 500); +#endif // Define a polygons and fill the outer rings. polygon_2d a; @@ -45,7 +49,6 @@ int main(void) } bg::correct(a); std::cout << "A: " << bg::dsv(a) << std::endl; - svg.add(a); polygon_2d b; { @@ -56,10 +59,13 @@ int main(void) } bg::correct(b); std::cout << "B: " << bg::dsv(b) << std::endl; +#if defined(HAVE_SVG) + svg.add(a); svg.add(b); svg.map(a, "opacity:0.6;fill:rgb(0,255,0);"); svg.map(b, "opacity:0.6;fill:rgb(0,0,255);"); +#endif // Calculate interesection(s) @@ -70,7 +76,9 @@ int main(void) BOOST_FOREACH(polygon_2d const& polygon, intersection) { std::cout << bg::dsv(polygon) << std::endl; +#if defined(HAVE_SVG) svg.map(polygon, "opacity:0.5;fill:none;stroke:rgb(255,0,0);stroke-width:6"); +#endif } return 0; diff --git a/example/05_b_overlay_linestring_polygon_example.cpp b/example/05_b_overlay_linestring_polygon_example.cpp index 93cc988616..16eff548ed 100644 --- a/example/05_b_overlay_linestring_polygon_example.cpp +++ b/example/05_b_overlay_linestring_polygon_example.cpp @@ -21,7 +21,9 @@ #include #include -#include +#if defined(HAVE_SVG) +# include +#endif int main(void) @@ -43,6 +45,7 @@ int main(void) } bg::correct(p); +#if defined(HAVE_SVG) // Create SVG-mapper std::ofstream stream("05_b_overlay_linestring_polygon_example.svg"); bg::svg_mapper svg(stream, 500, 500); @@ -52,7 +55,7 @@ int main(void) // Map geometries svg.map(ls, "opacity:0.6;stroke:rgb(255,0,0);stroke-width:2;"); svg.map(p, "opacity:0.6;fill:rgb(0,0,255);"); - +#endif // Calculate intersection points (turn points) typedef bg::detail::overlay::turn_info turn_info; @@ -76,8 +79,10 @@ int main(void) } std::cout << action << " polygon at " << bg::dsv(turn.point) << std::endl; +#if defined(HAVE_SVG) svg.map(turn.point, "fill:rgb(255,128,0);stroke:rgb(0,0,100);stroke-width:1"); svg.text(turn.point, action, "fill:rgb(0,0,0);font-family:Arial;font-size:10px"); +#endif } return 0; diff --git a/example/06_b_transformation_example.cpp b/example/06_b_transformation_example.cpp index f31c7fd137..0b6a0542b9 100644 --- a/example/06_b_transformation_example.cpp +++ b/example/06_b_transformation_example.cpp @@ -19,9 +19,12 @@ #include #include #include -#include #include +#if defined(HAVE_SVG) +# include +#endif + #include #include #include @@ -84,8 +87,9 @@ struct svg_output void put(G const& g, std::string const& label) { std::string style_str(style.fill(opacity) + style.stroke(5, opacity)); - os << ::boost::geometry::svg(g, style_str) << std::endl; - +#if defined(HAVE_SVG) + os << boost::geometry::svg(g, style_str) << std::endl; +#endif if (!label.empty()) { typename point_type::type c; @@ -101,6 +105,7 @@ struct svg_output random_style style; }; + int main() { using namespace boost::geometry::strategy::transform; diff --git a/example/07_a_graph_route_example.cpp b/example/07_a_graph_route_example.cpp index a41575a25c..4ea9c5ae80 100644 --- a/example/07_a_graph_route_example.cpp +++ b/example/07_a_graph_route_example.cpp @@ -30,10 +30,12 @@ // Yes, this example currently uses some extensions: // For output: - #include + #if defined(HAVE_SVG) + # include + #endif // For distance-calculations over the Earth: - #include + //#include @@ -260,10 +262,11 @@ inline void build_route(Graph const& graph, int main() { - // Define a point in the Geographic coordinate system + // Define a point in the Geographic coordinate system (currently Spherical) + // (geographic calculations are in an extension; for sample it makes no difference) typedef boost::geometry::model::point < - double, 2, boost::geometry::cs::geographic + double, 2, boost::geometry::cs::spherical > point_type; typedef boost::geometry::model::linestring line_type; @@ -302,8 +305,12 @@ int main() double const km = 1000.0; std::cout << "distances, all in KM" << std::endl << std::fixed << std::setprecision(0); + + // To calculate distance, declare and construct a strategy with average earth radius + boost::geometry::strategy::distance::haversine haversine(6372795.0); // Main functionality: calculate shortest routes from/to all cities + // For the first one, the complete route is stored as a linestring bool first = true; @@ -329,7 +336,7 @@ int main() if (! boost::equals(city1.get<1>(), city2.get<1>())) { double distance = costs[city2.get<2>()] / km; - double acof = boost::geometry::distance(city1.get<0>(), city2.get<0>()) / km; + double acof = boost::geometry::distance(city1.get<0>(), city2.get<0>(), haversine) / km; std::cout << std::setiosflags (std::ios_base::left) << std::setw(15) @@ -351,6 +358,7 @@ int main() } } +#if defined(HAVE_SVG) // Create the SVG std::ofstream stream("routes.svg"); boost::geometry::svg_mapper mapper(stream, 600, 600); @@ -378,6 +386,7 @@ int main() mapper.text(city.get<0>(), city.get<1>(), "fill:rgb(0,0,0);font-family:Arial;font-size:10px", 5, 5); } +#endif return 0; } diff --git a/example/07_b_graph_route_example.cpp b/example/07_b_graph_route_example.cpp index 7ab224433a..64f4844c98 100644 --- a/example/07_b_graph_route_example.cpp +++ b/example/07_b_graph_route_example.cpp @@ -34,10 +34,12 @@ // Yes, this example currently uses some extensions: // For output: - #include + #if defined(HAVE_SVG) + # include + #endif // For distance-calculations over the Earth: - #include + //#include @@ -246,10 +248,11 @@ inline void build_route(Graph const& graph, int main() { - // Define a point in the Geographic coordinate system + // Define a point in the Geographic coordinate system (currently Spherical) + // (geographic calculations are in an extension; for sample it makes no difference) typedef boost::geometry::model::point < - double, 2, boost::geometry::cs::geographic + double, 2, boost::geometry::cs::spherical > point_type; typedef boost::geometry::model::linestring line_type; @@ -291,6 +294,9 @@ int main() std::cout << "distances, all in KM" << std::endl << std::fixed << std::setprecision(0); + // To calculate distance, declare and construct a strategy with average earth radius + boost::geometry::strategy::distance::haversine haversine(6372795.0); + // Main functionality: calculate shortest routes from/to all cities // For the first one, the complete route is stored as a linestring @@ -317,7 +323,7 @@ int main() if (! boost::equals(city1.get<1>(), city2.get<1>())) { double distance = costs[city2.get<2>()] / km; - double acof = boost::geometry::distance(city1.get<0>(), city2.get<0>()) / km; + double acof = boost::geometry::distance(city1.get<0>(), city2.get<0>(), haversine) / km; std::cout << std::setiosflags (std::ios_base::left) << std::setw(15) @@ -339,6 +345,7 @@ int main() } } +#if defined(HAVE_SVG) // Create the SVG std::ofstream stream("routes.svg"); boost::geometry::svg_mapper mapper(stream, 600, 600); @@ -366,6 +373,7 @@ int main() mapper.text(city.get<0>(), city.get<1>(), "fill:rgb(0,0,0);font-family:Arial;font-size:10px", 5, 5); } +#endif return 0; } diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 141ee1537b..8f12d888a1 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -26,7 +26,7 @@ exe 07_b_graph_route_example : 07_b_graph_route_example.cpp ; exe c01_custom_point_example : c01_custom_point_example.cpp ; exe c02_custom_box_example : c02_custom_box_example.cpp ; -exe c03_custom_linestring_example : c03_custom_linestring_example.cpp ; +# exe c03_custom_linestring_example : c03_custom_linestring_example.cpp ; exe c04_a_custom_triangle_example : c04_a_custom_triangle_example.cpp ; exe c04_b_custom_triangle_example : c04_b_custom_triangle_example.cpp ; exe c06_custom_polygon_example : c06_custom_polygon_example.cpp ; diff --git a/example/c03_custom_linestring_example.cpp b/example/c03_custom_linestring_example.cpp deleted file mode 100644 index 118bbacedb..0000000000 --- a/example/c03_custom_linestring_example.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 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) -// -// Custom Linestring Example - -#include -#include -#include - -#include -#include -#include - -// To register the 'geographic' distance function to calculate distance over the earth: -#include -#include - -// Define a GPS point with coordinates in latitude/longitude and some additional values -struct gps_point -{ - double latitude, longitude, height; - double speed; - // Date/time, heading, etc could be added - - // The default constructor is required if being used in a vector - gps_point() {} - - // Define a constructor to create the point in one line. Order of latitude/longitude - // does not matter as long as "E", "N", etc are included - gps_point(std::string const& c1, std::string const& c2, double h, double s) - : height(h) - , speed(s) - { - boost::geometry::parse(*this, c1, c2); - } -}; - -// Declare a custom linestring which will have the GPS points -struct gps_track : std::vector -{ - std::string owner; - int route_identifier; - // etc - - gps_track(int i, std::string const& o) - : owner(o) - , route_identifier(i) - {} -}; - - -// Register this point as being a recognizable point by Boost.Geometry -BOOST_GEOMETRY_REGISTER_POINT_2D(gps_point, double, cs::geographic, longitude, latitude) - - -// Register the track as well, as being a "linestring" -BOOST_GEOMETRY_REGISTER_LINESTRING(gps_track) - - -int main() -{ - // Declare a "GPS Track" and add some GPS points - gps_track track(23, "Mister G"); - track.push_back(gps_point("52 22 23 N", "4 53 32 E", 50, 180)); - track.push_back(gps_point("52 10 00 N", "4 59 59 E", 110, 170)); - track.push_back(gps_point("52 5 20 N", "5 6 56 E", 0, 90)); - - std::cout - << "track: " << track.route_identifier << std::endl - << "from: " << track.owner << std::endl - << "as wkt: " << boost::geometry::dsv(track) << std::endl - << "length: " << boost::geometry::length(track)/1000.0 << " km" << std::endl; - - // Above gives the idea, shows that custom linestrings can be useful. - // We could of course do anything with this track which the library can handle, e.g.: - // - simplify it - // - calculate distance of point-to-line - // - project it to UTM, then transform it to a GIF image (see p03_example) - - return 0; -} diff --git a/example/with_external_libs/x02_gd_example.cpp b/example/with_external_libs/x02_gd_example.cpp deleted file mode 100644 index e51e6d09f7..0000000000 --- a/example/with_external_libs/x02_gd_example.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Copyright (c) 2007-2011 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) -// -// GD example - -// GD is a well-known and often used graphic library to write GIF (and other formats) - -// To build and run this example: -// 1) download GD from http://www.libgd.org (currently gd-2.0.35 is assumed) -// 2) add 11 files -// gd.c, gd_gd.c, gd_gif_out.c, gd_io*.c, gd_security.c, gd_topal.c, gdhelpers.c, gdtables.c -// to the project or makefile or jamfile -// 3) for windows, add define NONDLL to indicate GD is not used as a DLL -// (Note that steps 2 and 3 are done in the MSVC gd_example project file and property sheets) - -#include -#include -#include - -#include -#include - - -#include - -#include -#include -#include -#include -#include - -#include - - -#include - -namespace bg = boost::geometry; - - -// ---------------------------------------------------------------------------- -// Read an ASCII file containing WKT's -// (note this function is shared by various examples) -// ---------------------------------------------------------------------------- -template -inline void read_wkt(std::string const& filename, std::vector& geometries) -{ - std::ifstream cpp_file(filename.c_str()); - if (cpp_file.is_open()) - { - while (! cpp_file.eof() ) - { - std::string line; - std::getline(cpp_file, line); - if (! line.empty()) - { - Geometry geometry; - bg::read_wkt(line, geometry); - geometries.push_back(geometry); - } - } - } -} - - -int main() -{ - // Adapt if necessary - std::string filename = "../data/world.wkt"; - - - // The world is measured in latlong (degrees), so latlong is appropriate. - // We ignore holes in this sample (below) - typedef bg::model::ll::point point_type; - typedef bg::model::polygon polygon_type; - typedef bg::model::multi_polygon country_type; - - std::vector countries; - - // Read (for example) world countries - read_wkt(filename, countries); - - - // Create a GD image. - // A world map, as world.shp, is usually mapped in latitude-longitude (-180..180 and -90..90) - // For this example we use a very simple "transformation" - // mapping to 0..720 and 0..360 - const double factor = 2.0; - gdImagePtr im = gdImageCreateTrueColor(int(360 * factor), int(180 * factor)); - - // Allocate three colors - int blue = gdImageColorResolve(im, 0, 52, 255); - int green = gdImageColorResolve(im, 0, 255, 0); - int black = gdImageColorResolve(im, 0, 0, 0); - - // Paint background in blue - gdImageFilledRectangle(im, 0, 0, im->sx, im->sy, blue); - - // Paint all countries in green - BOOST_FOREACH(country_type const& country, countries) - { - BOOST_FOREACH(polygon_type const& polygon, country) - { - // Ignore holes, so take only exterior ring - bg::model::ring const& ring = bg::exterior_ring(polygon); - - // If wished, suppress too small polygons. - // (Note that even in latlong, area is calculated in square meters) - double const a = bg::area(ring); - if (std::fabs(a) > 5000.0e6) - { - int const n = ring.size(); - gdPoint* points = new gdPoint[n]; - - for (int i = 0; i < n; i++) - { - // Translate lon/lat or x/y to GD x/y points - points[i].x = int(factor * (bg::get<0>(ring[i]) + 180.0)); - points[i].y = im->sy - int(factor * (bg::get<1>(ring[i]) + 90.0)); - } - - // Draw the polygon... - gdImageFilledPolygon(im, points, n, green); - // .. and the outline in black... - gdImagePolygon(im, points, n, black); - - delete[] points; - } - } - } - - // Use GD to create a GIF file - std::FILE* out = std::fopen("world.gif", "wb"); - if (out != NULL) - { - gdImageGif(im, out); - std::fclose(out); - } - - gdImageDestroy(im); - - return 0; -} diff --git a/example/with_external_libs/x03_c_soci_example.cpp b/example/with_external_libs/x03_c_soci_example.cpp deleted file mode 100644 index d2310ba759..0000000000 --- a/example/with_external_libs/x03_c_soci_example.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Copyright (c) 2009-2011 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) -// Boost.Geometry (aka GGL, Generic Geometry Library) -// SOCI example - -// c: using WKB to retrieve geometries - -// SOCI is a generic C++ template interface to access relational databases - -// To build and run this example, see comments in example a -// Alternatively compile composing and executing compiler command directoy in examples directory, -// for example using GCC compiler: -// g++ -I../../../boost -I/home/mloskot/usr/include/soci \ -// -I /home/mloskot/usr/include/soci/postgresql -I/usr/include/postgresql \ -// -L/home/mloskot/usr/lib -lsoci_core-gcc-3_0 -lsoci_postgresql-gcc-3_0 x03_c_soci_example.cpp - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -// user-defined type with GGL geometry -struct tree -{ - int id; - boost::geometry::model::point > location; -}; - -// conversion of row of result to user-defined type - performs WKB parsing -namespace soci -{ - template <> - struct type_conversion - { - typedef soci::values base_type; - - static void from_base(base_type const& v, soci::indicator ind, tree& value) - { - try - { - value.id = v.get("id"); - - // intermediate step: hex-encoded binary string to raw WKB - std::string const& hex = v.get("wkb"); - std::vector wkb; - if (!boost::geometry::hex2wkb(hex, std::back_inserter(wkb))) - throw std::runtime_error("hex2wkb translation failed"); - - // parse WKB and construct point geometry - if (!boost::geometry::read_wkb(wkb.begin(), wkb.end(), value.location)) - throw std::runtime_error("read_wkb failed"); - } - catch(const std::exception& e) - { - std::cout << e.what() << std::endl; - } - } - - static void to_base(tree const& value, base_type& v, soci::indicator& ind) - { - throw std::runtime_error("todo: wkb writer not yet implemented"); - } - }; -} - -int main() -{ - try - { - // establish database connection - soci::session sql(soci::postgresql, "dbname=ggl user=ggl password=ggl"); - - // construct schema of table for trees (point geometries) - sql << "DELETE FROM geometry_columns WHERE f_table_name = 'trees'"; - sql << "DROP TABLE IF EXISTS trees CASCADE"; - sql << "CREATE TABLE trees (id INTEGER)"; - sql << "SELECT AddGeometryColumn('trees', 'geom', -1, 'POINT', 2)"; - - // insert sample data using plain WKT input - sql << "INSERT INTO trees VALUES(1, ST_GeomFromText('POINT(1.23 2.34)', -1))"; - sql << "INSERT INTO trees VALUES(2, ST_GeomFromText('POINT(3.45 4.56)', -1))"; - sql << "INSERT INTO trees VALUES(3, ST_GeomFromText('POINT(5.67 6.78)', -1))"; - sql << "INSERT INTO trees VALUES(4, ST_GeomFromText('POINT(7.89 9.01)', -1))"; - - // query data in WKB form and read to geometry object - typedef std::vector trees_t; - soci::rowset rows = (sql.prepare << "SELECT id, encode(ST_AsBinary(geom), 'hex') AS wkb FROM trees"); - trees_t trees; - std::copy(rows.begin(), rows.end(), std::back_inserter(trees)); - - // print trees output - for (trees_t::const_iterator it = trees.begin(); it != trees.end(); ++it) - { - std::cout << "Tree #" << it->id << " located at\t" << boost::geometry::wkt(it->location) << std::endl; - } - } - catch (std::exception const &e) - { - std::cerr << "Error: " << e.what() << '\n'; - } - return 0; -} - diff --git a/example/with_external_libs/x03_d_soci_example.cpp b/example/with_external_libs/x03_d_soci_example.cpp deleted file mode 100644 index 448bc3658a..0000000000 --- a/example/with_external_libs/x03_d_soci_example.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Copyright (c) 2009-2011 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) -// Boost.Geometry (aka GGL, Generic Geometry Library) -// SOCI example - -// d: using WKB to retrieve geometries - -// SOCI is a generic C++ template interface to access relational databases - -// To build and run this example, see comments in example a -// Alternatively compile composing and executing compiler command directoy in examples directory, -// for example using GCC compiler: -// g++ -I../../../boost -I/home/mloskot/usr/include/soci \ -// -I /home/mloskot/usr/include/soci/postgresql -I/usr/include/postgresql \ -// -L/home/mloskot/usr/lib -lsoci_core-gcc-3_0 -lsoci_postgresql-gcc-3_0 x03_c_soci_example.cpp - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -int main() -{ - try - { - // establish database connection - soci::session sql(soci::postgresql, "dbname=ggl user=ggl password=ggl"); - - // construct schema of table for trees (point geometries) - sql << "DELETE FROM geometry_columns WHERE f_table_name = 'parcels'"; - sql << "DROP TABLE IF EXISTS parcels CASCADE"; - sql << "CREATE TABLE parcels (id INTEGER)"; - sql << "SELECT AddGeometryColumn('parcels', 'geom', -1, 'GEOMETRY', 2)"; - - // insert sample data using plain WKT input - sql << "INSERT INTO parcels VALUES(1, ST_GeomFromText('POLYGON ((10 10, 10 20, 20 20, 20 15, 10 10))', -1))"; - sql << "INSERT INTO parcels VALUES(2, ST_GeomFromText('POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', -1))"; - sql << "INSERT INTO parcels VALUES(3, ST_GeomFromText('POLYGON((1 1,2 1,2 2,1 2,1 1))', -1))"; - - // query data in WKB form and read to geometry object - soci::rowset rows = (sql.prepare << "SELECT encode(ST_AsBinary(geom), 'hex') AS wkb FROM parcels"); - - // calculate area of each parcel - for (soci::rowset::iterator it = rows.begin(); it != rows.end(); ++it) - { - // parse WKB and construct geometry object - std::string const& hex = *it; - std::vector wkb; - if (!boost::geometry::hex2wkb(*it, std::back_inserter(wkb))) - throw std::runtime_error("hex2wkb translation failed"); - - boost::geometry::model::d2::polygon parcel; - if (!boost::geometry::read_wkb(wkb.begin(), wkb.end(), parcel)) - throw std::runtime_error("read_wkb failed"); - - double a = boost::geometry::area(parcel); - std::cout << "Parcel geometry: " << boost::geometry::wkt(parcel) << std::endl - << "\thas area is " << a << " in coordinate units" << std::endl; - } - } - catch (std::exception const &e) - { - std::cerr << "Error: " << e.what() << '\n'; - } - return 0; -} - From 33d334adbc5633b5141347d662825dc57b4069bc Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 3 Apr 2011 07:57:20 +0000 Subject: [PATCH 006/135] Removed vcprojs for release branch [SVN r70921] --- example/01_point_example.vcproj | 171 ------------------ example/02_linestring_example.vcproj | 171 ------------------ example/03_polygon_example.vcproj | 171 ------------------ example/04_boost_example.vcproj | 171 ------------------ example/05_a_overlay_polygon_example.vcproj | 171 ------------------ ..._overlay_linestring_polygon_example.vcproj | 171 ------------------ example/06_a_transformation_example.vcproj | 171 ------------------ example/06_b_transformation_example.vcproj | 171 ------------------ example/07_a_graph_route_example.vcproj | 171 ------------------ example/07_b_graph_route_example.vcproj | 171 ------------------ example/basic_examples.sln | 73 -------- example/c01_custom_point_example.vcproj | 171 ------------------ example/c02_custom_box_example.vcproj | 171 ------------------ example/c03_custom_linestring_example.vcproj | 171 ------------------ example/c04_a_custom_triangle_example.vcproj | 171 ------------------ example/c04_b_custom_triangle_example.vcproj | 171 ------------------ .../c05_custom_point_pointer_example.vcproj | 171 ------------------ example/c06_custom_polygon_example.vcproj | 171 ------------------ .../c07_custom_ring_pointer_example.vcproj | 171 ------------------ example/c08_custom_non_std_example.vcproj | 171 ------------------ example/c09_custom_fusion_example.vcproj | 171 ------------------ example/c10_custom_cs_example.vcproj | 171 ------------------ .../c11_custom_cs_transform_example.vcproj | 171 ------------------ example/custom_examples.sln | 85 --------- 24 files changed, 3920 deletions(-) delete mode 100644 example/01_point_example.vcproj delete mode 100644 example/02_linestring_example.vcproj delete mode 100644 example/03_polygon_example.vcproj delete mode 100644 example/04_boost_example.vcproj delete mode 100644 example/05_a_overlay_polygon_example.vcproj delete mode 100644 example/05_b_overlay_linestring_polygon_example.vcproj delete mode 100644 example/06_a_transformation_example.vcproj delete mode 100644 example/06_b_transformation_example.vcproj delete mode 100644 example/07_a_graph_route_example.vcproj delete mode 100644 example/07_b_graph_route_example.vcproj delete mode 100644 example/basic_examples.sln delete mode 100644 example/c01_custom_point_example.vcproj delete mode 100644 example/c02_custom_box_example.vcproj delete mode 100644 example/c03_custom_linestring_example.vcproj delete mode 100644 example/c04_a_custom_triangle_example.vcproj delete mode 100644 example/c04_b_custom_triangle_example.vcproj delete mode 100644 example/c05_custom_point_pointer_example.vcproj delete mode 100644 example/c06_custom_polygon_example.vcproj delete mode 100644 example/c07_custom_ring_pointer_example.vcproj delete mode 100644 example/c08_custom_non_std_example.vcproj delete mode 100644 example/c09_custom_fusion_example.vcproj delete mode 100644 example/c10_custom_cs_example.vcproj delete mode 100644 example/c11_custom_cs_transform_example.vcproj delete mode 100644 example/custom_examples.sln diff --git a/example/01_point_example.vcproj b/example/01_point_example.vcproj deleted file mode 100644 index 0af7ed87f4..0000000000 --- a/example/01_point_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/02_linestring_example.vcproj b/example/02_linestring_example.vcproj deleted file mode 100644 index c7272d1003..0000000000 --- a/example/02_linestring_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/03_polygon_example.vcproj b/example/03_polygon_example.vcproj deleted file mode 100644 index 08800dcac6..0000000000 --- a/example/03_polygon_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/04_boost_example.vcproj b/example/04_boost_example.vcproj deleted file mode 100644 index 1954819759..0000000000 --- a/example/04_boost_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/05_a_overlay_polygon_example.vcproj b/example/05_a_overlay_polygon_example.vcproj deleted file mode 100644 index 2616230693..0000000000 --- a/example/05_a_overlay_polygon_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/05_b_overlay_linestring_polygon_example.vcproj b/example/05_b_overlay_linestring_polygon_example.vcproj deleted file mode 100644 index 23b7195b9c..0000000000 --- a/example/05_b_overlay_linestring_polygon_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/06_a_transformation_example.vcproj b/example/06_a_transformation_example.vcproj deleted file mode 100644 index 480836c5c3..0000000000 --- a/example/06_a_transformation_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/06_b_transformation_example.vcproj b/example/06_b_transformation_example.vcproj deleted file mode 100644 index deaa35a334..0000000000 --- a/example/06_b_transformation_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/07_a_graph_route_example.vcproj b/example/07_a_graph_route_example.vcproj deleted file mode 100644 index b18384c946..0000000000 --- a/example/07_a_graph_route_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/07_b_graph_route_example.vcproj b/example/07_b_graph_route_example.vcproj deleted file mode 100644 index 7f215e5772..0000000000 --- a/example/07_b_graph_route_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/basic_examples.sln b/example/basic_examples.sln deleted file mode 100644 index eaeccf2652..0000000000 --- a/example/basic_examples.sln +++ /dev/null @@ -1,73 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01_point_example", "01_point_example.vcproj", "{E7BFC111-F0E5-420F-869C-1FC3212270B5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02_linestring_example", "02_linestring_example.vcproj", "{D5CE1A26-1EB7-44A4-84F9-526CFA8C2B74}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03_polygon_example", "03_polygon_example.vcproj", "{1E299DA7-CFD1-4586-B0B0-1ABF2A32ED5B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06_a_transformation_example", "06_a_transformation_example.vcproj", "{34346EC5-1EE8-49D5-AF24-D915B4D7D144}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06_b_transformation_example", "06_b_transformation_example.vcproj", "{34346EC5-1EE8-49D5-AC21-D915B4D7D144}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05_a_overlay_polygon_example", "05_a_overlay_polygon_example.vcproj", "{119F9CCD-4B5F-4623-B4C1-F65E6323B24F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05_b_overlay_linestring_polygon_example", "05_b_overlay_linestring_polygon_example.vcproj", "{3A803CEA-0902-4355-886A-799C596D0B46}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07_a_graph_route_example", "07_a_graph_route_example.vcproj", "{47D30DD8-CBB1-4527-811F-F0193E22B317}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07_b_graph_route_example", "07_b_graph_route_example.vcproj", "{940B049A-51AF-48DE-B366-11B42B98E3B3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04_boost_example", "04_boost_example.vcproj", "{6254AA18-1E45-4ECD-B574-D20F97F5BBA3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E7BFC111-F0E5-420F-869C-1FC3212270B5}.Debug|Win32.ActiveCfg = Debug|Win32 - {E7BFC111-F0E5-420F-869C-1FC3212270B5}.Debug|Win32.Build.0 = Debug|Win32 - {E7BFC111-F0E5-420F-869C-1FC3212270B5}.Release|Win32.ActiveCfg = Release|Win32 - {E7BFC111-F0E5-420F-869C-1FC3212270B5}.Release|Win32.Build.0 = Release|Win32 - {D5CE1A26-1EB7-44A4-84F9-526CFA8C2B74}.Debug|Win32.ActiveCfg = Debug|Win32 - {D5CE1A26-1EB7-44A4-84F9-526CFA8C2B74}.Debug|Win32.Build.0 = Debug|Win32 - {D5CE1A26-1EB7-44A4-84F9-526CFA8C2B74}.Release|Win32.ActiveCfg = Release|Win32 - {D5CE1A26-1EB7-44A4-84F9-526CFA8C2B74}.Release|Win32.Build.0 = Release|Win32 - {1E299DA7-CFD1-4586-B0B0-1ABF2A32ED5B}.Debug|Win32.ActiveCfg = Debug|Win32 - {1E299DA7-CFD1-4586-B0B0-1ABF2A32ED5B}.Debug|Win32.Build.0 = Debug|Win32 - {1E299DA7-CFD1-4586-B0B0-1ABF2A32ED5B}.Release|Win32.ActiveCfg = Release|Win32 - {1E299DA7-CFD1-4586-B0B0-1ABF2A32ED5B}.Release|Win32.Build.0 = Release|Win32 - {34346EC5-1EE8-49D5-AF24-D915B4D7D144}.Debug|Win32.ActiveCfg = Debug|Win32 - {34346EC5-1EE8-49D5-AF24-D915B4D7D144}.Debug|Win32.Build.0 = Debug|Win32 - {34346EC5-1EE8-49D5-AF24-D915B4D7D144}.Release|Win32.ActiveCfg = Release|Win32 - {34346EC5-1EE8-49D5-AF24-D915B4D7D144}.Release|Win32.Build.0 = Release|Win32 - {34346EC5-1EE8-49D5-AC21-D915B4D7D144}.Debug|Win32.ActiveCfg = Debug|Win32 - {34346EC5-1EE8-49D5-AC21-D915B4D7D144}.Debug|Win32.Build.0 = Debug|Win32 - {34346EC5-1EE8-49D5-AC21-D915B4D7D144}.Release|Win32.ActiveCfg = Release|Win32 - {34346EC5-1EE8-49D5-AC21-D915B4D7D144}.Release|Win32.Build.0 = Release|Win32 - {119F9CCD-4B5F-4623-B4C1-F65E6323B24F}.Debug|Win32.ActiveCfg = Debug|Win32 - {119F9CCD-4B5F-4623-B4C1-F65E6323B24F}.Debug|Win32.Build.0 = Debug|Win32 - {119F9CCD-4B5F-4623-B4C1-F65E6323B24F}.Release|Win32.ActiveCfg = Release|Win32 - {119F9CCD-4B5F-4623-B4C1-F65E6323B24F}.Release|Win32.Build.0 = Release|Win32 - {3A803CEA-0902-4355-886A-799C596D0B46}.Debug|Win32.ActiveCfg = Debug|Win32 - {3A803CEA-0902-4355-886A-799C596D0B46}.Debug|Win32.Build.0 = Debug|Win32 - {3A803CEA-0902-4355-886A-799C596D0B46}.Release|Win32.ActiveCfg = Release|Win32 - {3A803CEA-0902-4355-886A-799C596D0B46}.Release|Win32.Build.0 = Release|Win32 - {47D30DD8-CBB1-4527-811F-F0193E22B317}.Debug|Win32.ActiveCfg = Debug|Win32 - {47D30DD8-CBB1-4527-811F-F0193E22B317}.Debug|Win32.Build.0 = Debug|Win32 - {47D30DD8-CBB1-4527-811F-F0193E22B317}.Release|Win32.ActiveCfg = Release|Win32 - {47D30DD8-CBB1-4527-811F-F0193E22B317}.Release|Win32.Build.0 = Release|Win32 - {940B049A-51AF-48DE-B366-11B42B98E3B3}.Debug|Win32.ActiveCfg = Debug|Win32 - {940B049A-51AF-48DE-B366-11B42B98E3B3}.Debug|Win32.Build.0 = Debug|Win32 - {940B049A-51AF-48DE-B366-11B42B98E3B3}.Release|Win32.ActiveCfg = Release|Win32 - {940B049A-51AF-48DE-B366-11B42B98E3B3}.Release|Win32.Build.0 = Release|Win32 - {6254AA18-1E45-4ECD-B574-D20F97F5BBA3}.Debug|Win32.ActiveCfg = Debug|Win32 - {6254AA18-1E45-4ECD-B574-D20F97F5BBA3}.Debug|Win32.Build.0 = Debug|Win32 - {6254AA18-1E45-4ECD-B574-D20F97F5BBA3}.Release|Win32.ActiveCfg = Release|Win32 - {6254AA18-1E45-4ECD-B574-D20F97F5BBA3}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/example/c01_custom_point_example.vcproj b/example/c01_custom_point_example.vcproj deleted file mode 100644 index 0ea9afc6e1..0000000000 --- a/example/c01_custom_point_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c02_custom_box_example.vcproj b/example/c02_custom_box_example.vcproj deleted file mode 100644 index 083c956379..0000000000 --- a/example/c02_custom_box_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c03_custom_linestring_example.vcproj b/example/c03_custom_linestring_example.vcproj deleted file mode 100644 index 784ed286cb..0000000000 --- a/example/c03_custom_linestring_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c04_a_custom_triangle_example.vcproj b/example/c04_a_custom_triangle_example.vcproj deleted file mode 100644 index 936115b2cc..0000000000 --- a/example/c04_a_custom_triangle_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c04_b_custom_triangle_example.vcproj b/example/c04_b_custom_triangle_example.vcproj deleted file mode 100644 index 5e4d3e6715..0000000000 --- a/example/c04_b_custom_triangle_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c05_custom_point_pointer_example.vcproj b/example/c05_custom_point_pointer_example.vcproj deleted file mode 100644 index e36b917b3f..0000000000 --- a/example/c05_custom_point_pointer_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c06_custom_polygon_example.vcproj b/example/c06_custom_polygon_example.vcproj deleted file mode 100644 index 79d849de8c..0000000000 --- a/example/c06_custom_polygon_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c07_custom_ring_pointer_example.vcproj b/example/c07_custom_ring_pointer_example.vcproj deleted file mode 100644 index 6e48ac88e0..0000000000 --- a/example/c07_custom_ring_pointer_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c08_custom_non_std_example.vcproj b/example/c08_custom_non_std_example.vcproj deleted file mode 100644 index 1260044683..0000000000 --- a/example/c08_custom_non_std_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c09_custom_fusion_example.vcproj b/example/c09_custom_fusion_example.vcproj deleted file mode 100644 index 68f6972948..0000000000 --- a/example/c09_custom_fusion_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c10_custom_cs_example.vcproj b/example/c10_custom_cs_example.vcproj deleted file mode 100644 index 8d23b1f4ed..0000000000 --- a/example/c10_custom_cs_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/c11_custom_cs_transform_example.vcproj b/example/c11_custom_cs_transform_example.vcproj deleted file mode 100644 index c4764b4835..0000000000 --- a/example/c11_custom_cs_transform_example.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/custom_examples.sln b/example/custom_examples.sln deleted file mode 100644 index d8d168a97c..0000000000 --- a/example/custom_examples.sln +++ /dev/null @@ -1,85 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c01_custom_point_example", "c01_custom_point_example.vcproj", "{B368C99D-8464-493C-A05B-904F53909046}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c04_a_custom_triangle_example", "c04_a_custom_triangle_example.vcproj", "{5E12A414-E180-4E5F-A575-CC98B449B278}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c04_b_custom_triangle_example", "c04_b_custom_triangle_example.vcproj", "{D005D88D-50BD-4D80-8C3B-72F81B1B9719}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c02_custom_box_example", "c02_custom_box_example.vcproj", "{1A68AD9E-7C1A-4340-A8C9-D5362609B0C1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c03_custom_linestring_example", "c03_custom_linestring_example.vcproj", "{D24F5517-E2B5-4933-B6E7-47A2F8A08911}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c05_custom_point_pointer_example", "c05_custom_point_pointer_example.vcproj", "{DAC38456-5241-4DDB-87FF-74A2FF7DE368}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c06_custom_polygon_example", "c06_custom_polygon_example.vcproj", "{A8AA1E80-2FC7-42C0-9920-B3E28D2C0665}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c07_custom_ring_pointer_example", "c07_custom_ring_pointer_example.vcproj", "{158FBCF6-2FFE-447B-8EB1-07E22B0BE724}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c08_custom_non_std_example", "c08_custom_non_std_example.vcproj", "{C215F131-F021-4155-A96E-BB2D91918A17}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c10_custom_cs_example", "c10_custom_cs_example.vcproj", "{E16737C9-E1F7-450E-9251-B35840FE69B5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c11_custom_cs_transform_example", "c11_custom_cs_transform_example.vcproj", "{E73E52EC-9BDC-4777-ABB2-DB14FAF27AA5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c09_custom_fusion_example", "c09_custom_fusion_example.vcproj", "{DA36AD55-E448-43DE-A974-EA765AE3967A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B368C99D-8464-493C-A05B-904F53909046}.Debug|Win32.ActiveCfg = Debug|Win32 - {B368C99D-8464-493C-A05B-904F53909046}.Debug|Win32.Build.0 = Debug|Win32 - {B368C99D-8464-493C-A05B-904F53909046}.Release|Win32.ActiveCfg = Release|Win32 - {B368C99D-8464-493C-A05B-904F53909046}.Release|Win32.Build.0 = Release|Win32 - {5E12A414-E180-4E5F-A575-CC98B449B278}.Debug|Win32.ActiveCfg = Debug|Win32 - {5E12A414-E180-4E5F-A575-CC98B449B278}.Debug|Win32.Build.0 = Debug|Win32 - {5E12A414-E180-4E5F-A575-CC98B449B278}.Release|Win32.ActiveCfg = Release|Win32 - {5E12A414-E180-4E5F-A575-CC98B449B278}.Release|Win32.Build.0 = Release|Win32 - {D005D88D-50BD-4D80-8C3B-72F81B1B9719}.Debug|Win32.ActiveCfg = Debug|Win32 - {D005D88D-50BD-4D80-8C3B-72F81B1B9719}.Debug|Win32.Build.0 = Debug|Win32 - {D005D88D-50BD-4D80-8C3B-72F81B1B9719}.Release|Win32.ActiveCfg = Release|Win32 - {D005D88D-50BD-4D80-8C3B-72F81B1B9719}.Release|Win32.Build.0 = Release|Win32 - {1A68AD9E-7C1A-4340-A8C9-D5362609B0C1}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A68AD9E-7C1A-4340-A8C9-D5362609B0C1}.Debug|Win32.Build.0 = Debug|Win32 - {1A68AD9E-7C1A-4340-A8C9-D5362609B0C1}.Release|Win32.ActiveCfg = Release|Win32 - {1A68AD9E-7C1A-4340-A8C9-D5362609B0C1}.Release|Win32.Build.0 = Release|Win32 - {D24F5517-E2B5-4933-B6E7-47A2F8A08911}.Debug|Win32.ActiveCfg = Debug|Win32 - {D24F5517-E2B5-4933-B6E7-47A2F8A08911}.Debug|Win32.Build.0 = Debug|Win32 - {D24F5517-E2B5-4933-B6E7-47A2F8A08911}.Release|Win32.ActiveCfg = Release|Win32 - {D24F5517-E2B5-4933-B6E7-47A2F8A08911}.Release|Win32.Build.0 = Release|Win32 - {DAC38456-5241-4DDB-87FF-74A2FF7DE368}.Debug|Win32.ActiveCfg = Debug|Win32 - {DAC38456-5241-4DDB-87FF-74A2FF7DE368}.Debug|Win32.Build.0 = Debug|Win32 - {DAC38456-5241-4DDB-87FF-74A2FF7DE368}.Release|Win32.ActiveCfg = Release|Win32 - {DAC38456-5241-4DDB-87FF-74A2FF7DE368}.Release|Win32.Build.0 = Release|Win32 - {A8AA1E80-2FC7-42C0-9920-B3E28D2C0665}.Debug|Win32.ActiveCfg = Debug|Win32 - {A8AA1E80-2FC7-42C0-9920-B3E28D2C0665}.Debug|Win32.Build.0 = Debug|Win32 - {A8AA1E80-2FC7-42C0-9920-B3E28D2C0665}.Release|Win32.ActiveCfg = Release|Win32 - {A8AA1E80-2FC7-42C0-9920-B3E28D2C0665}.Release|Win32.Build.0 = Release|Win32 - {158FBCF6-2FFE-447B-8EB1-07E22B0BE724}.Debug|Win32.ActiveCfg = Debug|Win32 - {158FBCF6-2FFE-447B-8EB1-07E22B0BE724}.Debug|Win32.Build.0 = Debug|Win32 - {158FBCF6-2FFE-447B-8EB1-07E22B0BE724}.Release|Win32.ActiveCfg = Release|Win32 - {158FBCF6-2FFE-447B-8EB1-07E22B0BE724}.Release|Win32.Build.0 = Release|Win32 - {C215F131-F021-4155-A96E-BB2D91918A17}.Debug|Win32.ActiveCfg = Debug|Win32 - {C215F131-F021-4155-A96E-BB2D91918A17}.Debug|Win32.Build.0 = Debug|Win32 - {C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.ActiveCfg = Release|Win32 - {C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.Build.0 = Release|Win32 - {E16737C9-E1F7-450E-9251-B35840FE69B5}.Debug|Win32.ActiveCfg = Debug|Win32 - {E16737C9-E1F7-450E-9251-B35840FE69B5}.Debug|Win32.Build.0 = Debug|Win32 - {E16737C9-E1F7-450E-9251-B35840FE69B5}.Release|Win32.ActiveCfg = Release|Win32 - {E16737C9-E1F7-450E-9251-B35840FE69B5}.Release|Win32.Build.0 = Release|Win32 - {E73E52EC-9BDC-4777-ABB2-DB14FAF27AA5}.Debug|Win32.ActiveCfg = Debug|Win32 - {E73E52EC-9BDC-4777-ABB2-DB14FAF27AA5}.Debug|Win32.Build.0 = Debug|Win32 - {E73E52EC-9BDC-4777-ABB2-DB14FAF27AA5}.Release|Win32.ActiveCfg = Release|Win32 - {E73E52EC-9BDC-4777-ABB2-DB14FAF27AA5}.Release|Win32.Build.0 = Release|Win32 - {DA36AD55-E448-43DE-A974-EA765AE3967A}.Debug|Win32.ActiveCfg = Debug|Win32 - {DA36AD55-E448-43DE-A974-EA765AE3967A}.Debug|Win32.Build.0 = Debug|Win32 - {DA36AD55-E448-43DE-A974-EA765AE3967A}.Release|Win32.ActiveCfg = Release|Win32 - {DA36AD55-E448-43DE-A974-EA765AE3967A}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal From 05f7a8bbe6a151a9a81dc40e0cf874c6a29b0626 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 3 Apr 2011 07:57:51 +0000 Subject: [PATCH 007/135] Merged changes with ifdefs for release branch [SVN r70922] --- doc/src/examples/algorithms/assign_2d_point.cpp | 6 +++--- doc/src/examples/algorithms/create_svg_overlay.hpp | 7 ++++++- doc/src/examples/algorithms/create_svg_two.hpp | 7 ++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/doc/src/examples/algorithms/assign_2d_point.cpp b/doc/src/examples/algorithms/assign_2d_point.cpp index 140f0f0c55..e01da8d7af 100644 --- a/doc/src/examples/algorithms/assign_2d_point.cpp +++ b/doc/src/examples/algorithms/assign_2d_point.cpp @@ -16,7 +16,7 @@ #include #include -#if defined(_MSC_VER) +#if defined(HAVE_TTMATH) # include #endif @@ -29,7 +29,7 @@ int main() boost::geometry::model::d2::point_xy p1; assign(p1, 1.2345, 2.3456); -#if defined(_MSC_VER) +#if defined(HAVE_TTMATH) boost::geometry::model::d2::point_xy > p2; assign(p2, "1.2345", "2.3456"); /*< It is possible to assign coordinates with other types than the coordinate type. For ttmath, you can e.g. conveniently use strings. The advantage is that it then has higher precision, because @@ -40,7 +40,7 @@ int main() std::cout << std::setprecision(20) << boost::geometry::dsv(p1) << std::endl -#if defined(_MSC_VER) +#if defined(HAVE_TTMATH) << boost::geometry::dsv(p2) << std::endl #endif ; diff --git a/doc/src/examples/algorithms/create_svg_overlay.hpp b/doc/src/examples/algorithms/create_svg_overlay.hpp index f44dd56e91..a8ed47bcf9 100644 --- a/doc/src/examples/algorithms/create_svg_overlay.hpp +++ b/doc/src/examples/algorithms/create_svg_overlay.hpp @@ -13,11 +13,15 @@ #include #include -#include + +#if defined(HAVE_SVG) +# include +#endif template void create_svg(std::string const& filename, Geometry const& a, Geometry const& b, Range const& range) { +#if defined(HAVE_SVG) std::cout << std::endl << "[$img/algorithms/" << boost::replace_all_copy(filename, ".svg", ".png") << "]" << std::endl << std::endl; typedef typename boost::geometry::point_type::type point_type; @@ -38,6 +42,7 @@ void create_svg(std::string const& filename, Geometry const& a, Geometry const& mapper.text(boost::geometry::return_centroid(g), out.str(), "fill:rgb(0,0,0);font-family:Arial;font-size:10px"); } +#endif } // NOTE: convert manually from svg to png using Inkscape ctrl-shift-E diff --git a/doc/src/examples/algorithms/create_svg_two.hpp b/doc/src/examples/algorithms/create_svg_two.hpp index db7843a905..98be922c63 100644 --- a/doc/src/examples/algorithms/create_svg_two.hpp +++ b/doc/src/examples/algorithms/create_svg_two.hpp @@ -13,11 +13,15 @@ #include #include -#include + +#if defined(HAVE_SVG) +# include +#endif template void create_svg(std::string const& filename, Geometry1 const& a, Geometry2 const& b) { +#if defined(HAVE_SVG) std::cout << std::endl << "[$img/algorithms/" << boost::replace_all_copy(filename, ".svg", ".png") << "]" << std::endl << std::endl; typedef typename boost::geometry::point_type::type point_type; @@ -36,6 +40,7 @@ void create_svg(std::string const& filename, Geometry1 const& a, Geometry2 const { mapper.map(b, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round"); } +#endif } // NOTE: convert manually from svg to png using Inkscape ctrl-shift-E From b38c8a16ddb9a9310d18be5205e727433d270fda Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 8 Apr 2011 15:41:37 +0000 Subject: [PATCH 008/135] Merged 71027,71093,71117 (centroid nD plus convert to detail) [SVN r71119] --- include/boost/geometry/algorithms/append.hpp | 2 +- .../boost/geometry/algorithms/centroid.hpp | 6 +- .../algorithms/{ => detail}/convert.hpp | 26 ++++-- .../detail/convert_point_to_point.hpp | 4 +- .../detail/overlay/clip_linestring.hpp | 6 +- .../detail/overlay/convert_ring.hpp | 8 +- .../detail/overlay/copy_segment_point.hpp | 4 +- .../overlay/get_intersection_points.hpp | 4 +- .../detail/overlay/get_turn_info.hpp | 18 ++-- .../detail/overlay/intersection_insert.hpp | 6 +- .../boost/geometry/algorithms/envelope.hpp | 1 - .../boost/geometry/algorithms/simplify.hpp | 4 +- include/boost/geometry/core/radian_access.hpp | 2 +- .../geometry/domains/gis/io/wkt/write_wkt.hpp | 4 +- include/boost/geometry/geometries/box.hpp | 6 +- include/boost/geometry/geometry.hpp | 1 - .../agnostic/simplify_douglas_peucker.hpp | 1 - .../cartesian/centroid_weighted_length.hpp | 51 ++++++----- .../cartesian/distance_projected_point.hpp | 8 +- .../strategies/strategy_transform.hpp | 16 ++-- include/boost/geometry/util/copy.hpp | 87 ------------------- include/boost/geometry/util/write_dsv.hpp | 2 - 22 files changed, 96 insertions(+), 171 deletions(-) rename include/boost/geometry/algorithms/{ => detail}/convert.hpp (91%) delete mode 100644 include/boost/geometry/util/copy.hpp diff --git a/include/boost/geometry/algorithms/append.hpp b/include/boost/geometry/algorithms/append.hpp index 0557d21f53..7e5f6b7b5a 100644 --- a/include/boost/geometry/algorithms/append.hpp +++ b/include/boost/geometry/algorithms/append.hpp @@ -51,7 +51,7 @@ struct append_point int = 0, int = 0) { typename geometry::point_type::type copy; - geometry::detail::convert::convert_point_to_point(point, copy); + geometry::detail::conversion::convert_point_to_point(point, copy); traits::push_back::apply(geometry, copy); } }; diff --git a/include/boost/geometry/algorithms/centroid.hpp b/include/boost/geometry/algorithms/centroid.hpp index a400e2e0ba..9b51ba07dd 100644 --- a/include/boost/geometry/algorithms/centroid.hpp +++ b/include/boost/geometry/algorithms/centroid.hpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -83,7 +83,7 @@ struct centroid_point static inline void apply(Point const& point, PointCentroid& centroid, Strategy const&) { - geometry::convert(point, centroid); + geometry::detail::convert(point, centroid); } }; @@ -163,7 +163,7 @@ inline bool range_ok(Range const& range, Point& centroid) else // if (n == 1) { // Take over the first point in a "coordinate neutral way" - geometry::convert(*boost::begin(range), centroid); + geometry::detail::convert(*boost::begin(range), centroid); return false; } return true; diff --git a/include/boost/geometry/algorithms/convert.hpp b/include/boost/geometry/algorithms/detail/convert.hpp similarity index 91% rename from include/boost/geometry/algorithms/convert.hpp rename to include/boost/geometry/algorithms/detail/convert.hpp index 607898a3fe..9301006a74 100644 --- a/include/boost/geometry/algorithms/convert.hpp +++ b/include/boost/geometry/algorithms/detail/convert.hpp @@ -11,8 +11,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP -#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP #include @@ -33,7 +33,7 @@ namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace convert +namespace detail { namespace conversion { template @@ -75,7 +75,7 @@ struct point_to_box }; -}} // namespace detail::convert +}} // namespace detail::conversion #endif // DOXYGEN_NO_DETAIL @@ -117,7 +117,7 @@ template typename Geometry1, typename Geometry2 > struct convert - : detail::convert::point_to_point + : detail::conversion::point_to_point {}; @@ -186,11 +186,11 @@ struct convert { static inline void apply(Point const& point, Box& box) { - detail::convert::point_to_box + detail::conversion::point_to_box < Point, Box, min_corner, 0, DimensionCount >::apply(point, box); - detail::convert::point_to_box + detail::conversion::point_to_box < Point, Box, max_corner, 0, DimensionCount >::apply(point, box); @@ -232,6 +232,11 @@ struct convert } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + /*! \brief Converts one geometry to another geometry \details The convert algorithm converts one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only @@ -241,6 +246,8 @@ if it is possible and applicable. \tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry (source) \param geometry2 \param_geometry (target) +\note It is moved to namespace detail because it overlaps functionality + of assign. So assign will be changed such that it also can convert. */ template inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) @@ -257,8 +264,11 @@ inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) >::apply(geometry1, geometry2); } +} +#endif // DOXYGEN_NO_DETAIL + }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP diff --git a/include/boost/geometry/algorithms/detail/convert_point_to_point.hpp b/include/boost/geometry/algorithms/detail/convert_point_to_point.hpp index 48981ce09a..0c42fd936f 100644 --- a/include/boost/geometry/algorithms/detail/convert_point_to_point.hpp +++ b/include/boost/geometry/algorithms/detail/convert_point_to_point.hpp @@ -28,7 +28,7 @@ namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace convert +namespace detail { namespace conversion { @@ -60,7 +60,7 @@ inline void convert_point_to_point(Source const& source, Destination& destinatio -}} // namespace detail::convert +}} // namespace detail::conversion #endif // DOXYGEN_NO_DETAIL }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp index 6e8a7f6c37..b5bbab84c7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -181,8 +181,8 @@ OutputIterator clip_range_with_box(Box const& b, Range const& range, ++previous, ++vertex) { point_type p1, p2; - geometry::convert(*previous, p1); - geometry::convert(*vertex, p2); + geometry::detail::convert(*previous, p1); + geometry::detail::convert(*vertex, p2); // Clip the segment. Five situations: // 1. Segment is invisible, finish line if any (shouldn't occur) diff --git a/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp index d81826f51e..4339080614 100644 --- a/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp @@ -19,7 +19,7 @@ #include #include -#include +#include namespace boost { namespace geometry @@ -50,7 +50,7 @@ struct convert_ring { if (! append) { - geometry::convert(source, destination); + geometry::detail::convert(source, destination); if (reverse) { boost::reverse(destination); @@ -69,7 +69,7 @@ struct convert_ring { if (! append) { - geometry::convert(source, exterior_ring(destination)); + geometry::detail::convert(source, exterior_ring(destination)); if (reverse) { boost::reverse(exterior_ring(destination)); @@ -79,7 +79,7 @@ struct convert_ring { interior_rings(destination).resize( interior_rings(destination).size() + 1); - geometry::convert(source, interior_rings(destination).back()); + geometry::detail::convert(source, interior_rings(destination).back()); if (reverse) { boost::reverse(interior_rings(destination).back()); diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index ead7862801..927cefb515 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -71,7 +71,7 @@ struct copy_segment_point_range rview_type view(cview); - geometry::convert(*(boost::begin(view) + index), point); + geometry::detail::convert(*(boost::begin(view) + index), point); return true; } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index 4a0fdc952c..da7695e91e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -12,7 +12,7 @@ #include -#include +#include #include @@ -64,7 +64,7 @@ struct get_turn_without_info { TurnInfo tp; - geometry::convert(result.template get<0>().intersections[i], tp.point); + geometry::detail::convert(result.template get<0>().intersections[i], tp.point); *out++ = tp; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 2e7195310a..74abdca0de 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include @@ -94,7 +94,7 @@ struct touch_interior : public base_turn_handler DirInfo const& dir_info) { ti.method = method_touch_interior; - geometry::convert(intersection_info.intersections[0], ti.point); + geometry::detail::convert(intersection_info.intersections[0], ti.point); // Both segments of q touch segment p somewhere in its interior // 1) We know: if q comes from LEFT or RIGHT @@ -213,7 +213,7 @@ struct touch : public base_turn_handler DirInfo const& dir_info) { ti.method = method_touch; - geometry::convert(intersection_info.intersections[0], ti.point); + geometry::detail::convert(intersection_info.intersections[0], ti.point); int const side_qi_p1 = dir_info.sides.template get<1, 0>(); int const side_qk_p1 = SideStrategy::apply(pi, pj, qk); @@ -376,7 +376,7 @@ struct touch : public base_turn_handler << " qk " << get<0>(qk) << " , " << get<1>(qk) << std::endl; #endif - + } }; @@ -404,7 +404,7 @@ struct equal : public base_turn_handler { ti.method = method_equal; // Copy the SECOND intersection point - geometry::convert(intersection_info.intersections[1], ti.point); + geometry::detail::convert(intersection_info.intersections[1], ti.point); int const side_pk_q2 = SideStrategy::apply(qj, qk, pk); int const side_pk_p = SideStrategy::apply(pi, pj, pk); @@ -486,7 +486,7 @@ struct collinear : public base_turn_handler DirInfo const& dir_info) { ti.method = method_collinear; - geometry::convert(intersection_info.intersections[1], ti.point); + geometry::detail::convert(intersection_info.intersections[1], ti.point); int const arrival = dir_info.arrival[0]; // Should not be 0, this is checked before @@ -585,7 +585,7 @@ private : // If P arrives within Q, set info on P (which is done above, index=0), // this turn-info belongs to the second intersection point, index=1 // (see e.g. figure CLO1) - geometry::convert(intersection_info.intersections[1 - Index], tp.point); + geometry::detail::convert(intersection_info.intersections[1 - Index], tp.point); return true; } @@ -661,7 +661,7 @@ struct crosses : public base_turn_handler DirInfo const& dir_info) { ti.method = method_crosses; - geometry::convert(intersection_info.intersections[0], ti.point); + geometry::detail::convert(intersection_info.intersections[0], ti.point); // In all casees: // If Q crosses P from left to right @@ -877,7 +877,7 @@ struct get_turn_info #ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS std::cout << "get_turns, nyi: " << method << std::endl; #endif - break; + break; } return out; diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 75d240bc2f..222e84fbcb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -65,7 +65,7 @@ struct intersection_segment_segment_point for (std::size_t i = 0; i < is.count; i++) { PointOut p; - geometry::convert(is.intersections[i], p); + geometry::detail::convert(is.intersections[i], p); *out++ = p; } return out; @@ -95,7 +95,7 @@ struct intersection_linestring_linestring_point it = boost::begin(turns); it != boost::end(turns); ++it) { PointOut p; - geometry::convert(it->point, p); + geometry::detail::convert(it->point, p); *out++ = p; } return out; diff --git a/include/boost/geometry/algorithms/envelope.hpp b/include/boost/geometry/algorithms/envelope.hpp index cae9fa0e15..370812f556 100644 --- a/include/boost/geometry/algorithms/envelope.hpp +++ b/include/boost/geometry/algorithms/envelope.hpp @@ -19,7 +19,6 @@ #include -#include #include #include #include diff --git a/include/boost/geometry/algorithms/simplify.hpp b/include/boost/geometry/algorithms/simplify.hpp index e6a75cc773..21ba86432d 100644 --- a/include/boost/geometry/algorithms/simplify.hpp +++ b/include/boost/geometry/algorithms/simplify.hpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include @@ -181,7 +181,7 @@ struct simplify static inline void apply(Point const& point, Point& out, Distance const& max_distance, Strategy const& strategy) { - geometry::convert(point, out); + geometry::detail::convert(point, out); } }; diff --git a/include/boost/geometry/core/radian_access.hpp b/include/boost/geometry/core/radian_access.hpp index 37556e2266..9aa833704f 100644 --- a/include/boost/geometry/core/radian_access.hpp +++ b/include/boost/geometry/core/radian_access.hpp @@ -78,7 +78,7 @@ struct radian_access } }; -// Specialize, any "degree" coordinate system will convert to radian +// Specialize, any "degree" coordinate system will be converted to radian // but only for dimension 0,1 (so: dimension 2 and heigher are untouched) template diff --git a/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp b/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp index 424b2c429f..fcf168aa7b 100644 --- a/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp @@ -24,7 +24,7 @@ #include -#include +#include #include #include #include @@ -199,7 +199,7 @@ struct wkt_box // Convert to ring, then stream typedef model::ring ring_type; ring_type ring; - geometry::convert(box, ring); + geometry::detail::convert(box, ring); os << "POLYGON("; wkt_sequence::apply(os, ring); os << ")"; diff --git a/include/boost/geometry/geometries/box.hpp b/include/boost/geometry/geometries/box.hpp index a42e72c91b..6537f12980 100644 --- a/include/boost/geometry/geometries/box.hpp +++ b/include/boost/geometry/geometries/box.hpp @@ -18,7 +18,7 @@ #include -#include +#include #include @@ -57,8 +57,8 @@ class box */ inline box(Point const& min_corner, Point const& max_corner) { - geometry::convert(min_corner, m_min_corner); - geometry::convert(max_corner, m_max_corner); + geometry::detail::convert(min_corner, m_min_corner); + geometry::detail::convert(max_corner, m_max_corner); } inline Point const& min_corner() const { return m_min_corner; } diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp index e0acee9657..e8405f7a7b 100644 --- a/include/boost/geometry/geometry.hpp +++ b/include/boost/geometry/geometry.hpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp index c8e8f0a0b7..b4e95b8a40 100644 --- a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp +++ b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp @@ -20,7 +20,6 @@ #include #include -#include #include diff --git a/include/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp b/include/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp index 1538dcabf9..0d89c735ff 100644 --- a/include/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp +++ b/include/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp @@ -13,10 +13,9 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP -#include - -#include #include +#include +#include #include #include #include @@ -37,16 +36,19 @@ namespace detail template struct weighted_length_sums { + typedef typename geometry::model::point + < + Type, DimensionCount, + cs::cartesian + > work_point; + Type length; - boost::array average_sum; + work_point average_sum; inline weighted_length_sums() : length(Type()) { - for (std::size_t i = 0; i < DimensionCount; i++) - { - average_sum[i] = Type(); - } + geometry::assign_zero(average_sum); } }; } @@ -66,7 +68,11 @@ private : >::type distance_type; public : - typedef detail::weighted_length_sums state_type; + typedef detail::weighted_length_sums + < + distance_type, + geometry::dimension::type::value + > state_type; static inline void apply(PointOfSegment const& p1, PointOfSegment const& p2, state_type& state) @@ -74,13 +80,12 @@ public : distance_type const d = geometry::distance(p1, p2); state.length += d; - distance_type two(2); - - // Might be made generic for N dimensions using specializations - distance_type const mx = (get<0>(p1) + get<0>(p2)) / two; - distance_type const my = (get<1>(p1) + get<1>(p2)) / two; - state.average_sum[0] += d * mx; - state.average_sum[1] += d * my; + typename state_type::work_point weighted_median; + geometry::assign_zero(weighted_median); + geometry::add_point(weighted_median, p1); + geometry::add_point(weighted_median, p2); + geometry::multiply_value(weighted_median, d/2); + geometry::add_point(state.average_sum, weighted_median); } static inline bool result(state_type const& state, Point& centroid) @@ -88,8 +93,9 @@ public : distance_type const zero = distance_type(); if (! geometry::math::equals(state.length, zero)) { - set<0>(centroid, state.average_sum[0] / state.length); - set<1>(centroid, state.average_sum[1] / state.length); + assign_zero(centroid); + add_point(centroid, state.average_sum); + divide_value(centroid, state.length); return true; } @@ -103,13 +109,15 @@ public : namespace services { -// Register this strategy for linestrings and polygons, in two or three dimensions -template + +// Register this strategy for linear geometries, in all dimensions + +template struct default_strategy < cartesian_tag, linear_tag, - 2, + N, Point, Geometry > @@ -122,7 +130,6 @@ struct default_strategy }; - } // namespace services diff --git a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp index 52eb4bd694..d0293c4b6c 100644 --- a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -132,8 +132,8 @@ public : // For consistency we define w also in FP fp_vector_type v, w; - geometry::convert(p2, v); - geometry::convert(p, w); + geometry::detail::convert(p2, v); + geometry::detail::convert(p, w); subtract_point(v, p1); subtract_point(w, p1); @@ -163,7 +163,7 @@ public : >::apply(strategy); fp_point_type projected; - geometry::convert(p1, projected); + geometry::detail::convert(p1, projected); multiply_value(v, b); add_point(projected, v); diff --git a/include/boost/geometry/strategies/strategy_transform.hpp b/include/boost/geometry/strategies/strategy_transform.hpp index cb9a144040..3961ee276a 100644 --- a/include/boost/geometry/strategies/strategy_transform.hpp +++ b/include/boost/geometry/strategies/strategy_transform.hpp @@ -20,7 +20,7 @@ #include -#include +#include #include #include #include @@ -104,7 +104,7 @@ struct copy_per_coordinate // Defensive check, dimensions are equal, selected by specialization assert_dimension_equal(); - geometry::convert(p1, p2); + geometry::detail::convert(p1, p2); return true; } }; @@ -312,14 +312,14 @@ struct default_strategy type; }; -/// Specialization to convert from degree to radian for any coordinate system / point type combination +/// Specialization to transform from degree to radian for any coordinate system / point type combination template class CoordSys, typename P1, typename P2> struct default_strategy, CoordSys, 2, 2, P1, P2> { typedef degree_radian_vv type; }; -/// Specialization to convert from radian to degree for any coordinate system / point type combination +/// Specialization to transform from radian to degree for any coordinate system / point type combination template class CoordSys, typename P1, typename P2> struct default_strategy, CoordSys, 2, 2, P1, P2> { @@ -341,28 +341,28 @@ struct default_strategy, CoordSys type; }; -/// Specialization to convert from unit sphere(phi,theta) to XYZ +/// Specialization to transform from unit sphere(phi,theta) to XYZ template struct default_strategy { typedef from_spherical_2_to_cartesian_3 type; }; -/// Specialization to convert from sphere(phi,theta,r) to XYZ +/// Specialization to transform from sphere(phi,theta,r) to XYZ template struct default_strategy { typedef from_spherical_3_to_cartesian_3 type; }; -/// Specialization to convert from XYZ to unit sphere(phi,theta) +/// Specialization to transform from XYZ to unit sphere(phi,theta) template struct default_strategy { typedef from_cartesian_3_to_spherical_2 type; }; -/// Specialization to convert from XYZ to sphere(phi,theta,r) +/// Specialization to transform from XYZ to sphere(phi,theta,r) template struct default_strategy { diff --git a/include/boost/geometry/util/copy.hpp b/include/boost/geometry/util/copy.hpp deleted file mode 100644 index 10497df9e6..0000000000 --- a/include/boost/geometry/util/copy.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_UTIL_COPY_HPP -#define BOOST_GEOMETRY_UTIL_COPY_HPP - -#if defined(BOOST_MSVC_FULL_VER) -#pragma message ("copy_coordinates is deprecated. Use 'convert'") -#else -#warning "copy_coordinates is deprecated. Use 'convert'" -#endif - - - -#include - -#include -#include - -#include - -#include - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace copy -{ - -template -struct copy_coordinates -{ - static inline void copy(Src const& source, Dst& dest) - { - typedef typename coordinate_type::type coordinate_type; - - set(dest, boost::numeric_cast(get(source))); - copy_coordinates::copy(source, dest); - } -}; - -template -struct copy_coordinates -{ - static inline void copy(Src const& , Dst& ) - { - } -}; - -}} // namespace detail::copy -#endif // DOXYGEN_NO_DETAIL - - -// Deprecated! -// This is the same as "convert", but this is specific to point, convert is more generic -template -inline void copy_coordinates(Src const& source, Dst& dest) -{ - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); - BOOST_CONCEPT_ASSERT( (concept::Point) ); - - - //assert_dimension_equal(); - detail::copy::copy_coordinates - < - Src, - Dst, - 0, - dimension::type::value - >::copy(source, dest); -} - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_UTIL_COPY_HPP diff --git a/include/boost/geometry/util/write_dsv.hpp b/include/boost/geometry/util/write_dsv.hpp index 27df5d69cf..3fef63e778 100644 --- a/include/boost/geometry/util/write_dsv.hpp +++ b/include/boost/geometry/util/write_dsv.hpp @@ -23,8 +23,6 @@ #include #include -#include - #include #include #include From 596cefb5b1531a7a47e338dbfd15f50b140e32bc Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 8 Apr 2011 15:43:58 +0000 Subject: [PATCH 009/135] Merged 71027,71093,71117 (centroid nD plus convert to detail) [SVN r71120] --- test/algorithms/Jamfile.v2 | 1 - test/algorithms/algorithms_tests.sln | 6 ------ test/algorithms/centroid.cpp | 2 ++ test/algorithms/detail/Jamfile.v2 | 1 + test/algorithms/{ => detail}/convert.cpp | 10 +++++----- test/algorithms/{ => detail}/convert.vcproj | 8 ++++---- test/algorithms/detail/detail.sln | 6 ++++++ 7 files changed, 18 insertions(+), 16 deletions(-) rename test/algorithms/{ => detail}/convert.cpp (93%) rename test/algorithms/{ => detail}/convert.vcproj (92%) diff --git a/test/algorithms/Jamfile.v2 b/test/algorithms/Jamfile.v2 index 4c3a0f705a..daf06b6d42 100644 --- a/test/algorithms/Jamfile.v2 +++ b/test/algorithms/Jamfile.v2 @@ -16,7 +16,6 @@ test-suite boost-geometry-algorithms [ run buffer.cpp ] [ run centroid.cpp ] [ run comparable_distance.cpp ] - [ run convert.cpp ] [ run convex_hull.cpp ] [ run correct.cpp ] [ run difference.cpp ] diff --git a/test/algorithms/algorithms_tests.sln b/test/algorithms/algorithms_tests.sln index c4105b533c..f929e0ba5a 100644 --- a/test/algorithms/algorithms_tests.sln +++ b/test/algorithms/algorithms_tests.sln @@ -8,8 +8,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assign", "assign.vcproj", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "expand", "expand.vcproj", "{5330DAB1-DF27-44FC-971B-3C5094F82FA3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convert", "convert.vcproj", "{FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convex_hull", "convex_hull.vcproj", "{0AFF7A85-63A7-4178-92A5-CC692B09F5B9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "distance", "distance.vcproj", "{347D08A4-22E9-45B1-A55B-AE84AA2EAA53}" @@ -78,10 +76,6 @@ Global {5330DAB1-DF27-44FC-971B-3C5094F82FA3}.Debug|Win32.Build.0 = Debug|Win32 {5330DAB1-DF27-44FC-971B-3C5094F82FA3}.Release|Win32.ActiveCfg = Release|Win32 {5330DAB1-DF27-44FC-971B-3C5094F82FA3}.Release|Win32.Build.0 = Release|Win32 - {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Debug|Win32.ActiveCfg = Debug|Win32 - {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Debug|Win32.Build.0 = Debug|Win32 - {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Release|Win32.ActiveCfg = Release|Win32 - {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Release|Win32.Build.0 = Release|Win32 {0AFF7A85-63A7-4178-92A5-CC692B09F5B9}.Debug|Win32.ActiveCfg = Debug|Win32 {0AFF7A85-63A7-4178-92A5-CC692B09F5B9}.Debug|Win32.Build.0 = Debug|Win32 {0AFF7A85-63A7-4178-92A5-CC692B09F5B9}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/test/algorithms/centroid.cpp b/test/algorithms/centroid.cpp index 22ce6bc11f..e2b5d5205d 100644 --- a/test/algorithms/centroid.cpp +++ b/test/algorithms/centroid.cpp @@ -78,6 +78,7 @@ void test_2d() template void test_3d() { + test_centroid >("LINESTRING(1 2 3,4 5 -6,7 -8 9,-10 11 12,13 -14 -15, 16 17 18)", 5.6748865168734692, 0.31974938587214002, 1.9915270387763671); test_centroid >("POLYGON((1 2 3,5 6 7))", 3, 4, 5); test_centroid

("POINT(1 2 3)", 1, 2, 3); } @@ -93,6 +94,7 @@ int test_main(int, char* []) #if defined(HAVE_TTMATH) test_2d >(); + test_3d >(); #endif return 0; diff --git a/test/algorithms/detail/Jamfile.v2 b/test/algorithms/detail/Jamfile.v2 index e34d4986cd..70eadd9978 100644 --- a/test/algorithms/detail/Jamfile.v2 +++ b/test/algorithms/detail/Jamfile.v2 @@ -10,6 +10,7 @@ test-suite boost-geometry-algorithms-detail : + [ run convert.cpp ] [ run partition.cpp ] ; diff --git a/test/algorithms/convert.cpp b/test/algorithms/detail/convert.cpp similarity index 93% rename from test/algorithms/convert.cpp rename to test/algorithms/detail/convert.cpp index 5a3669e0ac..2c6d227d38 100644 --- a/test/algorithms/convert.cpp +++ b/test/algorithms/detail/convert.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include @@ -35,7 +35,7 @@ void test_all() bg::assign(p, 1, 2); box_type b; - bg::convert(p, b); + bg::detail::convert(p, b); BOOST_CHECK_CLOSE((bg::get<0, 0>(b)), 1.0, 0.001); BOOST_CHECK_CLOSE((bg::get<0, 1>(b)), 2.0, 0.001); @@ -59,7 +59,7 @@ void test_std() bg::set(b, 4); ring_type ring; - bg::convert(b, ring); + bg::detail::convert(b, ring); //std::cout << bg::wkt(b) << std::endl; //std::cout << bg::wkt(ring) << std::endl; @@ -85,10 +85,10 @@ void test_std() polygon_type polygon; - bg::convert(ring, polygon); + bg::detail::convert(ring, polygon); BOOST_CHECK_EQUAL(bg::num_points(polygon), 5u); - bg::convert(polygon, ring); + bg::detail::convert(polygon, ring); BOOST_CHECK_EQUAL(bg::num_points(ring), 5u); } diff --git a/test/algorithms/convert.vcproj b/test/algorithms/detail/convert.vcproj similarity index 92% rename from test/algorithms/convert.vcproj rename to test/algorithms/detail/convert.vcproj index c75bf0ee5e..b3a11404f5 100644 --- a/test/algorithms/convert.vcproj +++ b/test/algorithms/detail/convert.vcproj @@ -20,7 +20,7 @@ OutputDirectory="$(SolutionDir)$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)\convert" ConfigurationType="1" - InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops" + InheritedPropertySheets="..\..\boost.vsprops;..\..\ttmath.vsprops" CharacterSet="1" > @@ -114,7 +114,7 @@ /> Date: Sat, 16 Apr 2011 22:58:30 +0000 Subject: [PATCH 010/135] Removed doc/other for release branch [SVN r71335] --- doc/other/ggl.png | Bin 10540 -> 0 bytes doc/other/ggl.svg | 150 ------------------ doc/other/overlay/de9im_polygons.ppt | Bin 703488 -> 0 bytes doc/other/overlay/de9im_segments.ppt | Bin 407552 -> 0 bytes doc/other/overlay/intersection.ppt | Bin 207360 -> 0 bytes doc/other/overlay/overlay.ppt | Bin 323584 -> 0 bytes .../overlay_spatial_set_operations.ppt | Bin 113152 -> 0 bytes doc/other/status.xls | Bin 18944 -> 0 bytes doc/other/testcases/assemble.ppt | Bin 51712 -> 0 bytes doc/other/testcases/buffer.ppt | Bin 56320 -> 0 bytes doc/other/testcases/dissolve.ppt | Bin 38912 -> 0 bytes doc/other/testcases/get_turn_info.ppt | Bin 402944 -> 0 bytes doc/other/testcases/get_turn_info.xls | Bin 133120 -> 0 bytes doc/other/testcases/multi_overlay_cases.ppt | Bin 36352 -> 0 bytes doc/other/testcases/overlay_cases.ppt | Bin 1225216 -> 0 bytes doc/other/testcases/relate.ppt | Bin 53760 -> 0 bytes ...strategy_segment_intersection_obsolete.ppt | Bin 356352 -> 0 bytes 17 files changed, 150 deletions(-) delete mode 100644 doc/other/ggl.png delete mode 100644 doc/other/ggl.svg delete mode 100644 doc/other/overlay/de9im_polygons.ppt delete mode 100644 doc/other/overlay/de9im_segments.ppt delete mode 100644 doc/other/overlay/intersection.ppt delete mode 100644 doc/other/overlay/overlay.ppt delete mode 100644 doc/other/overlay/overlay_spatial_set_operations.ppt delete mode 100644 doc/other/status.xls delete mode 100644 doc/other/testcases/assemble.ppt delete mode 100644 doc/other/testcases/buffer.ppt delete mode 100644 doc/other/testcases/dissolve.ppt delete mode 100644 doc/other/testcases/get_turn_info.ppt delete mode 100644 doc/other/testcases/get_turn_info.xls delete mode 100644 doc/other/testcases/multi_overlay_cases.ppt delete mode 100644 doc/other/testcases/overlay_cases.ppt delete mode 100644 doc/other/testcases/relate.ppt delete mode 100644 doc/other/testcases/strategy_segment_intersection_obsolete.ppt diff --git a/doc/other/ggl.png b/doc/other/ggl.png deleted file mode 100644 index 0ef978a2f3396e9448e46b5cbf1a1ab0bfef6fc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10540 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 - - - - - - - - - - image/svg+xml - - Generic Geometry Library Logo - - - Steven M. Ottens - - - - - logo - library - - - Big version of Generic Geometry Library logo graphics - - - Steven M. Ottens, Barend Gerhles - - - - - Mateusz Loskot - - - en-US - - - - - - - - - - - - - - - - - - - GenericGeometryLibrary - - diff --git a/doc/other/overlay/de9im_polygons.ppt b/doc/other/overlay/de9im_polygons.ppt deleted file mode 100644 index a5c7260df97fffe77d9620f9bb786e8623911431..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 703488 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 z zD2ess6Q|E{D=aKD_s?zrN_6OenRUySiDjGEi8(K25w7^ef|U8@H=Z?v_9kG;;sh}a z|3->-f)ZSll5Jl9p$+;z#gWV2Fw)+Bl!0I^t)`3+$A~_=yPMx>y4!E=`BwL`TZ?$e zv_BcAeWLqr^x}!0M(^FM37G-YKH+J}pZLVj-jRs9^oU(vHjR>avUDrtVXR0=^NED0 zbIn!nJSCH{-)_W}P(Y3^v>nI$cuW31g!`zHW;iFKH*pxW$-V%A-%uF-ZbRUAGw@md zE(0yIv3MAZAka&YUjB}0G3qk~4~$is%lH$6uYzraPjVeS2#7`<|80b3hz)_gw5NAP zQ)A2_U-&5RPJCM$gctV@72{d_w66EM#DU#?Xk<#JEMHECM6w0Tsykb-)b^yDS(7fv z_nU=xLwu$oLIJ!)&EaoFBH|LESIIX@!FS;? zf3wWMKOmr|H3s1)fcsgzNW zsH`E-RSuZqAJBGypLWm?A5GVIz+Lc@-Cd}h!8iDxq+3Tpx7qQ!=+fRvS9(g)9SMob z(xp>_hqO6IDxlOk@>50F+H-kb1>2Erb+KhGCtK+P$ySxid*{xao-rx!0(WzHyn=H= zXI-3W$OR~+n9Iq%V!2$qySJNtfO4Gx3^V;5*2J0rt4x$b0=Hr z+sJk~b8k>JXt@tv!J?1I6jQ_`F;nD-0^t{}(N;(l18~ldzik1(=#GDWv>^Oqdx@Vf z>3{?5ioZt!r7i(AeVa>QtHFb|j|a7+C{+E8psVT-HoL>9r_kKmQMxoohe6FrHyO@h z44Cd#wZP8Vr{LUbf-cU?6S6r(?%_CBrYeL74m(s8gLckI3eKrnx;Qgukh64_;W$^O zV5m6f`U=jk&(Ou0Hcigb7lz|p8QTuexdl>`)tzJo=WhABILoHK^oZoV6aoi(!qvWR zIMe5pE(3-nPRY&l&&bWWU~2C4wt;;s|JjrBGc)|T(-Si?yJS!E=T7klCPcOk?CB9( z;2u`riEKf#5>>jy9tY&)C)B=`Il~@`loHUG-cTf|B~}?|A?&!A4GCpHT53QFT>)v* z>oR@I0|lplNHwI-s#0l{DLDN@t08?h$e6y>FbfWjJgnNRfK6daVKs?^rD#xXQqTrz z6H*GhEgr7)0(44+3nYa&?{*ju~m$d=zW%_oH)UaBtfHp`gu-jsPcqCbp z7?9$h+_(M!`qn32xU46n)YG>vMBZU*ad$&74I!GLF8F_$PZEi3Jfc2^1P(vl5W8M7#KL}c#flCd(c@{4I0Dx%YY~NhcfZ)%CQ9TE zio#Kv@%Qr{k^63x_;jIH_*0|APkm#>wx)67nD64mI}g_p=RfBWU-a>cq;?*0O4DfZ zLGx&_rGyw`}F?2JtGHuG~5 z(0fu|=JX7Izs#(>%$$7dd#dx4snZG8cN*e&NcQBs-2B`r1^%H^resgf^bgCOm6~EQ)jsk81Is@E7r8^wwXW+TwzxV^Z_&vET2MqU zkR>aBxAFDGqT3sb#j4}Jg0uOm?$+lPn;wI

kPSw&&e69xumveqU~Tajp2*cg=JP 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 diff --git a/doc/other/overlay/de9im_segments.ppt b/doc/other/overlay/de9im_segments.ppt deleted file mode 100644 index 5dee5a954b056ddf98bbcc8d956c49ee37630e0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407552 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 z 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 diff --git a/doc/other/overlay/overlay.ppt b/doc/other/overlay/overlay.ppt deleted file mode 100644 index 5aaed832cc53135bf7e4275e5b3aa973fdea9de7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323584 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 Z+*IMlp3hP)N&U}KNb#3xGFtB<@H0g+InMw9 diff --git a/doc/other/overlay/overlay_spatial_set_operations.ppt b/doc/other/overlay/overlay_spatial_set_operations.ppt deleted file mode 100644 index 54808507a4ae1d44fcc44816858466222afc9354..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113152 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%0Ap|~=a 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∨Mxns7T6)G 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 diff --git a/doc/other/testcases/multi_overlay_cases.ppt b/doc/other/testcases/multi_overlay_cases.ppt deleted file mode 100644 index 0a1b74f28f1781ddf2ba288d551d27d42fdd3e88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36352 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 diff --git a/doc/other/testcases/overlay_cases.ppt b/doc/other/testcases/overlay_cases.ppt deleted file mode 100644 index 4f630e56343319f570085b406fbb087b616354f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1225216 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

op>s{CcNZEtRKo> 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 G|K9<`W!%O9 diff --git a/doc/other/testcases/relate.ppt b/doc/other/testcases/relate.ppt deleted file mode 100644 index e37643fc182841998f14a0f27781c6917c7803f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53760 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 a|CCi%HgXLq!zx;dwe*|!KVZSv%>6eLaAgtz diff --git a/doc/other/testcases/strategy_segment_intersection_obsolete.ppt b/doc/other/testcases/strategy_segment_intersection_obsolete.ppt deleted file mode 100644 index 76681a5e1308333a7210fa347d9825ca6c63ea0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356352 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

;k?t8eUz!R4vQukbrT-#)d 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

MwxRhmWgg8Of(hnc;$?L)tX77Q_O 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 z Date: Sat, 16 Apr 2011 22:59:01 +0000 Subject: [PATCH 011/135] Removed doc/quickbook for release branch [SVN r71336] --- doc/quickbook/arithmetic.qbk | 233 --------- doc/quickbook/boolean.qbk | 249 --------- doc/quickbook/geometries.qbk | 36 -- doc/quickbook/geometry_concepts.qbk | 232 --------- doc/quickbook/geometry_types.qbk | 209 -------- doc/quickbook/misc.qbk | 172 ------- doc/quickbook/quickref.xml | 738 --------------------------- doc/quickbook/readme.txt | 13 - doc/quickbook/references.qbk | 86 ---- doc/quickbook/strategy_rationale.qbk | 148 ------ 10 files changed, 2116 deletions(-) delete mode 100644 doc/quickbook/arithmetic.qbk delete mode 100644 doc/quickbook/boolean.qbk delete mode 100644 doc/quickbook/geometries.qbk delete mode 100644 doc/quickbook/geometry_concepts.qbk delete mode 100644 doc/quickbook/geometry_types.qbk delete mode 100644 doc/quickbook/misc.qbk delete mode 100644 doc/quickbook/quickref.xml delete mode 100644 doc/quickbook/readme.txt delete mode 100644 doc/quickbook/references.qbk delete mode 100644 doc/quickbook/strategy_rationale.qbk diff --git a/doc/quickbook/arithmetic.qbk b/doc/quickbook/arithmetic.qbk deleted file mode 100644 index d7d4f5aed2..0000000000 --- a/doc/quickbook/arithmetic.qbk +++ /dev/null @@ -1,233 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section Arithmetic] - -__boost_geometry__ provides a set of arithmetic operations defined for point geometries. - -[section add_point] - -[heading Description] - -Adds one point to another. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void add_point(Point1 &p1, Point2 const &p2); - }} - -[table Parameters - [[Parameter] [Requirement] [Description]] - [[`p1`, `p2`] [Models of __concept_point__] - [First point used as operation input and output. Second point usedas input]] -] - -[table Expression Semantics - [[Expression] [Return Type] [Description]] - [[__add_point__(p1, p2);] [`void`] - [Coordinates of `p2` are added to corresponding coordinates of `p1`. The `p2` is not modified]] -] - -[heading Header] - - #include - -[heading Example] - - #include - #include - #include - #include - - int main() - { - using namespace boost::geometry; - point_xy p1(1, 3); - point_xy p2(2, 4); - - add_point(p1, p2); - - std::cout << "p1 = " << dsv(p1) << std::endl; - } - -[endsect] [/ end of section add_point] - -[section add_value] - -[heading Description] - -Adds a value to each coordinate of a point. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void add_value(Point &p, typename detail::param::type value) - }} - -[heading Header] - - #include - -[heading Example] - - int foo(); - -[endsect] [/ end of section add_value] - -[section divide_point] - -[heading Description] - -Divides a point by another. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void divide_point(Point1 &p1, Point2 const &p2); - }} - -[heading Header] - - #include - -[heading Example] - - int foo(); - -[endsect] [/ end of section divide_point] - -[section divide_value] - -[heading Description] - -Divides each coordinate of a point by a value. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void divide_value(Point &p, typename detail::param< Point>::type value); - }} - -[heading Header] - - #include - -[heading Example] - - int foo(); - -[endsect] [/ end of section divide_value] - -[section multiply_point] - -[heading Description] - -Multiplies a point by another. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void multiply_point(Point1 &p1, Point2 const &p2); - }} - -[heading Header] - - #include - -[heading Example] - - int foo(); - -[endsect] [/ end of section multiply_point] - -[section multiply_value] - -[heading Description] - -Multiplies each coordinate of a point by a value. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void multiply_value(Point &p, typename detail::param::type value); - }} - -[heading Header] - - #include - -[heading Example] - - int foo(); - -[endsect] [/ end of section multiply_value] - -[section subtract_point] - -[heading Description] - -Subtracts a point to another. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void subtract_point(Point1 &p1, Point2 const &p2) - }} - -[heading Header] - - #include - -[heading Example] - - int foo(); - -[endsect] [/ end of section subtract_point] - -[section subtract_value] - -[heading Description] - -Subtracts a value to each coordinate of a point. - -[heading Synopsis] - - namespace boost { namespace geometry { - - template - void subtract_value(Point &p, typename detail::param::type value) - }} - -[heading Header] - - #include - -[heading Example] - - int foo(); - -[endsect] [/ end of section subtract_value] - -[endsect] [/ end of section Arithmetic] \ No newline at end of file diff --git a/doc/quickbook/boolean.qbk b/doc/quickbook/boolean.qbk deleted file mode 100644 index a984fa077e..0000000000 --- a/doc/quickbook/boolean.qbk +++ /dev/null @@ -1,249 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section:boolean Spatial Boolean Operations] - -The __boost_geometry__ implementation of the algorithms like intersection, union, difference and -symmetric difference is based on principles of __wiki_set_theory__, where a set is formed by -spatial object, a geometry or collection of geometries. - -Intersection and union are so-called set-theoretic operations. Those operations work on sets, -and geometries (especially polygons and multipolygons) can be seen as sets, sets of points. - -The first section will repeat a small, relevant part of the algebra of sets, also describing the -notation used in this page. The next section will extend this algebra of sets for spatial sets -(polygons). - -[section:algebra Algebra of Sets in Spatial Context] - -The following section explaines meaning of __wiki_set_algebra__ in context of spatial operations. - -* A __set_intersect__ B : intersection of two sets A and B is the set that contains all - elements of A that also belong to B, also known as AND. -* A __set_union__ B : union of two sets A and B is the set that contains all elements - that belong to A or B, also known as OR. -* A__set_complement__ : complement of set A is the set of elements which do not belong to A -* A __set_difference__ B : difference of two sets A and B is the set of elements which - belong to A but not to B -* A __set_symdifference__ B : symmetric difference of two sets A and B is the set of - elements which belong to either A or to B, but not to A and B, also known as XOR. - -There are several laws on sets and we will not discuss them all here. The most important for this -page are: - -* B __set_difference__ A = A__set_complement__ __set_intersect__ B and, vice versa, A __set_difference__ B = B__set_complement__ __set_intersect__ A -* A __set_symdifference__ B = (B __set_difference__ A) __set_union__ (A __set_difference__ B) - -[heading References] - -* __wiki_set_theory__ in Wikipedia -* __wiki_set_algebra__ in Wikipedia -* [@http://www.tutorvista.com/content/math/number-theory/sets/operations-sets.php Operations on Sets,Union of sets,Intersection of sets] at TutorVista.com - -[endsect] [/ end of section Algebra] - -[section:polygons Polygons] - -Polygons are sets of points, and, therefore polygons follow all definitions and laws for sets. -For pragmatic reasons and implementations in computer programs, polygons have an orientation, -clockwise or counter clockwise. Orientation is not part of most set theory descriptions, but is an -important aspect for the appliance of sets to polygon operations. - -If a polygon is (arbitrarily) defined as having its vertices in clockwise direction: - -* then its interior lies on the right side of the edges (see [@http://gandraxa.com/draw_orthogonal_polygons.aspx Draw Orthogonal Polygons]) -* and its exterior lies, therefore, on the left side of the edges - -This definition is important for the spatial interpretation sets. - -* If set A describes the interior of a polygon, then A__set_complement__, its complement, - describes the exterior of a polygon. -* Stated differently, set A is a polygon, all points belonging to A are inside the polygon. - Its complement, A__set_complement__, contains all points not belonging to A. -* If A is a polygon with its vertices oriented clockwise, A__set_complement__ is a polygon - with the same vertices, but in reverse order, so counter clockwise. Both sets have their points belonging to them at the right side of their edges - -__img_set_a_ac__ - -The last observation is helpful in calculating the difference and the symmetric difference: - -* the difference B __set_difference__ A is defined above by the - law B __set_difference__ A = A__set_complement__ __set_intersect__ B. In polygon terms it is - therefore the intersection of the "reverse of A" with B. To calculate it, it is enough to have - polygon A input in reverse order, and intersect this with polygon B -* the symmetric difference A __set_symdifference__ B is defined above by the law - (B __set_difference__ A) __set_union__ (A __set_difference__ B), which leads to - (A__set_complement__ __set_intersect__ B) __set_union__ (B__set_complement__ __set_intersect__ A). - To calculate the symmetric difference, it is enough to have polygon A input in reverse order, intersect this with polygon B, store the result; then have polygon B input in reverse order, - intersect this with polygon A, add this to the result and this is the symmetric difference. - The combination of both sub-results does not have to be intersected as it is only touching on - vertices and do not have overlaps. - -[endsect] [/ end of section Polygons] - -[section:implementation Implementation of Intersection and Union] - -All spatial set-theoretic operations are implemented in shared code. There is hardly any difference -in code between the calculation of an intersection or a union. The only difference is that at each -intersection point, for an intersection the right turn should be taken. For union the left turn -should be taken. - -__img_set_int_right_union_left__ - -This is implemented as such in __boost_geometry__. The turn to be taken is a variable. - -There is an alternative to calculate union as well: - -* the union A __set_union__ B equals to the complement of the intersection of the complements - of the inputs, (A__set_complement__ __set_intersect__ B__set_complement__)__set_complement__ - (see __wiki_demorgan_laws__ and __wiki_set_law_complements__) - -There is an additional difference in the handling of disjoint holes (holes which are not intersected). This is also implemented in the same generic way (the implementation will still be tweaked a -little to have it even more generic). - -For a counter clockwise polygon, the behaviour is the reverse: for intersection take the left path, -for union take the right path. This is a trivial thing to implement, but it still has to be done -(as the orientation was introduced in a later phase in __boost_geometry__). - -[endsect] [/ end of section Implementation] - -[section:iterating Iterating Forward or Reverse] - -['TODO: Does this section belong to boolean operations at all? --mloskot] - -As explained above, for a difference, the vertices of the first polygon should be iterated by a -forward iterator, but the vertices of the second polygon should be iterated by a reverse iterator -(or vice versa). This (trivial) implementation still has to be done. It will not be implemented -by creating a copy, reversing it, and presenting it as input to the set operation (as outlined above). - -That is easy and will work but has a performance penalty. Instead a reversible iterator will used, -extended from __boost_range__ iterators, and decorating a Boost.Range iterator at the same time, -which can travel forward or backward. - -It is currently named `reversible_view` and usage looks like: - - template - void walk(Range const & range) - { - typedef reversible_view view_type; - view_type view(range); - - typename boost::range_const_iterator::type it; - for (it = boost::begin(view); it != boost::end(view); ++it) - { - // do something - } - } - - walk<1>(range); // forward - walk<-1>(range); // backward - -[endsect] [/ end of section Iterating] - -[section:intersection Characteristics of the Intersection Algorithm] - -The algorithm is a modern variant of the graph traversal algorithm, after __wiki_weiler_atherton__. - -It has the following characteristics (part of these points are deviations from __wiki_weiler_atherton__) - -* No copy is necessary (the original Weiler-Atherton, and its descendants, insert intersections in - (linked) lists, which require to make first copies of both input geometries). -* All turning points (which are intersection points with side/turn information) are unaware of - the context, so we have (and need) no information about if, before the intersection point, - a segment was inside or outside of the other geometry -* It can do intersections, unions, symmetric differences, differences -* It can handle polygons with holes, non-convex polygons, polygons-with-polygons, - polygons-with-boxes (clip), rings, multi-polygons -* It can handle one polygon at the time (resolve self-intersections), two polygons (the normal - use case), or more polygons (applicable for intersections and unions) -* It can handle clockwise and counter-clockwise geometries - -[heading Outline of the Intersection Algorithm] - -The actual implementation consists of the next phases. - -1. The input geometries are indexed (if necessary). Currently we use monotonic sections for the -index. It is done by the algorithm sectionalize. Sections are created is done on the fly, -so no preparation is required before (though this would improve performance - it is possible that -there will be an alternative variant where prepared sections or other indexes are part of the input). -For box-polygon this phase is not necessary and skipped. Sectionalizing is done in linear time. - -2. Intersection points are calculated. Segments of polygon A are compared with segments of polygon B. -Segment intersection is only done for segments in overlapping sections. Intersection points are not -inserted into the original polygon or in a copy. A linked list is therefore not necessary. This phase -is called get_intersection_points. This function can currently be used for one or two input geometries, -for self-intersection or for intersection. Because found intersections are provided with intersection -information, including a reference to their source, it is possible (but currently not implemented) -to have more than two geometry inputs. - -The complexity of getting the intersections is (much) less than quadratic (n*m) because of the -monotonic sections. The exact complexity depends on the number of sections, of how the input polygons -look like. In a worst case scenario, there are only two monotonic sections per polygon and both -overlap. The complexity is then quadratic. However, the sectionalize algorithm has a maximum number of -segments per section, so for large polygons there are always more monotonic sections and in those cases -they do not overlap by the definition of "monotonic". For boxes, the complexity is linear time. - -To give another idea of how sections and indexes work: For a test processing 3918 polygons (but not -processing those of which envelopes do not overlap): - -* brute force (O(n2)): 11856331 combinations -* monotonic sections: 213732 combinations (55 times less) -* a spatial index: 34877 combinations (1/6 of using monotonic sections) So there can still be gained - some performance by another index. However the current spatial index implementation (in an extension, - not in Formal Review) will still be revisited, so it is currently not used. - -In "normal" cases 84% of the time is spent on finding intersection points. These divisions in 's -refers to the performance test described elsewhere - -One piece of information per intersection points is if it is trivial. It is trivial if the intersection -is not located at segment end points. - -3. The found intersection points are merged (merge_intersection_points), and some intersections -can be deleted (e.g. in case of collinearities). This merge process consists of sorting -the intersection points in X (major) and Y (minor) direction, and merging intersections -with a common location together. Intersections with common locations do occur as soon as segments -are collinear or meet at their end points. This phase is skipped if all intersection points -are trivial. - -About 6% is spent on merging. - -4. Some turns need to be adapted. If segments intersect in their interiors, this is never necessary. -However, if segments intersect on their end points, it is sometimes necessary to change "side" -information to "turn" information. This phase is called adapt_turns. - -The image below gives one example when adapting turns is necessary. There is side information, both -segments have sides left and right, there is also collinear. However, for an intersection no turn -should be taken at all, so no right turn. For a union, both polygons have to be travelled. In this -case the side information is adapted to turn information, both turns will be left. This phase is -skipped if all intersection points are trivial. - -__img_set_adapt_turns__ - -5. The merged intersection points are enriched (enrich_intersection_points) with information -about a.o. the next intersection point (travel information). - -About 3% is spent on enrichment. - -6. Polygons are traversed (traverse) using the intersection points, enriched with travel information. -The input polygons are traversed and at all intersection poitns a direction is taken, left for union, -right for intersection point (for counter clockwise polygons this is the other way round). -In some cases separate rings are produced. In some cases new holes are formed. - -About 6% is spent on traversal. - -7. The created rings are assembled (assemble) into polygon(s) with exterior rings and interior rings. -Even if there are no intersection points found, this process can be important to find containment -and coverage. - -['Timing of this phase is not yet available, as the comparison program work on rings.] - -[endsect] [/ end of section Intersection ] - -[endsect] [/ end of section Boolean] \ No newline at end of file diff --git a/doc/quickbook/geometries.qbk b/doc/quickbook/geometries.qbk deleted file mode 100644 index 0832848f84..0000000000 --- a/doc/quickbook/geometries.qbk +++ /dev/null @@ -1,36 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section Geometries] - -Boost Geometry can be used with the geometry types provided by the library, as well as with -custom geometry types which can be registered for Boost Geometry using traits or dedicated -registration macros. - -This section refers to the geometry types provided by the library wich are ready to use -and do not require to be adapted or registered for the library. - -[/ section Geometry Concepts] -[include geometry_concepts.qbk] -[/ end of section Geometry Concepts] - -[/ section Geometry Types] -[include geometry_types.qbk] -[/ end of section Geometry Types] - -[section:adaption Adaption and Registration (?)] -['TODO: adapting user-defined geometry types...] -[endsect] [/ end of section Adaption and Registration] - -[heading Headers] - - #include - -[endsect] [/ end of section Geometries] diff --git a/doc/quickbook/geometry_concepts.qbk b/doc/quickbook/geometry_concepts.qbk deleted file mode 100644 index e96a4f9bfa..0000000000 --- a/doc/quickbook/geometry_concepts.qbk +++ /dev/null @@ -1,232 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section:Geometry Geometry Concepts] - -[:['["A concept is a set of requirements consisting of valid expressions, -associated types, invariants, and complexity guarantees]] - --- David Abrahams, __boost_gtp__ -] - -Boost Geometry is a generic library. Instead of providing a collection of concrete and -final definitions of types and algorithms, the library rather lets users to generate -them based on parameters specified during templates specialization. - -Boost Geometry uses concepts as a technique for describing requirements on types and -combinations of types. This mechanism allows precise specification of requirements on -template parameters which can be used to instantiate concrete types. It means that -a geometry type, in order to be usable with Boost Geometr algorithms, has to model -specific concepts which corresponds to a role that particular type is dedicated to play. - -Boost Geometry uses __boost_concept__ to define checking classes, specify and verify -concept requirements. The mechanism of concepts uses standard C++ and introduce no -run-time overhead as it is compile-time technique. - -Boost Geometry algorithms necessarily impose restrictions on the types that they take, -so they heavily rely on concepts. It means that all algorithms can work with the provided -geometries as well as user-defined and custom geometries as long as all geometry types -model required concepts. - -[/ TODO: declaring? shouldn't be using?] -By declaring registration macros or by specializating type traits it is possible to adapt -user-defined or even legacy geometry types to fulfil requirements of Boost Geometry as -defined by concepts. - -In practice, it means that Boost Geometry potentially can handle geometry types in -variety of forms and definitions, like: - -* predefined geometry types provided by the library -* user-defined type for point geometry -* tuples as point geometry types -* sequences of elments of fundamental types as coordinates -* sequences of elments of user-defined point types -* various legacy geometries - -For definition of point geometry, number of choices are possible: - -* user-defined class -* C array of coordiantes -* __boost_tuple__ or `std::pair` [/ TODO: confirm if std::pair is usable] - -Boost Geometry uses __boost_range__ library to access various sequences in unified manner -and thus it is capable to iterate over elements of: - -* C array -* C++ standard sequences: `std::vector`, `std::deque`, `std::array` -* a range specified by a pair of iterators -* __boost_array__ - -Boost Geometry specifies concepts for the following single geometries: - -* point -* line segment -* linestring (line, polyline) -* ring (linearring) -* box -* polygon - -Concepts are also provided for homogeneous aggregate geometries: - -* multipoint -* multilinestring -* multipolygon - -The aggregate geometry types are considered as ranges of points, linestrings and polygons, -respectively. - -[/Explanation of the terms included only next to the Point concept below to - help to diest concepts presentation full definitions at - http://www.sgi.com/tech/stl/doc_introduction.html] -[section:Point Point] - -[/Description - A summary of the concept's purpose.] -[heading Description] - -A Point is a 0-dimensional entity that has a location on a plane or in space. - -[/Notation - defines meaning of variables and identifiers used in definitions, - valid expressions and expression semantics.] -[variablelist Notation - [[`G`] [A type that is a model of `Point`]] - [[`D`] [An integral constant specifying number of dimensions of coordinate space]] - [[`K`] [An integral constant specifying nth-dimension of `D`-dimensional coordinate space]] - [[`p`] [Object of type `G`]] - [[`v`] [An arbitrary (?) numeric value ['TODO: arbitrary value? --mloskot] ]] -] - -[/Refinement - A list of other concepts that this concept refines.] -[heading Refinement of] - -none - -[/Associated Types - named types related to the modeling type, participate valid - expressions, value of constraint variable, parameter.] -[/heading Associated Types] -[heading Associated types] - -[table - [[Type] [Expression] [Description]] - [[Geometry tag] - [`boost::geometry::traits::tag::type`] - [Identifier of a point geometry type]] - [[Coordinate type] - [`boost::geometry::traits::coordinate_type::type`] - [Type of values of coordinates]] - [[Dimmension value] - [`boost::geometry::traits::dimension::value`] - [Value indicating number of coordinate dimensions (2, 3, ...)]] - [[Coordinate access type] - [`boost::geometry::traits::access`] - [Type implementing read and write access to point coordinates]] - [[Coordinate system type] - [`boost::geometry::traits::coordinate_system::type`] - [Definition of coordinate system, for instance cartesian or spherical, etc.]] -] - -[heading Valid Expressions] - -[table - [[Expression] [Return Type] [Type Requirements]] - [[`p.get()`] [`boost::geometry::traits::coordinate_type::type`][]] - [[`p.set(v)`] [][`p` is mutable, `v` is convertible to `boost::geometry::traits::coordinate_type::type`]] -] - -[heading Expression Semantics] - -The semantics of an expression are defined only where they differ from, or are not defined in -DefaultConstructible, CopyConstructible, Assignable. - -[table - [[Expression] [Semantics]] - [[`p.get()`] []] - [[`p.set(v)`] []] -] - -[/Model - A list of examples of types that are models of this concept.] -[heading Models] - -* __model_point__ -* __model_point_xy__ - -[/Header - A definition, link to the source code where concept is defined.] -[heading Header] - #include - -[endsect] [/ end of section Concept Point] - -[section:ConstPoint ConstPoint] - -[heading Description] - -A Point is a 0-dimensional entity that has a location on a plane or in space, -but does not apply write access to its coordinates. - -[variablelist Notation - [[`G`] [A type that is a model of `Point`]] - [[`D`] [An integral constant]] - [[`K`] [An integral constant specifying nth-dimension of `D`-dimensional coordinate space]] - [[`p`] [Object of type `G`]] - [[`v`] [An arbitrary (?) numeric value ['TODO: arbitrary value? --mloskot] ]] -] - -[heading Refinement of] - -__concept_point__ - -[heading Associated types] - -[table - [[Type] [Expression] [Description]] - [[Geometry tag] - [`boost::geometry::traits::tag::type`] - [Identifier of a point geometry type]] - [[Coordinate type] - [`boost::geometry::traits::coordinate_type::type`] - [Type of values of coordinates]] - [[Dimmension value] - [`boost::geometry::traits::dimension::value`] - [Value indicating number of coordinate dimensions (2, 3, ...)]] - [[Coordinate access type] - [`boost::geometry::traits::access`] - [Type implementing read-only access to point coordinates]] - [[Coordinate system type] - [`boost::geometry::traits::coordinate_system::type`] - [Definition of coordinate system, for instance cartesian or spherical, etc.]] -] - -[heading Valid Expressions] - -[table - [[Expression] [Return Type] [Type Requirements]] - [[`p.get()`] [`boost::geometry::traits::coordinate_type::type`][`p` is immutable]] -] - -[heading Expression Semantics] - -The semantics of an expression are defined only where they differ from, or are not defined -in Point. - -[table - [[Expression] [Semantics]] - [[`p.get()`] []] -] - -[heading Models] - -['TODO] - -[heading Header] - - #include - -[endsect] [/ end of section Concept ConstPoint] - -[endsect] [/ end of section Concepts] diff --git a/doc/quickbook/geometry_types.qbk b/doc/quickbook/geometry_types.qbk deleted file mode 100644 index 702e1c587d..0000000000 --- a/doc/quickbook/geometry_types.qbk +++ /dev/null @@ -1,209 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section:types Geometry Types] - -Boost.Geometry provides a collection of geometry models as class templates and their -specializations. - -[section Points] - -[section point] - -__model_point__ is a data type for 0-dimensional mathematical object, point, specified in -n-dimensional Euclidean space using n coordinates defined in a neutral way. ['TODO: What does the "neutral way" mean? --mloskot] - -[h4 Header] - - #include - -[h4 Synopsis] - - namespace boost { namespace geometry { - - template - class point - { - point(); - point(T const& v0, T const& v1 = 0, T const& v2 = 0); - - template - T const& get() const; - - template - void set(T value); - }; - }} - -[h4 Template Parameters] - -[table - [[Parameter] [Requirement] [Description]] - [[T] [] [Type of numeric coordinates. For example `double`, `float`, `int`, a type of - arbitrary-precision arithmetic provided by __boost_numericadaptor__]] - [[D] [`0 < D`] [Value of number of coordinate space dimensions. For example `2` for two-dimensional plane]] - [[C] [] [Type of coordinate system. For example `boost::geometry::cs::cartesian`]] - [[K] [`0 < K < D`] [Value identifying coordiante nth-dimension of D dimensions.]] -] - -[h4 Model of] - -__concept_point__ - -[h4 Description] - - point(); - -[*Effects:] Constructs an object of the class point, no initialization of coordinate values occurs. - - point(T const& v0, T const& v1 = 0, T const& v2 = 0); - -[*Effects:] Constructs an object of the class point with initialization of all three coordinate values. - - template - T const& get() const; - -[*Requires:] Value `K` is less-than value `D` specified as the class template parameter. - -[*Effects:] Returns value of K-th coordinate of the point object. - - template - void set(T value); - -[*Requires:] Value `K` is less-than value `D` specified as the class template parameter. - -[*Effects:] Sets value of K-th coordinate in the point object. - -[h4 Example] - - // create point object - point p; - // set coordinate values - p.set<0>(1.0); - p.set<1>(2.0); - // query coordinates - double r = p.get<0>(); - double i = p.get<1>(); - -[endsect] [/ end of section point] - -[section point_xy] - -__model_point_xy__ is a data type for 0-dimensional mathematical object, point, specified in -two-dimensional Euclidean space using two coordinates, `x` and `y`. - -[h4 Header] - - #include - -[h4 Synopsis] - - namespace boost { namespace geometry { - - template - class point_xy - { - point_xy(); - point_xy(T const& x, T const& y); - - T const& get<0>() const; - T const& get<1>() const; - - void set<0>(T value); - void set<1>(T value); - - T const& x() const - T const& y() const; - - void x(T const& v); - void y(T const& v); - }; - }} - -[h4 Template Parameters] - -[table - [[Parameter] [Requirement] [Description]] - [[T] [] [Type of numeric coordinates. For example `double`, `float`, `int`, a type of - arbitrary-precision arithmetic provided by __boost_numericadaptor__]] - [[C] [] [Type of coordinate system. For example `boost::geometry::cs::cartesian`]] -] - -[h4 Model of] - -__concept_point__ - -[h4 Description] - - point_xy(); - -[*Effects:] Constructs an object of the class point_xy, no initialization of coordinate values occurs. - - point_xy(T const& x, T const& y); - -[*Effects:] Constructs an object of the class point_xy with initialization of both coordinate values. - - T const& get<0>() const; - -[*Effects:] Returns value, of the first coordinate of the point object, namely of the `x` coordinate. - - T const& get<1>() const; - -[*Effects:] Returns value, of the second coordinate of the point object, namely of the `y` coordinate. - - void set<0>(T value); - -[*Effects:] Sets value, of the first coordinate of the point object, namely of the `x` coordinate. - - void set<1>(T value); - -[*Effects:] Sets value, of the second coordinate of the point object, namely of the `y` coordinate. - - T const& x() const; - -[*Effects:] Returns value, of the first coordinate of the point object, namely of the `x` -coordinate. Named accessor provided for convenience, uses `get<0>()`. - - T const& y() const; - -[*Effects:] Returns value, of the second coordinate of the point object, namely of the `y` -coordinate. Named accessor provided for convenience, uses `get<1>()`. - - void x(T const& v); - -[*Effects:] Sets value, of the first coordinate of the point object, namely of the `x` coordinate. -Named accessor provided for convenience, uses `set<0>()`. - - void y(T const& v); - -[*Effects:] Sets value, of the second coordinate of the point object, namely of the `y` coordinate. -Named accessor provided for convenience, uses `set<1>()`. - -[h4 Example] - - // create object with initialized coordinates - point_xy p(5, 7); - // query coordinates - int x = p.get<0>(); - int y = p.get<1>(); - -[endsect] [/ end of section point_xy] - -[endsect] [/ end of section Points] - -[section Lines] -['TODO: built-in line types...] -[endsect] - -[section Polygons] -['TODO: built-in polygon types...] -[endsect] - -[endsect] [/ end of section Geometry Types] diff --git a/doc/quickbook/misc.qbk b/doc/quickbook/misc.qbk deleted file mode 100644 index e97074741a..0000000000 --- a/doc/quickbook/misc.qbk +++ /dev/null @@ -1,172 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section:misc Miscellaneous] -['TODO: long misc stories here...] - -[section:release Release Notes (?)] [/TODO: current status] -['TODO: about giving birth here...] -[endsect] [/ end of Release Notes] - -[section Compilation] - -__boost_geometry__ is a headers-only library. Users only need to include the library -headers in their programs in order to be able to access definitions and algorithms -provided by the __boost_geometry__ library. No linking against any binaries is required. - -__boost_geometry__ is only dependant on headers-only __boost__ libraries. -It does not introduce indirect dependencies on any binary libraries. - -In order to be able to use __boost_geometry__, the only thing users need to do is to -install __boost_cpp_lib__ and specify location to include directories, so `include` -directives of this scheme will work: - - #include - -[heading Supported Compilers] - -__boost_geometry__ library has been successfully tested with the following compilers: - -* __msvc__ (including Express Edition) - * 9.0 (__msvs__ 2008) - * 8.0 (__msvs__ 2005) -* __gcc__ - * 4.x (confirmed versoins 4.1, 4.2, 4.4) - * 3.4 - -For __msvs__, the examples contains some project files (for 2005). However, because the library -is header only, it will be no problem to integrate it in your own project files. - -__boost_geometry__ uses __boost_bb__, a text-based system for developing and testing software, to -configure, build and execute unit tests and example programs. The build configuration is provided -as a collection of `Jamfile.v2` files. - -For __gcc__ , flag `-Wno-long-long` can be used to surpress some warnings originating from Boost. - -[heading Basic Includes] - -This section concentrates on how to include __boost_geometry__ headers efficiently. - -['TODO: link header names to files? --mloskot] - -The most convenient headerfile including all algorithms and strategies is `geometry.hpp`: - - #include - -This is the main header of the __boost_geometry__ library and it is recommended to include this file. - -Alternatively, it is possible to include __boost_geometry__ header files separately. However, -this may be inconvenient as header files might be renamed or moved occasionaly in future. - -Another often used header is `geometries.hpp`: - - #include - -This includes definitions of all provided geometry tyoes: __model_point__, linestring, polygon, -linear_ring, box. The `geometries.hpp` is not included in the `geometry.hpp` headerfile because -users should be given the liberty to use their own geometries and not the provided ones. -However, for the __boost_geometry__ users who want to use the provided geometries it is -useful to include it. - -For users using only Cartesian points, with floating point coordinates (of C++ type `double`), -in 2D or 3D, you can use instead: - - #include - -This includes all 2D Cartesian geometries: point_2d, linestring_2d, etc. -Using this header file, the library seems to be a non-template library, so it is convenient -for users who do not feel strong with using and specializing C++ templates on their own. - -For users using multi-geometries: - - #include - -[heading Advanced Includes] - -This section is for users who have their own geometries and want to use algorithms from -the __boost_geometry__ library. - -If you want to use your own points it makes sense to use the registration macro's: - - #include - -Defines preprocessor macros for point geometry types registration. - - #include - -Defines preprocessor macros for box geometry type registration. - -If you are using standard containers containing points and want to handle them as a linestring. - - #include - -Allows you to use things like `std::vector` and put them as parameters into algorithms. - -If you are using boost tuples and want to handle them as Cartesian points - - #include - -[heading Extensions] - -['TODO: Do we want this sub-section here? or moving completely to the Extensions node? --mloskot] - -[section Hints] - -[heading Performance] - -The enumeration below is not exhaustive but can contain hints to improve the performance: - -* For Microsoft __msvc__, set define `_SECURE_SCL=0` for preprocessor. -* For Microsoft __msvc__, set define `_HAS_ITERATOR_DEBUGGING=0` for preprocessor. -* Our measurements indicate that Visual C++ 8.0 generates faster code than Visual C++ 9.0 -* Use of __stlport__, a very popular open-source implementation of the STL, may result in - significantly faster code than use of the C++ standard library provided by __msvc__ compiler. -* Turn on compiler optimizations, compile in release mode. - -[endsect] [/ end of Hints] - -[section:issues Known Problems] - -[heading Problems with Intellisense] - -Both versions of __msvs__, 2005 and 2008 (including Express Edition) can hang trying to resolve -symbols and give [@http://en.wikipedia.org/wiki/IntelliSense IntelliSense] suggestions while -typing in a bracket or angle bracket. -This is not directly related to __boost_geometry__, but is caused by problems with handling by this -IDE large C++ code base with intensively used templates, such as Boost and __boost_geometry__. -If this is inconvenient, IntelliSense can easily be turned off: - -[:['["(...)disabling IntelliSense in VC++. There is a file called `feacp.dll` in -`/VC/vcpackages` folder. Renaming this file will disable Intellisense feature.]] - --- [@http://blogs.msdn.com/yash/archive/2007/09/19/intellisense-issues-in-visual-c-2005.aspx Intellisense issues in Visual C++ 2005] -] - -[endsect] [/ end of Problems] - -[endsect] [/ end of Compilation] - -[section Performance (?)] -['TODO: how fast we are here...] -[endsect] [/ end of Performance] - -[section:users Who uses Boost.Geometry (?)] -['TODO: users here...] -[endsect] [/ end of Who Uses] - -[section:future Future Work (?)] [/TODO: Roadmap? --mloskot] -['TODO: roadmap here...] -[endsect] [/ end of ] - -[section Acknowledgments (?)] -['TODO: who is who here...] -[endsect] [/ end of Acknowledgments] - -[endsect] [/ end of Miscellaneous] diff --git a/doc/quickbook/quickref.xml b/doc/quickbook/quickref.xml deleted file mode 100644 index 03f494cef5..0000000000 --- a/doc/quickbook/quickref.xml +++ /dev/null @@ -1,738 +0,0 @@ - - - - - - - - - - - - - - - - - - Geometry Concepts - - - - - - - 0-dimensional - - boost::geometry::concept::Point - boost::geometry::concept::ConstPoint - - - - 1-dimensional - - boost::geometry::concept::Segment - boost::geometry::concept::ConstSegment - boost::geometry::concept::Linestring - boost::geometry::concept::ConstLinestring - - - - 2-dimensional - - boost::geometry::concept::Box - boost::geometry::concept::ConstBox - boost::geometry::concept::Ring - boost::geometry::concept::ConstRing - boost::geometry::concept::Polygon - boost::geometry::concept::ConstPolygon - - - - - - Functions - - boost::geometry::concept::check - boost::geometry::concept::check_concepts_and_equal_dimensions - - - - - - - - - - - - - - - Geometry Models - - - - - - - 0-dimensional - - boost::geometry::point - boost::geometry::point_xy - boost::geometry::point_2d - boost::geometry::point_3d - - - - 1-dimensional - - boost::geometry::segment - boost::geometry::segment_2d - boost::geometry::linestring - boost::geometry::linestring_2d - boost::geometry::linestring_3d - - - - 2-dimensional - - boost::geometry::box - boost::geometry::box_2d - boost::geometry::box_3d - boost::geometry::box - boost::geometry::linear_ring - boost::geometry::ring_2d - boost::geometry::ring_3d - boost::geometry::polygon - boost::geometry::polygon_2d - boost::geometry::polygon_3d - - - - - - Functions - - - Macros - - - - - - - - - - - - - - - - Core - - - - - - - Metafunctions - - boost::geometry::cs_tag - boost::geometry::coordinate_type - boost::geometry::coordinate_system - boost::geometry::dimension - boost::geometry::geometry_id - boost::geometry::interior_type - boost::geometry::is_linear - boost::geometry::is_multi - boost::geometry::is_radian - boost::geometry::point_order - boost::geometry::point_type - boost::geometry::ring_type - boost::geometry::replace_point_type - boost::geometry::reverse_dispatch - boost::geometry::tag - boost::geometry::topological_dimension - - - - Access Functions - - boost::geometry::exterior_ring - boost::geometry::get - boost::geometry::get_as_radian - boost::geometry::interior_rings - boost::geometry::num_interior_rings - boost::geometry::num_points - boost::geometry::set - boost::geometry::set_from_radian - - Classes - - boost::geometry::exception - boost::geometry::centroid_exception - - - - - - - - - - - - - - Constants - - - - - - - Numeric - - boost::geometry::max_corner - boost::geometry::min_corner - boost::geometry::order_selector - boost::geometry::math::pi - boost::geometry::math::two_pi - boost::geometry::math::d2r - boost::geometry::math::r2d - - - - Types - - boost::geometry::degree - boost::geometry::radian - - - - - - - - - - - - - - - Coordinate Systems - - - Iterators - - - - - - - Classes - - boost::geometry::cs::cartesian - boost::geometry::cs::geographic - boost::geometry::cs::polar - boost::geometry::cs::spherical - - - - Metafunctions - - boost::geometry::range_type - - Classes - - boost::geometry::circular_iterator - boost::geometry::ever_circling_iterator - boost::geometry::one_section_segment_iterator - boost::geometry::section_iterator - boost::geometry::segment_iterator - - - - Functions - - boost::geometry::make_segment_iterator - boost::geometry::operator== - boost::geometry::operator!= - - - - - - - - - - - - - - - Algorithms - - - - - - - Geometry Constructors - - boost::geometry::make - boost::geometry::make_inverse - boost::geometry::make_zero - - Predicates - - boost::geometry::disjoint - boost::geometry::equals - boost::geometry::intersects - boost::geometry::overlaps - boost::geometry::selected - boost::geometry::within - - - - Append - - boost::geometry::append - - Area - - boost::geometry::area - - Assign - - boost::geometry::assign - boost::geometry::assign_box_corners - boost::geometry::assign_inverse - boost::geometry::assign_point_from_index - boost::geometry::assign_point_to_index - boost::geometry::assign_zero - - Buffer - - boost::geometry::buffer - boost::geometry::make_buffer - - - - Centroid - - boost::geometry::centroid - boost::geometry::make_centroid - - Clear - - boost::geometry::clear - - Combine - - boost::geometry::combine - - Convert - - boost::geometry::convert - - Convex Hull - - boost::geometry::convex_hull - boost::geometry::convex_hull_inserter - - Correct - - boost::geometry::correct - - - - - - Distance - - boost::geometry::distance - - Difference - - boost::geometry::difference - boost::geometry::sym_difference - - Dissolve - - boost::geometry::dissolve - - Envelope - - boost::geometry::envelope - boost::geometry::make_envelope - - for_each - - boost::geometry::for_each_point - boost::geometry::for_each_segment - - Intersection - - boost::geometry::intersection_inserter - - - - Length - - boost::geometry::length - - Overlay - - boost::geometry::copy_segments - boost::geometry::copy_segment_point - boost::geometry::copy_segment_points - boost::geometry::enrich_intersection_points - boost::geometry::get_turns - boost::geometry::traverse - - Perimeter - - boost::geometry::perimeter - - Reverse - - boost::geometry::reverse - - - - Section - - boost::geometry::get_section - boost::geometry::sectionalize - - Simplify - - boost::geometry::simplify - boost::geometry::simplify_inserter - - Transform - - boost::geometry::transform - - Union - - boost::geometry::union_inserter - - Unique - - boost::geometry::unique - - Miscellaneous Utilities - - boost::geometry::parse - - - - - - - - - - - - - - Policies - - - - - - - Compare - - boost::geometry::equal_to - boost::geometry::greater - boost::geometry::less - - - - Relate - - boost::geometry::policies::relate::direction_type - boost::geometry::policies::relate::segments_de9im - boost::geometry::policies::relate::segments_direction - boost::geometry::policies::relate::segments_intersection_points - boost::geometry::policies::relate::segments_tupled - - - - - - - - - - - - - - Strategy Concepts - - - - - - - - boost::geometry::concept::AreaStrategy - boost::geometry::concept::CentroidStrategy - boost::geometry::concept::ConvexHullStrategy - boost::geometry::concept::PointDistanceStrategy - boost::geometry::concept::PointSegmentDistanceStrategy - - - - - boost::geometry::concept::SegmentIntersectStrategy - boost::geometry::concept::SimplifyStrategy - boost::geometry::concept::WithinStrategy - - - - - - - - - - - - - - - Strategies - - - - - - - Area - - boost::geometry::strategy_area - boost::geometry::area_result - boost::geometry::strategy::area::by_triangles - boost::geometry::strategy::area::huiller - - - - Buffer - - boost::geometry::strategy::buffer::join_miter - boost::geometry::strategy::buffer::join_bevel - boost::geometry::strategy::buffer::join_round - - - - Centroid - - boost::geometry::strategy_centroid - boost::geometry::strategy::centroid_::bashein_detmer - boost::geometry::strategy::centroid_::centroid_average - - - - - - Compare - - boost::geometry::strategy_compare - boost::geometry::strategy::compare::default_strategy - boost::geometry::strategy::compare::circular_comparator - - - - Convex Hull - - boost::geometry::strategy_convex_hull - boost::geometry::strategy::convex_hull::graham_andrew - - - - Distance - - boost::geometry::strategy_distance - boost::geometry::strategy_distance_segment - boost::geometry::cartesian_distance - boost::geometry::distance_result - boost::geometry::make_distance_result - boost::geometry::close_to_zero - boost::geometry::fuzzy_equals - boost::geometry::strategy::distance::projected_point - boost::geometry::strategy::distance::pythagoras - boost::geometry::strategy::distance::cross_track - boost::geometry::strategy::distance::haversine - - - - - - Intersection - - boost::geometry::de9im - boost::geometry::de9im_segment - boost::geometry::segment_intersection_points - boost::geometry::strategy_intersection - boost::geometry::strategy::intersection::liang_barsky - boost::geometry::strategy::intersection::relate_cartesian_segments - boost::geometry::strategy::intersection::relate_cartesian_segments - - - - Side - - boost::geometry::strategy_side - boost::geometry::side_info - boost::geometry::strategy::side::course - boost::geometry::strategy::side::side_by_triangle - boost::geometry::strategy::side::side_by_cross_track - - - - Simplify - - boost::geometry::strategy::simplify::douglas_peucker - - - - - - Transform - - boost::geometry::strategy_transform - boost::geometry::strategy::copy_direct - boost::geometry::strategy::copy_per_coordinate - boost::geometry::strategy::degree_radian_vv - boost::geometry::strategy::degree_radian_vv_3 - boost::geometry::strategy::from_spherical_2_to_cartesian_3 - boost::geometry::strategy::from_spherical_3_to_cartesian_3 - boost::geometry::strategy::from_cartesian_3_to_spherical_2 - boost::geometry::strategy::from_cartesian_3_to_spherical_3 - boost::geometry::strategy::inverse_transformer - boost::geometry::strategy::map_transformer - boost::geometry::strategy::ublas_transformer - boost::geometry::strategy::translate_transformer - boost::geometry::strategy::scale_transformer - boost::geometry::strategy::rotate_transformer - - - - Within - - boost::geometry::strategy::winding - boost::geometry::strategy::crossings_multiply - boost::geometry::strategy::franklin - - - - Miscellaneous Utilities - - boost::geometry::strategy::not_implemented - - - - - - - - - - - - - - - - Arithmetic - - - - - - - Add - - boost::geometry::add_point - boost::geometry::add_value - - - - Subtract - - boost::geometry::subtract_point - boost::geometry::subtract_value - - - - Multiply - - boost::geometry::multiply_point - boost::geometry::multiply_value - - - - Divide - - boost::geometry::divide_point - boost::geometry::divide_value - - - - - - Products - - boost::geometry::cross_product - boost::geometry::dot_product - - - - - - - - - - - - - - - Extensions - - - - - - - TODO - - ... - - - - - - - diff --git a/doc/quickbook/readme.txt b/doc/quickbook/readme.txt deleted file mode 100644 index afcc3292af..0000000000 --- a/doc/quickbook/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -=========================================================================== - Copyright (c) 2010 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)9 -============================================================================ - -This folder quickbook was the first phase of the documentation. - -Files left here should be merged with the current phase, one folder higher. - -Barend, 31-12-2010 diff --git a/doc/quickbook/references.qbk b/doc/quickbook/references.qbk deleted file mode 100644 index 077a4264f2..0000000000 --- a/doc/quickbook/references.qbk +++ /dev/null @@ -1,86 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section References] - -The following section lists references and relations between __boost_geometry__ and other -software libraries as well as various specifications and documents discussing subjects directly -related to the matter of the library implementation. - -[section:std C++ Standard Library] - -The __boost_geometry__ makes substantial use of the __wiki_std__ and is designed to be -compatible with it. Quick list of uses of the `std` namespace elements: - -* provided geometries (linestring, ring, polygon, multi-s) make default use of `std::vector`, - but that is configurable. -* std sorting, unique copies, maps can make use of provided functors in compare. -* internally, there are vector's, deque's, there is sorting, many things are implemented - using the std library - -[endsect] [/ end of C++Std] - -[section Boost C++ Libraries] - -The __boost_geometry__ makes use of the following __boost_cpp_lib__: - -* __boost_range__ -* __boost_traits__ (e.g. remove_const) -* __boost_concept__ -* __boost_numericconv__ (cast, bounds) -* __boost_mpl__ -* __boost_staticassert__ -* __boost_iterator__ -* __boost_smart_ptr__ (shared_ptr, in the extensions spatial index and projections) -* __boost_ublas__ -* Adapted geometries: - * __boost_array__ - * __boost_tuple__ -* IO and parsing - * __boost_tokenizer__ - * __boost_conversion__ (lexical cast) - * __boost_stringalgo__ -* Testing - * __boost_test__ - * __boost_timer__ -* Examples - * __boost_graph__ - -Many of these are used a lot inside the library. - -The __boost_range__ library is used everywhere to declare iterators and to walk through standard -containers or custom ranges. - -The __boost_concept__ is used to check concepts, for geometries as well as for strategies. - -Tranformations are implemented using __boost_ublas__ - -The __boost_mpl__ is used for a.o. reverse dispatching - -Finally, the library can perfectly be used together with the __boost_graph__, as shown in example 7. - -[endsect] [/ end of Boost] - -[section:other Other Libraries] - -__boost_geometry__ is designed to support use of arbitrary-precision arithmetic data types -and algorithms provided by third-party libraries like __gmp__ and __cln__. - -['TODO: to be extended --mloskot] - -['TODO: do we discuss only what libraries Boost Geometry core can use or extensions too? --mloskot] - -[endsect] [/ end of Other Libraries] - -[section:opengis Standards of the Open Geospatial Consortium (?)] [/TODO: matrix on Wiki] -['TODO: about ogc here...] -[endsect] [/ end of OGC] - -[endsect] [/ end of References] \ No newline at end of file diff --git a/doc/quickbook/strategy_rationale.qbk b/doc/quickbook/strategy_rationale.qbk deleted file mode 100644 index 911c1a08cb..0000000000 --- a/doc/quickbook/strategy_rationale.qbk +++ /dev/null @@ -1,148 +0,0 @@ -[/============================================================================== - Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2008-2011 Bruno Lalande, Paris, France. - Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) -===============================================================================/] - -[section:strategy Strategy Rationale] - -[@http://en.wikipedia.org/wiki/Strategy_pattern Strategy] is a [@http://en.wikipedia.org/wiki/Design_pattern_(computer_science) software design pattern] used to -achieve algorithms slection at runtime. An idiomatic variation of the Strategy pattern specific -to C++ programming language is known as Policy pattern with related technique of [@http://en.wikipedia.org/wiki/Policy-based_design Policy-based design]. Thus, in the C++ template -contexts, policy is usually meant as selection of algorithms at compile time. - -['TODO: the two sentences below need to be clarified, what is "another context", etc. --mloskot] - -__boost_geometry__ uses (sparsely) the term policy in a broader, or in another, context. The term -Strategy is used specificly for a computation method targeted to a specific coordinate system. - -In __boost_geometry__ strategies do have the following purposes: - -* for each coordinate system, a default strategy is selected by compile time, using the coordinate - system tag. This is effectively tag dispatching. -* users can override the default choice by using the overloaded function, which has a strategy - as an extra parameter, and take another strategy -* users can override the default choice by using the overloaded function, to use the default - strategy, but constructed with specific parameters -* users can override the default choice by using the overloaded function, to use the default - strategy (which can be a templated structure), with other template parameters then the default ones -* users can override the default choice by using the overloaded function, to use the default - strategy, which can be a class template, with other template parameters then the default ones, - with the specific purpose as to select another calculation type (e.g. __gmp__ or another - arbitrary precision number type) - -All these decisions and choices listed above occur at compile-time. - -Let's discuss a short example to explaining how strategies work in __boost_geometry__. -Note, it is also explained in the design rationale section. - -Considering calculation of distance in three common coordinate systems, for each of the coordinate -systems a default strategy implementing distance calculation has been assigned: - -* __wiki_cs_cartesian__ uses Pythagoras as default strategy for point-point distance calculations -* __wiki_cs_spherical__ uses Haversine strategy a default -* __wiki_cs_geographic__ uses Andoyer. - -The Haversine works on the unit sphere, radius `1`. Library users can use the distance function, -specifying haversine strategy constructed with a radius of `2`. Or, for example, they can -use the distance function, specifying the more precise Vincenty strategy -(for __wiki_cs_geographic__, but that might not even be checked there). - -Specifying strategies is useful, even if not point-point distance is to be calculated, for -example, point-polygon distance. In the end, it will call the elementary specified functionality. -Note, that for this example, the point-segment distance strategy is also considered as "elementary". -Note also, that it can have an optional template parameter defining the underlying -point-point-distance-strategy. - -[section:properties Properties of Strategies] - -Strategies can be constructed outside a calling function, thus they can be specified as an -optional parameter (implemented as an overloaded function), and not only as a template parameter. -Furthermore, strategies can be reused number of times, in subsequent function calls. -Therefore strategies as function parameter are declared as reference to `const` and they -should be stateless, except that they can be provided with some initialization details -during construction. - -The strategy needs to access construction information (member variables), its calculation method -is therefore usually not a `static` method but a non-static `const` method. It can then access -member variables, while still being `const`, non-mutable, stateless and read-only object, and -being able to be called across several function calls. - -['TODO: The next 2-3 paragraphs might need some refactoring, to rephrase what is said in - clearer and simple manner --mloskot] - -For some algorithms, strategies may need to store some intermediate results of calculation -(a state). For this purpose, strategies should declare a `state_type`. An instance of the `state_type` -is created before first call is performed and specified in each call. - -The calculation method is always called apply (as convention in __boost_geometry__) and gets the -most elementary information as a parameter: a point, a segment, a range. It depends on the -algorithm and, sometimes, on the source geometry passed. That should actually be the case as -least as possisble. -In most cases, there is an additional method result which returns the calculated result. -That result-method is a also non-static const method, and the state is passed. Note that the -methods might be non-static const, but they might also be static. That is not checked by the -concept-checker. - -A strategy for a specific algorithm has a concept. The distance-strategy should follow the -distance-strategy-concept. The point-in-polygon strategy should follow the -point-in-polygon-strategy-concept. Those concepts are not modelled as traits classes (contrary -to the geometries). The reason for this is that it seems not necessary to use legacy classes -as concepts, without modification. A wrapper can be built. So the strategies should have a method -apply and should define some types. - -Which types, and which additional methods (often a method result), is dependant on the algorithm -and type of strategy. - -Strategies are checked by a strategy-concept-checker. For this checker (and sometimes for -checking alone), they should define some types. Because if no types are defined, the -cannot be checked at compile time... The strategy-concept-checkers are thus implemented per -algorithm and they use the __boost_concept__ for concepts checking. - -According to what was explained above, the essentials of the design are: - -* function determines default-strategy, or is called with specified strategy -* function calls dispatch (dispatching is done on geometry tag) -* dispatch calls implementation (in namespace detail), which can be shared for different geometry - types, for single as well as for aggregate geometries (multi-geometries) -* implementation calls strategy (if applicable), with the smallest common (geometric) - element applicable for all calculation method, the common denominator. - -[endsect] [/ end of section Properties of Strategies] - -[section:alternative Alternative Design] - -Some calculations (strategies) might need to take the whole geometry, instead of working on -point-per-point or segment-per-segment base. This would bypass the dispatch functionality. -Because all strategies would take the whole geometry, it is not necessary to dispatch per -geometry type. In fact this dispatching on geometry-type is moved to the strategy_traits class -(which are specialized per coordinate system in the current design). So in this alternative design, -the strategy traits class specializes on both geometry-tag and coordinate-system-tag, to select -the default strategy. For the default strategy, this move from "dispatch" to another dispatch -called `strategy_XXX` (XXX is the algorithm) might make sense. However, if library users would -call the overloaded function and specify a strategy, the only thing what would happen is that -that specified strategy is called. - -For example: - - template - bool within(G1 const& g1, G2 const& g2, S& const strategy) - { - return strategy.apply(g1, g2); - } - -The library user could call just this `strategy.apply()` method directly. If more strategies are -provided by the library or its extensions, it would still make sense: the user can still call -within and does not have to call the apply method of the strategy. - -The convex hull strategy currently works on a whole geometry. However, it is possible that it will -be reshaped to work per range (the algorithm internally works per range), plus a mechanism to -pass ranges multiple times (it currently is two-pass). - -[endsect] [/ end of section Alternative Design] - -[endsect] [/ end of section Strategies] From a1f2e966de04dca45e23b02c770b0c068502267b Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 16 Apr 2011 23:19:36 +0000 Subject: [PATCH 012/135] Merged Boost.Geometry from revision 71123 to 71336 [SVN r71337] --- include/boost/geometry/algorithms/assign.hpp | 494 ++---------------- .../boost/geometry/algorithms/centroid.hpp | 6 +- include/boost/geometry/algorithms/clear.hpp | 4 + .../algorithms/comparable_distance.hpp | 9 +- .../algorithms/{detail => }/convert.hpp | 25 +- .../boost/geometry/algorithms/convex_hull.hpp | 6 +- include/boost/geometry/algorithms/correct.hpp | 11 +- .../algorithms/detail/assign_values.hpp | 450 ++++++++++++++++ .../detail/equals/collect_vectors.hpp | 2 +- .../detail/overlay/clip_linestring.hpp | 6 +- .../detail/overlay/convert_ring.hpp | 8 +- .../detail/overlay/copy_segment_point.hpp | 4 +- .../overlay/get_intersection_points.hpp | 4 +- .../detail/overlay/get_turn_info.hpp | 14 +- .../detail/overlay/intersection_insert.hpp | 6 +- .../geometry/algorithms/detail/partition.hpp | 1 + .../detail/sections/sectionalize.hpp | 4 +- .../boost/geometry/algorithms/distance.hpp | 12 +- .../boost/geometry/algorithms/envelope.hpp | 1 + include/boost/geometry/algorithms/equals.hpp | 10 +- include/boost/geometry/algorithms/expand.hpp | 8 +- include/boost/geometry/algorithms/length.hpp | 4 +- include/boost/geometry/algorithms/make.hpp | 64 ++- include/boost/geometry/algorithms/reverse.hpp | 7 +- .../boost/geometry/algorithms/simplify.hpp | 4 +- .../boost/geometry/algorithms/transform.hpp | 21 +- include/boost/geometry/algorithms/unique.hpp | 2 + .../boost/geometry/arithmetic/arithmetic.hpp | 82 ++- include/boost/geometry/core/closure.hpp | 9 +- .../geometry/core/coordinate_dimension.hpp | 40 +- .../boost/geometry/core/coordinate_system.hpp | 13 +- .../boost/geometry/core/coordinate_type.hpp | 7 +- include/boost/geometry/core/cs.hpp | 12 +- include/boost/geometry/core/point_order.hpp | 10 +- include/boost/geometry/core/point_type.hpp | 7 +- include/boost/geometry/core/tag.hpp | 8 +- include/boost/geometry/core/tag_cast.hpp | 24 +- .../geometry/domains/gis/io/wkt/read_wkt.hpp | 8 +- .../geometry/domains/gis/io/wkt/write_wkt.hpp | 8 +- include/boost/geometry/geometries/box.hpp | 6 +- include/boost/geometry/geometry.hpp | 2 + .../boost/geometry/iterators/box_iterator.hpp | 4 +- .../iterators/segment_range_iterator.hpp | 4 +- .../cartesian/distance_projected_point.hpp | 8 +- .../strategies/strategy_transform.hpp | 4 +- 45 files changed, 824 insertions(+), 619 deletions(-) rename include/boost/geometry/algorithms/{detail => }/convert.hpp (90%) create mode 100644 include/boost/geometry/algorithms/detail/assign_values.hpp diff --git a/include/boost/geometry/algorithms/assign.hpp b/include/boost/geometry/algorithms/assign.hpp index 4df4e2d6f8..df5cd663df 100644 --- a/include/boost/geometry/algorithms/assign.hpp +++ b/include/boost/geometry/algorithms/assign.hpp @@ -25,6 +25,10 @@ #include #include +#include +#include + +#include #include #include #include @@ -40,444 +44,6 @@ namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace assign -{ - -template -struct assign_operation -{ - inline assign_operation(CoordinateType const& value) - : m_value(value) - {} - - template - inline void apply(P& point) const - { - geometry::set(point, m_value); - } - -private: - - CoordinateType m_value; -}; - - -/*! - \brief Assigns all coordinates of a specific point to a value - \ingroup assign - \details - \param p Point - \param value Value which is assigned to all coordinates of point p - */ -template -inline void assign_value(Point& p, - typename coordinate_type::type const& value) -{ - for_each_coordinate(p, - assign_operation::type>(value)); -} - - - -template -< - typename Box, std::size_t Index, - std::size_t Dimension, std::size_t DimensionCount -> -struct initialize -{ - typedef typename coordinate_type::type coordinate_type; - - static inline void apply(Box& box, coordinate_type const& value) - { - geometry::set(box, value); - initialize::apply(box, value); - } -}; - - -template -struct initialize -{ - typedef typename coordinate_type::type coordinate_type; - - static inline void apply(Box&, coordinate_type const& ) - {} -}; - - -template -struct assign_zero_point -{ - static inline void apply(Point& point) - { - typedef typename coordinate_type::type coordinate_type; - assign_value(point, 0); - } -}; - - -template -struct assign_inverse_box_or_segment -{ - typedef typename point_type::type point_type; - - static inline void apply(BoxOrSegment& geometry) - { - typedef typename coordinate_type::type coordinate_type; - - typedef typename boost::mpl::if_ - < - typename boost::is_arithmetic::type, - coordinate_type, - double - >::type bound_type; - - initialize - < - BoxOrSegment, 0, 0, dimension::type::value - >::apply( - geometry, boost::numeric::bounds::highest()); - initialize - < - BoxOrSegment, 1, 0, dimension::type::value - >::apply( - geometry, boost::numeric::bounds::lowest()); - } -}; - - -template -struct assign_zero_box_or_segment -{ - static inline void apply(BoxOrSegment& geometry) - { - typedef typename coordinate_type::type coordinate_type; - - initialize - < - BoxOrSegment, 0, 0, dimension::type::value - >::apply(geometry, coordinate_type()); - initialize - < - BoxOrSegment, 1, 0, dimension::type::value - >::apply(geometry, coordinate_type()); - } -}; - - -template -< - std::size_t Corner1, std::size_t Corner2, - typename Box, typename Point -> -inline void assign_box_2d_corner(Box const& box, Point& point) -{ - // Be sure both are 2-Dimensional - assert_dimension(); - assert_dimension(); - - // Copy coordinates - typedef typename coordinate_type::type coordinate_type; - - geometry::set<0>(point, boost::numeric_cast(get(box))); - geometry::set<1>(point, boost::numeric_cast(get(box))); -} - - - -template -< - typename Geometry, typename Point, - std::size_t Index, - std::size_t Dimension, std::size_t DimensionCount -> -struct assign_point_to_index -{ - - static inline void apply(Point const& point, Geometry& geometry) - { - geometry::set(geometry, boost::numeric_cast - < - typename coordinate_type::type - >(geometry::get(point))); - - assign_point_to_index - < - Geometry, Point, Index, Dimension + 1, DimensionCount - >::apply(point, geometry); - } -}; - -template -< - typename Geometry, typename Point, - std::size_t Index, - std::size_t DimensionCount -> -struct assign_point_to_index - < - Geometry, Point, - Index, - DimensionCount, DimensionCount - > -{ - static inline void apply(Point const& , Geometry& ) - { - } -}; - - -template -< - typename Geometry, typename Point, - std::size_t Index, - std::size_t Dimension, std::size_t DimensionCount -> -struct assign_point_from_index -{ - - static inline void apply(Geometry const& geometry, Point& point) - { - geometry::set( point, boost::numeric_cast - < - typename coordinate_type::type - >(geometry::get(geometry))); - - assign_point_from_index - < - Geometry, Point, Index, Dimension + 1, DimensionCount - >::apply(geometry, point); - } -}; - -template -< - typename Geometry, typename Point, - std::size_t Index, - std::size_t DimensionCount -> -struct assign_point_from_index - < - Geometry, Point, - Index, - DimensionCount, DimensionCount - > -{ - static inline void apply(Geometry const&, Point&) - { - } -}; - - -template -struct assign_2d_box_or_segment -{ - typedef typename coordinate_type::type coordinate_type; - - // Here we assign 4 coordinates to a box of segment - // -> Most logical is: x1,y1,x2,y2 - // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED) - - template - static inline void apply(Geometry& geometry, - Type const& x1, Type const& y1, Type const& x2, Type const& y2) - { - geometry::set<0, 0>(geometry, boost::numeric_cast(x1)); - geometry::set<0, 1>(geometry, boost::numeric_cast(y1)); - geometry::set<1, 0>(geometry, boost::numeric_cast(x2)); - geometry::set<1, 1>(geometry, boost::numeric_cast(y2)); - } -}; - - -}} // namespace detail::assign -#endif // DOXYGEN_NO_DETAIL - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -struct assign -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; - -template -struct assign -{ - typedef typename coordinate_type::type coordinate_type; - - template - static inline void apply(Point& point, T const& c1, T const& c2) - { - set<0>(point, boost::numeric_cast(c1)); - set<1>(point, boost::numeric_cast(c2)); - } -}; - -template -struct assign -{ - typedef typename coordinate_type::type coordinate_type; - - template - static inline void apply(Point& point, T const& c1, T const& c2, T const& c3) - { - set<0>(point, boost::numeric_cast(c1)); - set<1>(point, boost::numeric_cast(c2)); - set<2>(point, boost::numeric_cast(c3)); - } -}; - -template -struct assign - : detail::assign::assign_2d_box_or_segment -{}; - -template -struct assign - : detail::assign::assign_2d_box_or_segment -{}; - - - -template -struct assign_zero {}; - - -template -struct assign_zero - : detail::assign::assign_zero_point -{}; - -template -struct assign_zero - : detail::assign::assign_zero_box_or_segment -{}; - -template -struct assign_zero - : detail::assign::assign_zero_box_or_segment -{}; - - -template -struct assign_inverse {}; - -template -struct assign_inverse - : detail::assign::assign_inverse_box_or_segment -{}; - -template -struct assign_inverse - : detail::assign::assign_inverse_box_or_segment -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -/*! -\brief Assign two coordinates to a geometry (usually a 2D point) -\ingroup assign -\tparam Geometry \tparam_geometry -\tparam Type \tparam_numeric to specify the coordinates -\param geometry \param_geometry -\param c1 \param_x -\param c2 \param_y - -\qbk{distinguish, 2 coordinate values} -\qbk{ -[heading Example] -[assign_2d_point] [assign_2d_point_output] - -[heading See also] -\* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make] -} - */ -template -inline void assign(Geometry& geometry, Type const& c1, Type const& c2) -{ - concept::check(); - - dispatch::assign - < - typename tag::type, - Geometry, - geometry::dimension::type::value - >::apply(geometry, c1, c2); -} - -/*! -\brief Assign three values to a geometry (usually a 3D point) -\ingroup assign -\tparam Geometry \tparam_geometry -\tparam Type \tparam_numeric to specify the coordinates -\param geometry \param_geometry -\param c1 \param_x -\param c2 \param_y -\param c3 \param_z - -\qbk{distinguish, 3 coordinate values} -\qbk{ -[heading Example] -[assign_3d_point] [assign_3d_point_output] - -[heading See also] -\* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make] -} - */ -template -inline void assign(Geometry& geometry, - Type const& c1, Type const& c2, Type const& c3) -{ - concept::check(); - - dispatch::assign - < - typename tag::type, - Geometry, - geometry::dimension::type::value - >::apply(geometry, c1, c2, c3); -} - -/*! -\brief Assign four values to a geometry (usually a box or segment) -\ingroup assign -\tparam Geometry \tparam_geometry -\tparam Type \tparam_numeric to specify the coordinates -\param geometry \param_geometry -\param c1 First coordinate (usually x1) -\param c2 Second coordinate (usually y1) -\param c3 Third coordinate (usually x2) -\param c4 Fourth coordinate (usually y2) - -\qbk{distinguish, 4 coordinate values} - */ -template -inline void assign(Geometry& geometry, - Type const& c1, Type const& c2, Type const& c3, Type const& c4) -{ - concept::check(); - - dispatch::assign - < - typename tag::type, - Geometry, - geometry::dimension::type::value - >::apply(geometry, c1, c2, c3, c4); -} - - /*! \brief Assign a range of points to a linestring, ring or polygon \note The point-type of the range might be different from the point-type of the geometry @@ -487,20 +53,18 @@ inline void assign(Geometry& geometry, \param geometry \param_geometry \param range \param_range_point -\qbk{distinguish, with a range} \qbk{ [heading Notes] [note Assign automatically clears the geometry before assigning (use append if you don't want that)] [heading Example] -[assign_with_range] [assign_with_range_output] +[assign_points] [assign_points_output] [heading See also] -\* [link geometry.reference.algorithms.make.make_1_with_a_range make] -\* [link geometry.reference.algorithms.append.append append] +\* [link geometry.reference.algorithms.append append] } */ template -inline void assign(Geometry& geometry, Range const& range) +inline void assign_points(Geometry& geometry, Range const& range) { concept::check(); @@ -559,6 +123,12 @@ inline void assign_zero(Geometry& geometry) } +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ +// Note: this is moved to namespace detail because the names and parameter orders +// are not yet 100% clear. + /*! \brief Assign the four points of a 2D box \ingroup assign @@ -666,8 +236,46 @@ inline void assign_point_from_index(Geometry const& geometry, Point& point) >::apply(geometry, point); } +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +/*! +\brief Assigns one geometry to another geometry +\details The assign algorithm assigns one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only +if it is possible and applicable. +\ingroup assign +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry (target) +\param geometry2 \param_geometry (source) + +\qbk{ +[heading Example] +[assign] [assign_output] + +[heading See also] +\* [link geometry.reference.algorithms.convert convert] +} + */ +template +inline void assign(Geometry1& geometry1, Geometry2 const& geometry2) +{ + concept::check_concepts_and_equal_dimensions(); + + dispatch::convert + < + typename tag::type, + typename tag::type, + dimension::type::value, + Geometry2, + Geometry1 + >::apply(geometry2, geometry1); +} + }} // namespace boost::geometry + #endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP diff --git a/include/boost/geometry/algorithms/centroid.hpp b/include/boost/geometry/algorithms/centroid.hpp index 9b51ba07dd..a400e2e0ba 100644 --- a/include/boost/geometry/algorithms/centroid.hpp +++ b/include/boost/geometry/algorithms/centroid.hpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -83,7 +83,7 @@ struct centroid_point static inline void apply(Point const& point, PointCentroid& centroid, Strategy const&) { - geometry::detail::convert(point, centroid); + geometry::convert(point, centroid); } }; @@ -163,7 +163,7 @@ inline bool range_ok(Range const& range, Point& centroid) else // if (n == 1) { // Take over the first point in a "coordinate neutral way" - geometry::detail::convert(*boost::begin(range), centroid); + geometry::convert(*boost::begin(range), centroid); return false; } return true; diff --git a/include/boost/geometry/algorithms/clear.hpp b/include/boost/geometry/algorithms/clear.hpp index 5635710d7b..d4cf7fd776 100644 --- a/include/boost/geometry/algorithms/clear.hpp +++ b/include/boost/geometry/algorithms/clear.hpp @@ -134,7 +134,11 @@ struct clear the case of a polygon, this clear functionality is automatically called for the exterior ring, and for the interior ring collection. In the case of a point, boxes and segments, nothing will happen. \ingroup clear +\tparam Geometry \tparam_geometry +\param geometry \param_geometry which will be cleared \note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero" + +\qbk{[include reference/algorithms/clear.qbk]} */ template inline void clear(Geometry& geometry) diff --git a/include/boost/geometry/algorithms/comparable_distance.hpp b/include/boost/geometry/algorithms/comparable_distance.hpp index 57837a5edf..fa48942727 100644 --- a/include/boost/geometry/algorithms/comparable_distance.hpp +++ b/include/boost/geometry/algorithms/comparable_distance.hpp @@ -25,13 +25,18 @@ namespace boost { namespace geometry /*! \brief \brief_calc2{comparable distance measurement} \ingroup distance -\details The default strategy is used, belonging to the corresponding coordinate system of the geometries - and the comparable strategy is used +\details The free function comparable_distance does not necessarily calculate the distance, + but it calculates a distance measure such that two distances are comparable to each other. + For example: for the Cartesian coordinate system, Pythagoras is used but the square root + is not taken, which makes it faster and the results of two point pairs can still be + compared to each other. \tparam Geometry1 first geometry type \tparam Geometry2 second geometry type \param geometry1 \param_geometry \param geometry2 \param_geometry \return \return_calc{comparable distance} + +\qbk{[include reference/algorithms/comparable_distance.qbk]} */ template inline typename default_distance_result::type comparable_distance( diff --git a/include/boost/geometry/algorithms/detail/convert.hpp b/include/boost/geometry/algorithms/convert.hpp similarity index 90% rename from include/boost/geometry/algorithms/detail/convert.hpp rename to include/boost/geometry/algorithms/convert.hpp index 9301006a74..b90e008c1d 100644 --- a/include/boost/geometry/algorithms/detail/convert.hpp +++ b/include/boost/geometry/algorithms/convert.hpp @@ -20,9 +20,11 @@ #include #include +#include #include -#include +#include #include +#include #include #include @@ -147,19 +149,19 @@ struct convert geometry::clear(ring); typename point_type::type point; - geometry::assign(point, get(box), get(box)); + geometry::assign_values(point, get(box), get(box)); geometry::append(ring, point); - geometry::assign(point, get(box), get(box)); + geometry::assign_values(point, get(box), get(box)); geometry::append(ring, point); - geometry::assign(point, get(box), get(box)); + geometry::assign_values(point, get(box), get(box)); geometry::append(ring, point); - geometry::assign(point, get(box), get(box)); + geometry::assign_values(point, get(box), get(box)); geometry::append(ring, point); - geometry::assign(point, get(box), get(box)); + geometry::assign_values(point, get(box), get(box)); geometry::append(ring, point); } }; @@ -233,10 +235,6 @@ struct convert #endif // DOXYGEN_NO_DISPATCH -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - /*! \brief Converts one geometry to another geometry \details The convert algorithm converts one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only @@ -246,8 +244,8 @@ if it is possible and applicable. \tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry (source) \param geometry2 \param_geometry (target) -\note It is moved to namespace detail because it overlaps functionality - of assign. So assign will be changed such that it also can convert. + +\qbk{[include reference/algorithms/convert.qbk]} */ template inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) @@ -264,9 +262,6 @@ inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) >::apply(geometry1, geometry2); } -} -#endif // DOXYGEN_NO_DETAIL - }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/convex_hull.hpp b/include/boost/geometry/algorithms/convex_hull.hpp index bde0f6fbdf..32ed84b3ef 100644 --- a/include/boost/geometry/algorithms/convex_hull.hpp +++ b/include/boost/geometry/algorithms/convex_hull.hpp @@ -152,8 +152,10 @@ inline void convex_hull(Geometry1 const& geometry, \details \details_calc{convex_hull,convex hull}. \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry -\param geometry \param_geometry, used for input +\param geometry \param_geometry, input geometry \param hull \param_geometry \param_set{convex hull} + +\qbk{[include reference/algorithms/convex_hull.qbk]} */ template inline void convex_hull(Geometry1 const& geometry, @@ -241,8 +243,6 @@ inline OutputIterator convex_hull_insert(Geometry const& geometry, #endif // DOXYGEN_NO_DETAIL - - }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/correct.hpp b/include/boost/geometry/algorithms/correct.hpp index 79e47c1e91..cc7911f3c1 100644 --- a/include/boost/geometry/algorithms/correct.hpp +++ b/include/boost/geometry/algorithms/correct.hpp @@ -93,7 +93,7 @@ struct correct_box static inline void apply(Box& box) { - // Currently only for Cartesian coordinates + // Currently only for Cartesian coordinates // (or spherical without crossing dateline) // Future version: adapt using strategies correct_box_loop @@ -245,10 +245,15 @@ struct correct /*! \brief Corrects a geometry -\details Corrects a geometry +\details Corrects a geometry: all rings which are wrongly oriented with respect + to their expected orientation are reversed. To all rings which do not have a + closing point and are typed as they should have one, the first point is + appended. Also boxes can be corrected. \ingroup correct \tparam Geometry \tparam_geometry -\param geometry \param_geometry +\param geometry \param_geometry which will be corrected if necessary + +\qbk{[include reference/algorithms/correct.qbk]} */ template inline void correct(Geometry& geometry) diff --git a/include/boost/geometry/algorithms/detail/assign_values.hpp b/include/boost/geometry/algorithms/detail/assign_values.hpp new file mode 100644 index 0000000000..d9c6fc49d6 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/assign_values.hpp @@ -0,0 +1,450 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_ASSIGN_VALUES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace assign +{ + + +template +< + typename Box, std::size_t Index, + std::size_t Dimension, std::size_t DimensionCount +> +struct initialize +{ + typedef typename coordinate_type::type coordinate_type; + + static inline void apply(Box& box, coordinate_type const& value) + { + geometry::set(box, value); + initialize::apply(box, value); + } +}; + + +template +struct initialize +{ + typedef typename coordinate_type::type coordinate_type; + + static inline void apply(Box&, coordinate_type const& ) + {} +}; + + +template +struct assign_zero_point +{ + static inline void apply(Point& point) + { + geometry::assign_value(point, 0); + } +}; + + +template +struct assign_inverse_box_or_segment +{ + typedef typename point_type::type point_type; + + static inline void apply(BoxOrSegment& geometry) + { + typedef typename coordinate_type::type coordinate_type; + + typedef typename boost::mpl::if_ + < + typename boost::is_arithmetic::type, + coordinate_type, + double + >::type bound_type; + + initialize + < + BoxOrSegment, 0, 0, dimension::type::value + >::apply( + geometry, boost::numeric::bounds::highest()); + initialize + < + BoxOrSegment, 1, 0, dimension::type::value + >::apply( + geometry, boost::numeric::bounds::lowest()); + } +}; + + +template +struct assign_zero_box_or_segment +{ + static inline void apply(BoxOrSegment& geometry) + { + typedef typename coordinate_type::type coordinate_type; + + initialize + < + BoxOrSegment, 0, 0, dimension::type::value + >::apply(geometry, coordinate_type()); + initialize + < + BoxOrSegment, 1, 0, dimension::type::value + >::apply(geometry, coordinate_type()); + } +}; + + +template +< + std::size_t Corner1, std::size_t Corner2, + typename Box, typename Point +> +inline void assign_box_2d_corner(Box const& box, Point& point) +{ + // Be sure both are 2-Dimensional + assert_dimension(); + assert_dimension(); + + // Copy coordinates + typedef typename coordinate_type::type coordinate_type; + + geometry::set<0>(point, boost::numeric_cast(get(box))); + geometry::set<1>(point, boost::numeric_cast(get(box))); +} + + + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t Dimension, std::size_t DimensionCount +> +struct assign_point_to_index +{ + + static inline void apply(Point const& point, Geometry& geometry) + { + geometry::set(geometry, boost::numeric_cast + < + typename coordinate_type::type + >(geometry::get(point))); + + assign_point_to_index + < + Geometry, Point, Index, Dimension + 1, DimensionCount + >::apply(point, geometry); + } +}; + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t DimensionCount +> +struct assign_point_to_index + < + Geometry, Point, + Index, + DimensionCount, DimensionCount + > +{ + static inline void apply(Point const& , Geometry& ) + { + } +}; + + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t Dimension, std::size_t DimensionCount +> +struct assign_point_from_index +{ + + static inline void apply(Geometry const& geometry, Point& point) + { + geometry::set( point, boost::numeric_cast + < + typename coordinate_type::type + >(geometry::get(geometry))); + + assign_point_from_index + < + Geometry, Point, Index, Dimension + 1, DimensionCount + >::apply(geometry, point); + } +}; + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t DimensionCount +> +struct assign_point_from_index + < + Geometry, Point, + Index, + DimensionCount, DimensionCount + > +{ + static inline void apply(Geometry const&, Point&) + { + } +}; + + +template +struct assign_2d_box_or_segment +{ + typedef typename coordinate_type::type coordinate_type; + + // Here we assign 4 coordinates to a box of segment + // -> Most logical is: x1,y1,x2,y2 + // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED) + + template + static inline void apply(Geometry& geometry, + Type const& x1, Type const& y1, Type const& x2, Type const& y2) + { + geometry::set<0, 0>(geometry, boost::numeric_cast(x1)); + geometry::set<0, 1>(geometry, boost::numeric_cast(y1)); + geometry::set<1, 0>(geometry, boost::numeric_cast(x2)); + geometry::set<1, 1>(geometry, boost::numeric_cast(y2)); + } +}; + + +}} // namespace detail::assign +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct assign +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (types) + ); +}; + +template +struct assign +{ + typedef typename coordinate_type::type coordinate_type; + + template + static inline void apply(Point& point, T const& c1, T const& c2) + { + set<0>(point, boost::numeric_cast(c1)); + set<1>(point, boost::numeric_cast(c2)); + } +}; + +template +struct assign +{ + typedef typename coordinate_type::type coordinate_type; + + template + static inline void apply(Point& point, T const& c1, T const& c2, T const& c3) + { + set<0>(point, boost::numeric_cast(c1)); + set<1>(point, boost::numeric_cast(c2)); + set<2>(point, boost::numeric_cast(c3)); + } +}; + +template +struct assign + : detail::assign::assign_2d_box_or_segment +{}; + +template +struct assign + : detail::assign::assign_2d_box_or_segment +{}; + + + +template +struct assign_zero {}; + + +template +struct assign_zero + : detail::assign::assign_zero_point +{}; + +template +struct assign_zero + : detail::assign::assign_zero_box_or_segment +{}; + +template +struct assign_zero + : detail::assign::assign_zero_box_or_segment +{}; + + +template +struct assign_inverse {}; + +template +struct assign_inverse + : detail::assign::assign_inverse_box_or_segment +{}; + +template +struct assign_inverse + : detail::assign::assign_inverse_box_or_segment +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +/*! +\brief Assign two coordinates to a geometry (usually a 2D point) +\ingroup assign +\tparam Geometry \tparam_geometry +\tparam Type \tparam_numeric to specify the coordinates +\param geometry \param_geometry +\param c1 \param_x +\param c2 \param_y + +\qbk{distinguish, 2 coordinate values} +\qbk{ +[heading Example] +[assign_2d_point] [assign_2d_point_output] + +[heading See also] +\* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make] +} + */ +template +inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2) +{ + concept::check(); + + dispatch::assign + < + typename tag::type, + Geometry, + geometry::dimension::type::value + >::apply(geometry, c1, c2); +} + +/*! +\brief Assign three values to a geometry (usually a 3D point) +\ingroup assign +\tparam Geometry \tparam_geometry +\tparam Type \tparam_numeric to specify the coordinates +\param geometry \param_geometry +\param c1 \param_x +\param c2 \param_y +\param c3 \param_z + +\qbk{distinguish, 3 coordinate values} +\qbk{ +[heading Example] +[assign_3d_point] [assign_3d_point_output] + +[heading See also] +\* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make] +} + */ +template +inline void assign_values(Geometry& geometry, + Type const& c1, Type const& c2, Type const& c3) +{ + concept::check(); + + dispatch::assign + < + typename tag::type, + Geometry, + geometry::dimension::type::value + >::apply(geometry, c1, c2, c3); +} + +/*! +\brief Assign four values to a geometry (usually a box or segment) +\ingroup assign +\tparam Geometry \tparam_geometry +\tparam Type \tparam_numeric to specify the coordinates +\param geometry \param_geometry +\param c1 First coordinate (usually x1) +\param c2 Second coordinate (usually y1) +\param c3 Third coordinate (usually x2) +\param c4 Fourth coordinate (usually y2) + +\qbk{distinguish, 4 coordinate values} + */ +template +inline void assign_values(Geometry& geometry, + Type const& c1, Type const& c2, Type const& c3, Type const& c4) +{ + concept::check(); + + dispatch::assign + < + typename tag::type, + Geometry, + geometry::dimension::type::value + >::apply(geometry, c1, c2, c3, c4); +} + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP diff --git a/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp index 4c67dfe278..f38c50effa 100644 --- a/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp +++ b/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp @@ -162,7 +162,7 @@ struct box_collect_vectors { typename point_type::type lower_left, lower_right, upper_left, upper_right; - assign_box_corners(box, lower_left, lower_right, + geometry::detail::assign_box_corners(box, lower_left, lower_right, upper_left, upper_right); typedef typename boost::range_value::type item; diff --git a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp index b5bbab84c7..6e8a7f6c37 100644 --- a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -181,8 +181,8 @@ OutputIterator clip_range_with_box(Box const& b, Range const& range, ++previous, ++vertex) { point_type p1, p2; - geometry::detail::convert(*previous, p1); - geometry::detail::convert(*vertex, p2); + geometry::convert(*previous, p1); + geometry::convert(*vertex, p2); // Clip the segment. Five situations: // 1. Segment is invisible, finish line if any (shouldn't occur) diff --git a/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp index 4339080614..d81826f51e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp @@ -19,7 +19,7 @@ #include #include -#include +#include namespace boost { namespace geometry @@ -50,7 +50,7 @@ struct convert_ring { if (! append) { - geometry::detail::convert(source, destination); + geometry::convert(source, destination); if (reverse) { boost::reverse(destination); @@ -69,7 +69,7 @@ struct convert_ring { if (! append) { - geometry::detail::convert(source, exterior_ring(destination)); + geometry::convert(source, exterior_ring(destination)); if (reverse) { boost::reverse(exterior_ring(destination)); @@ -79,7 +79,7 @@ struct convert_ring { interior_rings(destination).resize( interior_rings(destination).size() + 1); - geometry::detail::convert(source, interior_rings(destination).back()); + geometry::convert(source, interior_rings(destination).back()); if (reverse) { boost::reverse(interior_rings(destination).back()); diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 927cefb515..ead7862801 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -71,7 +71,7 @@ struct copy_segment_point_range rview_type view(cview); - geometry::detail::convert(*(boost::begin(view) + index), point); + geometry::convert(*(boost::begin(view) + index), point); return true; } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index da7695e91e..4a0fdc952c 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -12,7 +12,7 @@ #include -#include +#include #include @@ -64,7 +64,7 @@ struct get_turn_without_info { TurnInfo tp; - geometry::detail::convert(result.template get<0>().intersections[i], tp.point); + geometry::convert(result.template get<0>().intersections[i], tp.point); *out++ = tp; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 74abdca0de..783a63bb1a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include @@ -94,7 +94,7 @@ struct touch_interior : public base_turn_handler DirInfo const& dir_info) { ti.method = method_touch_interior; - geometry::detail::convert(intersection_info.intersections[0], ti.point); + geometry::convert(intersection_info.intersections[0], ti.point); // Both segments of q touch segment p somewhere in its interior // 1) We know: if q comes from LEFT or RIGHT @@ -213,7 +213,7 @@ struct touch : public base_turn_handler DirInfo const& dir_info) { ti.method = method_touch; - geometry::detail::convert(intersection_info.intersections[0], ti.point); + geometry::convert(intersection_info.intersections[0], ti.point); int const side_qi_p1 = dir_info.sides.template get<1, 0>(); int const side_qk_p1 = SideStrategy::apply(pi, pj, qk); @@ -404,7 +404,7 @@ struct equal : public base_turn_handler { ti.method = method_equal; // Copy the SECOND intersection point - geometry::detail::convert(intersection_info.intersections[1], ti.point); + geometry::convert(intersection_info.intersections[1], ti.point); int const side_pk_q2 = SideStrategy::apply(qj, qk, pk); int const side_pk_p = SideStrategy::apply(pi, pj, pk); @@ -486,7 +486,7 @@ struct collinear : public base_turn_handler DirInfo const& dir_info) { ti.method = method_collinear; - geometry::detail::convert(intersection_info.intersections[1], ti.point); + geometry::convert(intersection_info.intersections[1], ti.point); int const arrival = dir_info.arrival[0]; // Should not be 0, this is checked before @@ -585,7 +585,7 @@ private : // If P arrives within Q, set info on P (which is done above, index=0), // this turn-info belongs to the second intersection point, index=1 // (see e.g. figure CLO1) - geometry::detail::convert(intersection_info.intersections[1 - Index], tp.point); + geometry::convert(intersection_info.intersections[1 - Index], tp.point); return true; } @@ -661,7 +661,7 @@ struct crosses : public base_turn_handler DirInfo const& dir_info) { ti.method = method_crosses; - geometry::detail::convert(intersection_info.intersections[0], ti.point); + geometry::convert(intersection_info.intersections[0], ti.point); // In all casees: // If Q crosses P from left to right diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 222e84fbcb..75d240bc2f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -65,7 +65,7 @@ struct intersection_segment_segment_point for (std::size_t i = 0; i < is.count; i++) { PointOut p; - geometry::detail::convert(is.intersections[i], p); + geometry::convert(is.intersections[i], p); *out++ = p; } return out; @@ -95,7 +95,7 @@ struct intersection_linestring_linestring_point it = boost::begin(turns); it != boost::end(turns); ++it) { PointOut p; - geometry::detail::convert(it->point, p); + geometry::convert(it->point, p); *out++ = p; } return out; diff --git a/include/boost/geometry/algorithms/detail/partition.hpp b/include/boost/geometry/algorithms/detail/partition.hpp index 3fbd98b773..59bdad7064 100644 --- a/include/boost/geometry/algorithms/detail/partition.hpp +++ b/include/boost/geometry/algorithms/detail/partition.hpp @@ -10,6 +10,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP #include +#include #include #include diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 775e8582e4..52cf158667 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -461,8 +461,10 @@ struct sectionalize_box // (or polygon would be a helper-type). // Therefore we mimic a linestring/std::vector of 5 points + // TODO: might be replaced by assign_box_corners_oriented + // or just "convert" point_type ll, lr, ul, ur; - assign_box_corners(box, ll, lr, ul, ur); + geometry::detail::assign_box_corners(box, ll, lr, ul, ur); std::vector points; points.push_back(ll); diff --git a/include/boost/geometry/algorithms/distance.hpp b/include/boost/geometry/algorithms/distance.hpp index f2b6c7a9ca..c28d4a6c0e 100644 --- a/include/boost/geometry/algorithms/distance.hpp +++ b/include/boost/geometry/algorithms/distance.hpp @@ -78,8 +78,8 @@ struct point_to_segment >::type segment_strategy; typename point_type::type p[2]; - geometry::assign_point_from_index<0>(segment, p[0]); - geometry::assign_point_from_index<1>(segment, p[1]); + geometry::detail::assign_point_from_index<0>(segment, p[0]); + geometry::detail::assign_point_from_index<1>(segment, p[1]); return segment_strategy.apply(point, p[0], p[1]); } }; @@ -419,8 +419,8 @@ struct distance { typename point_type::type p[2]; - geometry::assign_point_from_index<0>(segment, p[0]); - geometry::assign_point_from_index<1>(segment, p[1]); + geometry::detail::assign_point_from_index<0>(segment, p[0]); + geometry::detail::assign_point_from_index<1>(segment, p[1]); return strategy.apply(point, p[0], p[1]); } }; @@ -523,12 +523,14 @@ inline typename strategy::distance::services::return_type::type distan /*! \brief \brief_calc2{distance} \ingroup distance -\details The default strategy is used, belonging to the corresponding coordinate system of the geometries +\details The default strategy is used, corresponding to the coordinate system of the geometries \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry \param geometry2 \param_geometry \return \return_calc{distance} + +\qbk{[include reference/algorithms/distance.qbk]} */ template inline typename default_distance_result::type distance( diff --git a/include/boost/geometry/algorithms/envelope.hpp b/include/boost/geometry/algorithms/envelope.hpp index 370812f556..0964affd1c 100644 --- a/include/boost/geometry/algorithms/envelope.hpp +++ b/include/boost/geometry/algorithms/envelope.hpp @@ -19,6 +19,7 @@ #include +#include #include #include #include diff --git a/include/boost/geometry/algorithms/equals.hpp b/include/boost/geometry/algorithms/equals.hpp index d80406327b..b42dbcf042 100644 --- a/include/boost/geometry/algorithms/equals.hpp +++ b/include/boost/geometry/algorithms/equals.hpp @@ -271,12 +271,20 @@ struct equals_reversed /*! \brief \brief_check{are spatially equal} +\details \details_check12{equals, is spatially equal}. Spatially equal means + that the same point set is included. A box can therefore be spatially equal + to a ring or a polygon, or a linestring can be spatially equal to a + multi-linestring or a segment. This only theoretically, not all combinations + are implemented yet. \ingroup equals \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry \param geometry2 \param_geometry -\return \return_check2{are spatially disjoint} +\return \return_check2{are spatially equal} + +\qbk{[include reference/algorithms/equals.qbk]} + */ template inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2) diff --git a/include/boost/geometry/algorithms/expand.hpp b/include/boost/geometry/algorithms/expand.hpp index 81217b23cc..7d4496b960 100644 --- a/include/boost/geometry/algorithms/expand.hpp +++ b/include/boost/geometry/algorithms/expand.hpp @@ -291,12 +291,14 @@ inline void expand(Box& box, Geometry const& geometry, /*! -\brief Expands a box using the extend (envelope) of another geometry (box, point) +\brief Expands a box using the bounding box (envelope) of another geometry (box, point) \ingroup expand \tparam Box type of the box \tparam Geometry \tparam_geometry -\param box box to expand another geometry with, might be changed -\param geometry \param_geometry +\param box box to be expanded using another geometry, mutable +\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box + +\qbk{[include reference/algorithms/expand.qbk]} */ template inline void expand(Box& box, Geometry const& geometry) diff --git a/include/boost/geometry/algorithms/length.hpp b/include/boost/geometry/algorithms/length.hpp index 434ea865fd..d01a1110d9 100644 --- a/include/boost/geometry/algorithms/length.hpp +++ b/include/boost/geometry/algorithms/length.hpp @@ -50,8 +50,8 @@ struct segment_length { typedef typename point_type::type point_type; point_type p1, p2; - assign_point_from_index<0>(segment, p1); - assign_point_from_index<1>(segment, p2); + geometry::detail::assign_point_from_index<0>(segment, p1); + geometry::detail::assign_point_from_index<1>(segment, p2); return strategy.apply(p1, p2); } }; diff --git a/include/boost/geometry/algorithms/make.hpp b/include/boost/geometry/algorithms/make.hpp index 06b962b1ad..8693f5dcf5 100644 --- a/include/boost/geometry/algorithms/make.hpp +++ b/include/boost/geometry/algorithms/make.hpp @@ -21,6 +21,40 @@ namespace boost { namespace geometry { +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace make +{ + +/*! +\brief Construct a geometry +\ingroup make +\tparam Geometry \tparam_geometry +\tparam Range \tparam_range_point +\param range \param_range_point +\return The constructed geometry, here: a linestring or a ring + +\qbk{distinguish, with a range} +\qbk{ +[heading Example] +[make_with_range] [make_with_range_output] + +[heading See also] +\* [link geometry.reference.algorithms.assign.assign_points assign] +} + */ +template +inline Geometry make_points(Range const& range) +{ + concept::check(); + + Geometry geometry; + geometry::append(geometry, range); + return geometry; +} + +}} // namespace detail::make +#endif // DOXYGEN_NO_DETAIL + /*! \brief Construct a geometry \ingroup make @@ -38,7 +72,7 @@ namespace boost { namespace geometry [make_2d_point] [make_2d_point_output] [heading See also] -\* [link geometry.reference.algorithms.assign.assign_3_2_coordinate_values assign] +\* [link geometry.reference.algorithms.assign.assign_values_3_2_coordinate_values assign] } */ template @@ -72,7 +106,7 @@ inline Geometry make(Type const& c1, Type const& c2) [make_3d_point] [make_3d_point_output] [heading See also] -\* [link geometry.reference.algorithms.assign.assign_4_3_coordinate_values assign] +\* [link geometry.reference.algorithms.assign.assign_values_4_3_coordinate_values assign] } */ template @@ -107,32 +141,6 @@ inline Geometry make(Type const& c1, Type const& c2, Type const& c3, Type const& -/*! -\brief Construct a geometry -\ingroup make -\tparam Geometry \tparam_geometry -\tparam Range \tparam_range_point -\param range \param_range_point -\return The constructed geometry, here: a linestring or a ring - -\qbk{distinguish, with a range} -\qbk{ -[heading Example] -[make_with_range] [make_with_range_output] - -[heading See also] -\* [link geometry.reference.algorithms.assign.assign_2_with_a_range assign] -} - */ -template -inline Geometry make(Range const& range) -{ - concept::check(); - - Geometry geometry; - append(geometry, range); - return geometry; -} /*! diff --git a/include/boost/geometry/algorithms/reverse.hpp b/include/boost/geometry/algorithms/reverse.hpp index b8cf28d8a2..3d208120b0 100644 --- a/include/boost/geometry/algorithms/reverse.hpp +++ b/include/boost/geometry/algorithms/reverse.hpp @@ -106,10 +106,15 @@ struct reverse /*! -\brief Reverses a geometry +\brief Reverses the points within a geometry +\details Generic function to reverse a geometry. It resembles the std::reverse + functionality, but it takes the geometry type into account. Only for a ring + or for a linestring it is the same as the std::reverse. \ingroup reverse \tparam Geometry \tparam_geometry \param geometry \param_geometry which will be reversed + +\qbk{[include reference/algorithms/reverse.qbk]} */ template inline void reverse(Geometry& geometry) diff --git a/include/boost/geometry/algorithms/simplify.hpp b/include/boost/geometry/algorithms/simplify.hpp index 21ba86432d..e6a75cc773 100644 --- a/include/boost/geometry/algorithms/simplify.hpp +++ b/include/boost/geometry/algorithms/simplify.hpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include @@ -181,7 +181,7 @@ struct simplify static inline void apply(Point const& point, Point& out, Distance const& max_distance, Strategy const& strategy) { - geometry::detail::convert(point, out); + geometry::convert(point, out); } }; diff --git a/include/boost/geometry/algorithms/transform.hpp b/include/boost/geometry/algorithms/transform.hpp index 47d142ad0f..eaec16e322 100644 --- a/include/boost/geometry/algorithms/transform.hpp +++ b/include/boost/geometry/algorithms/transform.hpp @@ -101,15 +101,15 @@ struct transform_box_or_segment typedef typename point_type::type point_type2; point_type1 source_point[2]; - assign_point_from_index<0>(source, source_point[0]); - assign_point_from_index<1>(source, source_point[1]); + geometry::detail::assign_point_from_index<0>(source, source_point[0]); + geometry::detail::assign_point_from_index<1>(source, source_point[1]); point_type2 target_point[2]; if (strategy.apply(source_point[0], target_point[0]) && strategy.apply(source_point[1], target_point[1])) { - assign_point_to_index<0>(target_point[0], target); - assign_point_to_index<1>(target_point[1], target); + geometry::detail::assign_point_to_index<0>(target_point[0], target); + geometry::detail::assign_point_to_index<1>(target_point[1], target); return true; } return false; @@ -289,14 +289,19 @@ struct transform /*! -\brief Transforms from one geometry to another geometry using a strategy +\brief Transforms from one geometry to another geometry \brief_strategy \ingroup transform \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry \tparam Strategy strategy \param geometry1 \param_geometry \param geometry2 \param_geometry -\param strategy the strategy to be used for transformation +\param strategy The strategy to be used for transformation +\return True if the transformation could be done + +\qbk{distinguish,with strategy} + +\qbk{[include reference/algorithms/transform_with_strategy.qbk]} */ template inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2, @@ -325,7 +330,9 @@ inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2, \tparam Geometry2 \tparam_geometry \param geometry1 \param_geometry \param geometry2 \param_geometry -\return true if the transformation could be done +\return True if the transformation could be done + +\qbk{[include reference/algorithms/transform.qbk]} */ template inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2) diff --git a/include/boost/geometry/algorithms/unique.hpp b/include/boost/geometry/algorithms/unique.hpp index 1f15f39d17..63c7357cbc 100644 --- a/include/boost/geometry/algorithms/unique.hpp +++ b/include/boost/geometry/algorithms/unique.hpp @@ -124,6 +124,8 @@ struct unique \details \details_calc{unique,minimal set (where duplicate consecutive points are removed)}. \tparam Geometry \tparam_geometry \param geometry \param_geometry which will be made unique + +\qbk{[include reference/algorithms/unique.qbk]} */ template inline void unique(Geometry& geometry) diff --git a/include/boost/geometry/arithmetic/arithmetic.hpp b/include/boost/geometry/arithmetic/arithmetic.hpp index 7afee3ff66..395a603b22 100644 --- a/include/boost/geometry/arithmetic/arithmetic.hpp +++ b/include/boost/geometry/arithmetic/arithmetic.hpp @@ -31,6 +31,7 @@ namespace boost { namespace geometry namespace detail { + template struct param { @@ -40,6 +41,7 @@ struct param >::param_type type; }; + template class Function> struct value_operation { @@ -74,11 +76,45 @@ struct point_operation } }; + +template +struct value_assignment +{ + C m_value; + + inline value_assignment(C const &value) + : m_value(value) + {} + + template + inline void apply(P& point) const + { + set(point, m_value); + } +}; + +template +struct point_assignment +{ + PointSrc const& m_source_point; + + inline point_assignment(PointSrc const& point) + : m_source_point(point) + {} + + template + inline void apply(PointDst& dest_point) const + { + set(dest_point, get(m_source_point)); + } +}; + + } // namespace detail #endif // DOXYGEN_NO_DETAIL /*! - \brief Adds a value to each coordinate of a point + \brief Adds the same value to each coordinate of a point \ingroup arithmetic \details \param p point @@ -110,7 +146,7 @@ inline void add_point(Point1& p1, Point2 const& p2) } /*! - \brief Subtracts a value to each coordinate of a point + \brief Subtracts the same value to each coordinate of a point \ingroup arithmetic \details \param p point @@ -142,7 +178,7 @@ inline void subtract_point(Point1& p1, Point2 const& p2) } /*! - \brief Multiplies each coordinate of a point by a value + \brief Multiplies each coordinate of a point by the same value \ingroup arithmetic \details \param p point @@ -159,7 +195,7 @@ inline void multiply_value(Point& p, typename detail::param::type value) /*! \brief Multiplies a point by another \ingroup arithmetic - \details The coordinates of the second point will be multiplied by those of the first point. + \details The coordinates of the first point will be multiplied by those of the second point. The second point is not modified. \param p1 first point \param p2 second point @@ -175,7 +211,7 @@ inline void multiply_point(Point1& p1, Point2 const& p2) } /*! - \brief Divides each coordinate of a point by a value + \brief Divides each coordinate of the same point by a value \ingroup arithmetic \details \param p point @@ -192,7 +228,7 @@ inline void divide_value(Point& p, typename detail::param::type value) /*! \brief Divides a point by another \ingroup arithmetic - \details The coordinates of the second point will be divided by those of the first point. + \details The coordinates of the first point will be divided by those of the second point. The second point is not modified. \param p1 first point \param p2 second point @@ -206,6 +242,40 @@ inline void divide_point(Point1& p1, Point2 const& p2) for_each_coordinate(p1, detail::point_operation(p2)); } +/*! + \brief Assign each coordinate of a point the same value + \ingroup arithmetic + \details + \param p point + \param value value to assign + */ +template +inline void assign_value(Point& p, typename detail::param::type value) +{ + BOOST_CONCEPT_ASSERT( (concept::Point) ); + + for_each_coordinate(p, detail::value_assignment::type>(value)); +} + +/*! + \brief Assign a point with another + \ingroup arithmetic + \details The coordinates of the first point will be assigned those of the second point. + The second point is not modified. + \param p1 first point + \param p2 second point + */ +template +inline void assign_point(Point1& p1, const Point2& p2) +{ + BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + + for_each_coordinate(p1, detail::point_assignment(p2)); +} + + }} // namespace boost::geometry + #endif // BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP diff --git a/include/boost/geometry/core/closure.hpp b/include/boost/geometry/core/closure.hpp index 858ac906dc..bb806b3aae 100644 --- a/include/boost/geometry/core/closure.hpp +++ b/include/boost/geometry/core/closure.hpp @@ -149,14 +149,11 @@ struct closure /*! -\brief Meta-function which defines closure of a geometry type +\brief \brief_meta{value, closure (clockwise\, counterclockwise), \meta_geometry_type} +\tparam Geometry \tparam_geometry \ingroup core -\details -\qbk{ -[heading See also] -[link geometry.reference.enumerations.order_selector The order_selector enumeration] -} +\qbk{[include reference/core/closure.qbk]} */ template struct closure diff --git a/include/boost/geometry/core/coordinate_dimension.hpp b/include/boost/geometry/core/coordinate_dimension.hpp index 8d7ebe3d0a..f9f9055ba3 100644 --- a/include/boost/geometry/core/coordinate_dimension.hpp +++ b/include/boost/geometry/core/coordinate_dimension.hpp @@ -22,7 +22,6 @@ #include #include -#include #include namespace boost { namespace geometry @@ -65,53 +64,56 @@ struct dimension : traits::dimension

box_type; + typedef bg::model::ring

ring_type; + typedef bg::model::polygon

polygon_type; + + P p; + bg::assign_values(p, 1, 2); + + box_type b; + bg::assign(b, p); + + BOOST_CHECK_CLOSE((bg::get<0, 0>(b)), 1.0, 0.001); + BOOST_CHECK_CLOSE((bg::get<0, 1>(b)), 2.0, 0.001); + BOOST_CHECK_CLOSE((bg::get<1, 0>(b)), 1.0, 0.001); + BOOST_CHECK_CLOSE((bg::get<1, 1>(b)), 2.0, 0.001); + + + bg::set(b, 1); + bg::set(b, 2); + bg::set(b, 3); + bg::set(b, 4); + + ring_type ring; + bg::assign(ring, b); + + //std::cout << bg::wkt(b) << std::endl; + //std::cout << bg::wkt(ring) << std::endl; + + typename boost::range_const_iterator::type it = ring.begin(); + BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001); + it++; + BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001); + it++; + BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001); + it++; + BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001); + it++; + BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001); + + BOOST_CHECK_EQUAL(ring.size(), 5u); + + + polygon_type polygon; + + bg::assign(polygon, ring); + BOOST_CHECK_EQUAL(bg::num_points(polygon), 5u); + + ring_type ring2; + bg::assign(ring2, polygon); + BOOST_CHECK_EQUAL(bg::num_points(ring2), 5u); +} + + template void test_assign_point_2d() { Point p; - bg::assign(p, 1, 2); + bg::assign_values(p, 1, 2); BOOST_CHECK(bg::get<0>(p) == 1); BOOST_CHECK(bg::get<1>(p) == 2); - bg::detail::assign::assign_value(p, 123); + bg::assign_value(p, 123); BOOST_CHECK(bg::get<0>(p) == 123); BOOST_CHECK(bg::get<1>(p) == 123); @@ -148,6 +209,10 @@ void test_assign_point_2d() BOOST_CHECK(bg::get<1>(p) == 0); } + + + + int test_main(int, char* []) { test_assign_point_3d(); @@ -165,6 +230,9 @@ int test_main(int, char* []) test_assign_point_2d >(); test_assign_point_2d >(); + test_assign_conversion >(); + + // Segment (currently) cannot handle array's because derived from std::pair test_assign_box_2d(); test_assign_box_2d(); diff --git a/test/algorithms/detail/convert.cpp b/test/algorithms/convert.cpp similarity index 92% rename from test/algorithms/detail/convert.cpp rename to test/algorithms/convert.cpp index 2c6d227d38..185aceb11f 100644 --- a/test/algorithms/detail/convert.cpp +++ b/test/algorithms/convert.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include @@ -32,10 +32,10 @@ void test_all() typedef bg::model::box

box_type; P p; - bg::assign(p, 1, 2); + bg::assign_values(p, 1, 2); box_type b; - bg::detail::convert(p, b); + bg::convert(p, b); BOOST_CHECK_CLOSE((bg::get<0, 0>(b)), 1.0, 0.001); BOOST_CHECK_CLOSE((bg::get<0, 1>(b)), 2.0, 0.001); @@ -59,7 +59,7 @@ void test_std() bg::set(b, 4); ring_type ring; - bg::detail::convert(b, ring); + bg::convert(b, ring); //std::cout << bg::wkt(b) << std::endl; //std::cout << bg::wkt(ring) << std::endl; @@ -85,10 +85,10 @@ void test_std() polygon_type polygon; - bg::detail::convert(ring, polygon); + bg::convert(ring, polygon); BOOST_CHECK_EQUAL(bg::num_points(polygon), 5u); - bg::detail::convert(polygon, ring); + bg::convert(polygon, ring); BOOST_CHECK_EQUAL(bg::num_points(ring), 5u); } diff --git a/test/algorithms/detail/convert.vcproj b/test/algorithms/convert.vcproj similarity index 92% rename from test/algorithms/detail/convert.vcproj rename to test/algorithms/convert.vcproj index b3a11404f5..c75bf0ee5e 100644 --- a/test/algorithms/detail/convert.vcproj +++ b/test/algorithms/convert.vcproj @@ -20,7 +20,7 @@ OutputDirectory="$(SolutionDir)$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)\convert" ConfigurationType="1" - InheritedPropertySheets="..\..\boost.vsprops;..\..\ttmath.vsprops" + InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops" CharacterSet="1" > @@ -114,7 +114,7 @@ /> -#include #include #include #include -#include -#include #include #include +#if defined(TEST_WITH_SVG) +# include +#endif + +#include +#include +#include +#include + template struct box_item @@ -214,6 +220,234 @@ void test_all() } +//------------------- higher volumes + +template +struct svg_visitor +{ + SvgMapper& m_mapper; + + svg_visitor(SvgMapper& mapper) + : m_mapper(mapper) + {} + + template + inline void apply(Box const& box, int level) + { + /* + std::string color("rgb(64,64,64)"); + switch(level) + { + case 0 : color = "rgb(255,0,0)"; break; + case 1 : color = "rgb(0,255,0)"; break; + case 2 : color = "rgb(0,0,255)"; break; + case 3 : color = "rgb(255,255,0)"; break; + case 4 : color = "rgb(255,0,255)"; break; + case 5 : color = "rgb(0,255,255)"; break; + case 6 : color = "rgb(255,128,0)"; break; + case 7 : color = "rgb(0,128,255)"; break; + } + std::ostringstream style; + style << "fill:none;stroke-width:" << (5.0 - level / 2.0) << ";stroke:" << color << ";"; + m_mapper.map(box, style.str()); + */ + m_mapper.map(box, "fill:none;stroke-width:2;stroke:rgb(0,0,0);"); + + } +}; + + + + +template +void fill_points(Collection& collection, int seed, int size, int count) +{ + typedef boost::minstd_rand base_generator_type; + + base_generator_type generator(seed); + + boost::uniform_int<> random_coordinate(0, size - 1); + boost::variate_generator > + coordinate_generator(generator, random_coordinate); + + std::set > included; + + int n = 0; + for (int i = 0; n < count && i < count*count; i++) + { + int x = coordinate_generator(); + int y = coordinate_generator(); + std::pair pair = std::make_pair(x, y); + if (included.find(pair) == included.end()) + { + included.insert(pair); + typename boost::range_value::type item; + item.x = x; + item.y = y; + collection.push_back(item); + n++; + } + } +} + +void test_many_points(int seed, int size, int count) +{ + bg::model::multi_point mp1, mp2; + + fill_points(mp1, seed, size, count); + fill_points(mp2, seed * 2, size, count); + + // Test equality in quadratic loop + int expected_count = 0; + BOOST_FOREACH(point_item const& item1, mp1) + { + BOOST_FOREACH(point_item const& item2, mp2) + { + if (bg::equals(item1, item2)) + { + expected_count++; + } + } + } + +#if defined(TEST_WITH_SVG) + std::ostringstream filename; + filename << "partition" << seed << ".svg"; + std::ofstream svg(filename.str().c_str()); + + bg::svg_mapper mapper(svg, 800, 800); + + { + point_item p; + p.x = -1; p.y = -1; mapper.add(p); + p.x = size + 1; p.y = size + 1; mapper.add(p); + } + + typedef svg_visitor > box_visitor_type; + box_visitor_type box_visitor(mapper); +#else + typedef bg::visit_no_policy box_visitor_type; + box_visitor_type box_visitor; +#endif + + point_visitor visitor; + bg::partition + < + bg::model::box, get_point, ovelaps_point, + box_visitor_type + >::apply(mp1, mp2, visitor, 2, box_visitor); + + BOOST_CHECK_EQUAL(visitor.count, expected_count); + +#if defined(TEST_WITH_SVG) + BOOST_FOREACH(point_item const& item, mp1) + { + mapper.map(item, "fill:rgb(255,128,0);stroke:rgb(0,0,100);stroke-width:1", 8); + } + BOOST_FOREACH(point_item const& item, mp2) + { + mapper.map(item, "fill:rgb(0,128,255);stroke:rgb(0,0,100);stroke-width:1", 4); + } +#endif +} + +template +void fill_boxes(Collection& collection, int seed, int size, int count) +{ + typedef boost::minstd_rand base_generator_type; + + base_generator_type generator(seed); + + boost::uniform_int<> random_coordinate(0, size * 10 - 1); + boost::variate_generator > + coordinate_generator(generator, random_coordinate); + + int n = 0; + for (int i = 0; n < count && i < count*count; i++) + { + int w = coordinate_generator() % 30; + int h = coordinate_generator() % 30; + if (w > 0 && h > 0) + { + int x = coordinate_generator(); + int y = coordinate_generator(); + if (x + w < size * 10 && y + h < size * 10) + { + typename boost::range_value::type item(n+1); + bg::assign_values(item.box, x / 10.0, y / 10.0, (x + w) / 10.0, (y + h) / 10.0); + collection.push_back(item); + n++; + } + } + } +} + + + +void test_many_boxes(int seed, int size, int count) +{ + typedef bg::model::box box_type; + std::vector > boxes; + + fill_boxes(boxes, seed, size, count); + + // Test equality in quadratic loop + int expected_count = 0; + double expected_area = 0.0; + BOOST_FOREACH(box_item const& item1, boxes) + { + BOOST_FOREACH(box_item const& item2, boxes) + { + if (item1.id < item2.id) + { + if (bg::intersects(item1.box, item2.box)) + { + box_type b; + bg::intersection(item1.box, item2.box, b); + expected_area += bg::area(b); + expected_count++; + } + } + } + } + + +#if defined(TEST_WITH_SVG) + std::ostringstream filename; + filename << "partition_box_" << seed << ".svg"; + std::ofstream svg(filename.str().c_str()); + + bg::svg_mapper mapper(svg, 800, 800); + + { + point_item p; + p.x = -1; p.y = -1; mapper.add(p); + p.x = size + 1; p.y = size + 1; mapper.add(p); + } + + BOOST_FOREACH(box_item const& item, boxes) + { + mapper.map(item.box, "opacity:0.6;fill:rgb(50,50,210);stroke:rgb(0,0,0);stroke-width:1"); + } + + typedef svg_visitor > partition_visitor_type; + partition_visitor_type partition_visitor(mapper); + + + box_visitor visitor; + bg::partition + < + box_type, get_box, ovelaps_box, + partition_visitor_type + >::apply(boxes, visitor, 2, partition_visitor); + + BOOST_CHECK_EQUAL(visitor.count, expected_count); + BOOST_CHECK_CLOSE(visitor.area, expected_area, 0.001); + +#endif +} + + @@ -221,5 +455,20 @@ int test_main( int , char* [] ) { test_all >(); + test_many_points(12345, 20, 40); + test_many_points(54321, 20, 60); + test_many_points(67890, 20, 80); + test_many_points(98765, 20, 100); + for (int i = 1; i < 10; i++) + { + test_many_points(i, 30, i * 20); + } + + test_many_boxes(12345, 20, 40); + for (int i = 1; i < 10; i++) + { + test_many_boxes(i, 20, i * 10); + } + return 0; } diff --git a/test/algorithms/intersection.cpp b/test/algorithms/intersection.cpp index 5a3bada286..5a7b2c6479 100644 --- a/test/algorithms/intersection.cpp +++ b/test/algorithms/intersection.cpp @@ -324,7 +324,7 @@ void test_pointer_version() p = new test::test_point_xy; p->x = 10; p->y = 10; ln.push_back(p); bg::model::box > box; - bg::assign(box, 2, 2, 8, 8); + bg::assign_values(box, 2, 2, 8, 8); typedef bg::model::linestring > output_type; std::vector clip; diff --git a/test/algorithms/make.cpp b/test/algorithms/make.cpp index 58a26c43f4..65b63fe9ea 100644 --- a/test/algorithms/make.cpp +++ b/test/algorithms/make.cpp @@ -62,7 +62,7 @@ void test_linestring_2d() T coors[][2] = {{1,2}, {3,4}}; - L line = bg::make(coors); + L line = bg::detail::make::make_points(coors); BOOST_CHECK_EQUAL(line.size(), 2u); } @@ -74,7 +74,7 @@ void test_linestring_3d() T coors[][3] = {{1,2,3}, {4,5,6}}; - L line = bg::make(coors); + L line = bg::detail::make::make_points(coors); BOOST_CHECK_EQUAL(line.size(), 2u); //std::cout << dsv(line) << std::endl; diff --git a/test/algorithms/transform.cpp b/test/algorithms/transform.cpp index e4d5bc9a71..af8ba28c7c 100644 --- a/test/algorithms/transform.cpp +++ b/test/algorithms/transform.cpp @@ -80,7 +80,7 @@ void test_transformations(double phi, double theta, double r) { typedef bg::model::point > spherical_type; spherical_type sph1; - assign(sph1, phi, theta, r); + assign_values(sph1, phi, theta, r); BOOST_CHECK(transform(sph1, p)); spherical_type sph2; @@ -97,7 +97,7 @@ void test_transformations(double phi, double theta, double r) { typedef bg::model::point > spherical_type; spherical_type sph1, sph2; - assign(sph1, phi, theta); + assign_values(sph1, phi, theta); BOOST_CHECK(transform(sph1, p)); BOOST_CHECK(transform(p, sph2)); diff --git a/test/arithmetic/arithmetic.cpp b/test/arithmetic/arithmetic.cpp index 8ed3cd8d1e..1ae1915f4a 100644 --- a/test/arithmetic/arithmetic.cpp +++ b/test/arithmetic/arithmetic.cpp @@ -30,14 +30,14 @@ template void test_addition() { P p1; - bg::assign(p1, 1, 2, 3); + bg::assign_values(p1, 1, 2, 3); bg::add_value(p1, 10); BOOST_CHECK(bg::get<0>(p1) == 11); BOOST_CHECK(bg::get<1>(p1) == 12); BOOST_CHECK(bg::get<2>(p1) == 13); P p2; - bg::assign(p2, 4, 5, 6); + bg::assign_values(p2, 4, 5, 6); bg::add_point(p1, p2); BOOST_CHECK(bg::get<0>(p1) == 15); BOOST_CHECK(bg::get<1>(p1) == 17); @@ -48,14 +48,14 @@ template void test_subtraction() { P p1; - bg::assign(p1, 1, 2, 3); + bg::assign_values(p1, 1, 2, 3); bg::subtract_value(p1, 10); BOOST_CHECK(bg::get<0>(p1) == -9); BOOST_CHECK(bg::get<1>(p1) == -8); BOOST_CHECK(bg::get<2>(p1) == -7); P p2; - bg::assign(p2, 4, 6, 8); + bg::assign_values(p2, 4, 6, 8); bg::subtract_point(p1, p2); BOOST_CHECK(bg::get<0>(p1) == -13); BOOST_CHECK(bg::get<1>(p1) == -14); @@ -66,14 +66,14 @@ template void test_multiplication() { P p1; - bg::assign(p1, 1, 2, 3); + bg::assign_values(p1, 1, 2, 3); bg::multiply_value(p1, 5); BOOST_CHECK(bg::get<0>(p1) == 5); BOOST_CHECK(bg::get<1>(p1) == 10); BOOST_CHECK(bg::get<2>(p1) == 15); P p2; - bg::assign(p2, 4, 5, 6); + bg::assign_values(p2, 4, 5, 6); bg::multiply_point(p1, p2); BOOST_CHECK(bg::get<0>(p1) == 20); BOOST_CHECK(bg::get<1>(p1) == 50); @@ -84,20 +84,37 @@ template void test_division() { P p1; - bg::assign(p1, 50, 100, 150); + bg::assign_values(p1, 50, 100, 150); bg::divide_value(p1, 5); BOOST_CHECK(bg::get<0>(p1) == 10); BOOST_CHECK(bg::get<1>(p1) == 20); BOOST_CHECK(bg::get<2>(p1) == 30); P p2; - bg::assign(p2, 2, 4, 6); + bg::assign_values(p2, 2, 4, 6); bg::divide_point(p1, p2); BOOST_CHECK(bg::get<0>(p1) == 5); BOOST_CHECK(bg::get<1>(p1) == 5); BOOST_CHECK(bg::get<2>(p1) == 5); } +template +void test_assign() +{ + P p1; + P p2; + bg::assign_values(p1, 12, 34, 56); + bg::assign_point(p2, p1); + BOOST_CHECK(bg::get<0>(p2) == 12); + BOOST_CHECK(bg::get<1>(p2) == 34); + BOOST_CHECK(bg::get<2>(p2) == 56); + + bg::assign_value(p2, 78); + BOOST_CHECK(bg::get<0>(p2) == 78); + BOOST_CHECK(bg::get<1>(p2) == 78); + BOOST_CHECK(bg::get<2>(p2) == 78); +} + template void test_all() @@ -106,6 +123,7 @@ void test_all() test_subtraction

(); test_multiplication

(); test_division

(); + test_assign

(); } diff --git a/test/arithmetic/dot_product.cpp b/test/arithmetic/dot_product.cpp index 806b104242..777124ca2f 100644 --- a/test/arithmetic/dot_product.cpp +++ b/test/arithmetic/dot_product.cpp @@ -30,9 +30,9 @@ template void test_all() { P p1; - bg::assign(p1, 1, 2, 3); + bg::assign_values(p1, 1, 2, 3); P p2; - bg::assign(p2, 4, 5, 6); + bg::assign_values(p2, 4, 5, 6); BOOST_CHECK(bg::dot_product(p1, p2) == 1*4 + 2*5 + 3*6); } diff --git a/test/compile_test.cpp b/test/compile_test.cpp deleted file mode 100644 index 31d02020e9..0000000000 --- a/test/compile_test.cpp +++ /dev/null @@ -1,220 +0,0 @@ -// TODO: OLD! - -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Copyright (c) 2007-2011 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) - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -template -struct modifying_functor -{ - double sum; - modifying_functor() : sum(0) - {} - inline void operator()(P& p) - { - p.x(1); - } - - inline void operator()(bg::segment

& s) - { - s.first.x(1); - } -}; - -template -struct const_functor -{ - double sum; - const_functor() : sum(0) - {} - inline void operator()(P const& p) - { - sum += p.x(); - } - - inline void operator()(bg::segment

const& s) - { - sum += s.first.x() - s.second.x(); - } -}; - -template class V> -void check_linestring() -{ - typedef bg::model::d2::point_xy P; - typedef bg::model::linestring line_type; - line_type line; - line.push_back(P(0,0)); - line.push_back(P(1,1)); - - typedef bg::multi_linestring multi_line_type; - multi_line_type multi; - multi.push_back(line); - - double len = bg::length(line); - len = bg::length(multi); - double d = bg::distance(P(0,1), line); - //d = bg::distance(P(0,1), multi); not defined yet! - - line_type simp; - bg::simplify(line, simp, 3); - multi_line_type simpm; - bg::simplify(multi, simpm, 3); - - typedef bg::model::box

box_type; - box_type box1; - bg::envelope(line, box1); - box_type box2; - bg::envelope(multi, box2); - - // FIXME: Where is output stream op for line/multi --mloskot - //std::stringstream out; - // out << line << std::endl; - //out << multi << std::endl; - - // For each, const - /* TODO: Fix for_each/functor - const_functor

cf; - std::for_each(line.begin(), line.end(), cf); - - const line_type& cl = line; - const multi_line_type& cm = multi; - - bg::for_each_point(cl, cf); - bg::for_each_point(cm, cf); - bg::for_each_segment(cl, cf); - bg::for_each_segment(cm, cf); - - // For each, modifying - modifying_functor

mf; - line_type& ml = line; - multi_line_type& mm = multi; - std::for_each(line.begin(), line.end(), mf); - bg::for_each_point(ml, mf); - bg::for_each_point(mm, mf); - bg::for_each_segment(ml, mf); - bg::for_each_segment(mm, mf); - */ - -} - -template -< - typename T, - template class VP, - template class VR -> -void check_polygon() -{ - typedef bg::model::d2::point_xy P; - typedef bg::model::polygon Y; - Y poly; - poly.outer().push_back(P(0,0)); - poly.outer().push_back(P(2,0)); - poly.outer().push_back(P(2,2)); - poly.outer().push_back(P(0,2)); - - bg::correct(poly); - - // multi - typedef bg::multi_polygon MY; - MY multi; - multi.push_back(poly); - - double a = bg::area(poly); - a = bg::area(multi); - - //double d = bg::distance(P(0,1), poly); - - Y simp; - bg::simplify(poly, simp, 3); - MY msimp; - bg::simplify(multi, msimp, 3); - - typedef bg::model::box

box_type; - box_type box1; - bg::envelope(poly, box1); - box_type box2; - bg::envelope(multi, box2); - - P ctr; - bg::centroid(poly, ctr); - - // within - bg::model::d2::point_xy circ_centre(10,10); - - bool w = bg::within(P(1, 1), poly); - //w = bg::within(poly, b); tbd - w = bg::within(P(1, 1), multi); - - //bg::circle circ(circ_centre, 10); - //w = bg::within(poly, circ); - //w = bg::within(multi, circ); - //w = bg::within(multi, b); tbd - - // For each, const - /* TODO: Fix for_each/functor - const_functor

cf; - std::for_each(poly.outer().begin(), poly.outer().end(), cf); - - const Y& cp = poly; - const MY& cm = multi; - - bg::for_each_point(cp, cf); - bg::for_each_point(cm, cf); - bg::for_each_segment(cp, cf); - bg::for_each_segment(cm, cf); - - // For each, modifying - modifying_functor

mf; - Y& mp = poly; - MY& mm = multi; - std::for_each(poly.outer().begin(), poly.outer().end(), mf); - bg::for_each_point(mp, mf); - bg::for_each_point(mm, mf); - bg::for_each_segment(mp, mf); - bg::for_each_segment(mm, mf); - */ -} - - -int main() -{ - check_linestring(); - check_linestring(); - check_linestring(); - check_linestring(); - - //check_linestring(); - check_linestring(); - - check_polygon(); - check_polygon(); - check_polygon(); - check_polygon(); - - //check_polygon(); - check_polygon(); - //check_polygon(); - check_polygon(); - - return 0; -} - diff --git a/test/compile_test.sln b/test/compile_test.sln deleted file mode 100644 index 761a5e9825..0000000000 --- a/test/compile_test.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compile_test", "compile_test.vcproj", "{618D4B05-A06E-443B-87C0-94964CEA7164}" - ProjectSection(ProjectDependencies) = postProject - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A} = {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ggl_headers", "ggl_headers.vcproj", "{B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {618D4B05-A06E-443B-87C0-94964CEA7164}.Debug|Win32.ActiveCfg = Debug|Win32 - {618D4B05-A06E-443B-87C0-94964CEA7164}.Debug|Win32.Build.0 = Debug|Win32 - {618D4B05-A06E-443B-87C0-94964CEA7164}.Release|Win32.ActiveCfg = Release|Win32 - {618D4B05-A06E-443B-87C0-94964CEA7164}.Release|Win32.Build.0 = Release|Win32 - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Debug|Win32.ActiveCfg = Debug|Win32 - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Debug|Win32.Build.0 = Debug|Win32 - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Release|Win32.ActiveCfg = Release|Win32 - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/test/compile_test.vcproj b/test/compile_test.vcproj deleted file mode 100644 index 9686952a21..0000000000 --- a/test/compile_test.vcproj +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom_tests.sln b/test/custom_tests.sln deleted file mode 100644 index b9262d093f..0000000000 --- a/test/custom_tests.sln +++ /dev/null @@ -1,37 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "point_concept_well_formed_point", "point_concept\well_formed_point.vcproj", "{B63710DE-960E-4C00-B79A-7C8F80D6BC15}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "point_concept_well_formed_point_traits", "point_concept\well_formed_point_traits.vcproj", "{4F767915-5FC0-4BEB-8948-F371896BBD59}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "point_concept_array_point", "point_concept\array_point.vcproj", "{436E02F5-A4E6-40F8-8E41-57560875D67F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "point_concept_point_with_incorrect_coord_count", "point_concept\point_with_incorrect_coord_count.vcproj", "{B696EDCA-4602-4962-8A1C-043B3F44B978}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Debug|Win32.ActiveCfg = Debug|Win32 - {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Debug|Win32.Build.0 = Debug|Win32 - {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Release|Win32.ActiveCfg = Release|Win32 - {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Release|Win32.Build.0 = Release|Win32 - {4F767915-5FC0-4BEB-8948-F371896BBD59}.Debug|Win32.ActiveCfg = Debug|Win32 - {4F767915-5FC0-4BEB-8948-F371896BBD59}.Debug|Win32.Build.0 = Debug|Win32 - {4F767915-5FC0-4BEB-8948-F371896BBD59}.Release|Win32.ActiveCfg = Release|Win32 - {4F767915-5FC0-4BEB-8948-F371896BBD59}.Release|Win32.Build.0 = Release|Win32 - {436E02F5-A4E6-40F8-8E41-57560875D67F}.Debug|Win32.ActiveCfg = Debug|Win32 - {436E02F5-A4E6-40F8-8E41-57560875D67F}.Debug|Win32.Build.0 = Debug|Win32 - {436E02F5-A4E6-40F8-8E41-57560875D67F}.Release|Win32.ActiveCfg = Release|Win32 - {436E02F5-A4E6-40F8-8E41-57560875D67F}.Release|Win32.Build.0 = Release|Win32 - {B696EDCA-4602-4962-8A1C-043B3F44B978}.Debug|Win32.ActiveCfg = Debug|Win32 - {B696EDCA-4602-4962-8A1C-043B3F44B978}.Debug|Win32.Build.0 = Debug|Win32 - {B696EDCA-4602-4962-8A1C-043B3F44B978}.Release|Win32.ActiveCfg = Release|Win32 - {B696EDCA-4602-4962-8A1C-043B3F44B978}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/test/geometries/boost_polygon.cpp b/test/geometries/boost_polygon.cpp index 95f72b3e54..b8c614b0ec 100644 --- a/test/geometries/boost_polygon.cpp +++ b/test/geometries/boost_polygon.cpp @@ -77,8 +77,8 @@ void test_coordinate_type() boost::polygon::rectangle_data boost_polygon_box; bg::model::box boost_geometry_box; - bg::assign(boost_polygon_box, 0, 1, 5, 6); - bg::assign(boost_geometry_box, 0, 1, 5, 6); + bg::assign_values(boost_polygon_box, 0, 1, 5, 6); + bg::assign_values(boost_geometry_box, 0, 1, 5, 6); T boost_polygon_area = bg::area(boost_polygon_box); T boost_geometry_area = bg::area(boost_geometry_box); T boost_polygon_area_by_boost_polygon = boost::polygon::area(boost_polygon_box); diff --git a/test/geometries/box.cpp b/test/geometries/box.cpp index 17e89a9ba4..44a9a012f9 100644 --- a/test/geometries/box.cpp +++ b/test/geometries/box.cpp @@ -30,8 +30,8 @@ bg::model::box

create_box() { P p1; P p2; - bg::assign(p1, 1, 2, 5); - bg::assign(p2, 3, 4, 6); + bg::assign_values(p1, 1, 2, 5); + bg::assign_values(p2, 3, 4, 6); return bg::model::box

(p1, p2); } diff --git a/test/ggl_headers.sln b/test/ggl_headers.sln deleted file mode 100644 index efd7ebbc3a..0000000000 --- a/test/ggl_headers.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ggl_headers", "ggl_headers.vcproj", "{B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Debug|Win32.ActiveCfg = Debug|Win32 - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Debug|Win32.Build.0 = Debug|Win32 - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Release|Win32.ActiveCfg = Release|Win32 - {B3B37654-5AB4-49F3-A1D3-DFDE73EA5E1A}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/test/ggl_headers.vcproj b/test/ggl_headers.vcproj deleted file mode 100644 index a13b94483d..0000000000 --- a/test/ggl_headers.vcproj +++ /dev/null @@ -1,1339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/strategies/cross_track.cpp b/test/strategies/cross_track.cpp index ac43c1bb26..f53f6255b9 100644 --- a/test/strategies/cross_track.cpp +++ b/test/strategies/cross_track.cpp @@ -60,9 +60,9 @@ void test_distance( Point p1, p2, p3; - bg::assign(p1, lon1, lat1); - bg::assign(p2, lon2, lat2); - bg::assign(p3, lon3, lat3); + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + bg::assign_values(p3, lon3, lat3); strategy_type strategy; diff --git a/test/strategies/haversine.cpp b/test/strategies/haversine.cpp index 432602cd8f..3ad5458780 100644 --- a/test/strategies/haversine.cpp +++ b/test/strategies/haversine.cpp @@ -60,8 +60,8 @@ struct test_distance haversine_type strategy(radius); Point p1, p2; - bg::assign(p1, lon1, lat1); - bg::assign(p2, lon2, lat2); + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); return_type d = strategy.apply(p1, p2); BOOST_CHECK_CLOSE(d, expected, tolerance); @@ -102,10 +102,10 @@ void test_services() } P1 p1; - bg::assign(p1, 4, 52); + bg::assign_values(p1, 4, 52); P2 p2; - bg::assign(p2, 2, 48); + bg::assign_values(p2, 2, 48); // ~ Amsterdam/Paris, 467 kilometers double const km = 1000.0; @@ -177,8 +177,8 @@ void time_compare_s(int const n) { boost::timer t; P p1, p2; - bg::assign(p1, 1, 1); - bg::assign(p2, 2, 2); + bg::assign_values(p1, 1, 1); + bg::assign_values(p2, 2, 2); Strategy strategy; typename Strategy::return_type s = 0; for (int i = 0; i < n; i++) diff --git a/test/strategies/projected_point.cpp b/test/strategies/projected_point.cpp index 86fe161906..7ad1e91fb4 100644 --- a/test/strategies/projected_point.cpp +++ b/test/strategies/projected_point.cpp @@ -36,11 +36,11 @@ template void test_services() { PS p1, p2; - bg::assign(p1, 0, 0); - bg::assign(p2, 0, 4); + bg::assign_values(p1, 0, 0); + bg::assign_values(p2, 0, 4); P p; - bg::assign(p, 2, 0); + bg::assign_values(p, 2, 0); CalculationType const sqr_expected = 4; CalculationType const expected = 2; diff --git a/test/strategies/pythagoras.cpp b/test/strategies/pythagoras.cpp index 2b022fdfa6..204386422b 100644 --- a/test/strategies/pythagoras.cpp +++ b/test/strategies/pythagoras.cpp @@ -45,9 +45,9 @@ template void test_null_distance_3d() { P1 p1; - bg::assign(p1, 1, 2, 3); + bg::assign_values(p1, 1, 2, 3); P2 p2; - bg::assign(p2, 1, 2, 3); + bg::assign_values(p2, 1, 2, 3); typedef bg::strategy::distance::pythagoras pythagoras_type; typedef typename bg::strategy::distance::services::return_type::type return_type; @@ -62,9 +62,9 @@ template void test_axis_3d() { P1 p1; - bg::assign(p1, 0, 0, 0); + bg::assign_values(p1, 0, 0, 0); P2 p2; - bg::assign(p2, 1, 0, 0); + bg::assign_values(p2, 1, 0, 0); typedef bg::strategy::distance::pythagoras pythagoras_type; typedef typename bg::strategy::distance::services::return_type::type return_type; @@ -74,11 +74,11 @@ void test_axis_3d() return_type result = pythagoras.apply(p1, p2); BOOST_CHECK_EQUAL(result, return_type(1)); - bg::assign(p2, 0, 1, 0); + bg::assign_values(p2, 0, 1, 0); result = pythagoras.apply(p1, p2); BOOST_CHECK_EQUAL(result, return_type(1)); - bg::assign(p2, 0, 0, 1); + bg::assign_values(p2, 0, 0, 1); result = pythagoras.apply(p1, p2); BOOST_CHECK_CLOSE(result, return_type(1), 0.001); } @@ -87,9 +87,9 @@ template void test_arbitrary_3d() { P1 p1; - bg::assign(p1, 1, 2, 3); + bg::assign_values(p1, 1, 2, 3); P2 p2; - bg::assign(p2, 9, 8, 7); + bg::assign_values(p2, 9, 8, 7); { typedef bg::strategy::distance::pythagoras strategy_type; @@ -125,10 +125,10 @@ void test_services() P1 p1; - bg::assign(p1, 1, 2, 3); + bg::assign_values(p1, 1, 2, 3); P2 p2; - bg::assign(p2, 4, 5, 6); + bg::assign_values(p2, 4, 5, 6); double const sqr_expected = 3*3 + 3*3 + 3*3; // 27 double const expected = sqrt(sqr_expected); // sqrt(27)=5.1961524227 @@ -201,8 +201,8 @@ void test_big_2d_with(AssignType const& x1, AssignType const& y1, point_type p1, p2; - bg::assign(p1, x1, y1); - bg::assign(p2, x2, y2); + bg::assign_values(p1, x1, y1); + bg::assign_values(p2, x2, y2); return_type d = pythagoras.apply(p1, p2); /*** @@ -258,8 +258,8 @@ void time_compare_s(int const n) { boost::timer t; P p1, p2; - bg::assign(p1, 1, 1); - bg::assign(p2, 2, 2); + bg::assign_values(p1, 1, 1); + bg::assign_values(p2, 2, 2); Strategy strategy; typename bg::strategy::distance::services::return_type::type s = 0; for (int i = 0; i < n; i++) diff --git a/test/strategies/segment_intersection.cpp b/test/strategies/segment_intersection.cpp index ddf096f0e3..cbf40f2788 100644 --- a/test/strategies/segment_intersection.cpp +++ b/test/strategies/segment_intersection.cpp @@ -93,10 +93,10 @@ static void test_segment_intersection(int caseno, typedef segment segment_type; P p1, p2, p3, p4; - bg::assign(p1, x1, y1); - bg::assign(p2, x2, y2); - bg::assign(p3, x3, y3); - bg::assign(p4, x4, y4); + bg::assign_values(p1, x1, y1); + bg::assign_values(p2, x2, y2); + bg::assign_values(p3, x3, y3); + bg::assign_values(p4, x4, y4); segment_type s12(p1,p2); segment_type s34(p3,p4); diff --git a/test/strategies/segment_intersection_collinear.cpp b/test/strategies/segment_intersection_collinear.cpp index e2bc08e188..3c02f39adf 100644 --- a/test/strategies/segment_intersection_collinear.cpp +++ b/test/strategies/segment_intersection_collinear.cpp @@ -67,10 +67,10 @@ static void test_segment_intersection(std::string const& case_id, typedef bg::segment segment_type; P p1, p2, p3, p4; - bg::assign(p1, x1, y1); - bg::assign(p2, x2, y2); - bg::assign(p3, x3, y3); - bg::assign(p4, x4, y4); + bg::assign_values(p1, x1, y1); + bg::assign_values(p2, x2, y2); + bg::assign_values(p3, x3, y3); + bg::assign_values(p4, x4, y4); segment_type s12(p1,p2); segment_type s34(p3,p4); diff --git a/test/strategies/side_by_cross_track.cpp b/test/strategies/side_by_cross_track.cpp index 68c8c2495a..e02f3267d2 100644 --- a/test/strategies/side_by_cross_track.cpp +++ b/test/strategies/side_by_cross_track.cpp @@ -29,9 +29,9 @@ void test_side(double lon1, double lat1, typedef bg::strategy::side::side_by_cross_track strategy; Point p1, p2, p3; - bg::assign(p1, lon1, lat1); - bg::assign(p2, lon2, lat2); - bg::assign(p3, lon3, lat3); + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + bg::assign_values(p3, lon3, lat3); int s = strategy::apply(p1, p2, p3); } diff --git a/test/strategies/transformer.cpp b/test/strategies/transformer.cpp index c8467817b5..3826ce8238 100644 --- a/test/strategies/transformer.cpp +++ b/test/strategies/transformer.cpp @@ -46,7 +46,7 @@ template void test_all() { P p; - bg::assign(p, 1, 1); + bg::assign_values(p, 1, 1); { bg::strategy::transform::translate_transformer trans(1, 1); diff --git a/test/util/for_each_coordinate.cpp b/test/util/for_each_coordinate.cpp index 3187d3de1e..993c6a4d1c 100644 --- a/test/util/for_each_coordinate.cpp +++ b/test/util/for_each_coordinate.cpp @@ -55,7 +55,7 @@ template void test_all() { P p; - bg::assign(p, 1, 2, 3); + bg::assign_values(p, 1, 2, 3); bg::for_each_coordinate(p, test_operation()); BOOST_CHECK(bg::get<0>(p) == 10); BOOST_CHECK(bg::get<1>(p) == 20); From 26ecd9e57ad205380e6e03d2b459020bc47d7902 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 16 Apr 2011 23:26:32 +0000 Subject: [PATCH 015/135] Merged Boost.Geometry from revision 71123 to 71336 [SVN r71340] --- doc/reference/algorithms/clear.qbk | 35 ++++++++++++++ doc/reference/algorithms/expand.qbk | 32 +++++++++++++ doc/reference/algorithms/reverse.qbk | 38 +++++++++++++++ doc/reference/algorithms/unique.qbk | 37 ++++++++++++++ doc/src/examples/algorithms/reverse.cpp | 64 +++++++++++++++++++++++++ doc/src/examples/algorithms/unique.cpp | 38 +++++++++++++++ 6 files changed, 244 insertions(+) create mode 100644 doc/reference/algorithms/clear.qbk create mode 100644 doc/reference/algorithms/expand.qbk create mode 100644 doc/reference/algorithms/reverse.qbk create mode 100644 doc/reference/algorithms/unique.qbk create mode 100644 doc/src/examples/algorithms/reverse.cpp create mode 100644 doc/src/examples/algorithms/unique.cpp diff --git a/doc/reference/algorithms/clear.qbk b/doc/reference/algorithms/clear.qbk new file mode 100644 index 0000000000..6214528a04 --- /dev/null +++ b/doc/reference/algorithms/clear.qbk @@ -0,0 +1,35 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[def __is_cleared__ is cleared] + +[heading Behavior] +[table +[[Case] [Behavior] ] +[[__point__][__does_nothing__]] +[[__segment__][__does_nothing__]] +[[__box__][__does_nothing__]] +[[__linestring__][__linestring__ __is_cleared__]] +[[__ring__][__ring__ is cleared]] +[[__polygon__][The exterior ring __is_cleared__ and all interior rings are removed]] +[[__multi_point__][__multi_point__ __is_cleared__]] +[[__multi_linestring__][__multi_linestring__ __is_cleared__]] +[[__multi_polygon__][__multi_polygon__ __is_cleared__]] +] + +[heading Complexity] +Constant + +[heading Example] +[clear] +[clear_output] + diff --git a/doc/reference/algorithms/expand.qbk b/doc/reference/algorithms/expand.qbk new file mode 100644 index 0000000000..de146ae930 --- /dev/null +++ b/doc/reference/algorithms/expand.qbk @@ -0,0 +1,32 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[def __apply_expand__ Box is expanded to include the specified] + +[heading Behavior] +[table +[[Case] [Behavior] ] +[[__box__ / __point__][__apply_expand__ __point__]] +[[__box__ / __box__][__apply_expand__ __box__]] +[[__box__ / __other__][__nyiversion__]] +] + +[tip Expand is not defined within OGC or ISO] +[note To use expand with another geometry type then specified, use expand(make_envelope(geometry)] + +[heading Complexity] +Linear + +[heading Example] +[expand] +[expand_output] + diff --git a/doc/reference/algorithms/reverse.qbk b/doc/reference/algorithms/reverse.qbk new file mode 100644 index 0000000000..9e16585499 --- /dev/null +++ b/doc/reference/algorithms/reverse.qbk @@ -0,0 +1,38 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + + +[heading Behavior] +[table +[[Case] [Behavior] ] +[[__point__][__does_nothing__]] +[[__segment__][__nyiversion__]] +[[__box__][__does_nothing__]] +[[__linestring__][Reverses the __linestring__]] +[[__ring__][Reverses the __ring__]] +[[__polygon__][Reverses the exterior ring and all interior rings in the polygon]] +[[__multi_point__][__does_nothing__]] +[[__multi_linestring__][Reverses all contained linestrings individually]] +[[__multi_polygon__][Reverses all contained polygons individually]] +] + +[note The reverse of a (multi)polygon or ring might make a valid geometry invalid because the (counter)clockwise orientation reverses.] + +[tip Conforms to std::reverse functionality. It is not defined within OGC or ISO] + +[heading Complexity] +Linear + +[heading Example] +[reverse] +[reverse_output] + diff --git a/doc/reference/algorithms/unique.qbk b/doc/reference/algorithms/unique.qbk new file mode 100644 index 0000000000..955de48beb --- /dev/null +++ b/doc/reference/algorithms/unique.qbk @@ -0,0 +1,37 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[def __applies_unique__ Removes all consecutive duplicate points] + +[heading Behavior] +[table +[[Case] [Behavior] ] +[[__point__][__does_nothing__]] +[[__segment__][__does_nothing__]] +[[__box__][__does_nothing__]] +[[__linestring__][__applies_unique__]] +[[__ring__][__applies_unique__]] +[[__polygon__][__applies_unique__ in all rings]] +[[__multi_point__][__does_nothing__. Even if two equal points happen to be stored consecutively, they are kept]] +[[__multi_linestring__][__applies_unique__ in all contained linestrings]] +[[__multi_polygon__][__applies_unique__ in all contained polygons (all rings)]] +] + +[tip Conforms to std::unique functionality. It is not defined within OGC or ISO] + +[heading Complexity] +Linear + +[heading Example] +[unique] +[unique_output] + diff --git a/doc/src/examples/algorithms/reverse.cpp b/doc/src/examples/algorithms/reverse.cpp new file mode 100644 index 0000000000..33fc690fcd --- /dev/null +++ b/doc/src/examples/algorithms/reverse.cpp @@ -0,0 +1,64 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[reverse +//` Shows how to reverse a ring or polygon + +#include + +#include +#include +#include + +#include + +int main() +{ + using boost::assign::tuple_list_of; + + typedef boost::tuple point; + typedef boost::geometry::model::polygon polygon; + typedef boost::geometry::model::ring ring; + + + polygon poly; + boost::geometry::exterior_ring(poly) = tuple_list_of(0, 0)(0, 9)(10, 10)(0, 0); + boost::geometry::interior_rings(poly).push_back(tuple_list_of(1, 2)(4, 6)(2, 8)(1, 2)); + + double area_before = boost::geometry::area(poly); + boost::geometry::reverse(poly); + double area_after = boost::geometry::area(poly); + std::cout << boost::geometry::dsv(poly) << std::endl; + std::cout << area_before << " -> " << area_after << std::endl; + + ring r = tuple_list_of(0, 0)(0, 9)(8, 8)(0, 0); + + area_before = boost::geometry::area(r); + boost::geometry::reverse(r); + area_after = boost::geometry::area(r); + std::cout << boost::geometry::dsv(r) << std::endl; + std::cout << area_before << " -> " << area_after << std::endl; + + return 0; +} + +//] + + +//[reverse_output +/*` +Output: +[pre +(((0, 0), (10, 10), (0, 9), (0, 0)), ((1, 2), (2, 8), (4, 6), (1, 2))) +38 -> -38 +((0, 0), (8, 8), (0, 9), (0, 0)) +36 -> -36 +] +*/ +//] diff --git a/doc/src/examples/algorithms/unique.cpp b/doc/src/examples/algorithms/unique.cpp new file mode 100644 index 0000000000..294e1cd986 --- /dev/null +++ b/doc/src/examples/algorithms/unique.cpp @@ -0,0 +1,38 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[unique +//` Shows how to make a so-called minimal set of a polygon by removing duplicate points + +#include + +#include +#include + +int main() +{ + boost::geometry::model::polygon > poly; + boost::geometry::read_wkt("POLYGON((0 0,0 0,0 5,5 5,5 5,5 5,5 0,5 0,0 0,0 0,0 0,0 0))", poly); + boost::geometry::unique(poly); + std::cout << boost::geometry::wkt(poly) << std::endl; + + return 0; +} + +//] + + +//[unique_output +/*` +Output: +[pre +POLYGON((0 0,0 5,5 5,5 0,0 0)) +] +*/ +//] From 5476006aa05cd68569cf43d223168ebc812e0a45 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 16 Apr 2011 23:39:53 +0000 Subject: [PATCH 016/135] Merged Boost.Geometry from revision 71123 to 71336 (doc non-recursive) [SVN r71341] --- doc/imports.qbk | 27 +++++++++++++++++++---- doc/make_qbk.py | 7 +++--- doc/quickref.xml | 38 ++++++++++++++++---------------- doc/reference.qbk | 56 ++++++++++++++--------------------------------- 4 files changed, 63 insertions(+), 65 deletions(-) diff --git a/doc/imports.qbk b/doc/imports.qbk index 788bc68d3d..208bb28d81 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -11,21 +11,25 @@ =============================================================================/] [import src/examples/quick_start.cpp] + [import src/examples/algorithms/area.cpp] [import src/examples/algorithms/area_with_strategy.cpp] [import src/examples/algorithms/append.cpp] +[import src/examples/algorithms/assign.cpp] [import src/examples/algorithms/assign_2d_point.cpp] [import src/examples/algorithms/assign_3d_point.cpp] -[import src/examples/algorithms/assign_box_corners.cpp] [import src/examples/algorithms/assign_inverse.cpp] -[import src/examples/algorithms/assign_with_range.cpp] -[import src/examples/algorithms/assign_point_to_index.cpp] -[import src/examples/algorithms/assign_point_from_index.cpp] +[import src/examples/algorithms/assign_points.cpp] [import src/examples/algorithms/clear.cpp] [import src/examples/algorithms/centroid.cpp] +[import src/examples/algorithms/comparable_distance.cpp] +[import src/examples/algorithms/convert.cpp] +[import src/examples/algorithms/convex_hull.cpp] +[import src/examples/algorithms/correct.cpp] [import src/examples/algorithms/distance.cpp] [import src/examples/algorithms/difference.cpp] [import src/examples/algorithms/envelope.cpp] +[import src/examples/algorithms/equals.cpp] [import src/examples/algorithms/expand.cpp] [import src/examples/algorithms/for_each_point.cpp] [import src/examples/algorithms/for_each_point_const.cpp] @@ -47,12 +51,27 @@ [import src/examples/algorithms/return_envelope.cpp] [import src/examples/algorithms/simplify.cpp] [import src/examples/algorithms/sym_difference.cpp] +[import src/examples/algorithms/transform.cpp] +[import src/examples/algorithms/transform_with_strategy.cpp] [import src/examples/algorithms/union.cpp] [import src/examples/algorithms/unique.cpp] [import src/examples/algorithms/within.cpp] + +[import src/examples/core/coordinate_type.cpp] +[import src/examples/core/coordinate_system.cpp] +[import src/examples/core/coordinate_dimension.cpp] +[import src/examples/core/point_order.cpp] +[import src/examples/core/closure.cpp] + [import src/examples/core/get_point.cpp] [import src/examples/core/get_box.cpp] [import src/examples/core/set_point.cpp] [import src/examples/core/set_box.cpp] +[import src/examples/core/degree_radian.cpp] + +[import src/examples/core/point_type.cpp] +[import src/examples/core/tag.cpp] +[import src/examples/core/tag_cast.cpp] + [import src/examples/geometries/point.cpp] [import src/examples/geometries/register/point.cpp] diff --git a/doc/make_qbk.py b/doc/make_qbk.py index 5401471b7d..c57c66b408 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -81,9 +81,10 @@ def cs_to_quickbook(section): coordinate_systems = ["cartesian", "geographic", "polar", "spherical"] core = ["closure", "coordinate_system", "coordinate_type", "cs_tag" - , "dimension", "exception", "geometry_id", "interior_type" - , "is_areal", "is_linear", "is_radian", "point_order" - , "point_type", "ring_type", "tag", "topological_dimension" ] + , "dimension", "exception", "interior_type" + , "degree", "radian" + , "is_radian", "point_order" + , "point_type", "ring_type", "tag", "tag_cast" ] exceptions = ["exception", "centroid_exception"]; diff --git a/doc/quickref.xml b/doc/quickref.xml index 268fcfaa5e..3241aba287 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -133,25 +133,17 @@ Metafunctions cs_tag + closure coordinate_type coordinate_system dimension - geometry_id interior_type - is_radian point_order point_type ring_type - tag - topological_dimension + tag_cast @@ -194,8 +186,8 @@ Numeric - max_corner - min_corner + max_corner + min_corner order_selector closure_selector @@ -203,8 +195,8 @@ Types - degree - radian + degree + radian @@ -298,12 +290,16 @@ Assign - assign - assign_box_corners + assign assign_inverse - assign_point_from_index - assign_point_to_index assign_zero + assign_points + assign_values ( + 2 + 3 + 4 + coordinate values) + @@ -315,6 +311,10 @@ clear + Convert + + convert + Convex Hull convex_hull @@ -387,7 +387,7 @@ Union - union + union Unique diff --git a/doc/reference.qbk b/doc/reference.qbk index 40d5ca87db..54cb12783c 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -52,9 +52,9 @@ [section:assign assign] [include generated/assign.qbk] [endsect] -[section:append append] +[/section:append append] [include generated/append.qbk] -[endsect] +[/endsect] [section:buffer buffer] @@ -65,25 +65,13 @@ [include generated/centroid.qbk] [endsect] -[section:clear clear] [include generated/clear.qbk] -[endsect] - -[section:convex_hull convex_hull] +[include generated/convert.qbk] [include generated/convex_hull.qbk] -[endsect] - [include generated/correct.qbk] - -[section:difference difference] [include generated/difference.qbk] -[endsect] - -[section:disjoint disjoint] [include generated/disjoint.qbk] -[endsect] - [section:distance distance] [include generated/distance.qbk] @@ -93,21 +81,16 @@ [include generated/envelope.qbk] [endsect] -[section:equals equals] [include generated/equals.qbk] -[endsect] - -[section:expand expand] [include generated/expand.qbk] -[endsect] [section:for_each for_each] [include generated/for_each.qbk] [endsect] -[section:intersection intersection] +[/section:intersection intersection] [include generated/intersection.qbk] -[endsect] +[/endsect] [section:intersects intersects] [include generated/intersects.qbk] @@ -126,9 +109,7 @@ [include generated/num_points.qbk] -[section:overlaps overlaps] [include generated/overlaps.qbk] -[endsect] [section:perimeter perimeter] [include generated/perimeter.qbk] @@ -140,18 +121,17 @@ [include generated/simplify.qbk] [endsect] -[section:sym_difference sym_difference] +[/section:sym_difference sym_difference] [include generated/sym_difference.qbk] -[endsect] +[/endsect] [section:transform transform] [include generated/transform.qbk] [endsect] - -[section:union union] +[/section:union union] [include generated/union.qbk] -[endsect] +[/endsect] [include generated/unique.qbk] @@ -161,13 +141,10 @@ [endsect] [/algorithms] - [section:arithmetic Arithmetic] [include generated/arithmetic.qbk] [endsect] - - [section:concepts Concepts] [include concept/point.qbk] [include concept/linestring.qbk] @@ -180,34 +157,35 @@ [include concept/segment.qbk] [endsect] [/concepts] +[section:constants Constants] +[include reference/core/min_corner.qbk] +[include reference/core/max_corner.qbk] +[endsect] + [section:cs Coordinate Systems] [include generated/cartesian.qbk] [include generated/spherical.qbk] [include generated/geographic.qbk] [endsect] [/coordinate systems] - - [section:core Core Metafunctions] [include generated/closure.qbk] [include generated/coordinate_system.qbk] [include generated/coordinate_type.qbk] [include generated/cs_tag.qbk] +[include generated/degree.qbk] [include generated/dimension.qbk] [include generated/exception.qbk] -[include generated/geometry_id.qbk] [include generated/interior_type.qbk] -[include generated/is_areal.qbk] -[include generated/is_linear.qbk] [include generated/is_radian.qbk] [include generated/point_order.qbk] [include generated/point_type.qbk] +[include generated/radian.qbk] [include generated/ring_type.qbk] [include generated/tag.qbk] -[include generated/topological_dimension.qbk] +[include generated/tag_cast.qbk] [endsect] [/core metafunctions] - [section:enumerations Enumerations] [include generated/enum.qbk] [endsect] From ea998cda966d6c7ced5a046a779228d37ece40b7 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 16 Apr 2011 23:45:24 +0000 Subject: [PATCH 017/135] Merged Boost.Geometry from revision 71338 through 71342 [SVN r71343] --- doc/generated/distance_status.qbk | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 doc/generated/distance_status.qbk diff --git a/doc/generated/distance_status.qbk b/doc/generated/distance_status.qbk new file mode 100644 index 0000000000..e9739e2343 --- /dev/null +++ b/doc/generated/distance_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[ ][Point][Segment][Box][Linestring][Ring][Polygon][MultiPoint][MultiLinestring][MultiPolygon]] +[[Point][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ]] +[[Segment][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Linestring][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ]] +[[Ring][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Polygon][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ]] +[[MultiPoint][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/ok.png ] ]] +[[MultiLinestring][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ]] +[[MultiPolygon][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png ] ][ [$img/ok.png ] ][ [$img/nyi.png] ]] +] From 996ab253cb16a9c3f71f33ded643f631df7d73af Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 8 May 2011 12:18:28 +0000 Subject: [PATCH 018/135] Merged updates for (small) changes for views/ranges/iterators (r71711 through r71812) [SVN r71815] --- doc/acknowledgments.qbk | 32 +++- doc/design_rationale.qbk | 133 ++++--------- doc/doxy/Doxyfile | 4 +- doc/geometry.qbk | 9 + doc/html/output_main.png | Bin 1289 -> 0 bytes doc/imports.qbk | 8 + doc/introduction.qbk | 30 +-- doc/make_qbk.py | 11 +- doc/quickref.xml | 29 ++- doc/quickstart.qbk | 78 +++++++- doc/reference.qbk | 8 +- .../geometries/adapted/boost_array.qbk | 2 +- .../geometries/adapted/boost_fusion.qbk | 2 +- .../geometries/adapted/boost_tuple.qbk | 2 +- doc/reference/geometries/adapted/c_array.qbk | 2 +- doc/src/examples/Jamfile.v2 | 4 + .../examples/geometries/register/Jamfile.v2 | 11 ++ .../geometries/register/linestring.cpp | 52 +++++ .../register/linestring_templated.cpp | 45 +++++ .../geometries/register/multi_linestring.cpp | 49 +++++ .../geometries/register/multi_point.cpp | 46 +++++ .../register/multi_point_templated.cpp | 46 +++++ .../geometries/register/multi_polygon.cpp | 49 +++++ doc/src/examples/geometries/register/ring.cpp | 49 +++++ .../geometries/register/ring_templated.cpp | 47 +++++ doc/src/examples/quick_start.cpp | 104 +++++----- doc/src/examples/views/Jamfile.v2 | 17 ++ doc/src/examples/views/box_view.cpp | 58 ++++++ doc/src/examples/views/segment_view.cpp | 57 ++++++ example/c04_a_custom_triangle_example.cpp | 5 +- example/c04_b_custom_triangle_example.cpp | 5 +- example/c06_custom_polygon_example.cpp | 8 +- example/c08_custom_non_std_example.cpp | 7 +- test/Jamfile.v2 | 1 - test/algorithms/convex_hull.cpp | 21 ++- .../detail/sections/range_by_section.cpp | 4 +- test/algorithms/within.cpp | 9 +- test/iterators/Jamfile.v2 | 3 - test/iterators/box_iterator.cpp | 54 ------ test/iterators/box_iterator.vcproj | 176 ----------------- test/iterators/circular_iterator.cpp | 113 ----------- test/iterators/circular_iterator.vcproj | 178 ------------------ test/iterators/iterators.sln | 24 --- test/iterators/segment_range_iterator.cpp | 52 ----- test/iterators/segment_range_iterator.vcproj | 176 ----------------- test/multi/algorithms/multi_convex_hull.cpp | 2 +- .../algorithms/overlay/multi_traverse.cpp | 2 +- test/util/as_range.cpp | 4 +- test/views/Jamfile.v2 | 2 + .../box_range.cpp => views/box_view.cpp} | 13 +- .../box_view.vcproj} | 10 +- .../segment_view.cpp} | 11 +- .../segment_view.vcproj} | 10 +- test/views/views.sln | 12 ++ 54 files changed, 845 insertions(+), 1041 deletions(-) delete mode 100644 doc/html/output_main.png create mode 100644 doc/src/examples/geometries/register/linestring.cpp create mode 100644 doc/src/examples/geometries/register/linestring_templated.cpp create mode 100644 doc/src/examples/geometries/register/multi_linestring.cpp create mode 100644 doc/src/examples/geometries/register/multi_point.cpp create mode 100644 doc/src/examples/geometries/register/multi_point_templated.cpp create mode 100644 doc/src/examples/geometries/register/multi_polygon.cpp create mode 100644 doc/src/examples/geometries/register/ring.cpp create mode 100644 doc/src/examples/geometries/register/ring_templated.cpp create mode 100644 doc/src/examples/views/Jamfile.v2 create mode 100644 doc/src/examples/views/box_view.cpp create mode 100644 doc/src/examples/views/segment_view.cpp delete mode 100644 test/iterators/box_iterator.cpp delete mode 100644 test/iterators/box_iterator.vcproj delete mode 100644 test/iterators/circular_iterator.cpp delete mode 100644 test/iterators/circular_iterator.vcproj delete mode 100644 test/iterators/segment_range_iterator.cpp delete mode 100644 test/iterators/segment_range_iterator.vcproj rename test/{ranges/box_range.cpp => views/box_view.cpp} (77%) rename test/{ranges/box_range.vcproj => views/box_view.vcproj} (94%) rename test/{ranges/segment_range.cpp => views/segment_view.cpp} (85%) rename test/{ranges/segment_range.vcproj => views/segment_view.vcproj} (93%) diff --git a/doc/acknowledgments.qbk b/doc/acknowledgments.qbk index 3678f49c5d..842f6c5204 100644 --- a/doc/acknowledgments.qbk +++ b/doc/acknowledgments.qbk @@ -12,15 +12,29 @@ [section Acknowledgments] -We like to thank all the people who helped in a way to develop this library. - -First of all we are grateful to Hartmut Kaiser for managing the formal review of this library. Hartmut was a very good review manager, who intervented when necessary and produced the review report quickly. He has also supported the library by subscribing to the GGL mailing list and participating actively on it. - -We thank the 14 reviewers of our library, reviewed from November 5, 2009 to November 22, 2009. Reviews have been written by: Brandon Kohn, Christophe Henry, Fabio Fracassi, Gordon Woodhull, Joachim Faulhaber, Jonathan Franklin, Jose, Lucanus Simonson, Michael Caisse, Michael Fawcett, Paul Bristow, Phil Endecott, Thomas Klimpel, Tom Brinkman - -We also thank all people who discussed on the list about Boost.Geometry, in preview stage or in review stage or after that. We cannot mention all those names, but we like to mention those who, sometimes with a short message, did have a major influence on our design: Dave Abrahams (for the hint on tag dispatching when we were lost in SFINAE), John Fem.... TODO (for the hint on the set of metafunctions for traits), and Mathias Gaunard (for the hint on ranges instead of iterators). - -Finally I (Barend) would like to thank my former employer, Geodan, I've worked there for 16 years, started a geographic library in 1995 which after a number of incarnations, redesigns, refactorings, previews, a review and even more refactorings have led to the now released Boost.Geometry. [/And with them I want to thank those who were initially involved in the library, Maarten Hilfering, Valik, Anne Blankert, and later on Sjoerd Schreuder, Steven Fruitier and Paul den Dulk.] +We like to thank all the people who helped to develop this library. + +First of all we are grateful to Hartmut Kaiser for managing the formal review +of this library. Hartmut is an excellent review manager, who intervented when +necessary and produced the review report quickly. + +We thank the 14 reviewers of our library, reviewed from November 5, 2009 to +November 22, 2009. Reviews have been written by: Brandon Kohn, Christophe +Henry, Fabio Fracassi, Gordon Woodhull, Joachim Faulhaber, Jonathan Franklin, +Jose, Lucanus Simonson, Michael Caisse, Michael Fawcett, Paul Bristow, Phil +Endecott, Thomas Klimpel, Tom Brinkman. + +We also thank all people who discussed on the mailing lists (either at boost, +or at osgeo) about __boost_geometry__, in preview stage, or in review stage, +or after that. + +Finally I (Barend) would like to thank my former employer, Geodan. They +allowed me to start a geographic library in 1995, which after a number of +incarnations, redesigns, refactorings, previews, a review and even more +refactorings have led to the now released __boost_geometry__. And with them I +want to thank the team initially involved in developing the library, Valik +Solorzano Barboza, Maarten Hilferink, Anne Blankert, and later Sjoerd +Schreuder, Steven Fruijtier, Paul den Dulk, and Joris Sierman. [endsect] diff --git a/doc/design_rationale.qbk b/doc/design_rationale.qbk index b718e89301..c659bee7e9 100644 --- a/doc/design_rationale.qbk +++ b/doc/design_rationale.qbk @@ -8,6 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] +[/ note the source code in this QBK is the only not (yet) checked by a compiler] + [section:design Design Rationale] Suppose you need a C++ program to calculate the distance between two points. @@ -27,9 +29,10 @@ and a function, containing the algorithm: return sqrt(dx * dx + dy * dy); } -Quite simple, and it is usable, but not generic. For a library it has to be designed way further. -The design above can only be used for 2D points, for the struct [*mypoint] (and no other struct), -in a __wiki_cs_cartesian__. A generic library should be able to calculate the distance: +Quite simple, and it is usable, but not generic. For a library it has to be +designed way further. The design above can only be used for 2D points, for the +struct [*mypoint] (and no other struct), in a Cartesian coordinate system. A +generic library should be able to calculate the distance: * for any point class or struct, not on just this [*mypoint] type * in more than two dimensions @@ -115,22 +118,6 @@ as shown in the distance algorithm at the start of this paragraph. So we wanted with methods like `x()`, and they are supported as long as there is a specialization of the access `struct` with a static `get` function returning `x()` for dimension 0, and similar for 1 and `y()`. -Alternatively we could implement, in the traits class, the dimension as a template parameter in -a member template function: - - template <> - struct access - { - template - static double get(mypoint const& p) - // either return x/y using an if-clause - // or call a detail-struct specialized - // per dimension - }; - -This alternative gives in the end the same functionality, either using an `if` statement (wihch -may be slower), or adding another level of indirection. - [heading Dimension Agnosticism] Now we can calculate the distance between points in 2D, points of any structure or class. @@ -159,7 +146,7 @@ more complex but attractive for template fans: } }; -The distance function is calling that [*pythagoras] structure, specifying the number of dimensions: +The distance function is calling that `pythagoras` structure, specifying the number of dimensions: template double distance(P1 const& a, P2 const& b) @@ -181,7 +168,8 @@ The dimension which is referred to is defined using another traits class: which has to be specialized again for the `struct mypoint`. -Because it only has to publish a value, we conveniently derive it from the __boost_mpl__ `class boost::mpl::int_`: +Because it only has to publish a value, we conveniently derive it from the +__boost_mpl__ `class boost::mpl::int_`: `` namespace traits @@ -233,7 +221,7 @@ A longer version is presented later on, the short function would look like this: struct coordinate_type : traits::coordinate_type

{}; We now can modify our distance algorithm again. Because it still returns double, we only -modify the [*pythagoras] computation class. It should return the coordinate type of its input. +modify the `pythagoras` computation class. It should return the coordinate type of its input. But, it has two input, possibly different, point types. They might also differ in their coordinate types. Not that that is very likely, but we’re designing a generic library and we should handle those strange cases. We have to choose one of the coordinate types and of course @@ -261,28 +249,30 @@ So our computation class becomes: [heading Different Geometries] -We’ve designed a dimension agnostic system supporting any point type of any coordinate type. -There are still some tweaks but they will be worked out later. Now we will see how we calculate -the distance between a point and a polygon, or between a point and a line-segment. These formulae -are more complex, and the influence on design is even larger. We don’t want to add a function -with another name: +We have designed a dimension agnostic system supporting any point type of any +coordinate type. There are still some tweaks but they will be worked out later. +Now we will see how we calculate the distance between a point and a polygon, or +between a point and a line-segment. These formulae are more complex, and the +influence on design is even larger. We don’t want to add a function with another +name: template double distance_point_segment(P const& p, S const& s) -We want to be generic, the distance function has to be called from code not knowing the type -of geometry it handles, so it has to be named distance. We also cannot create an overload because -that would be ambiguous, having the same template signature. There are two solutions: +We want to be generic, the distance function has to be called from code not +knowing the type of geometry it handles, so it has to be named distance. We also +cannot create an overload because that would be ambiguous, having the same +template signature. There are two solutions: * tag dispatching * SFINAE -We select tag dispatching because it fits into the traits system. The earlier versions (previews) of -Boost.Geometry used SFINAE but we found it had several drawbacks for such a big design, so the switch -to tag dispatching was made. +We select tag dispatching because it fits into the traits system. The earlier +versions (previews) of Boost.Geometry used SFINAE but we found it had several +drawbacks for such a big design, so the switch to tag dispatching was made. -With tag dispatching the distance algorithm inspects the type of geometry of the input parameters. The distance function will be changed -into this: +With tag dispatching the distance algorithm inspects the type of geometry of the +input parameters. The distance function will be changed into this: template double distance(G1 const& g1, G2 const& g2) @@ -489,7 +479,7 @@ systems. typedef pythagoras type; }; -So, here is our [*pythagoras] again, now defined as a strategy. The distance dispatch function just +So, here is our `pythagoras` again, now defined as a strategy. The distance dispatch function just calls its apply method. So this is an important step: for spherical or geographical coordinate systems, another @@ -582,7 +572,7 @@ concepts. This is handled in the upcoming section Concept Checking. We promised that calling `std::sqrt` was not always necessary. So we define a distance result `struct` that contains the squared value and is convertible to a double value. This, however, only has to -be done for [*pythagoras]. The spherical distance functions do not take the square root so for them +be done for `pythagoras`. The spherical distance functions do not take the square root so for them it is not necessary to avoid the expensive square root call; they can just return their distance. So the distance result struct is dependant on strategy, therefore made a member type of @@ -608,9 +598,9 @@ Each strategy should define its return type, within the strategy class, for exam or: - typedef double return_type + typedef double return_type; -for [*pythagoras] and spherical, respectively. +for cartesian (pythagoras) and spherical, respectively. Again our distance function will be modified, as expected, to reflect the new return type. For the overload with a strategy it is not complex: @@ -647,64 +637,15 @@ and modify our distance function: Of course also the apply functions in the dispatch specializations will return a result like this. They have a strategy as a template parameter everywhere, making the less verbose version possible. -[heading Reversibility] - -Our `dispatch::distance` class was specialized for <`point_tag`, `segment_tag`>. -Library users can also call the distance function with a segment and a point, in that order. -Actually, there are many geometry types (polygon, box, linestring), how to implement all those -without duplicating all tag dispatching functions? The answer is that we automatically -reverse the arguments, if appropriate. For distance it is appropriate because distance is a -commutative function. We add a meta-function `geometry_id`, which has specializations for each -geometry type, just derived from `boost::mpl::int_`, such that it can be ordered. Point is 1, -segment is e.g. 2. +[heading Summary] -Then we add a meta-function reverse_dispatch: +In this design rationale, __boost_geometry__ is step by step designed using tag dispatching, +concepts, traits, and metaprogramming. We used the well-known distance function +to show the design. - template - struct reverse_dispatch : detail::reverse_dispatch - < - geometry_id::type::value, - geometry_id::type::value - > - {}; - -Because of the order in geometry_id, we can arrange (template) parameters in that order, -in specializations. So the detail structure looks like: - - namespace detail - { - template - struct reverse_dispatch : boost::mpl::if_c - < - (Id1 > Id2), - boost::true_type, - boost::false_type - > - {}; - } - -and our distance function will be modified again with some template meta-programming: We get - - return boost::mpl::if_c - < - boost::geometry::reverse_dispatch ::type::value, - dispatch::distance_reversed - < - typename tag::type, - typename tag::type, - G1, G2, - // strategy - >, - dispatch::distance - < - typename tag::type, - typename tag::type, - G1, G2, - // strategy - > - >::type::apply(g1, g2, s); - -Where the `dispatch::distance_reversed` is a specific struct, forwarding its call to -`dispatch::distance`, reversing all its template arguments and function arguments. +__boost_geometry__ is designed like described here, with +some more techniques as automatically reversing template arguments, tag casting, +and reusing implementation classes or dispatch classes as policies in other +dispatch classes. [endsect] [/ end of section Design Rationale] diff --git a/doc/doxy/Doxyfile b/doc/doxy/Doxyfile index f1183a74e1..f6eda4d2c8 100644 --- a/doc/doxy/Doxyfile +++ b/doc/doxy/Doxyfile @@ -98,7 +98,7 @@ ALIASES = qbk{1}="\xmlonly \1 \endxmlonly" \ details_macro{2}="The macro \1 registers a \2 such that it is recognized by Boost.Geometry and that Boost.Geometry functionality can used with the specified type." \ details_macro_const="The const version registers only read access to the fields, the point type is therefore read-only" \ details_macro_getset="The get/set version registers get and set methods separately and can be used for classes with protected member variables and get/set methods to change coordinates" \ - details_macro_templated{1}="The type must have one template parameter, which should be a point type, and should not be specified. Boost.Geometry takes care of inserting the template parameter. Hence all types of this templated \1 are registered, regardless of their point type." \ + details_macro_templated{2}="The type must have one template parameter, which should be a \2 type, and should not be specified. Boost.Geometry takes care of inserting the template parameter. Hence all types of this templated \1 are registered, regardless of their point type." \ details_default_strategy="It uses the default strategy, based on the coordinate system of the geometry." \ details_strategy_reasons="Reasons to specify a strategy include: use another coordinate system for calculations; construct the strategy beforehand (e.g. with the radius of the Earth); select a strategy when there are more than one available for a calculation." \ details_return{1}="This version with the return_ prefix returns the \1, and a template parameter must therefore be specified in the call." \ @@ -190,12 +190,12 @@ INPUT = . .. ../../../../boost/geometry/core \ ../../../../boost/geometry/multi/algorithms/detail \ ../../../../boost/geometry/multi/core \ ../../../../boost/geometry/multi/geometries \ + ../../../../boost/geometry/multi/geometries/register \ ../../../../boost/geometry/multi/geometries/concepts \ ../../../../boost/geometry/multi/iterators \ ../../../../boost/geometry/multi/strategies/cartesian \ ../../../../boost/geometry/policies \ ../../../../boost/geometry/policies/relate \ - ../../../../boost/geometry/ranges \ ../../../../boost/geometry/strategies \ ../../../../boost/geometry/strategies/concepts \ ../../../../boost/geometry/strategies/agnostic \ diff --git a/doc/geometry.qbk b/doc/geometry.qbk index 4e2d304c0f..b42891feb4 100644 --- a/doc/geometry.qbk +++ b/doc/geometry.qbk @@ -66,8 +66,16 @@ All algorithms in Boost.Geometry will check any geometry arguments against the c [def __boost_geometry__ Boost.Geometry] +[def __boost_array__ Boost.Array] +[def __boost_fusion__ Boost.Fusion] +[def __boost_mpl__ Boost.MPL] +[def __boost_range__ Boost.Range] +[def __boost_tuple__ Boost.Tuple] [def __boost_gil__ [@http://www.boost.org/libs/gil/ Boost.GIL]] +[def __ttmath__ [@http://www.ttmath.org/ ttmath]] +[def __ogc__ [@http://www.opengeospatial.org OGC]] + [heading Contributions] Boost.Geometry contains contributions by: @@ -86,3 +94,4 @@ Boost.Geometry contains contributions by: [include matrix.qbk] [include reference.qbk] [include about_documentation.qbk] +[include acknowledgments.qbk] diff --git a/doc/html/output_main.png b/doc/html/output_main.png deleted file mode 100644 index 184ba5965ed321a90ed0f86d0ade58989a23b64c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1289 zcmV+k1@`)hP)-@00000000000000000000 z07UZBEPcP<`Jb=Xt0_>IKa9f;-YcEAPu>Lst)1@*L0lnBD= zl+rtQ=C_6V+=7`Z?Dlc#8IzYExXpHcmUV(Qo&x*gp68q7>wnkXJXY6?s!O(`2JDl9 z27Jn%HBAStE*I>{fPVlnV?H@2F?Eg|sM?z25?WT4;PXqt}0001hJ7DtX)3SK-YNFb6{&kJz4xL=DoGVc< zu&)6t(DUurMYe9c&3*?i$!tHy?PRAH_fMVkb4j=qK7_^RKMZ8EE@f%F`gyFo%r7zE z7MzrC-zzu9z$Rm6A+bHnbq%zCtUbbVx*78Hwm;UFDf0a67Yi#;^6d|d$>+_Wx)5)l zNul$OkYObudYY$r?djFy{XNh%-Z;PgsSS%z^6(0OY zq;K&XlgBgfwMvyw;+~dQ&#*sVSM9QAtx(;56ZY`d`SZl*A%NXi*9ZYWsI z&%BBg*nM({YX89c3jhGV8fl)7P0W~N(hsj^MVIpo@EA-vIhPLr@1B{Q|1-I31+X>k z+}mP|HFGEDvG3bQ`M_*$0r>Lmdr95N7IQj(A{8=-0lpJoPEIcxTx7ErbZREbHfq0MAC6=Y_lfo&C=PSw3(Gd3_Cg)y2YOkuL*q2c$7Ctc3HF&!R9#PINut z6)T1=Ktb>~Gt!zpa9L;X+2LB%hqoEvo=Exjy?3oYc=PaIhVRJ>SgKav-xlKVw~9>y z000000079i|6g4$fZy9=-aa$$7tFlJuGUM}?~eX``!pS6C(Ff)kmEEUU*|scW;6+2!Pa1l}9IrgdV>pQexL0p(I$lZGm$2Mh*Ce3Mu>)0Gh^;ruK0+Sh zz~a2O@iw!vm~R-|2mM`IOCNtGu_O+sLuQhmo+$k*u-K=N&xH&5_h05)mHOlP&h~^E z-0}Hd%DUiB3iDX{HxFOk7m(ZI@_UW>|FYk!%3JJXS7NbevaQusC4wsBRRC-W(;YmF zJ-%;$6-;XY0000000000000000000003h=l2)ci$KUeW100000NkvXXu0mjfsd|Sg diff --git a/doc/imports.qbk b/doc/imports.qbk index 675dd4be21..7f44713fda 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -93,5 +93,13 @@ [import src/examples/geometries/register/box_templated.cpp] [import src/examples/geometries/register/box_2d_4values.cpp] [import src/examples/geometries/register/point.cpp] +[import src/examples/geometries/register/linestring.cpp] +[import src/examples/geometries/register/linestring_templated.cpp] +[import src/examples/geometries/register/ring.cpp] +[import src/examples/geometries/register/ring_templated.cpp] +[import src/examples/geometries/register/multi_point.cpp] +[import src/examples/geometries/register/multi_point_templated.cpp] +[import src/examples/geometries/register/multi_linestring.cpp] +[import src/examples/geometries/register/multi_polygon.cpp] diff --git a/doc/introduction.qbk b/doc/introduction.qbk index c1a1552407..2669979465 100644 --- a/doc/introduction.qbk +++ b/doc/introduction.qbk @@ -15,15 +15,14 @@ __boost_geometry__ (aka Generic Geometry Library, GGL), part of collection of the Boost C++ Libraries, defines concepts, primitives and algorithms for solving -computational geometry problems. +geometry problems. __boost_geometry__ contains a dimension-agnostic, coordinate-system-agnostic -and scalable kernel, based on concepts, meta-functions and tag- dispatching. +and scalable kernel, based on concepts, meta-functions and tag dispatching. On top of that kernel, algorithms are built: area, length, perimeter, centroid, convex hull, intersection (clipping), within (point in polygon), distance, -envelope (bounding box), simplify, transform, convert, and more. -The library is also designed to support high precision arithmetic numbers, -such as __gmp__. +envelope (bounding box), simplify, transform, and much more. +The library supports high precision arithmetic numbers, such as __ttmath__. __boost_geometry__ contains instantiable geometry classes, but library users can also use their own. Using registration macros or traits classes their geometries @@ -32,11 +31,7 @@ can be adapted to fulfil __boost_geometry__ concepts. __boost_geometry__ might be used in all domains where geometry plays a role: mapping and GIS, game development, computer graphics and widgets, robotics, astronomy and more. The core is designed to be as generic as possible and support -those domains. However, for now the development has been mostly GIS-oriented. - -__boost_geometry__ supports the extension model, the same way as __boost_gil__ -also applies it. An extension is (mostly) something more specific to -like mentioned above. +those domains. For now, the development has been mostly GIS-oriented. The library follows existing conventions: @@ -44,9 +39,18 @@ The library follows existing conventions: * conventions from the std library * conventions and names from one of the __ogc__ standards on geometry -The library can be downloaded from the Boost Sandbox, go to the download page -for more information. +The library can be downloaded from [@http://svn.boost.org/svn/boost/trunk Boost.Trunk], +from [@http://svn.boost.org/svn/boost/branches/release Boost.Release], or will come +to you by the normal Boost distribution process. Note that [*extensions] are +only distributed in Boost.Trunk, and that they are subject to change. + +__boost_geometry__ was accepted by Boost at November 28, 2009 +([@http://permalink.gmane.org/gmane.comp.lib.boost.announce/246 review report]). -__boost_geometry__ bug tracker and Wiki are available at http://trac.osgeo.org/ggl/ +There are two mailing lists +where __boost_geometry__ is discussed: the boost developers list, and also the +[@http://lists.osgeo.org/mailman/listinfo/ggl GGL mailing list] at osgeo, at which, at the moment of writing, more than 70 people +are subscribed. The mailing list is also accessible from +[@http://boost-geometry.203548.n3.nabble.com/ Nabble] as Boost Geometry. [endsect] diff --git a/doc/make_qbk.py b/doc/make_qbk.py index c57c66b408..8cdcfc9195 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -88,14 +88,13 @@ def cs_to_quickbook(section): exceptions = ["exception", "centroid_exception"]; -iterators = ["box_iterator", "circular_iterator", "closing_iterator" - , "ever_circling_iterator", "segment_range_iterator"] +iterators = ["circular_iterator", "closing_iterator" + , "ever_circling_iterator"] models = ["point", "linestring", "box" , "polygon", "segment", "ring" , "multi_linestring", "multi_point", "multi_polygon", "referring_segment"] -ranges = ["box_range", "segment_range"]; strategies = ["distance::pythagoras", "distance::haversine" , "distance::cross_track", "distance::projected_point" @@ -110,7 +109,8 @@ def cs_to_quickbook(section): , "transform::translate_transformer", "transform::ublas_transformer" ] -views = ["closeable_view", "reversible_view", "identity_view"] +views = ["box_view", "segment_view" + , "closeable_view", "reversible_view", "identity_view"] @@ -135,9 +135,6 @@ def cs_to_quickbook(section): for i in models: model_to_quickbook(i) -for i in ranges: - class_to_quickbook(i) - for i in strategies: strategy_to_quickbook(i) diff --git a/doc/quickref.xml b/doc/quickref.xml index 3c0a1cf005..3d596993fa 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -134,11 +134,19 @@ BOOST_GEOMETRY_REGISTER_POINT_3D BOOST_GEOMETRY_REGISTER_POINT_3D_CONST BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET + + BOOST_GEOMETRY_REGISTER_MULTI_POINT + BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED + 1-dimensionial (macro's for adaption) + BOOST_GEOMETRY_REGISTER_LINESTRING + BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED + BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING + BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING_TEMPLATED @@ -147,6 +155,10 @@ BOOST_GEOMETRY_REGISTER_BOX BOOST_GEOMETRY_REGISTER_BOX_2D_4VALUES BOOST_GEOMETRY_REGISTER_BOX_TEMPLATED + BOOST_GEOMETRY_REGISTER_RING + BOOST_GEOMETRY_REGISTER_RING_TEMPLATED + BOOST_GEOMETRY_REGISTER_MULTI_POLYGON + BOOST_GEOMETRY_REGISTER_MULTI_POLYGON_TEMPLATED @@ -248,7 +260,7 @@ - + @@ -258,7 +270,7 @@ Iterators - Ranges + Views @@ -267,19 +279,16 @@ closing_iterator - circular_iterator ever_circling_iterator - box_iterator - segment_range_iterator - box_range - segment_range - closeable_view - reversible_view - identity_view + box_view + segment_view + closeable_view + reversible_view + identity_view diff --git a/doc/quickstart.qbk b/doc/quickstart.qbk index 98893fc8ca..0b46f810e3 100644 --- a/doc/quickstart.qbk +++ b/doc/quickstart.qbk @@ -12,26 +12,84 @@ [section:quickstart Quick Start] -It is not possible to present all features of the whole library at a glance. -However, a few very small examples are shown below. +This Quick Start section shows some of the features of __boost_geometry__ +in the form of annotated, relatively simple, code snippets. -[main1] +The code below assumes that `boost/geometry.hpp` is included, and that `namespace +boost::geometry` is used. __boost_geometry__ is header only, so including +headerfiles is enough. There is no linking with any library necessary. -The pieces above generate this output: +[quickstart_include] -[$output_main.png] +[h3 Cartesian] + +It is possible to use only a small part of the library. For example: the +distance between two points is a common use case. __boost_geometry__ can calculate +it from various types. Using one of its own types: + +[quickstart_distance] + +If the right headers are included and the types are bound to a coordinate +system, various other types can be used as points: plain C array's, __boost_array__'s, +__boost_tuple__'s, __boost_fusion__ imported structs, your own classes... + +Registering and using a C array: +[quickstart_register_c_array] +[quickstart_distance_c_array] + +Another often used algorithm is point-in-polygon. It is implemented in __boost_geometry__ +under the name `within`. We show its usage here checking a __boost_tuple__ (as a point) +located within a polygon, filled with C Array point pairs. + +But it is first necessary to register a __boost_tuple__, like the C array: +[quickstart_register_boost_tuple] +[quickstart_point_in_polygon] + +We can calculate the area of a polygon: +[quickstart_area] + +By the nature of a template library, it is possible to mix point types. +We calculate distance again, now using a C array point and a __boost_tuple__ point: +[quickstart_distance_mixed] + +The snippets listed above generate the following output: + +[pre +Distance p1-p2 is: 1.41421 +Distance a-b is: 2.23607 +Point p is in polygon? true +Area: 3.015 +Distance a-p is: 2.87924 +] + + +[h3 Non-Cartesian] It is also possible to use non-Cartesian points. For example: points on a sphere. When then an algorithm such as distance is used the library "inspects" that it is handling spherical points and calculates the distance over the sphere, instead of applying the Pythagorean theorem. -Finally an example from a totally different domain: developing window-based applications, -for example using QtWidgets. We check if two rectangles overlap and if so, move the second -one to another place: +[note __boost_geometry__ supports a geographical coordinate system, but that is +in an extension and not released in the current Boost release.] + +We approximate the Earth as a sphere and calculate the distance between Amsterdam +and Paris: +[quick_start_spherical] + +It writes: [pre Distance in miles: 267.02] + +[h3 Adapted structs] + +Finally an example from a totally different domain: developing window-based +applications, for example using QtWidgets. As soon as Qt classes are registered +in __boost_geometry__ we can use them. We can, for example, check if two +rectangles overlap and if so, move the second one to another place: + +[quickstart_qt] -[main3] -More examples are on the page Examples +[h3 More] +In the reference many more examples can be found. [endsect] diff --git a/doc/reference.qbk b/doc/reference.qbk index 335b78614c..db995b8d4e 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -211,10 +211,8 @@ [section:iterators Iterators] [include generated/closing_iterator.qbk] -[include generated/box_iterator.qbk] [include generated/circular_iterator.qbk] [include generated/ever_circling_iterator.qbk] -[include generated/segment_range_iterator.qbk] [endsect] @@ -259,9 +257,9 @@ [endsect] -[section:ranges Ranges] -[include generated/box_range.qbk] -[include generated/segment_range.qbk] +[section:views Views] +[include generated/box_view.qbk] +[include generated/segment_view.qbk] [include generated/closeable_view.qbk] [include generated/reversible_view.qbk] [include generated/identity_view.qbk] diff --git a/doc/reference/geometries/adapted/boost_array.qbk b/doc/reference/geometries/adapted/boost_array.qbk index 6c1e960786..18af141a7a 100644 --- a/doc/reference/geometries/adapted/boost_array.qbk +++ b/doc/reference/geometries/adapted/boost_array.qbk @@ -28,7 +28,7 @@ box, and ring [heading Header] `#include ` -The standard header `` does not include this header. +__not_in_boost_geometry_hpp__ [heading Example] [boost_array] diff --git a/doc/reference/geometries/adapted/boost_fusion.qbk b/doc/reference/geometries/adapted/boost_fusion.qbk index a55ae232b7..9cde090cba 100644 --- a/doc/reference/geometries/adapted/boost_fusion.qbk +++ b/doc/reference/geometries/adapted/boost_fusion.qbk @@ -25,7 +25,7 @@ point concept. They can therefore be used in many Boost.Geometry algorithms. [heading Header] `#include ` -The standard header `` does not include this header. +__not_in_boost_geometry_hpp__ [heading Example] [boost_fusion] diff --git a/doc/reference/geometries/adapted/boost_tuple.qbk b/doc/reference/geometries/adapted/boost_tuple.qbk index 32b0ddbeb3..9d3bedaae9 100644 --- a/doc/reference/geometries/adapted/boost_tuple.qbk +++ b/doc/reference/geometries/adapted/boost_tuple.qbk @@ -37,7 +37,7 @@ box, and ring [heading Header] `#include ` -The standard header `` does not include this header. +__not_in_boost_geometry_hpp__ [heading Example] [boost_tuple] diff --git a/doc/reference/geometries/adapted/c_array.qbk b/doc/reference/geometries/adapted/c_array.qbk index be560a870a..15cdc15bb0 100644 --- a/doc/reference/geometries/adapted/c_array.qbk +++ b/doc/reference/geometries/adapted/c_array.qbk @@ -30,7 +30,7 @@ the point type. [heading Header] `#include ` -The standard header `` does not include this header. +__not_in_boost_geometry_hpp__ [heading Example] [c_array] diff --git a/doc/src/examples/Jamfile.v2 b/doc/src/examples/Jamfile.v2 index 527b07c19b..a7d966bfc2 100644 --- a/doc/src/examples/Jamfile.v2 +++ b/doc/src/examples/Jamfile.v2 @@ -13,5 +13,9 @@ project boost-geometry-doc-src-example : # requirements ; +exe quick_start : quick_start.cpp ; + build-project algorithms ; +build-project core ; build-project geometries ; +build-project views ; diff --git a/doc/src/examples/geometries/register/Jamfile.v2 b/doc/src/examples/geometries/register/Jamfile.v2 index cb87e3a0ed..111ebfbac4 100644 --- a/doc/src/examples/geometries/register/Jamfile.v2 +++ b/doc/src/examples/geometries/register/Jamfile.v2 @@ -17,3 +17,14 @@ exe box : box.cpp ; exe box_templated : box_templated.cpp ; exe box_2d_4values : box_2d_4values.cpp ; exe point : point.cpp ; + +exe linestring : linestring.cpp ; +exe linestring_templated : linestring_templated.cpp ; +exe ring : ring.cpp ; +exe ring_templated : ring_templated.cpp ; + +exe multi_point : multi_point.cpp ; +exe multi_point_templated : multi_point_templated.cpp ; + +exe multi_linestring : multi_linestring.cpp ; +exe multi_polygon : multi_polygon.cpp ; diff --git a/doc/src/examples/geometries/register/linestring.cpp b/doc/src/examples/geometries/register/linestring.cpp new file mode 100644 index 0000000000..bbbbe0b48b --- /dev/null +++ b/doc/src/examples/geometries/register/linestring.cpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_linestring +//` Show the use of BOOST_GEOMETRY_REGISTER_LINESTRING + +#include +#include +#include + +typedef boost::geometry::model::d2::point_xy point_2d; + +BOOST_GEOMETRY_REGISTER_LINESTRING(std::vector) + +int main() +{ + // Normal usage of std:: + std::vector line; + line.push_back(point_2d(1, 1)); + line.push_back(point_2d(2, 2)); + line.push_back(point_2d(3, 1)); + + // Usage of Boost.Geometry's length and wkt functions + std::cout << "Length: " + << boost::geometry::length(line) + << std::endl; + + std::cout << "WKT: " + << boost::geometry::wkt(line) + << std::endl; + + return 0; +} + +//] + + +//[register_linestring_output +/*` +Output: +[pre +Length: 2.82843 +WKT: LINESTRING(1 1,2 2,3 1) +] +*/ +//] diff --git a/doc/src/examples/geometries/register/linestring_templated.cpp b/doc/src/examples/geometries/register/linestring_templated.cpp new file mode 100644 index 0000000000..221c61a586 --- /dev/null +++ b/doc/src/examples/geometries/register/linestring_templated.cpp @@ -0,0 +1,45 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_linestring_templated +//` Show the use of the macro BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED + +#include +#include +#include +#include + +// Adapt any deque to Boost.Geometry Linestring Concept +BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::deque) + +int main() +{ + std::deque > line(2); + boost::geometry::assign_values(line[0], 1, 1); + boost::geometry::assign_values(line[1], 2, 2); + + // Boost.Geometry algorithms work on any deque now + std::cout << "Length: " << boost::geometry::length(line) << std::endl; + std::cout << "Line: " << boost::geometry::dsv(line) << std::endl; + + return 0; +} + +//] + + +//[register_linestring_templated_output +/*` +Output: +[pre +Length: 1.41421 +Line: ((1, 1), (2, 2)) +] +*/ +//] diff --git a/doc/src/examples/geometries/register/multi_linestring.cpp b/doc/src/examples/geometries/register/multi_linestring.cpp new file mode 100644 index 0000000000..ab72a92cf6 --- /dev/null +++ b/doc/src/examples/geometries/register/multi_linestring.cpp @@ -0,0 +1,49 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_multi_linestring +//` Show the use of the macro BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING + +#include +#include +#include +#include + +typedef boost::geometry::model::linestring + < + boost::tuple + > linestring_type; + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING(std::deque) + +int main() +{ + // Normal usage of std:: + std::deque lines(2); + boost::geometry::read_wkt("LINESTRING(0 0,1 1)", lines[0]); + boost::geometry::read_wkt("LINESTRING(2 2,3 3)", lines[1]); + + // Usage of Boost.Geometry + std::cout << "LENGTH: " << boost::geometry::length(lines) << std::endl; + + return 0; +} + +//] + + +//[register_multi_linestring_output +/*` +Output: +[pre +LENGTH: 2.82843 +] +*/ +//] diff --git a/doc/src/examples/geometries/register/multi_point.cpp b/doc/src/examples/geometries/register/multi_point.cpp new file mode 100644 index 0000000000..fa8ad3308b --- /dev/null +++ b/doc/src/examples/geometries/register/multi_point.cpp @@ -0,0 +1,46 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_multi_point +//` Show the use of the macro BOOST_GEOMETRY_REGISTER_MULTI_POINT + +#include +#include +#include +#include + +typedef boost::tuple point_type; + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_MULTI_POINT(std::deque< ::point_type >) + +int main() +{ + // Normal usage of std:: + std::deque multi_point; + multi_point.push_back(point_type(1, 1)); + multi_point.push_back(point_type(3, 2)); + + // Usage of Boost.Geometry + std::cout << "WKT: " << boost::geometry::wkt(multi_point) << std::endl; + + return 0; +} + +//] + + +//[register_multi_point_output +/*` +Output: +[pre +WKT: MULTIPOINT((1 1),(3 2)) +] +*/ +//] diff --git a/doc/src/examples/geometries/register/multi_point_templated.cpp b/doc/src/examples/geometries/register/multi_point_templated.cpp new file mode 100644 index 0000000000..b1738432dd --- /dev/null +++ b/doc/src/examples/geometries/register/multi_point_templated.cpp @@ -0,0 +1,46 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_multi_point_templated +//` Show the use of the macro BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED + +#include +#include +#include +#include + + +BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED(std::deque) + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + +int main() +{ + // Normal usage of std:: + std::deque > multi_point; + multi_point.push_back(boost::tuple(1, 1)); + multi_point.push_back(boost::tuple(3, 2)); + + // Usage of Boost.Geometry + std::cout << "WKT: " << boost::geometry::wkt(multi_point) << std::endl; + + return 0; +} + +//] + + +//[register_multi_point_templated_output +/*` +Output: +[pre +WKT: MULTIPOINT((1 1),(3 2)) +] +*/ +//] diff --git a/doc/src/examples/geometries/register/multi_polygon.cpp b/doc/src/examples/geometries/register/multi_polygon.cpp new file mode 100644 index 0000000000..db6a3130d1 --- /dev/null +++ b/doc/src/examples/geometries/register/multi_polygon.cpp @@ -0,0 +1,49 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_multi_polygon +//` Show the use of the macro BOOST_GEOMETRY_REGISTER_MULTI_POLYGON + +#include +#include +#include +#include + +typedef boost::geometry::model::polygon + < + boost::tuple + > polygon_type; + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_MULTI_POLYGON(std::vector) + +int main() +{ + // Normal usage of std:: + std::vector polygons(2); + boost::geometry::read_wkt("POLYGON((0 0,0 1,1 1,1 0,0 0))", polygons[0]); + boost::geometry::read_wkt("POLYGON((3 0,3 1,4 1,4 0,3 0))", polygons[1]); + + // Usage of Boost.Geometry + std::cout << "AREA: " << boost::geometry::area(polygons) << std::endl; + + return 0; +} + +//] + + +//[register_multi_polygon_output +/*` +Output: +[pre +AREA: 2 +] +*/ +//] diff --git a/doc/src/examples/geometries/register/ring.cpp b/doc/src/examples/geometries/register/ring.cpp new file mode 100644 index 0000000000..bad0e3a54c --- /dev/null +++ b/doc/src/examples/geometries/register/ring.cpp @@ -0,0 +1,49 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_ring +//` Show the use of the macro BOOST_GEOMETRY_REGISTER_RING + +#include +#include +#include + +typedef boost::geometry::model::d2::point_xy point_2d; + +BOOST_GEOMETRY_REGISTER_RING(std::vector) /*< The magic: adapt vector to Boost.Geometry Ring Concept >*/ + +int main() +{ + // Normal usage of std:: + std::vector ring; + ring.push_back(point_2d(1, 1)); + ring.push_back(point_2d(2, 2)); + ring.push_back(point_2d(2, 1)); + + + // Usage of Boost.Geometry + boost::geometry::correct(ring); + std::cout << "Area: " << boost::geometry::area(ring) << std::endl; + std::cout << "WKT: " << boost::geometry::wkt(ring) << std::endl; + + return 0; +} + +//] + + +//[register_ring_output +/*` +Output: +[pre +Area: 0.5 +WKT: POLYGON((1 1,2 2,2 1,1 1)) +] +*/ +//] diff --git a/doc/src/examples/geometries/register/ring_templated.cpp b/doc/src/examples/geometries/register/ring_templated.cpp new file mode 100644 index 0000000000..13308ef3d3 --- /dev/null +++ b/doc/src/examples/geometries/register/ring_templated.cpp @@ -0,0 +1,47 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[register_ring_templated +//` Show the use of the macro BOOST_GEOMETRY_REGISTER_RING_TEMPLATED + +#include +#include +#include +#include + +// Adapt any deque to Boost.Geometry Ring Concept +BOOST_GEOMETRY_REGISTER_RING_TEMPLATED(std::deque) + +int main() +{ + std::deque > ring(3); + boost::geometry::assign_values(ring[0], 0, 0); + boost::geometry::assign_values(ring[2], 4, 1); + boost::geometry::assign_values(ring[1], 1, 4); + + // Boost.Geometry algorithms work on any deque now + boost::geometry::correct(ring); + std::cout << "Area: " << boost::geometry::area(ring) << std::endl; + std::cout << "Contents: " << boost::geometry::wkt(ring) << std::endl; + + return 0; +} + +//] + + +//[register_ring_templated_output +/*` +Output: +[pre +Area: 7.5 +Line: ((0, 0), (1, 4), (4, 1), (0, 0)) +] +*/ +//] diff --git a/doc/src/examples/quick_start.cpp b/doc/src/examples/quick_start.cpp index 8b2beb4d2f..b246afad0d 100644 --- a/doc/src/examples/quick_start.cpp +++ b/doc/src/examples/quick_start.cpp @@ -13,23 +13,33 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include #if defined(_MSC_VER) // We deliberately mix float/double's here so turn off warning //#pragma warning( disable : 4244 ) #endif // defined(_MSC_VER) +//[quickstart_include + #include -#include -#include + +using namespace boost::geometry; +//] + #include -#include -BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +//[quickstart_register_c_array +#include + BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +//] +//[quickstart_register_boost_tuple +#include + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +//] // Small QRect simulations following http://doc.trolltech.com/4.4/qrect.html // Todo: once work the traits out further, would be nice if there is a real example of this. @@ -89,33 +99,48 @@ struct indexed_access }}} -void example_for_main_page() +int main(void) { + //[quickstart_distance + model::d2::point_xy p1(1, 1), p2(2, 2); + std::cout << "Distance p1-p2 is: " << distance(p1, p2) << std::endl; + //] - //[main1 - //` Snippets below assume the namespace boost::geometry is known - using namespace boost::geometry; - - //` It should be possible to use a very small part of the library, for example only the distance between two points. + //[quickstart_distance_c_array int a[2] = {1,1}; int b[2] = {2,3}; double d = distance(a, b); - std::cout << "Distance a-b is:" << d << std::endl; - - //` Other often used algorithms are point-in-polygon: + std::cout << "Distance a-b is: " << d << std::endl; + //] + + //[quickstart_point_in_polygon double points[][2] = {{2.0, 1.3}, {4.1, 3.0}, {5.3, 2.6}, {2.9, 0.7}, {2.0, 1.3}}; model::polygon > poly; append(poly, points); boost::tuple p = boost::make_tuple(3.7, 2.0); - std::cout << "Point p is in polygon? " << (within(p, poly) ? "YES" : "NO") << std::endl; - - //` or area: + std::cout << "Point p is in polygon? " << std::boolalpha << within(p, poly) << std::endl; + //] + + //[quickstart_area std::cout << "Area: " << area(poly) << std::endl; + //] - //` It is possible, by the nature of a template library, to mix the point types declared above: + //[quickstart_distance_mixed double d2 = distance(a, p); - std::cout << "Distance a-p is:" << d2 << std::endl; - + std::cout << "Distance a-p is: " << d2 << std::endl; + //] + + //[quick_start_spherical + typedef boost::geometry::model::point + < + double, 2, boost::geometry::cs::spherical + > spherical_point; + + spherical_point amsterdam(4.90, 52.37); + spherical_point paris(2.35, 48.86); + + double const earth_radius = 3959; // miles + std::cout << "Distance in miles: " << distance(amsterdam, paris) * earth_radius << std::endl; //] /*** @@ -126,7 +151,7 @@ void example_for_main_page() std::cout << "Distance A'dam-Paris: " << distance(amsterdam, paris) / 1000.0 << " kilometers " << std::endl; ***/ - //[main3 + //[quickstart_qt QRect r1(100, 200, 15, 15); QRect r2(110, 210, 20, 20); if (overlaps(r1, r2)) @@ -134,40 +159,7 @@ void example_for_main_page() assign_values(r2, 200, 300, 220, 320); } //] -} - - -void example_for_transform() -{ - using namespace boost::geometry; - - typedef model::point XYZ; - typedef model::point > SPH; - XYZ p; - - SPH sph1, sph2; - assign_values(sph1, 12.5, 41.90, 1.0); - // Go from spherical to Cartesian-3D: - transform(sph1, p); - // Go back from Cartesian 3D to spherical: - transform(p, sph2); - - std::cout << dsv(p) << " <-> " << dsv(sph2) << std::endl; - - typedef model::d2::point_xy XY; - typedef model::d2::point_xy PIXEL; - XY xy(50, 50); - strategy::transform::map_transformer map(0, 0, 100, 100, 1024, 768); - PIXEL pix; - transform(xy, pix, map); - std::cout << pix.x() << "," << pix.y() << std::endl; - -} - - -int main(void) -{ - example_for_main_page(); - example_for_transform(); + return 0; } + diff --git a/doc/src/examples/views/Jamfile.v2 b/doc/src/examples/views/Jamfile.v2 new file mode 100644 index 0000000000..becef40371 --- /dev/null +++ b/doc/src/examples/views/Jamfile.v2 @@ -0,0 +1,17 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +# Copyright (c) 2009-2011 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) + + +project boost-geometry-doc-example-views + : # requirements + ; + +exe box_view : box_view.cpp ; +exe segment_view : segment_view.cpp ; diff --git a/doc/src/examples/views/box_view.cpp b/doc/src/examples/views/box_view.cpp new file mode 100644 index 0000000000..e280ec4281 --- /dev/null +++ b/doc/src/examples/views/box_view.cpp @@ -0,0 +1,58 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[box_view +//` Shows usage of the Boost.Range compatible view on a box + +#include + +#include + + +int main() +{ + typedef boost::geometry::model::box + < + boost::geometry::model::point + > box_type; + + // Define the Boost.Range compatible type: + typedef boost::geometry::box_view box_view; + + box_type box; + boost::geometry::assign_values(box, 0, 0, 4, 4); + + box_view view(box); + + // Iterating in clockwise direction over the points of this box + for (boost::range_iterator::type it = boost::begin(view); + it != boost::end(view); ++it) + { + std::cout << " " << boost::geometry::dsv(*it); + } + std::cout << std::endl; + + // Note that a box_view is tagged as a ring, so supports area etc. + std::cout << "Area: " << boost::geometry::area(view) << std::endl; + + return 0; +} + +//] + + +//[box_view_output +/*` +Output: +[pre + (0, 0) (0, 4) (4, 4) (4, 0) (0, 0) +Area: 16 +] +*/ +//] diff --git a/doc/src/examples/views/segment_view.cpp b/doc/src/examples/views/segment_view.cpp new file mode 100644 index 0000000000..53a20c369c --- /dev/null +++ b/doc/src/examples/views/segment_view.cpp @@ -0,0 +1,57 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[segment_view +//` Shows usage of the Boost.Range compatible view on a box + +#include + +#include + + +int main() +{ + typedef boost::geometry::model::segment + < + boost::geometry::model::point + > segment_type; + + typedef boost::geometry::segment_view segment_view; + + segment_type segment; + boost::geometry::assign_values(segment, 0, 0, 1, 1); + + segment_view view(segment); + + // Iterating over the points of this segment + for (boost::range_iterator::type it = boost::begin(view); + it != boost::end(view); ++it) + { + std::cout << " " << boost::geometry::dsv(*it); + } + std::cout << std::endl; + + // Note that a segment_view is tagged as a linestring, so supports length etc. + std::cout << "Length: " << boost::geometry::length(view) << std::endl; + + return 0; +} + +//] + + +//[segment_view_output +/*` +Output: +[pre + (0, 0) (0, 4) (4, 4) (4, 0) (0, 0) +Area: 16 +] +*/ +//] diff --git a/example/c04_a_custom_triangle_example.cpp b/example/c04_a_custom_triangle_example.cpp index 8c4b7d6d86..ce2a53e15b 100644 --- a/example/c04_a_custom_triangle_example.cpp +++ b/example/c04_a_custom_triangle_example.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -30,9 +31,7 @@ struct triangle : public boost::array struct tag { typedef ring_tag type; }; -}}} +BOOST_GEOMETRY_REGISTER_RING(triangle) // Specializations of algorithms, where useful. If not specialized the default ones diff --git a/example/c04_b_custom_triangle_example.cpp b/example/c04_b_custom_triangle_example.cpp index 1e41c5f9b2..41e93f14ea 100644 --- a/example/c04_b_custom_triangle_example.cpp +++ b/example/c04_b_custom_triangle_example.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -31,9 +32,7 @@ struct triangle : public boost::array // Register triangle

as a ring -namespace boost { namespace geometry { namespace traits { -template struct tag > { typedef ring_tag type; }; -}}} +BOOST_GEOMETRY_REGISTER_RING_TEMPLATED(triangle) namespace boost { namespace geometry { namespace dispatch { diff --git a/example/c06_custom_polygon_example.cpp b/example/c06_custom_polygon_example.cpp index da4a978de2..b2c486fa8f 100644 --- a/example/c06_custom_polygon_example.cpp +++ b/example/c06_custom_polygon_example.cpp @@ -14,6 +14,7 @@ #include #include +#include struct my_point @@ -48,11 +49,7 @@ struct my_polygon // We can conveniently use macro's to register point and ring BOOST_GEOMETRY_REGISTER_POINT_2D(my_point, double, cs::cartesian, x, y) - -// Register my_ring as a ring -namespace boost { namespace geometry { namespace traits { -template <> struct tag { typedef ring_tag type; }; -}}} +BOOST_GEOMETRY_REGISTER_RING(my_ring) @@ -76,7 +73,6 @@ template<> struct interior_mutable_type typedef boost::array& type; }; - template<> struct exterior_ring { static my_ring& get(my_polygon& p) diff --git a/example/c08_custom_non_std_example.cpp b/example/c08_custom_non_std_example.cpp index 874917d8e5..6df1ff3d96 100644 --- a/example/c08_custom_non_std_example.cpp +++ b/example/c08_custom_non_std_example.cpp @@ -20,6 +20,7 @@ #include #include +#include #include // Sample point, having x/y @@ -215,9 +216,7 @@ template<> struct resize // 4) register with Boost.Geometry BOOST_GEOMETRY_REGISTER_POINT_2D(my_point, double, cs::cartesian, x, y) -namespace boost { namespace geometry { namespace traits { -template <> struct tag { typedef ring_tag type; }; -}}} +BOOST_GEOMETRY_REGISTER_RING(my_polygon) // end adaption @@ -238,7 +237,7 @@ void walk_using_iterator(my_polygon const& polygon) void walk_using_range(my_polygon const& polygon) { - for (boost::range_iterator::type it + for (boost::range_iterator::type it = boost::begin(polygon); it != boost::end(polygon); ++it) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6a26f87299..3ea87d1026 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -25,7 +25,6 @@ build-project geometries ; build-project arithmetic ; build-project algorithms ; build-project iterators ; -build-project ranges ; build-project strategies ; build-project policies ; build-project util ; diff --git a/test/algorithms/convex_hull.cpp b/test/algorithms/convex_hull.cpp index 53c0e246a9..d520a9afce 100644 --- a/test/algorithms/convex_hull.cpp +++ b/test/algorithms/convex_hull.cpp @@ -21,26 +21,29 @@ template -void test_all(bool do_rectangular = true) +void test_all() { // from sample linestring - test_geometry >( "linestring(1.1 1.1, 2.5 2.1, 3.1 3.1, 4.9 1.1, 3.1 1.9)", 5, 4, 3.8); - if (do_rectangular) - { - // rectangular, with concavity - test_geometry >( - "polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))", - 9, 5, 12.0); - } + // rectangular, with concavity + test_geometry >( + "polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))", + 9, 5, 12.0); // from sample polygon, with concavity test_geometry >( "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0" ", 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", 12, 8, 5.245); + + test_geometry >( + "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0" + ", 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", + 12, 8, 5.245); + + // Waits for next cycle test_geometry >("box(0 0,2 2)", 5, 5, 4); } int test_main(int, char* []) diff --git a/test/algorithms/detail/sections/range_by_section.cpp b/test/algorithms/detail/sections/range_by_section.cpp index 4ac576f2a0..920e95e828 100644 --- a/test/algorithms/detail/sections/range_by_section.cpp +++ b/test/algorithms/detail/sections/range_by_section.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -35,7 +35,7 @@ void test_sectionalize(std::string const caseid, Geometry const& geometry, std:: typedef typename bg::closeable_view < - typename bg::range_type::type const, + typename bg::detail::range_type::type const, bg::closure::value >::type cview_type; typedef typename bg::reversible_view diff --git a/test/algorithms/within.cpp b/test/algorithms/within.cpp index f91e240548..9020c364db 100644 --- a/test/algorithms/within.cpp +++ b/test/algorithms/within.cpp @@ -33,8 +33,13 @@ void test_all() test_geometry >("POINT(2 2)", "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,3 1,3 3,1 3,1 1))", false); + typedef bg::model::box

box_type; + + test_geometry("POINT(1 1)", "BOX(0 0,2 2)", true); + + test_geometry("BOX(1 1,2 2)", "BOX(0 0,3 3)", true); + test_geometry("BOX(0 0,3 3)", "BOX(1 1,2 2)", false); - test_geometry >("POINT(1 1)", "BOX(0 0,2 2)", true); // Mixed point types test_geometry @@ -45,7 +50,7 @@ void test_all() // Real-life problem (solved now), point is in the middle, 409623 is also a coordinate - // on the border, it was wrong first. + // on the border, has been wrong in the past (2009) test_ring

("POINT(146383 409623)", "POLYGON((146351 410597,146521 410659,147906 410363,148088 410420" ",148175 410296,148281 409750,148215 409623,148154 409666,148154 409666" diff --git a/test/iterators/Jamfile.v2 b/test/iterators/Jamfile.v2 index ad7a0368df..3450650986 100644 --- a/test/iterators/Jamfile.v2 +++ b/test/iterators/Jamfile.v2 @@ -10,9 +10,6 @@ test-suite boost-geometry-iterators : - [ run box_iterator.cpp ] - [ run circular_iterator.cpp ] [ run closing_iterator.cpp ] [ run ever_circling_iterator.cpp ] - [ run segment_range_iterator.cpp ] ; diff --git a/test/iterators/box_iterator.cpp b/test/iterators/box_iterator.cpp deleted file mode 100644 index db059fcc59..0000000000 --- a/test/iterators/box_iterator.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Box Library) -// -// Copyright (c) 2010 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) - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - - -template -void test_geometry(std::string const& wkt, std::string const& expected) -{ - Box box; - bg::read_wkt(wkt, box); - - { - std::ostringstream out; - bg::box_iterator it(box), end(box, true); - for ( ; it != end; ++it) - { - out << " " << bg::get<0>(*it) << bg::get<1>(*it); - } - BOOST_CHECK_EQUAL(out.str(), expected); - } -} - - -template -void test_all() -{ - test_geometry >("polygon((1 1,2 2))", " 11 12 22 21 11"); - test_geometry >("polygon((3 3,5 5))", " 33 35 55 53 33"); -} - - -int test_main(int, char* []) -{ - test_all >(); - - return 0; -} diff --git a/test/iterators/box_iterator.vcproj b/test/iterators/box_iterator.vcproj deleted file mode 100644 index 6f01f7be5e..0000000000 --- a/test/iterators/box_iterator.vcproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/iterators/circular_iterator.cpp b/test/iterators/circular_iterator.cpp deleted file mode 100644 index c6224867c0..0000000000 --- a/test/iterators/circular_iterator.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// Unit Test - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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) - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - - -template -void test_forward(Geometry const& geometry, CircularIterator end, - int offset, std::string const& expected) -{ - CircularIterator it(boost::begin(geometry), boost::end(geometry), - boost::begin(geometry) + offset); - - std::ostringstream out; - for (; it != end; ++it) - { - out << bg::get<0>(*it); - } - BOOST_CHECK_EQUAL(out.str(), expected); -} - - -template -void test_backward(Geometry const& geometry, CircularIterator end, - int offset, std::string const& expected) -{ - CircularIterator it(boost::begin(geometry), boost::end(geometry), - boost::begin(geometry) + offset); - - std::ostringstream out; - for (; it != end; --it) - { - out << bg::get<0>(*it); - } - BOOST_CHECK_EQUAL(out.str(), expected); -} - - - -template -void test_geometry(std::string const& wkt) -{ - G geo; - bg::read_wkt(wkt, geo); - typedef typename boost::range_const_iterator::type normal_iterator; - typedef bg::circular_iterator circular_iterator; - - circular_iterator end(boost::end(geo)); - - // 2: start somewhere in the middle (first == test before) - test_forward(geo, end, 0, "12345"); - test_forward(geo, end, 1, "23451"); - test_forward(geo, end, 2, "34512"); - test_forward(geo, end, 3, "45123"); - test_forward(geo, end, 4, "51234"); - - test_backward(geo, end, 0, "15432"); - test_backward(geo, end, 1, "21543"); - test_backward(geo, end, 2, "32154"); - test_backward(geo, end, 3, "43215"); - test_backward(geo, end, 4, "54321"); - - // 4: check copy behaviour - G copy; - - normal_iterator start = boost::begin(geo) + 2; - circular_iterator it(boost::begin(geo), boost::end(geo), start); - std::copy(it, end, std::back_inserter(copy)); - - std::ostringstream out; - for (normal_iterator cit = boost::begin(copy); cit != boost::end(copy); ++cit) - { - out << bg::get<0>(*cit); - } - BOOST_CHECK_EQUAL(out.str(), "34512"); -} - - -template -void test_all() -{ - test_geometry >("linestring(1 1,2 2,3 3,4 4,5 5)"); -} - - -int test_main(int, char* []) -{ - test_all >(); - - return 0; -} diff --git a/test/iterators/circular_iterator.vcproj b/test/iterators/circular_iterator.vcproj deleted file mode 100644 index 24210a2a02..0000000000 --- a/test/iterators/circular_iterator.vcproj +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/iterators/iterators.sln b/test/iterators/iterators.sln index ec406dc9a3..8b1e55c7e0 100644 --- a/test/iterators/iterators.sln +++ b/test/iterators/iterators.sln @@ -2,16 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ever_circling_iterator", "ever_circling_iterator.vcproj", "{73F8C969-FA1E-4D9D-81F9-35B1206F0C14}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "circular_iterator", "circular_iterator.vcproj", "{46571A34-B68D-4854-90C0-56D29EE63FFE}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "closing_iterator", "closing_iterator.vcproj", "{04C31A2D-BE88-4FDB-AFFE-EFDFFA9D9C39}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "segment_range_iterator", "segment_range_iterator.vcproj", "{887E64C9-6786-44E2-AE09-B02B855486DE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "box_iterator", "box_iterator.vcproj", "{CD4B14B2-ED74-4111-B8BF-093FA3930A5C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "segment_returning_iterator", "segment_returning_iterator.vcproj", "{A38B1CA8-5194-4FAD-B85E-55697BEECCB7}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -22,26 +14,10 @@ Global {73F8C969-FA1E-4D9D-81F9-35B1206F0C14}.Debug|Win32.Build.0 = Debug|Win32 {73F8C969-FA1E-4D9D-81F9-35B1206F0C14}.Release|Win32.ActiveCfg = Release|Win32 {73F8C969-FA1E-4D9D-81F9-35B1206F0C14}.Release|Win32.Build.0 = Release|Win32 - {46571A34-B68D-4854-90C0-56D29EE63FFE}.Debug|Win32.ActiveCfg = Debug|Win32 - {46571A34-B68D-4854-90C0-56D29EE63FFE}.Debug|Win32.Build.0 = Debug|Win32 - {46571A34-B68D-4854-90C0-56D29EE63FFE}.Release|Win32.ActiveCfg = Release|Win32 - {46571A34-B68D-4854-90C0-56D29EE63FFE}.Release|Win32.Build.0 = Release|Win32 {04C31A2D-BE88-4FDB-AFFE-EFDFFA9D9C39}.Debug|Win32.ActiveCfg = Debug|Win32 {04C31A2D-BE88-4FDB-AFFE-EFDFFA9D9C39}.Debug|Win32.Build.0 = Debug|Win32 {04C31A2D-BE88-4FDB-AFFE-EFDFFA9D9C39}.Release|Win32.ActiveCfg = Release|Win32 {04C31A2D-BE88-4FDB-AFFE-EFDFFA9D9C39}.Release|Win32.Build.0 = Release|Win32 - {887E64C9-6786-44E2-AE09-B02B855486DE}.Debug|Win32.ActiveCfg = Debug|Win32 - {887E64C9-6786-44E2-AE09-B02B855486DE}.Debug|Win32.Build.0 = Debug|Win32 - {887E64C9-6786-44E2-AE09-B02B855486DE}.Release|Win32.ActiveCfg = Release|Win32 - {887E64C9-6786-44E2-AE09-B02B855486DE}.Release|Win32.Build.0 = Release|Win32 - {CD4B14B2-ED74-4111-B8BF-093FA3930A5C}.Debug|Win32.ActiveCfg = Debug|Win32 - {CD4B14B2-ED74-4111-B8BF-093FA3930A5C}.Debug|Win32.Build.0 = Debug|Win32 - {CD4B14B2-ED74-4111-B8BF-093FA3930A5C}.Release|Win32.ActiveCfg = Release|Win32 - {CD4B14B2-ED74-4111-B8BF-093FA3930A5C}.Release|Win32.Build.0 = Release|Win32 - {A38B1CA8-5194-4FAD-B85E-55697BEECCB7}.Debug|Win32.ActiveCfg = Debug|Win32 - {A38B1CA8-5194-4FAD-B85E-55697BEECCB7}.Debug|Win32.Build.0 = Debug|Win32 - {A38B1CA8-5194-4FAD-B85E-55697BEECCB7}.Release|Win32.ActiveCfg = Release|Win32 - {A38B1CA8-5194-4FAD-B85E-55697BEECCB7}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/iterators/segment_range_iterator.cpp b/test/iterators/segment_range_iterator.cpp deleted file mode 100644 index 501e7f78c8..0000000000 --- a/test/iterators/segment_range_iterator.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Segment Library) -// -// Copyright (c) 2010 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) - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - - -template -void test_geometry(std::string const& wkt, std::string const& expected) -{ - Segment segment; - bg::read_wkt(wkt, segment); - - std::ostringstream out; - bg::segment_range_iterator it(segment), end(segment, true); - for ( ; it != end; ++it) - { - out << " " << bg::get<0>(*it) << bg::get<1>(*it); - } - BOOST_CHECK_EQUAL(out.str(), expected); -} - - -template -void test_all() -{ - test_geometry("linestring(1 1,2 2)", " 11 22"); - test_geometry("linestring(4 4,3 3)", " 44 33"); -} - - -int test_main(int, char* []) -{ - test_all >(); - - return 0; -} diff --git a/test/iterators/segment_range_iterator.vcproj b/test/iterators/segment_range_iterator.vcproj deleted file mode 100644 index b6264af2a1..0000000000 --- a/test/iterators/segment_range_iterator.vcproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/multi/algorithms/multi_convex_hull.cpp b/test/multi/algorithms/multi_convex_hull.cpp index 7112eab8d5..c649c0b908 100644 --- a/test/multi/algorithms/multi_convex_hull.cpp +++ b/test/multi/algorithms/multi_convex_hull.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/test/multi/algorithms/overlay/multi_traverse.cpp b/test/multi/algorithms/overlay/multi_traverse.cpp index 19f296223c..0199504b13 100644 --- a/test/multi/algorithms/overlay/multi_traverse.cpp +++ b/test/multi/algorithms/overlay/multi_traverse.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include diff --git a/test/util/as_range.cpp b/test/util/as_range.cpp index 3b51d4687a..9f8ac6d9bd 100644 --- a/test/util/as_range.cpp +++ b/test/util/as_range.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include @@ -43,7 +43,7 @@ void test_geometry(std::string const& wkt, double expected_x, double expected_y) // Declare a range-type, compatible with boost::range, // such that range_iterator etc could be called - typedef typename bg::range_type::type range_type; + typedef typename bg::detail::range_type::type range_type; bg::read_wkt(wkt, geometry); diff --git a/test/views/Jamfile.v2 b/test/views/Jamfile.v2 index e28d498c83..b567031409 100644 --- a/test/views/Jamfile.v2 +++ b/test/views/Jamfile.v2 @@ -10,6 +10,8 @@ test-suite boost-geometry-views : + [ run segment_view.cpp ] + [ run box_view.cpp ] [ run reversible_view.cpp ] [ run closeable_view.cpp ] [ run reversible_closeable.cpp ] diff --git a/test/ranges/box_range.cpp b/test/views/box_view.cpp similarity index 77% rename from test/ranges/box_range.cpp rename to test/views/box_view.cpp index 6acfccda8d..610804f4d8 100644 --- a/test/ranges/box_range.cpp +++ b/test/views/box_view.cpp @@ -16,19 +16,19 @@ #include #include -#include +#include #include -template +template void test_geometry(std::string const& wkt, std::string const& expected) { Box box; bg::read_wkt(wkt, box); - typedef bg::box_range range_type; + typedef bg::box_view range_type; range_type range(box); { @@ -56,15 +56,16 @@ void test_geometry(std::string const& wkt, std::string const& expected) } // Check Boost.Range concept - BOOST_CONCEPT_ASSERT( (boost::ForwardRangeConcept) ); + BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); } template void test_all() { - test_geometry >("polygon((1 1,2 2))", " 11 12 22 21 11"); - test_geometry >("polygon((3 3,5 5))", " 33 35 55 53 33"); + test_geometry, true> ("polygon((1 1,2 2))", " 11 12 22 21 11"); + test_geometry, false>("polygon((1 1,2 2))", " 11 21 22 12 11"); + test_geometry, true> ("polygon((3 3,5 5))", " 33 35 55 53 33"); } diff --git a/test/ranges/box_range.vcproj b/test/views/box_view.vcproj similarity index 94% rename from test/ranges/box_range.vcproj rename to test/views/box_view.vcproj index 61627ae0a4..ab1036beea 100644 --- a/test/ranges/box_range.vcproj +++ b/test/views/box_view.vcproj @@ -2,9 +2,9 @@ @@ -18,7 +18,7 @@ diff --git a/test/ranges/segment_range.cpp b/test/views/segment_view.cpp similarity index 85% rename from test/ranges/segment_range.cpp rename to test/views/segment_view.cpp index 1d48199c69..a56188771c 100644 --- a/test/ranges/segment_range.cpp +++ b/test/views/segment_view.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include @@ -27,7 +27,7 @@ void test_geometry(std::string const& wkt, std::string const& expected) Segment segment; bg::read_wkt(wkt, segment); - typedef bg::segment_range range_type; + typedef bg::segment_view range_type; range_type range(segment); { @@ -60,7 +60,7 @@ void test_geometry(std::string const& wkt, std::string const& expected) } // Check Boost.Range concept - BOOST_CONCEPT_ASSERT( (boost::ForwardRangeConcept) ); + BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); } @@ -75,6 +75,11 @@ void test_all() int test_main(int, char* []) { + std::vector a; + a.push_back(1); + boost::range_iterator const>::type it = a.end(); + --it; + std::cout << *it << std::endl; test_all >(); return 0; } diff --git a/test/ranges/segment_range.vcproj b/test/views/segment_view.vcproj similarity index 93% rename from test/ranges/segment_range.vcproj rename to test/views/segment_view.vcproj index 6f03d21cbc..9b88401933 100644 --- a/test/ranges/segment_range.vcproj +++ b/test/views/segment_view.vcproj @@ -2,9 +2,9 @@ @@ -18,7 +18,7 @@ diff --git a/test/views/views.sln b/test/views/views.sln index abe1a9eefe..7fcf73665b 100644 --- a/test/views/views.sln +++ b/test/views/views.sln @@ -6,6 +6,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reversible_closeable", "rev EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reversible_view", "reversible_view.vcproj", "{BFB08FEE-76D6-4F3D-9184-BE03CC3F7968}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "box_view", "box_view.vcproj", "{34A1F53A-DA46-41E6-9E26-740D22D662DC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "segment_view", "segment_view.vcproj", "{B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -24,6 +28,14 @@ Global {BFB08FEE-76D6-4F3D-9184-BE03CC3F7968}.Debug|Win32.Build.0 = Debug|Win32 {BFB08FEE-76D6-4F3D-9184-BE03CC3F7968}.Release|Win32.ActiveCfg = Release|Win32 {BFB08FEE-76D6-4F3D-9184-BE03CC3F7968}.Release|Win32.Build.0 = Release|Win32 + {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Debug|Win32.Build.0 = Debug|Win32 + {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Release|Win32.ActiveCfg = Release|Win32 + {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Release|Win32.Build.0 = Release|Win32 + {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Debug|Win32.ActiveCfg = Debug|Win32 + {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Debug|Win32.Build.0 = Debug|Win32 + {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Release|Win32.ActiveCfg = Release|Win32 + {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From b7eff024e9035a99c3286e8b777a6c5b5a69e957 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 8 May 2011 12:45:21 +0000 Subject: [PATCH 019/135] Merged small change (71816,71817), updated ring.hpp/linestring.hpp manually Merged geometry.hpp from 71710 to 71817 (was not done in previous steps) Removed ranges manually as it was not in source anymore and could not be merged [SVN r71818] --- .../geometries/register/linestring.hpp | 32 ++++++++++++++++++- .../geometry/geometries/register/ring.hpp | 29 ++++++++++++++++- include/boost/geometry/geometry.hpp | 9 +++--- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/include/boost/geometry/geometries/register/linestring.hpp b/include/boost/geometry/geometries/register/linestring.hpp index c8d17195a8..69934aa551 100644 --- a/include/boost/geometry/geometries/register/linestring.hpp +++ b/include/boost/geometry/geometries/register/linestring.hpp @@ -19,12 +19,42 @@ #include #include - +/*! +\brief \brief_macro{linestring} +\ingroup register +\details \details_macro{BOOST_GEOMETRY_REGISTER_LINESTRING, linestring} The + linestring may contain template parameters, which must be specified then. +\param Linestring \param_macro_type{linestring} + +\qbk{ +[heading Example] +[register_linestring] +[register_linestring_output] +} +*/ #define BOOST_GEOMETRY_REGISTER_LINESTRING(Linestring) \ namespace boost { namespace geometry { namespace traits { \ template<> struct tag { typedef linestring_tag type; }; \ }}} +/*! +\brief \brief_macro{templated linestring} +\ingroup register +\details \details_macro{BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED, templated linestring} + \details_macro_templated{linestring, point} +\param Linestring \param_macro_type{linestring (without template parameters)} + +\qbk{ +[heading Example] +[register_linestring_templated] +[register_linestring_templated_output] +} +*/ +#define BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(Linestring) \ +namespace boost { namespace geometry { namespace traits { \ + template struct tag< Linestring

> { typedef linestring_tag type; }; \ +}}} + #endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP diff --git a/include/boost/geometry/geometries/register/ring.hpp b/include/boost/geometry/geometries/register/ring.hpp index 61f2e08d31..5ead4c2cc1 100644 --- a/include/boost/geometry/geometries/register/ring.hpp +++ b/include/boost/geometry/geometries/register/ring.hpp @@ -15,16 +15,43 @@ #ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP #define BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP + #include #include +/*! +\brief \brief_macro{ring} +\ingroup register +\details \details_macro{BOOST_GEOMETRY_REGISTER_RING, ring} The + ring may contain template parameters, which must be specified then. +\param Ring \param_macro_type{ring} + +\qbk{ +[heading Example] +[register_ring] +[register_ring_output] +} +*/ #define BOOST_GEOMETRY_REGISTER_RING(Ring) \ namespace boost { namespace geometry { namespace traits { \ template<> struct tag { typedef ring_tag type; }; \ }}} -#define BOOST_GEOMETRY_REGISTER_RING_TEMPLATIZED(Ring) \ +/*! +\brief \brief_macro{templated ring} +\ingroup register +\details \details_macro{BOOST_GEOMETRY_REGISTER_RING_TEMPLATED, templated ring} + \details_macro_templated{ring, point} +\param Ring \param_macro_type{ring (without template parameters)} + +\qbk{ +[heading Example] +[register_ring_templated] +[register_ring_templated_output] +} +*/ +#define BOOST_GEOMETRY_REGISTER_RING_TEMPLATED(Ring) \ namespace boost { namespace geometry { namespace traits { \ template struct tag< Ring

> { typedef ring_tag type; }; \ }}} diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp index c5586eeafa..c98be89047 100644 --- a/include/boost/geometry/geometry.hpp +++ b/include/boost/geometry/geometry.hpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -72,13 +73,10 @@ #include #include - // Include multi a.o. because it can give weird effects -// if you don't (e.g. area=0 of a filled multipolygon) +// if you don't (e.g. area=0 of a multipolygon) #include - - // check includes all concepts #include @@ -88,6 +86,9 @@ #include #include +#include +#include + #include From 0ec0c170a6cdf56e24f88dc64042c865ecdfd614 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 8 May 2011 12:47:12 +0000 Subject: [PATCH 020/135] Merged small change (71816,71817) [SVN r71819] --- test/ranges/Jamfile.v2 | 15 --------------- test/ranges/ranges.sln | 25 ------------------------- 2 files changed, 40 deletions(-) delete mode 100644 test/ranges/Jamfile.v2 delete mode 100644 test/ranges/ranges.sln diff --git a/test/ranges/Jamfile.v2 b/test/ranges/Jamfile.v2 deleted file mode 100644 index 991051bf04..0000000000 --- a/test/ranges/Jamfile.v2 +++ /dev/null @@ -1,15 +0,0 @@ -# Boost.Geometry (aka GGL, Generic Geometry Library) -# -# Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2011 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) - -test-suite boost-geometry-ranges - : - [ run segment_range.cpp ] - [ run box_range.cpp ] - ; diff --git a/test/ranges/ranges.sln b/test/ranges/ranges.sln deleted file mode 100644 index 5fee651c70..0000000000 --- a/test/ranges/ranges.sln +++ /dev/null @@ -1,25 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "segment_range", "segment_range.vcproj", "{B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "box_range", "box_range.vcproj", "{34A1F53A-DA46-41E6-9E26-740D22D662DC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Debug|Win32.ActiveCfg = Debug|Win32 - {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Debug|Win32.Build.0 = Debug|Win32 - {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Release|Win32.ActiveCfg = Release|Win32 - {B49AC3E2-3497-465B-88C2-BCADA4B4ADAF}.Release|Win32.Build.0 = Release|Win32 - {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Debug|Win32.ActiveCfg = Debug|Win32 - {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Debug|Win32.Build.0 = Debug|Win32 - {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Release|Win32.ActiveCfg = Release|Win32 - {34A1F53A-DA46-41E6-9E26-740D22D662DC}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal From 53cd02a7eeb228598cea7e8c1bcbdeab49bf320b Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 22 May 2011 15:58:43 +0000 Subject: [PATCH 021/135] Merged r72075 .. 72082 [SVN r72083] --- doc/Jamfile.v2 | 11 ++++++----- doc/html/index.html | 16 ++++++++++++++++ .../tools/doxygen_xml2qbk/quickbook_output.hpp | 4 ++-- .../algorithms/detail/has_self_intersections.hpp | 2 +- test/algorithms/detail/partition.vcproj | 2 +- test/algorithms/difference.vcproj | 2 +- test/algorithms/intersection.vcproj | 2 +- test/algorithms/intersects.vcproj | 2 +- test/algorithms/overlaps.vcproj | 2 +- test/algorithms/overlay/assemble.vcproj | 2 +- test/algorithms/overlay/ccw_traverse.vcproj | 2 +- test/algorithms/overlay/dissolver.vcproj | 2 +- .../overlay/enrich_intersection_points.vcproj | 2 +- test/algorithms/overlay/get_turn_info.vcproj | 2 +- test/algorithms/overlay/get_turns.vcproj | 2 +- .../overlay/merge_intersection_points.vcproj | 2 +- test/algorithms/overlay/relative_order.vcproj | 2 +- .../overlay/robustness/interior_triangles.vcproj | 2 +- .../overlay/robustness/intersection_pies.vcproj | 2 +- .../overlay/robustness/recursive_polygons.vcproj | 2 +- .../overlay/robustness/star_comb.vcproj | 2 +- test/algorithms/overlay/select_rings.vcproj | 2 +- .../overlay/self_intersection_points.vcproj | 2 +- test/algorithms/overlay/split_rings.vcproj | 2 +- test/algorithms/overlay/traverse.vcproj | 2 +- test/algorithms/union.vcproj | 2 +- test/geometries/concepts/check.vcproj | 2 +- test/multi/algorithms/multi_difference.vcproj | 2 +- test/multi/algorithms/multi_intersection.vcproj | 2 +- test/multi/algorithms/multi_union.vcproj | 2 +- .../algorithms/overlay/multi_traverse.vcproj | 2 +- 31 files changed, 52 insertions(+), 35 deletions(-) create mode 100644 doc/html/index.html diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index cb4690a521..711c331896 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -11,7 +11,8 @@ project geometry/doc ; -using auto-index ; +# Auto-index, experimental. Commented otherwise does not build without. +#using auto-index ; import boostbook ; import quickbook ; @@ -23,10 +24,10 @@ boostbook geometry quickref.xml generated/point.qbk : chunk.section.depth=4 - off - on - off - index.on.type=1 +# off +# on +# off +# index.on.type=1 html chunk.first.sections=1 toc.section.depth=3 diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000000..2997cd972a --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,16 @@ + + + + + + + + +Automatic redirection failed, please go to +http://boost-sandbox.sourceforge.net/libs/geometry/doc/html/ + + diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp index 2d2cbf24cf..515b10ba50 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp @@ -298,8 +298,8 @@ inline void quickbook_output_indexterm(std::string const& term, std::ostream& ou { // "Unnamespace" it and add all terms (also namespaces) std::vector splitted; - boost::split(splitted, boost::replace_all_copy(term, "::", ":") - , boost::is_any_of(":"), boost::token_compress_on); + std::string for_split = boost::replace_all_copy(term, "::", ":"); + boost::split(splitted, for_split, boost::is_any_of(":"), boost::token_compress_on); BOOST_FOREACH(std::string const& part, splitted) { out << "" << part << ""; diff --git a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp index c6144f4d10..38493878c9 100644 --- a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp +++ b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -44,7 +44,7 @@ class overlay_invalid_input_exception : public geometry::exception virtual char const* what() const throw() { - return "Boost.Geometry Overlay invald input exception"; + return "Boost.Geometry Overlay invalid input exception"; } }; diff --git a/test/algorithms/detail/partition.vcproj b/test/algorithms/detail/partition.vcproj index 5bebf95fe3..66e26a9739 100644 --- a/test/algorithms/detail/partition.vcproj +++ b/test/algorithms/detail/partition.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../..;../../../../../boost/geometry/extensions/contrib/ttmath" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/difference.vcproj b/test/algorithms/difference.vcproj index 8b3d082c5f..2302ee27fe 100644 --- a/test/algorithms/difference.vcproj +++ b/test/algorithms/difference.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../..;..;../$(TTMATH_ROOT)" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/intersection.vcproj b/test/algorithms/intersection.vcproj index 8424157da3..a9bc3a6f3d 100644 --- a/test/algorithms/intersection.vcproj +++ b/test/algorithms/intersection.vcproj @@ -43,7 +43,7 @@ AdditionalOptions="/bigobj" Optimization="0" AdditionalIncludeDirectories="../../../..;.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/intersects.vcproj b/test/algorithms/intersects.vcproj index 5a02455123..f3f5f64db4 100644 --- a/test/algorithms/intersects.vcproj +++ b/test/algorithms/intersects.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../..;.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlaps.vcproj b/test/algorithms/overlaps.vcproj index f9e9881c13..06a51367f4 100644 --- a/test/algorithms/overlaps.vcproj +++ b/test/algorithms/overlaps.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../..;.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/assemble.vcproj b/test/algorithms/overlay/assemble.vcproj index 29f147208e..335b08ab71 100644 --- a/test/algorithms/overlay/assemble.vcproj +++ b/test/algorithms/overlay/assemble.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/ccw_traverse.vcproj b/test/algorithms/overlay/ccw_traverse.vcproj index 22f897d2d7..fc373c8476 100644 --- a/test/algorithms/overlay/ccw_traverse.vcproj +++ b/test/algorithms/overlay/ccw_traverse.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/dissolver.vcproj b/test/algorithms/overlay/dissolver.vcproj index 443ad698cc..c3c9d4bf00 100644 --- a/test/algorithms/overlay/dissolver.vcproj +++ b/test/algorithms/overlay/dissolver.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/enrich_intersection_points.vcproj b/test/algorithms/overlay/enrich_intersection_points.vcproj index 46b82a19a6..8880fb1f30 100644 --- a/test/algorithms/overlay/enrich_intersection_points.vcproj +++ b/test/algorithms/overlay/enrich_intersection_points.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/get_turn_info.vcproj b/test/algorithms/overlay/get_turn_info.vcproj index 48c7602d59..22bf1d1bd7 100644 --- a/test/algorithms/overlay/get_turn_info.vcproj +++ b/test/algorithms/overlay/get_turn_info.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/get_turns.vcproj b/test/algorithms/overlay/get_turns.vcproj index 5e804f12b5..8f1b41c0b3 100644 --- a/test/algorithms/overlay/get_turns.vcproj +++ b/test/algorithms/overlay/get_turns.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/merge_intersection_points.vcproj b/test/algorithms/overlay/merge_intersection_points.vcproj index 1ce9c51225..00afc97f98 100644 --- a/test/algorithms/overlay/merge_intersection_points.vcproj +++ b/test/algorithms/overlay/merge_intersection_points.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/relative_order.vcproj b/test/algorithms/overlay/relative_order.vcproj index c592e7b896..eb577fafe3 100644 --- a/test/algorithms/overlay/relative_order.vcproj +++ b/test/algorithms/overlay/relative_order.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/robustness/interior_triangles.vcproj b/test/algorithms/overlay/robustness/interior_triangles.vcproj index 3d6189d94d..831514b3e7 100644 --- a/test/algorithms/overlay/robustness/interior_triangles.vcproj +++ b/test/algorithms/overlay/robustness/interior_triangles.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../../../..;." - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;TEST_WITH_SVG;BOOST_ALL_NO_LIB" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;BOOST_ALL_NO_LIB" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/robustness/intersection_pies.vcproj b/test/algorithms/overlay/robustness/intersection_pies.vcproj index fdcbb983c9..1ead5e8e9b 100644 --- a/test/algorithms/overlay/robustness/intersection_pies.vcproj +++ b/test/algorithms/overlay/robustness/intersection_pies.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../../../..;." - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;TEST_WITH_SVG;BOOST_ALL_NO_LIB" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;BOOST_ALL_NO_LIB" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/robustness/recursive_polygons.vcproj b/test/algorithms/overlay/robustness/recursive_polygons.vcproj index 7d36aa59c9..b2cc413358 100644 --- a/test/algorithms/overlay/robustness/recursive_polygons.vcproj +++ b/test/algorithms/overlay/robustness/recursive_polygons.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../../../..;." - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;TEST_WITH_SVG;BOOST_ALL_NO_LIB" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;BOOST_ALL_NO_LIB" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/robustness/star_comb.vcproj b/test/algorithms/overlay/robustness/star_comb.vcproj index be2c997c18..01a30306a8 100644 --- a/test/algorithms/overlay/robustness/star_comb.vcproj +++ b/test/algorithms/overlay/robustness/star_comb.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../../../..;." - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;TEST_WITH_SVG;BOOST_ALL_NO_LIB" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;BOOST_ALL_NO_LIB" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/select_rings.vcproj b/test/algorithms/overlay/select_rings.vcproj index ff025e1a53..5706311fc6 100644 --- a/test/algorithms/overlay/select_rings.vcproj +++ b/test/algorithms/overlay/select_rings.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../..;../../../../../boost/geometry/extensions/contrib/ttmath" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/self_intersection_points.vcproj b/test/algorithms/overlay/self_intersection_points.vcproj index ff8c82d9e3..450ea2270f 100644 --- a/test/algorithms/overlay/self_intersection_points.vcproj +++ b/test/algorithms/overlay/self_intersection_points.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/split_rings.vcproj b/test/algorithms/overlay/split_rings.vcproj index 5a828c964a..cb9b6bf78c 100644 --- a/test/algorithms/overlay/split_rings.vcproj +++ b/test/algorithms/overlay/split_rings.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/overlay/traverse.vcproj b/test/algorithms/overlay/traverse.vcproj index 67d10e3609..f5c83a5513 100644 --- a/test/algorithms/overlay/traverse.vcproj +++ b/test/algorithms/overlay/traverse.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../..;../..;../../../../../boost/geometry/extensions/contrib/ttmath" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/algorithms/union.vcproj b/test/algorithms/union.vcproj index 778c689b9d..a3399b777a 100644 --- a/test/algorithms/union.vcproj +++ b/test/algorithms/union.vcproj @@ -43,7 +43,7 @@ AdditionalOptions="/bigobj" Optimization="0" AdditionalIncludeDirectories="../../../..;.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;NONDLL;_CRT_SECURE_NO_WARNINGS" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/geometries/concepts/check.vcproj b/test/geometries/concepts/check.vcproj index 9423f1403c..480b4145bf 100644 --- a/test/geometries/concepts/check.vcproj +++ b/test/geometries/concepts/check.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../../../../boost;../.." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/multi/algorithms/multi_difference.vcproj b/test/multi/algorithms/multi_difference.vcproj index b8e5e85b90..825789743d 100644 --- a/test/multi/algorithms/multi_difference.vcproj +++ b/test/multi/algorithms/multi_difference.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../../..;../..;." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/multi/algorithms/multi_intersection.vcproj b/test/multi/algorithms/multi_intersection.vcproj index 34561cd30a..a286b038c5 100644 --- a/test/multi/algorithms/multi_intersection.vcproj +++ b/test/multi/algorithms/multi_intersection.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../../..;../..;." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/multi/algorithms/multi_union.vcproj b/test/multi/algorithms/multi_union.vcproj index f5f475e767..9adb101458 100644 --- a/test/multi/algorithms/multi_union.vcproj +++ b/test/multi/algorithms/multi_union.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../../../..;../..;." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" diff --git a/test/multi/algorithms/overlay/multi_traverse.vcproj b/test/multi/algorithms/overlay/multi_traverse.vcproj index 4c0d1b1d27..c4cb7b8e07 100644 --- a/test/multi/algorithms/overlay/multi_traverse.vcproj +++ b/test/multi/algorithms/overlay/multi_traverse.vcproj @@ -42,7 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".;../../..;../../../../../..;../../../../../../boost/geometry/extensions/contrib/ttmath;../../../algorithms/overlay" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" From 779aec050b764d334fd936e8e32717c23f627cf0 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 22 May 2011 16:11:58 +0000 Subject: [PATCH 022/135] Added file slipped through merge process [SVN r72084] --- doc/compiling.qbk | 134 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 doc/compiling.qbk diff --git a/doc/compiling.qbk b/doc/compiling.qbk new file mode 100644 index 0000000000..b6e73c91fb --- /dev/null +++ b/doc/compiling.qbk @@ -0,0 +1,134 @@ +[/============================================================================== + Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2008-2011 Bruno Lalande, Paris, France. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK., 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) +===============================================================================/] + + + +[section Compilation] + +[def __msvc__ MSVC] +[def __stlport__ [@http://sourceforge.net/projects/stlport STLport]] + +__boost_geometry__ is a headers-only library. Users only need to include the +library headers in their programs in order to be able to access definitions +and algorithms provided by the __boost_geometry__ library. No linking against +any binaries is required. + +__boost_geometry__ is only dependant on headers-only __boost__ libraries. +It does not introduce indirect dependencies on any binary libraries. + +In order to be able to use __boost_geometry__, the only thing users need to do +is to download and/or install Boost and specify location to include +directories, so `include` directives of this scheme will work: + + #include + +[heading Supported Compilers] + +__boost_geometry__ library has been successfully tested with the following +compilers: + +* __msvc__ (including Express Editions) + * 10.0 (__msvc__ 2010) [/reported by Trunk report May 8, 2011] + * 9.0 (__msvc__ 2008) [/reported by Trunk report May 8, 2011] + * 8.0 (__msvc__ 2005) [/reported by Trunk report May 8, 2011] +* gcc + * gcc 4.6.1 [/reported by Trunk report May 8, 2011] + * gcc 4.6.0 (including C++0x) [/reported by Trunk report May 8, 2011] + * gcc 4.5.2 (including C++0x) [/reported by Trunk report May 8, 2011] + * gcc 4.4.0 [/reported by Trunk report May 8, 2011] + * gcc 4.3.4 [/reported by Trunk report March 26, 2011] + * gcc 4.2.1 [/reported by Trunk report May 8, 2011] + * gcc 3.4.6 [/reported by Trunk report March 26, 2011] +* clang + * clang x.x [/reported by Trunk report March 26, 2011] +* darwin + * darwin 4.0.1 [/reported by Trunk report March 26, 2011] + * darwin 4.4 [/reported by Trunk report March 26, 2011] +* intel + * intel 11.1 [/reported by Trunk report March 26, 2011] + * intel 11.0 [/reported by Trunk report March 26, 2011] + * intel 10.1 [/reported by Trunk report March 26, 2011] +* pathscale + * pathscale 4.0.8 [/reported by Trunk report March 26, 2011] + +__boost_geometry__ uses __boost_bb__, a text-based system for developing and +testing software, to configure, build and execute unit tests and example +programs. The build configuration is provided as a collection of `Jamfile.v2` +files. + +For gcc, flag [^-Wno-long-long] can be used to surpress some warnings +originating from Boost. + +[heading Includes] + +The most convenient headerfile including all algorithms and strategies is +`geometry.hpp`: + + #include + +This is the main header of the __boost_geometry__ library and it is +recommended to include this file. + +Alternatively, it is possible to include __boost_geometry__ header files +separately. However, this may be inconvenient as header files might be renamed +or moved occasionaly in future. + +Another often used header is `geometries.hpp`: + + #include + +This includes definitions of all provided geometry types: point, +linestring, polygon, ring, box. The file `geometries.hpp` is not included in +the `geometry.hpp` headerfile because users should be given the liberty to use +their own geometries and not the provided ones. However, for the +__boost_geometry__ users who want to use the provided geometries it is useful +to include. + +For users using multi-geometries: + + #include + +[heading Advanced Includes] + +Users who have their own geometries and want to use algorithms from +__boost_geometry__ might include the files containing registration +macro's, like: + + #include + +[heading Performance] + +The enumeration below is not exhaustive but can contain hints to improve the +performance: + +* For Microsoft __msvc__, set define `_SECURE_SCL=0` for preprocessor. +* For Microsoft __msvc__, set define `_HAS_ITERATOR_DEBUGGING=0` for preprocessor. +* Use of __stlport__, a popular open-source implementation of the STL, may result in + significantly faster code than use of the C++ standard library provided by __msvc__. +* Turn on compiler optimizations, compile in release mode. + +[heading Problems with Intellisense] + +Both versions of __msvc__, 2005 and 2008 (including Express Editions) can hang +trying to resolve symbols and give [@http://en.wikipedia.org/wiki/IntelliSense +IntelliSense] suggestions while typing in a bracket or angle bracket. +This is not directly related to __boost_geometry__, but is caused by problems +with handling by this IDE large C++ code base with intensively used templates, +such as Boost and __boost_geometry__. If this is inconvenient, IntelliSense +can be turned off: + +[:['["(...)disabling IntelliSense in VC++. There is a file called `feacp.dll` in +`/VC/vcpackages` folder. Renaming this file will disable Intellisense feature.]] + +-- [@http://blogs.msdn.com/yash/archive/2007/09/19/intellisense-issues-in-visual-c-2005.aspx Intellisense issues in Visual C++ 2005] +] + + +[endsect] [/ end of Compilation] From c76cee89328c06778b8a27cdf845f8dd3f8dfa79 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 5 Jun 2011 14:43:07 +0000 Subject: [PATCH 023/135] Boost.Geometry: Merged r72086 through r72406 [SVN r72409] --- doc/src/examples/algorithms/area.cpp | 4 +- .../algorithms/area_with_strategy.cpp | 4 +- .../algorithms/length_with_strategy.cpp | 2 +- doc/src/examples/algorithms/transform.cpp | 9 +- doc/src/examples/core/degree_radian.cpp | 4 +- doc/src/examples/quick_start.cpp | 2 +- example/06_a_transformation_example.cpp | 2 +- example/07_a_graph_route_example.cpp | 2 +- example/07_b_graph_route_example.cpp | 4 +- include/boost/geometry/core/cs.hpp | 30 +++- include/boost/geometry/core/tags.hpp | 8 +- .../agnostic/hull_graham_andrew.hpp | 4 +- .../point_in_poly_oriented_winding.hpp | 2 +- .../agnostic/point_in_poly_winding.hpp | 10 +- .../cartesian/distance_projected_point.hpp | 25 ++- .../strategies/cartesian/side_by_triangle.hpp | 19 ++- .../geometry/strategies/intersection.hpp | 2 +- include/boost/geometry/strategies/side.hpp | 19 ++- .../strategies/spherical/area_huiller.hpp | 68 ++++++--- .../strategies/spherical/compare_circular.hpp | 4 +- .../spherical/distance_cross_track.hpp | 61 +++++++- .../spherical/distance_haversine.hpp | 7 +- .../spherical/side_by_cross_track.hpp | 17 +-- .../geometry/strategies/spherical/ssf.hpp | 137 +++++++++++++++++ .../boost/geometry/strategies/strategies.hpp | 1 + .../strategies/strategy_transform.hpp | 97 +++++++++--- test/algorithms/area.cpp | 102 ++++++++++++- test/algorithms/overlay/ccw_traverse.cpp | 2 +- test/algorithms/overlay/traverse.cpp | 2 +- test/algorithms/overlay/traverse_gmp.cpp | 2 +- test/algorithms/simplify.cpp | 4 +- test/algorithms/test_area.hpp | 1 + test/algorithms/within.cpp | 48 ++++++ test/geometry_test_common.hpp | 23 +++ test/strategies/Jamfile.v2 | 1 + test/strategies/cross_track.cpp | 26 ++-- test/strategies/haversine.cpp | 40 ++--- test/strategies/segment_intersection.cpp | 2 +- .../segment_intersection_collinear.cpp | 2 +- test/strategies/side_by_cross_track.cpp | 54 ------- test/strategies/spherical_side.cpp | 142 ++++++++++++++++++ ...oss_track.vcproj => spherical_side.vcproj} | 10 +- test/strategies/strategies_tests.sln | 2 +- 43 files changed, 789 insertions(+), 218 deletions(-) create mode 100644 include/boost/geometry/strategies/spherical/ssf.hpp delete mode 100644 test/strategies/side_by_cross_track.cpp create mode 100644 test/strategies/spherical_side.cpp rename test/strategies/{side_by_cross_track.vcproj => spherical_side.vcproj} (92%) diff --git a/doc/src/examples/algorithms/area.cpp b/doc/src/examples/algorithms/area.cpp index 5b5ef9179c..e9dfbbf33e 100644 --- a/doc/src/examples/algorithms/area.cpp +++ b/doc/src/examples/algorithms/area.cpp @@ -27,8 +27,8 @@ int main() double area = bg::area(poly); std::cout << "Area: " << area << std::endl; - // Calculate the area of a spherical polygon - bg::model::polygon > > sph_poly; + // Calculate the area of a spherical equatorial polygon + bg::model::polygon > > sph_poly; bg::read_wkt("POLYGON((0 0,0 45,45 0,0 0))", sph_poly); area = bg::area(sph_poly); std::cout << "Area: " << area << std::endl; diff --git a/doc/src/examples/algorithms/area_with_strategy.cpp b/doc/src/examples/algorithms/area_with_strategy.cpp index d471208890..027889a15c 100644 --- a/doc/src/examples/algorithms/area_with_strategy.cpp +++ b/doc/src/examples/algorithms/area_with_strategy.cpp @@ -27,8 +27,8 @@ int main() double area = bg::area(poly); std::cout << "Area: " << area << std::endl; - // Calculate the area of a spherical polygon - bg::model::polygon > > sph_poly; + // Calculate the area of a spherical polygon (for latitude: 0 at equator) + bg::model::polygon > > sph_poly; bg::read_wkt("POLYGON((0 0,0 45,45 0,0 0))", sph_poly); area = bg::area(sph_poly); std::cout << "Area: " << area << std::endl; diff --git a/doc/src/examples/algorithms/length_with_strategy.cpp b/doc/src/examples/algorithms/length_with_strategy.cpp index 2c68f3ae88..564d6a8464 100644 --- a/doc/src/examples/algorithms/length_with_strategy.cpp +++ b/doc/src/examples/algorithms/length_with_strategy.cpp @@ -17,7 +17,7 @@ int main() { using namespace boost::geometry; - typedef model::point > P; + typedef model::point > P; model::linestring

line; line.push_back(P(2, 41)); line.push_back(P(2, 48)); diff --git a/doc/src/examples/algorithms/transform.cpp b/doc/src/examples/algorithms/transform.cpp index feee4ab130..b2fccaad04 100644 --- a/doc/src/examples/algorithms/transform.cpp +++ b/doc/src/examples/algorithms/transform.cpp @@ -18,7 +18,8 @@ int main() { namespace bg = boost::geometry; - bg::model::point > p1(5.0, 52.0); + // Select a point near the pole (theta=5.0, phi=15.0) + bg::model::point > p1(15.0, 5.0); // Transform from degree to radian. Default strategy is automatically selected, // it will convert from degree to radian @@ -45,9 +46,9 @@ int main() /*` Output: [pre -p1: (5, 52) -p2: (0.0872665, 0.907571) -p3: (0.785012, 0.0686797, 0.615661) +p1: (15, 5) +p2: (0.261799, 0.0872665) +p3: (0.084186, 0.0225576, 0.996195) ] */ //] diff --git a/doc/src/examples/core/degree_radian.cpp b/doc/src/examples/core/degree_radian.cpp index 3cd2d3dbac..af27a8652f 100644 --- a/doc/src/examples/core/degree_radian.cpp +++ b/doc/src/examples/core/degree_radian.cpp @@ -17,8 +17,8 @@ using namespace boost::geometry; int main() { - typedef model::point > degree_point; - typedef model::point > radian_point; + typedef model::point > degree_point; + typedef model::point > radian_point; degree_point d(4.893, 52.373); radian_point r(0.041, 0.8527); diff --git a/doc/src/examples/quick_start.cpp b/doc/src/examples/quick_start.cpp index ff96b19c79..7f16a76536 100644 --- a/doc/src/examples/quick_start.cpp +++ b/doc/src/examples/quick_start.cpp @@ -135,7 +135,7 @@ int main(void) //[quick_start_spherical typedef boost::geometry::model::point < - double, 2, boost::geometry::cs::spherical + double, 2, boost::geometry::cs::spherical_equatorial > spherical_point; spherical_point amsterdam(4.90, 52.37); diff --git a/example/06_a_transformation_example.cpp b/example/06_a_transformation_example.cpp index 75440f42ef..a0f0d2d713 100644 --- a/example/06_a_transformation_example.cpp +++ b/example/06_a_transformation_example.cpp @@ -50,7 +50,7 @@ int main() // - from Cartesian to Spherical coordinate systems and back // - from Cartesian to Cartesian (mapping, affine transformations) and back (inverse) // - Map Projections - // - from Degree to Radian and back in spherical or geographic coordinate systems + // - from Degree to Radian and back in spherical_equatorial or geographic coordinate systems return 0; } diff --git a/example/07_a_graph_route_example.cpp b/example/07_a_graph_route_example.cpp index 929af00a1b..8ad672431d 100644 --- a/example/07_a_graph_route_example.cpp +++ b/example/07_a_graph_route_example.cpp @@ -267,7 +267,7 @@ int main() // (geographic calculations are in an extension; for sample it makes no difference) typedef boost::geometry::model::point < - double, 2, boost::geometry::cs::spherical + double, 2, boost::geometry::cs::spherical_equatorial > point_type; typedef boost::geometry::model::linestring line_type; diff --git a/example/07_b_graph_route_example.cpp b/example/07_b_graph_route_example.cpp index 17dbea3a66..c28b3c06e7 100644 --- a/example/07_b_graph_route_example.cpp +++ b/example/07_b_graph_route_example.cpp @@ -249,11 +249,11 @@ inline void build_route(Graph const& graph, int main() { - // Define a point in the Geographic coordinate system (currently Spherical) + // Define a point in the Geographic coordinate system (currently spherical-equatorial) // (geographic calculations are in an extension; for sample it makes no difference) typedef boost::geometry::model::point < - double, 2, boost::geometry::cs::spherical + double, 2, boost::geometry::cs::spherical_equatorial > point_type; typedef boost::geometry::model::linestring line_type; diff --git a/include/boost/geometry/core/cs.hpp b/include/boost/geometry/core/cs.hpp index 93e0eec776..a53d6e278a 100644 --- a/include/boost/geometry/core/cs.hpp +++ b/include/boost/geometry/core/cs.hpp @@ -79,7 +79,7 @@ struct geographic /*! -\brief Spherical coordinate system, in degree or in radian +\brief Spherical (polar) coordinate system, in degree or in radian \details Defines the spherical coordinate system where points are defined in two angles and an optional radius usually known as r, theta, phi @@ -102,6 +102,25 @@ struct spherical typedef DegreeOrRadian units; }; + +/*! +\brief Spherical equatorial coordinate system, in degree or in radian +\details This one resembles the geographic coordinate system, and has latitude + up from zero at the equator, to 90 at the pole + (opposite to the spherical(polar) coordinate system). + Used in astronomy and in GIS (but there is also the geographic) + +\see http://en.wikipedia.org/wiki/Spherical_coordinates +\ingroup cs +*/ +template +struct spherical_equatorial +{ + typedef DegreeOrRadian units; +}; + + + /*! \brief Polar coordinate system \details Defines the polar coordinate system "in which each point @@ -144,9 +163,16 @@ struct cs_tag > template struct cs_tag > { - typedef spherical_tag type; + typedef spherical_polar_tag type; }; +template +struct cs_tag > +{ + typedef spherical_equatorial_tag type; +}; + + template<> struct cs_tag { diff --git a/include/boost/geometry/core/tags.hpp b/include/boost/geometry/core/tags.hpp index 6469b6c11b..f110a079ae 100644 --- a/include/boost/geometry/core/tags.hpp +++ b/include/boost/geometry/core/tags.hpp @@ -24,11 +24,15 @@ namespace boost { namespace geometry /// Tag indicating Cartesian coordinate system family (cartesian,epsg) struct cartesian_tag {}; +/// Tag indicating Spherical polar coordinate system family +struct spherical_polar_tag {}; + +/// Tag indicating Spherical equatorial coordinate system family +struct spherical_equatorial_tag {}; + /// Tag indicating Geographic coordinate system family (geographic) struct geographic_tag {}; -/// Tag indicating Spherical coordinate system family (spherical,celestial,...) -struct spherical_tag {}; // Tags defining tag hierarchy diff --git a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp index 1b91a1c23e..037e390b5c 100644 --- a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp +++ b/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp @@ -301,7 +301,7 @@ public : range_type, range_iterator, container_type, - typename strategy_side::type + typename strategy::side::services::default_strategy::type > assigner(extremes.left, extremes.right); geometry::detail::for_each_range(geometry, assigner); @@ -358,7 +358,7 @@ public : template static inline void add_to_hull(point_type const& p, container_type& output) { - typedef typename strategy_side::type side; + typedef typename strategy::side::services::default_strategy::type side; output.push_back(p); register std::size_t output_size = output.size(); diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp index bb550e61bb..a7ebc7f751 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp @@ -62,7 +62,7 @@ class oriented_winding >::type calculation_type; - typedef typename strategy_side + typedef typename strategy::side::services::default_strategy < typename cs_tag::type >::type strategy_side_type; diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index 373014f156..c98de8ab32 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -58,7 +58,7 @@ class winding >::type calculation_type; - typedef typename strategy_side + typedef typename strategy::side::services::default_strategy < typename cs_tag::type >::type strategy_side_type; @@ -188,7 +188,13 @@ struct default_strategy -struct default_strategy +struct default_strategy +{ + typedef winding type; +}; + +template +struct default_strategy { typedef winding type; }; diff --git a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp index 4378949ea1..063571fc37 100644 --- a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp @@ -116,13 +116,14 @@ public : { assert_dimension_equal(); - /* Algorithm - POINT v(x2 - x1, y2 - y1); - POINT w(px - x1, py - y1); - c1 = w . v - c2 = v . v - b = c1 / c2 - RETURN POINT(x1 + b * vx, y1 + b * vy); + /* + Algorithm [p1: (x1,y1), p2: (x2,y2), p: (px,py)] + VECTOR v(x2 - x1, y2 - y1) + VECTOR w(px - x1, py - y1) + c1 = w . v + c2 = v . v + b = c1 / c2 + RETURN POINT(x1 + b * vx, y1 + b * vy) */ // v is multiplied below with a (possibly) FP-value, so should be in FP @@ -137,21 +138,20 @@ public : Strategy strategy; boost::ignore_unused_variable_warning(strategy); - calculation_type zero = calculation_type(); - fp_type c1 = dot_product(w, v); + calculation_type const zero = calculation_type(); + fp_type const c1 = dot_product(w, v); if (c1 <= zero) { return strategy.apply(p, p1); } - fp_type c2 = dot_product(v, v); + fp_type const c2 = dot_product(v, v); if (c2 <= c1) { return strategy.apply(p, p2); } // See above, c1 > 0 AND c2 > c1 so: c2 != 0 - fp_type b = fp_type(c1) / fp_type(c2); - + fp_type const b = c1 / c2; fp_strategy_type fp_strategy = strategy::distance::services::get_similar @@ -168,7 +168,6 @@ public : return fp_strategy.apply(p, projected); } - }; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index 1236899755..da3c3ed775 100644 --- a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp @@ -21,6 +21,7 @@ #include +#include namespace boost { namespace geometry @@ -90,22 +91,28 @@ public : promoted_type const s = dx * dpy - dy * dpx; promoted_type zero = promoted_type(); - return math::equals(s, zero) ? 0 : s > zero ? 1 : -1; - //return s > 0 ? 1 : s < 0 ? -1 : 0; + return math::equals(s, zero) ? 0 + : s > zero ? 1 + : -1; } }; -}} // namespace strategy::side - #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + template -struct strategy_side +struct default_strategy { - typedef strategy::side::side_by_triangle type; + typedef side_by_triangle type; }; + +} #endif +}} // namespace strategy::side + }} // namespace boost::geometry diff --git a/include/boost/geometry/strategies/intersection.hpp b/include/boost/geometry/strategies/intersection.hpp index 0569101911..234d845d6c 100644 --- a/include/boost/geometry/strategies/intersection.hpp +++ b/include/boost/geometry/strategies/intersection.hpp @@ -77,7 +77,7 @@ private : CalculationType > segment_intersection_strategy_type; - typedef typename strategy_side + typedef typename strategy::side::services::default_strategy < Tag, CalculationType diff --git a/include/boost/geometry/strategies/side.hpp b/include/boost/geometry/strategies/side.hpp index 55a168b773..31587a87c1 100644 --- a/include/boost/geometry/strategies/side.hpp +++ b/include/boost/geometry/strategies/side.hpp @@ -21,6 +21,11 @@ namespace boost { namespace geometry { +namespace strategy { namespace side +{ + +namespace services +{ /*! \brief Traits class binding a side determination strategy to a coordinate system @@ -29,12 +34,22 @@ namespace boost { namespace geometry \tparam CalculationType \tparam_calculation */ template -struct strategy_side +struct default_strategy { - typedef strategy::not_implemented type; + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPE + , (types) + ); }; +} // namespace services + + +}} // namespace strategy::side + + }} // namespace boost::geometry #endif // BOOST_GEOMETRY_STRATEGIES_SIDE_HPP diff --git a/include/boost/geometry/strategies/spherical/area_huiller.hpp b/include/boost/geometry/strategies/spherical/area_huiller.hpp index 23fd0cd64c..0b739dcefb 100644 --- a/include/boost/geometry/strategies/spherical/area_huiller.hpp +++ b/include/boost/geometry/strategies/spherical/area_huiller.hpp @@ -10,7 +10,6 @@ #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP -#include #include @@ -45,6 +44,8 @@ polygons correctly. and works well in most cases but not in 180 meridian crossing cases. This probably could be solved. +\note This version is made for spherical equatorial coordinate systems + \qbk{ [heading Example] @@ -64,10 +65,21 @@ template > class huiller { +typedef typename boost::mpl::if_c + < + boost::is_void::type::value, + typename select_most_precise + < + typename coordinate_type::type, + double + >::type, + CalculationType + >::type calculation_type; + protected : struct excess_sum { - double sum; + calculation_type sum; // Distances are calculated on unit sphere here strategy::distance::haversine @@ -78,18 +90,18 @@ protected : : sum(0) , distance_over_unit_sphere(1) {} - inline double area(double radius) const + inline calculation_type area(calculation_type radius) const { return - sum * radius * radius; } }; public : - typedef double return_type; + typedef calculation_type return_type; typedef PointOfSegment segment_point_type; typedef excess_sum state_type; - inline huiller(double radius = 1.0) + inline huiller(calculation_type radius = 1.0) : m_radius(radius) {} @@ -99,26 +111,25 @@ public : { if (! geometry::math::equals(get<0>(p1), get<0>(p2))) { - namespace mc = boost::math::constants; - - double const two_pi = 2.0 * mc::pi(); - double const half = 0.5; - double const two = 2.0; - double const four = 4.0; + calculation_type const half = 0.5; + calculation_type const two = 2.0; + calculation_type const four = 4.0; + calculation_type const two_pi = two * geometry::math::pi(); + calculation_type const half_pi = half * geometry::math::pi(); // Distance p1 p2 - double a = state.distance_over_unit_sphere.apply(p1, p2); + calculation_type a = state.distance_over_unit_sphere.apply(p1, p2); // Sides on unit sphere to south pole - double b = half * mc::pi() - geometry::get_as_radian<1>(p2); - double c = half * mc::pi() - geometry::get_as_radian<1>(p1); + calculation_type b = half_pi - geometry::get_as_radian<1>(p2); + calculation_type c = half_pi - geometry::get_as_radian<1>(p1); // Semi parameter - double s = half * (a + b + c); + calculation_type s = half * (a + b + c); // E: spherical excess, using l'Huiller's formula // [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2] - double E = four * atan(sqrt(geometry::math::abs(tan(s / two) + calculation_type E = four * atan(sqrt(geometry::math::abs(tan(s / two) * tan((s - a) / two) * tan((s - b) / two) * tan((s - c) / two)))); @@ -130,11 +141,11 @@ public : // we have to take the dateline into account. // TODO: check this / enhance this, should be more robust. See also the "grow" for ll // TODO: use minmax or "smaller"/"compare" strategy for this - double lon1 = geometry::get_as_radian<0>(p1) < 0 + calculation_type lon1 = geometry::get_as_radian<0>(p1) < 0 ? geometry::get_as_radian<0>(p1) + two_pi : geometry::get_as_radian<0>(p1); - double lon2 = geometry::get_as_radian<0>(p2) < 0 + calculation_type lon2 = geometry::get_as_radian<0>(p2) < 0 ? geometry::get_as_radian<0>(p2) + two_pi : geometry::get_as_radian<0>(p2); @@ -154,18 +165,27 @@ public : private : /// Radius of the sphere - double m_radius; + calculation_type m_radius; }; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS namespace services { - template - struct default_strategy - { - typedef strategy::area::huiller type; - }; + + +template +struct default_strategy +{ + typedef strategy::area::huiller type; +}; + +// Note: spherical polar coordinate system requires "get_as_radian_equatorial" +/***template +struct default_strategy +{ + typedef strategy::area::huiller type; +};***/ } // namespace services diff --git a/include/boost/geometry/strategies/spherical/compare_circular.hpp b/include/boost/geometry/strategies/spherical/compare_circular.hpp index e33147c22d..fee1e2b7e1 100644 --- a/include/boost/geometry/strategies/spherical/compare_circular.hpp +++ b/include/boost/geometry/strategies/spherical/compare_circular.hpp @@ -117,7 +117,7 @@ template template class CoordinateSystem, typename Units > -struct strategy_compare, 0> +struct strategy_compare, 0> { typedef typename coordinate_type::type coordinate_type; typedef strategy::compare::circular_comparator @@ -134,7 +134,7 @@ template template class CoordinateSystem, typename Units > -struct strategy_compare, 0> +struct strategy_compare, 0> { typedef typename coordinate_type::type coordinate_type; typedef strategy::compare::circular_comparator diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp index 5c5f3e9a20..f902591bfa 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -219,7 +219,12 @@ struct comparable_type +template +< + typename Point, typename PointOfSegment, + typename CalculationType, + typename Strategy +> struct get_comparable > { typedef typename comparable_type @@ -234,7 +239,12 @@ public : }; -template +template +< + typename Point, typename PointOfSegment, + typename CalculationType, + typename Strategy +> struct result_from_distance > { private : @@ -248,7 +258,12 @@ public : }; -template +template +< + typename Point, typename PointOfSegment, + typename CalculationType, + typename Strategy +> struct strategy_point_point > { typedef Strategy type; @@ -256,9 +271,17 @@ struct strategy_point_point" template -struct default_strategy +struct default_strategy + < + segment_tag, Point, PointOfSegment, + spherical_polar_tag, spherical_polar_tag, + Strategy + > { typedef cross_track < @@ -271,12 +294,40 @@ struct default_strategy::type, Strategy >::type > type; }; +*/ + +template +struct default_strategy + < + segment_tag, Point, PointOfSegment, + spherical_equatorial_tag, spherical_equatorial_tag, + Strategy + > +{ + typedef cross_track + < + Point, + PointOfSegment, + void, + typename boost::mpl::if_ + < + boost::is_void, + typename default_strategy + < + point_tag, Point, PointOfSegment, + spherical_equatorial_tag, spherical_equatorial_tag + >::type, + Strategy + >::type + > type; +}; + } // namespace services diff --git a/include/boost/geometry/strategies/spherical/distance_haversine.hpp b/include/boost/geometry/strategies/spherical/distance_haversine.hpp index 3722de23ca..eb9bf553b3 100644 --- a/include/boost/geometry/strategies/spherical/distance_haversine.hpp +++ b/include/boost/geometry/strategies/spherical/distance_haversine.hpp @@ -306,13 +306,16 @@ public : }; -// Register it as the default for point-types in a spherical coordinate system +// Register it as the default for point-types +// in a spherical equatorial coordinate system template -struct default_strategy +struct default_strategy { typedef strategy::distance::haversine type; }; +// Note: spherical polar coordinate system requires "get_as_radian_equatorial" + } // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS diff --git a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp index 4342fc6ddd..bbae9df902 100644 --- a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp @@ -83,31 +83,18 @@ public : CalculationType >::type coordinate_type; - // Calculate the distance using the Haversine formula. - // That is also applicable on the spherical earth. A radius is not necessary. - double d1 = 0.001; // m_strategy.apply(sp1, p); double crs_AD = detail::course(p1, p); double crs_AB = detail::course(p1, p2); - double XTD = geometry::math::abs(asin(sin(d1) * sin(crs_AD - crs_AB))); + double XTD = asin(sin(d1) * sin(crs_AD - crs_AB)); - return math::equals(XTD, 0) ? 0 : XTD > 0 ? 1 : -1; - //return s > 0 ? 1 : s < 0 ? -1 : 0; + return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1; } }; }} // namespace strategy::side -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -template -struct strategy_side -{ - typedef strategy::side::side_by_cross_track type; -}; -#endif - - }} // namespace boost::geometry diff --git a/include/boost/geometry/strategies/spherical/ssf.hpp b/include/boost/geometry/strategies/spherical/ssf.hpp new file mode 100644 index 0000000000..96a7c379d6 --- /dev/null +++ b/include/boost/geometry/strategies/spherical/ssf.hpp @@ -0,0 +1,137 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2011 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_STRATEGIES_SPHERICAL_SSF_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP + +#include +#include + +#include +#include +#include + +#include +#include + +#include +//#include + + +namespace boost { namespace geometry +{ + + +namespace strategy { namespace side +{ + + +/*! +\brief Check at which side of a segment a point lies: +\details from a Great Circle segment between two points: + left of segment (> 0), right of segment (< 0), on segment (0) +\ingroup strategies +\tparam CalculationType \tparam_calculation + */ +template +class spherical_side_formula +{ + +public : + template + static inline int apply(P1 const& p1, P2 const& p2, P const& p) + { + typedef typename boost::mpl::if_c + < + boost::is_void::type::value, + + // Select at least a double... + typename select_most_precise + < + typename select_most_precise + < + typename select_most_precise + < + typename coordinate_type::type, + typename coordinate_type::type + >::type, + typename coordinate_type

::type + >::type, + double + >::type, + CalculationType + >::type coordinate_type; + + // Convenient shortcuts + typedef coordinate_type ct; + ct const lambda1 = get_as_radian<0>(p1); + ct const delta1 = get_as_radian<1>(p1); + ct const lambda2 = get_as_radian<0>(p2); + ct const delta2 = get_as_radian<1>(p2); + ct const lambda = get_as_radian<0>(p); + ct const delta = get_as_radian<1>(p); + + // Create temporary points (vectors) on unit a sphere + ct const cos_delta1 = cos(delta1); + ct const c1x = cos_delta1 * cos(lambda1); + ct const c1y = cos_delta1 * sin(lambda1); + ct const c1z = sin(delta1); + + ct const cos_delta2 = cos(delta2); + ct const c2x = cos_delta2 * cos(lambda2); + ct const c2y = cos_delta2 * sin(lambda2); + ct const c2z = sin(delta2); + + // (Third point is converted directly) + ct const cos_delta = cos(delta); + + // Apply the "Spherical Side Formula" as presented on my blog + ct const dist + = (c1y * c2z - c1z * c2y) * cos_delta * cos(lambda) + + (c1z * c2x - c1x * c2z) * cos_delta * sin(lambda) + + (c1x * c2y - c1y * c2x) * sin(delta); + + ct zero = ct(); + return dist > zero ? 1 + : dist < zero ? -1 + : 0; + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +/*template +struct default_strategy +{ + typedef spherical_side_formula type; +};*/ + +template +struct default_strategy +{ + typedef spherical_side_formula type; +}; + +template +struct default_strategy +{ + typedef spherical_side_formula type; +}; + +} +#endif + +}} // namespace strategy::side + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index 30668342d1..25369a7bfb 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/geometry/strategies/strategy_transform.hpp b/include/boost/geometry/strategies/strategy_transform.hpp index 35c6a4526e..34e19fc774 100644 --- a/include/boost/geometry/strategies/strategy_transform.hpp +++ b/include/boost/geometry/strategies/strategy_transform.hpp @@ -155,26 +155,48 @@ namespace detail /// Helper function for conversion, phi/theta are in radians template - inline void spherical_to_cartesian(T phi, T theta, R r, P& p) + inline void spherical_polar_to_cartesian(T phi, T theta, R r, P& p) { assert_dimension(); // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_spherical_coordinates + // http://www.vias.org/comp_geometry/math_coord_convert_3d.htm + // https://moodle.polymtl.ca/file.php/1183/Autres_Documents/Derivation_for_Spherical_Co-ordinates.pdf + // http://en.citizendium.org/wiki/Spherical_polar_coordinates + // Phi = first, theta is second, r is third, see documentation on cs::spherical // (calculations are splitted to implement ttmath) T r_sin_theta = r; + T r_cos_theta = r; r_sin_theta *= sin(theta); + r_cos_theta *= cos(theta); set<0>(p, r_sin_theta * cos(phi)); set<1>(p, r_sin_theta * sin(phi)); - - T r_cos_theta = r; - r_cos_theta *= cos(theta); - set<2>(p, r_cos_theta); } + + /// Helper function for conversion, lambda/delta (lon lat) are in radians + template + inline void spherical_equatorial_to_cartesian(T lambda, T delta, R r, P& p) + { + assert_dimension(); + + // http://mathworld.wolfram.com/GreatCircle.html + // http://www.spenvis.oma.be/help/background/coortran/coortran.html WRONG + + T r_cos_delta = r; + T r_sin_delta = r; + r_cos_delta *= cos(delta); + r_sin_delta *= sin(delta); + + set<0>(p, r_cos_delta * cos(lambda)); + set<1>(p, r_cos_delta * sin(lambda)); + set<2>(p, r_sin_delta); + } + /// Helper function for conversion template @@ -230,16 +252,28 @@ namespace detail \tparam P2 second point type */ template -struct from_spherical_2_to_cartesian_3 +struct from_spherical_polar_2_to_cartesian_3 +{ + inline bool apply(P1 const& p1, P2& p2) const + { + assert_dimension(); + detail::spherical_polar_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2); + return true; + } +}; + +template +struct from_spherical_equatorial_2_to_cartesian_3 { inline bool apply(P1 const& p1, P2& p2) const { assert_dimension(); - detail::spherical_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2); + detail::spherical_equatorial_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2); return true; } }; + /*! \brief Transformation strategy for 3D spherical (phi,theta,r) to 3D cartesian (x,y,z) \ingroup transform @@ -247,17 +281,30 @@ struct from_spherical_2_to_cartesian_3 \tparam P2 second point type */ template -struct from_spherical_3_to_cartesian_3 +struct from_spherical_polar_3_to_cartesian_3 +{ + inline bool apply(P1 const& p1, P2& p2) const + { + assert_dimension(); + detail::spherical_polar_to_cartesian( + get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2); + return true; + } +}; + +template +struct from_spherical_equatorial_3_to_cartesian_3 { inline bool apply(P1 const& p1, P2& p2) const { assert_dimension(); - detail::spherical_to_cartesian( + detail::spherical_equatorial_to_cartesian( get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2); return true; } }; + /*! \brief Transformation strategy for 3D cartesian (x,y,z) to 2D spherical (phi,theta) \details on Unit sphere @@ -267,7 +314,7 @@ struct from_spherical_3_to_cartesian_3 \note If x,y,z point is not lying on unit sphere, transformation will return false */ template -struct from_cartesian_3_to_spherical_2 +struct from_cartesian_3_to_spherical_polar_2 { inline bool apply(P1 const& p1, P2& p2) const { @@ -284,7 +331,7 @@ struct from_cartesian_3_to_spherical_2 \tparam P2 second point type */ template -struct from_cartesian_3_to_spherical_3 +struct from_cartesian_3_to_spherical_polar_3 { inline bool apply(P1 const& p1, P2& p2) const { @@ -343,30 +390,42 @@ struct default_strategy, CoordSys -struct default_strategy +struct default_strategy { - typedef from_spherical_2_to_cartesian_3 type; + typedef from_spherical_polar_2_to_cartesian_3 type; }; /// Specialization to transform from sphere(phi,theta,r) to XYZ template -struct default_strategy +struct default_strategy +{ + typedef from_spherical_polar_3_to_cartesian_3 type; +}; + +template +struct default_strategy +{ + typedef from_spherical_equatorial_2_to_cartesian_3 type; +}; + +template +struct default_strategy { - typedef from_spherical_3_to_cartesian_3 type; + typedef from_spherical_equatorial_3_to_cartesian_3 type; }; /// Specialization to transform from XYZ to unit sphere(phi,theta) template -struct default_strategy +struct default_strategy { - typedef from_cartesian_3_to_spherical_2 type; + typedef from_cartesian_3_to_spherical_polar_2 type; }; /// Specialization to transform from XYZ to sphere(phi,theta,r) template -struct default_strategy +struct default_strategy { - typedef from_cartesian_3_to_spherical_3 type; + typedef from_cartesian_3_to_spherical_polar_3 type; }; diff --git a/test/algorithms/area.cpp b/test/algorithms/area.cpp index 4ed4e70095..2cf80569f7 100644 --- a/test/algorithms/area.cpp +++ b/test/algorithms/area.cpp @@ -13,8 +13,6 @@ // http://www.boost.org/LICENSE_1_0.txt) -#include - #include #include @@ -60,15 +58,19 @@ void test_all() } template -void test_spherical() +void test_spherical(bool polar = false) { + typedef typename bg::coordinate_type::type ct; bg::model::polygon geometry; // unit-sphere has area of 4-PI. Polygon covering 1/8 of it: - double expected = 4.0 * boost::math::constants::pi() / 8.0; + // calculations splitted for ttmath + ct const four = 4.0; + ct const eight = 8.0; + ct expected = four * boost::geometry::math::pi() / eight; bg::read_wkt("POLYGON((0 0,0 90,90 0,0 0))", geometry); - double area = bg::area(geometry); + ct area = bg::area(geometry); BOOST_CHECK_CLOSE(area, expected, 0.0001); // With strategy, radius 2 -> 4 pi r^2 @@ -78,7 +80,91 @@ void test_spherical() > strategy(2.0); area = bg::area(geometry, strategy); - BOOST_CHECK_CLOSE(area, 2.0 * 2.0 * expected, 0.0001); + ct const two = 2.0; + BOOST_CHECK_CLOSE(area, two * two * expected, 0.0001); + + // Wrangel Island (dateline crossing) + // With (spherical) Earth strategy + bg::strategy::area::huiller + < + typename bg::point_type::type + > spherical_earth(6373); + bg::read_wkt("POLYGON((-178.7858 70.7852, 177.4758 71.2333, 179.7436 71.5733, -178.7858 70.7852))", geometry); + area = bg::area(geometry, spherical_earth); + // SQL Server gives: 4537.9654419375 + // PostGIS gives: 4537.9311668307 + // Note: those are Geographic, this test is Spherical + BOOST_CHECK_CLOSE(area, 4506.6389, 0.001); + + // Wrangel, more in detail + bg::read_wkt("POLYGON((-178.568604 71.564148,-178.017548 71.449692,-177.833313 71.3461,-177.502838 71.277466 ,-177.439453 71.226929,-177.620026 71.116638,-177.9389 71.037491,-178.8186 70.979965,-179.274445 70.907761,-180 70.9972,179.678314 70.895538,179.272766 70.888596,178.791016 70.7964,178.617737 71.035538,178.872192 71.217484,179.530273 71.4383 ,-180 71.535843 ,-179.628601 71.577194,-179.305298 71.551361,-179.03421 71.597748,-178.568604 71.564148))", geometry); + area = bg::area(geometry, spherical_earth); + // SQL Server gives: 7669.10402181435 + // PostGIS gives: 7669.55565459832 + BOOST_CHECK_CLOSE(area, 7616.523769, 0.001); + + // Check more at the equator + /* + select 1,geography::STGeomFromText('POLYGON((-178.7858 10.7852 , 179.7436 11.5733 , 177.4758 11.2333 , -178.7858 10.7852))',4326) .STArea()/1000000.0 + union select 2,geography::STGeomFromText('POLYGON((-178.7858 20.7852 , 179.7436 21.5733 , 177.4758 21.2333 , -178.7858 20.7852))',4326) .STArea()/1000000.0 + union select 3,geography::STGeomFromText('POLYGON((-178.7858 30.7852 , 179.7436 31.5733 , 177.4758 31.2333 , -178.7858 30.7852))',4326) .STArea()/1000000.0 + union select 0,geography::STGeomFromText('POLYGON((-178.7858 0.7852 , 179.7436 1.5733 , 177.4758 1.2333 , -178.7858 0.7852))',4326) .STArea()/1000000.0 + union select 4,geography::STGeomFromText('POLYGON((-178.7858 40.7852 , 179.7436 41.5733 , 177.4758 41.2333 , -178.7858 40.7852))',4326) .STArea()/1000000.0 + */ + + bg::read_wkt("POLYGON((-178.7858 0.7852, 177.4758 1.2333, 179.7436 1.5733, -178.7858 0.7852))", geometry); + area = bg::area(geometry, spherical_earth); + BOOST_CHECK_CLOSE(area, 14136.09946, 0.001); // SQL Server gives: 14064.1902284513 + + + bg::read_wkt("POLYGON((-178.7858 10.7852, 177.4758 11.2333, 179.7436 11.5733, -178.7858 10.7852))", geometry); + area = bg::area(geometry, spherical_earth); + BOOST_CHECK_CLOSE(area, 13760.2456, 0.001); // SQL Server gives: 13697.0941155193 + + bg::read_wkt("POLYGON((-178.7858 20.7852, 177.4758 21.2333, 179.7436 21.5733, -178.7858 20.7852))", geometry); + area = bg::area(geometry, spherical_earth); + BOOST_CHECK_CLOSE(area, 12987.8682, 0.001); // SQL Server gives: 12944.3970990317 -> -39m^2 + + bg::read_wkt("POLYGON((-178.7858 30.7852, 177.4758 31.2333, 179.7436 31.5733, -178.7858 30.7852))", geometry); + area = bg::area(geometry, spherical_earth); + BOOST_CHECK_CLOSE(area, 11856.3935, 0.001); // SQL Server gives: 11838.5338423574 -> -18m^2 + + bg::read_wkt("POLYGON((-178.7858 40.7852, 177.4758 41.2333, 179.7436 41.5733, -178.7858 40.7852))", geometry); + area = bg::area(geometry, spherical_earth); + BOOST_CHECK_CLOSE(area, 10404.627685523914, 0.001); // SQL Server gives: 10412.0607137119, -> +8m^2 + + // Concave + bg::read_wkt("POLYGON((0 40,1 42,0 44,2 43,4 44,3 42,4 40,2 41,0 40))", geometry); + area = bg::area(geometry, spherical_earth); + BOOST_CHECK_CLOSE(area, 73538.2958, 0.001); // SQL Server gives: 73604.2047689719 + + // With hole POLYGON((0 40,4 40,4 44,0 44,0 40),(1 41,2 43,3 42,1 41)) + bg::read_wkt("POLYGON((0 40,0 44,4 44,4 40,0 40),(1 41,3 42,2 43,1 41))", geometry); + area = bg::area(geometry, spherical_earth); + BOOST_CHECK_CLOSE(area, 133233.844876, 0.001); // SQL Server gives: 133353.335 + + { + bg::model::ring aurha; // a'dam-utr-rott.-den haag-a'dam + bg::read_wkt("POLYGON((4.892 52.373,5.119 52.093,4.479 51.930,4.23 52.08,4.892 52.373))", aurha); + if (polar) + { + // Create colatitudes (measured from pole) + BOOST_FOREACH(Point& p, aurha) + { + bg::set<1>(p, ct(90) - bg::get<1>(p)); + } + bg::correct(aurha); + } + bg::strategy::area::huiller + < + typename bg::point_type::type + > huiller(6372.795); + area = bg::area(aurha, huiller); + BOOST_CHECK_CLOSE(area, 1476.645675, 0.0001); + + // SQL Server gives: 1481.55595960659 + // for select geography::STGeomFromText('POLYGON((4.892 52.373,4.23 52.08,4.479 51.930,5.119 52.093,4.892 52.373))',4326).STArea()/1000000.0 + } } template @@ -116,7 +202,8 @@ int test_main(int, char* []) test_all >(); test_all >(); - test_spherical > >(); + test_spherical > >(); + //test_spherical > >(true); test_ccw >(); test_open >(); @@ -124,6 +211,7 @@ int test_main(int, char* []) #ifdef HAVE_TTMATH test_all >(); + test_spherical > >(); #endif return 0; diff --git a/test/algorithms/overlay/ccw_traverse.cpp b/test/algorithms/overlay/ccw_traverse.cpp index 82f9d3b1e5..463ecdbde4 100644 --- a/test/algorithms/overlay/ccw_traverse.cpp +++ b/test/algorithms/overlay/ccw_traverse.cpp @@ -35,7 +35,7 @@ template inline typename bg::coordinate_type::type intersect(Geometry1 const& g1, Geometry2 const& g2, std::string const& name, bg::detail::overlay::operation_type op) { - typedef typename bg::strategy_side + typedef typename bg::strategy::side::services::default_strategy < typename bg::cs_tag::type >::type side_strategy_type; diff --git a/test/algorithms/overlay/traverse.cpp b/test/algorithms/overlay/traverse.cpp index baf0653cbf..480b204aa0 100644 --- a/test/algorithms/overlay/traverse.cpp +++ b/test/algorithms/overlay/traverse.cpp @@ -134,7 +134,7 @@ struct test_traverse //std::cout << bg::area(g1) << " " << bg::area(g2) << std::endl; #endif - typedef typename bg::strategy_side + typedef typename bg::strategy::side::services::default_strategy < typename bg::cs_tag::type >::type side_strategy_type; diff --git a/test/algorithms/overlay/traverse_gmp.cpp b/test/algorithms/overlay/traverse_gmp.cpp index b8d6a4272c..24a4b2116b 100644 --- a/test/algorithms/overlay/traverse_gmp.cpp +++ b/test/algorithms/overlay/traverse_gmp.cpp @@ -62,7 +62,7 @@ void test_traverse(std::string const& caseid, G1 const& g1, G2 const& g2) typedef std::vector ip_vector; ip_vector ips; - typedef typename bg::strategy_side + typedef typename bg::strategy::side::services::default_strategy < typename bg::cs_tag::type >::type strategy_type; diff --git a/test/algorithms/simplify.cpp b/test/algorithms/simplify.cpp index 2555a638e0..09ca32135c 100644 --- a/test/algorithms/simplify.cpp +++ b/test/algorithms/simplify.cpp @@ -96,11 +96,11 @@ int test_main(int, char* []) test_all >(); test_all >(); - test_spherical > >(); + test_spherical > >(); #if defined(HAVE_TTMATH) test_all >(); - test_spherical > >(); + test_spherical > >(); #endif return 0; diff --git a/test/algorithms/test_area.hpp b/test/algorithms/test_area.hpp index 5441bcffc8..bf7d7a021b 100644 --- a/test/algorithms/test_area.hpp +++ b/test/algorithms/test_area.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include diff --git a/test/algorithms/within.cpp b/test/algorithms/within.cpp index ad59f4d789..b8820f99b1 100644 --- a/test/algorithms/within.cpp +++ b/test/algorithms/within.cpp @@ -62,7 +62,51 @@ void test_all() true, false); } +template +void test_spherical() +{ + typedef typename bg::coordinate_type::type ct; + bg::model::polygon wrangel; + + // SQL Server check (no geography::STWithin, so check with intersection trick) + /* + + with q as ( + select geography::STGeomFromText('POLYGON((-178.569 71.5641,-179.034 71.5977,-179.305 71.5514,-179.629 71.5772,-180 71.5358,179.53 71.4383,178.872 71.2175,178.618 71.0355,178.791 70.7964,179.273 70.8886,179.678 70.8955,-180 70.9972,-179.274 70.9078,-178.819 70.98,-177.939 71.0375,-177.62 71.1166,-177.439 71.2269,-177.503 71.2775,-177.833 71.3461,-178.018 71.4497,-178.569 71.5641))',4326) as wrangel + ) + + select wrangel.STArea()/1000000.0 + ,geography::STGeomFromText('POINT(-179.3 71.27)',4326).STIntersection(wrangel).STAsText() as workaround_within_1 + ,geography::STGeomFromText('POINT(-179.9 70.95)',4326).STIntersection(wrangel).STAsText() as workaround_within_2 + ,geography::STGeomFromText('POINT(179.9 70.95)',4326).STIntersection(wrangel).STAsText() as workaround_within_3 + from q + + -> 7669.10402181435 POINT (-179.3 71.27) GEOMETRYCOLLECTION EMPTY GEOMETRYCOLLECTION EMPTY + + PostGIS knows Within for Geography neither, and the intersection trick gives the same result + + */ + + bg::read_wkt("POLYGON((-178.568604 71.564148,-178.017548 71.449692,-177.833313 71.3461,-177.502838 71.277466 ,-177.439453 71.226929,-177.620026 71.116638,-177.9389 71.037491,-178.8186 70.979965,-179.274445 70.907761,-180 70.9972,179.678314 70.895538,179.272766 70.888596,178.791016 70.7964,178.617737 71.035538,178.872192 71.217484,179.530273 71.4383 ,-180 71.535843 ,-179.628601 71.577194,-179.305298 71.551361,-179.03421 71.597748,-178.568604 71.564148))", wrangel); + bool within = bg::within(Point(-179.3, 71.27), wrangel); + BOOST_CHECK_EQUAL(within, true); + + within = bg::within(Point(-179.9, 70.95), wrangel); + BOOST_CHECK_EQUAL(within, false); + + within = bg::within(Point(179.9, 70.95), wrangel); + BOOST_CHECK_EQUAL(within, false); + + // Test using great circle mapper + // http://www.gcmap.com/mapui?P=5E52N-9E53N-7E50N-5E52N,7E52.5N,8E51.5N,6E51N + + bg::model::polygon triangle; + bg::read_wkt("POLYGON((5 52,9 53,7 50,5 52))", triangle); + BOOST_CHECK_EQUAL(bg::within(Point(7, 52.5), triangle), true); + BOOST_CHECK_EQUAL(bg::within(Point(8.0, 51.5), triangle), false); + BOOST_CHECK_EQUAL(bg::within(Point(6.0, 51.0), triangle), false); +} int test_main( int , char* [] ) @@ -70,8 +114,12 @@ int test_main( int , char* [] ) test_all >(); test_all >(); + test_spherical > >(); + + #if defined(HAVE_TTMATH) test_all >(); + test_spherical > >(); #endif return 0; diff --git a/test/geometry_test_common.hpp b/test/geometry_test_common.hpp index 9fbe8b26d2..0af0a83408 100644 --- a/test/geometry_test_common.hpp +++ b/test/geometry_test_common.hpp @@ -94,6 +94,29 @@ template <> struct string_from_type #endif + +struct geographic_policy +{ + template + static inline CoordinateType apply(CoordinateType const& value) + { + return value; + } +}; + +struct mathematical_policy +{ + template + static inline CoordinateType apply(CoordinateType const& value) + { + return 90 - value; + } + +}; + + + + // For all tests: // - do NOT use "using namespace boost::geometry" to make clear what is Boost.Geometry // - use bg:: as short alias diff --git a/test/strategies/Jamfile.v2 b/test/strategies/Jamfile.v2 index 87e1a74e2e..08bfeea897 100644 --- a/test/strategies/Jamfile.v2 +++ b/test/strategies/Jamfile.v2 @@ -14,6 +14,7 @@ test-suite boost-geometry-strategies [ run haversine.cpp ] [ run projected_point.cpp ] [ run pythagoras.cpp ] + [ run spherical_side.cpp ] [ run transformer.cpp ] [ run within.cpp ] ; diff --git a/test/strategies/cross_track.cpp b/test/strategies/cross_track.cpp index f53f6255b9..debc5aba8f 100644 --- a/test/strategies/cross_track.cpp +++ b/test/strategies/cross_track.cpp @@ -28,9 +28,10 @@ #include +// This test is GIS oriented. -template +template void test_distance( typename bg::coordinate_type::type const& lon1, typename bg::coordinate_type::type const& lat1, @@ -60,9 +61,9 @@ void test_distance( Point p1, p2, p3; - bg::assign_values(p1, lon1, lat1); - bg::assign_values(p2, lon2, lat2); - bg::assign_values(p3, lon3, lat3); + bg::assign_values(p1, lon1, LatitudePolicy::apply(lat1)); + bg::assign_values(p2, lon2, LatitudePolicy::apply(lat2)); + bg::assign_values(p3, lon3, LatitudePolicy::apply(lat3)); strategy_type strategy; @@ -83,29 +84,30 @@ void test_distance( } - -template +template void test_all() { typename bg::coordinate_type::type const average_earth_radius = 6372795.0; // distance (Paris <-> Amsterdam/Barcelona), // with coordinates rounded as below ~87 km - // should be is equal - // to distance (Paris <-> Barcelona/Amsterdam) + // is equal to distance (Paris <-> Barcelona/Amsterdam) typename bg::coordinate_type::type const p_to_ab = 86.798321 * 1000.0; - test_distance(2, 48, 4, 52, 2, 41, average_earth_radius, p_to_ab, 0.1); - test_distance(2, 48, 2, 41, 4, 52, average_earth_radius, p_to_ab, 0.1); + test_distance(2, 48, 4, 52, 2, 41, average_earth_radius, p_to_ab, 0.1); + test_distance(2, 48, 2, 41, 4, 52, average_earth_radius, p_to_ab, 0.1); } int test_main(int, char* []) { - test_all > >(); + test_all >, geographic_policy >(); + + // NYI: haversine for mathematical spherical coordinate systems + // test_all >, mathematical_policya >(); #if defined(HAVE_TTMATH) typedef ttmath::Big<1,4> tt; - //test_all > >(); + //test_all >, geographic_policy>(); #endif return 0; diff --git a/test/strategies/haversine.cpp b/test/strategies/haversine.cpp index 3ad5458780..7da7206521 100644 --- a/test/strategies/haversine.cpp +++ b/test/strategies/haversine.cpp @@ -34,7 +34,7 @@ double const average_earth_radius = 6372795.0; -template +template struct test_distance { typedef bg::strategy::distance::haversine @@ -60,15 +60,15 @@ struct test_distance haversine_type strategy(radius); Point p1, p2; - bg::assign_values(p1, lon1, lat1); - bg::assign_values(p2, lon2, lat2); + bg::assign_values(p1, lon1, LatitudePolicy::apply(lat1)); + bg::assign_values(p2, lon2, LatitudePolicy::apply(lat2)); return_type d = strategy.apply(p1, p2); BOOST_CHECK_CLOSE(d, expected, tolerance); } }; -template +template void test_all() { // earth to unit-sphere -> divide by earth circumference, then it is from 0-1, @@ -77,19 +77,19 @@ void test_all() // ~ Amsterdam/Paris, 467 kilometers double const a_p = 467.2704 * 1000.0; - test_distance::test(4, 52, 2, 48, average_earth_radius, a_p, 1.0); - test_distance::test(2, 48, 4, 52, average_earth_radius, a_p, 1.0); - test_distance::test(4, 52, 2, 48, 1.0, a_p * e2u, 0.001); + test_distance::test(4, 52, 2, 48, average_earth_radius, a_p, 1.0); + test_distance::test(2, 48, 4, 52, average_earth_radius, a_p, 1.0); + test_distance::test(4, 52, 2, 48, 1.0, a_p * e2u, 0.001); // ~ Amsterdam/Barcelona double const a_b = 1232.9065 * 1000.0; - test_distance::test(4, 52, 2, 41, average_earth_radius, a_b, 1.0); - test_distance::test(2, 41, 4, 52, average_earth_radius, a_b, 1.0); - test_distance::test(4, 52, 2, 41, 1.0, a_b * e2u, 0.001); + test_distance::test(4, 52, 2, 41, average_earth_radius, a_b, 1.0); + test_distance::test(2, 41, 4, 52, average_earth_radius, a_b, 1.0); + test_distance::test(4, 52, 2, 41, 1.0, a_b * e2u, 0.001); } -template +template void test_services() { namespace bgsd = bg::strategy::distance; @@ -244,9 +244,12 @@ double time_normal(int n) int test_main(int, char* []) { - test_all > >(); - test_all > >(); - test_all > >(); + test_all >, geographic_policy>(); + test_all >, geographic_policy>(); + test_all >, geographic_policy>(); + + // NYI: haversine for mathematical spherical coordinate systems + // test_all >, mathematical_policy>(); //double t1 = time_sqrt(20000); //double t2 = time_normal(20000); @@ -255,15 +258,16 @@ int test_main(int, char* []) #if defined(HAVE_TTMATH) typedef ttmath::Big<1,4> tt; - test_all > >(); + test_all >, geographic_policy>(); #endif test_services < - bg::model::point >, - bg::model::point >, - double + bg::model::point >, + bg::model::point >, + double, + geographic_policy >(); return 0; diff --git a/test/strategies/segment_intersection.cpp b/test/strategies/segment_intersection.cpp index d68b6ee5cd..5dfe3ed0f3 100644 --- a/test/strategies/segment_intersection.cpp +++ b/test/strategies/segment_intersection.cpp @@ -91,7 +91,7 @@ static void test_segment_intersection(int caseno, #endif typedef typename bg::coordinate_type

::type coordinate_type; - typedef segment segment_type; + typedef bg::model::referring_segment segment_type; P p1, p2, p3, p4; bg::assign_values(p1, x1, y1); diff --git a/test/strategies/segment_intersection_collinear.cpp b/test/strategies/segment_intersection_collinear.cpp index 3c02f39adf..ea28f9cc5b 100644 --- a/test/strategies/segment_intersection_collinear.cpp +++ b/test/strategies/segment_intersection_collinear.cpp @@ -64,7 +64,7 @@ static void test_segment_intersection(std::string const& case_id, //#endif typedef typename bg::coordinate_type

::type coordinate_type; - typedef bg::segment segment_type; + typedef bg::model::referring_segment segment_type; P p1, p2, p3, p4; bg::assign_values(p1, x1, y1); diff --git a/test/strategies/side_by_cross_track.cpp b/test/strategies/side_by_cross_track.cpp deleted file mode 100644 index e02f3267d2..0000000000 --- a/test/strategies/side_by_cross_track.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// Unit Test - -// Copyright (c) 2007-2011 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) - - -#include - -#include - -#include - -#include - -#include -#include - - -template -void test_side(double lon1, double lat1, - double lon2, double lat2, - double lon3, double lat3, - int expected) -{ - typedef bg::strategy::side::side_by_cross_track strategy; - - Point p1, p2, p3; - bg::assign_values(p1, lon1, lat1); - bg::assign_values(p2, lon2, lat2); - bg::assign_values(p3, lon3, lat3); - int s = strategy::apply(p1, p2, p3); - -} - -template -void test_all() -{ - test_side(2.0, 48.0, 4.0, 52.0, 2.0, 41.0, 1); - test_side(2.0, 48.0, 2.0, 41.0, 4.0, 52.0, -1); -} - -int test_main(int, char* []) -{ - test_all > >(); - - double a = 0; - double b = sin(a); - - return 0; -} diff --git a/test/strategies/spherical_side.cpp b/test/strategies/spherical_side.cpp new file mode 100644 index 0000000000..5410c69928 --- /dev/null +++ b/test/strategies/spherical_side.cpp @@ -0,0 +1,142 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2011 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) + + +#include + + +#include + + +#include +//#include +#include +#include + +#include + +#include +#include + + +namespace boost { namespace geometry { + +template +static inline Vector create_vector(Point1 const& p1, Point2 const& p2) +{ + Vector v; + convert(p1, v); + subtract_point(v, p2); + return v; +} + +}} + +inline char side_char(int side) +{ + return side == 1 ? 'L' + : side == -1 ? 'R' + : '-' + ; +} + +template +void test_side1(std::string const& case_id, Point const& p1, Point const& p2, Point const& p3, + int expected, int expected_cartesian) +{ + // std::cout << case_id << ": "; + //int s = bg::strategy::side::side_via_plane<>::apply(p1, p2, p3); + int side_ssf = bg::strategy::side::spherical_side_formula<>::apply(p1, p2, p3); + //int side2 = bg::strategy::side::side_via_plane<>::apply(p1, p2, p3); + int side_ct = bg::strategy::side::side_by_cross_track<>::apply(p1, p2, p3); + + typedef bg::strategy::side::services::default_strategy::type cartesian_strategy; + int side_cart = cartesian_strategy::apply(p1, p2, p3); + + + BOOST_CHECK_EQUAL(side_ssf, expected); + BOOST_CHECK_EQUAL(side_ct, expected); + BOOST_CHECK_EQUAL(side_cart, expected_cartesian); + /* + std::cout + << "exp: " << side_char(expected) + << " ssf: " << side_char(side1) + << " pln: " << side_char(side2) + << " ct: " << side_char(side3) + //<< " def: " << side_char(side4) + << " cart: " << side_char(side5) + << std::endl; + */ +} + +template +void test_side(std::string const& case_id, Point const& p1, Point const& p2, Point const& p3, + int expected, int expected_cartesian = -999) +{ + if (expected_cartesian == -999) + { + expected_cartesian = expected; + } + test_side1(case_id, p1, p2, p3, expected, expected_cartesian); + test_side1(case_id, p2, p1, p3, -expected, -expected_cartesian); +} + + +template +void test_all() +{ + typedef std::pair pair; + + Point amsterdam(5.9, 52.4); + Point barcelona(2.0, 41.0); + Point paris(2.0, 48.0); + Point milan(7.0, 45.0); + + //goto wrong; + + test_side("bp-m", barcelona, paris, milan, -1); + test_side("bm-p", barcelona, milan, paris, 1); + test_side("mp-b", milan, paris, barcelona, 1); + + test_side("am-p", amsterdam, milan, paris, -1); + test_side("pm-a", paris, milan, amsterdam, 1); + + // http://www.gcmap.com/mapui?P=30N+10E-50N+50E,39N+30E + Point gcmap_p1(10.0, 30.0); + Point gcmap_p2(50.0, 50.0); + test_side("blog1", gcmap_p1, gcmap_p2, Point(30.0, 41.0), -1, 1); + test_side("blog1", gcmap_p1, gcmap_p2, Point(30.0, 42.0), -1, 1); + test_side("blog1", gcmap_p1, gcmap_p2, Point(30.0, 43.0), -1, 1); + test_side("blog1", gcmap_p1, gcmap_p2, Point(30.0, 44.0), 1); + + // http://www.gcmap.com/mapui?P=50N+80E-60N+50W,65N+30E + Point gcmap_np1(80.0, 50.0); + Point gcmap_np2(-50.0, 60.0); + // http://www.gcmap.com/mapui?P=50N+140E-60N+10E,65N+30E + //Point gcmap_np1(140.0, 50.0); + //Point gcmap_np2(10.0, 60.0); + //test_side(gcmap_np1, gcmap_np2, gcmap_np, 1); + test_side("40", gcmap_np1, gcmap_np2, Point(30.0, 60.0), 1, -1); + test_side("45", gcmap_np1, gcmap_np2, Point(30.0, 65.0), 1, -1); + test_side("70", gcmap_np1, gcmap_np2, Point(30.0, 70.0), 1, -1); + test_side("75", gcmap_np1, gcmap_np2, Point(30.0, 75.0), -1); +} + +int test_main(int, char* []) +{ + test_all > >(); + test_all > >(); + +#if defined(HAVE_TTMATH) + typedef ttmath::Big<1,4> tt; + test_all > >(); +#endif + + return 0; +} diff --git a/test/strategies/side_by_cross_track.vcproj b/test/strategies/spherical_side.vcproj similarity index 92% rename from test/strategies/side_by_cross_track.vcproj rename to test/strategies/spherical_side.vcproj index e5f1a93594..70dd8689c8 100644 --- a/test/strategies/side_by_cross_track.vcproj +++ b/test/strategies/spherical_side.vcproj @@ -2,9 +2,9 @@ @@ -18,7 +18,7 @@ diff --git a/test/strategies/strategies_tests.sln b/test/strategies/strategies_tests.sln index 6120639f4c..226baff48b 100644 --- a/test/strategies/strategies_tests.sln +++ b/test/strategies/strategies_tests.sln @@ -14,7 +14,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "projected_point", "projecte EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "segment_intersection_collinear", "segment_intersection_collinear.vcproj", "{2D0CB6D3-6ABC-4119-A235-66E6065A279E}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "side_by_cross_track", "side_by_cross_track.vcproj", "{ADBE38D8-1828-48A2-BBA1-81F50B53C67C}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spherical_side", "spherical_side.vcproj", "{ADBE38D8-1828-48A2-BBA1-81F50B53C67C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "within", "within.vcproj", "{AB13D2AC-FD34-4DE4-BD8E-4D463050E5DD}" EndProject From 8cbd04307aed3b92f1437aaa6ad9581735e21bb0 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 5 Jun 2011 21:14:57 +0000 Subject: [PATCH 024/135] Boost.Geometry: Merged r72410 through r72424 [SVN r72425] --- doc/make_qbk.py | 4 ++-- doc/quickref.xml | 2 ++ doc/reference.qbk | 2 ++ .../boost/geometry/strategies/cartesian/side_by_triangle.hpp | 3 +-- .../geometry/strategies/spherical/side_by_cross_track.hpp | 3 +-- include/boost/geometry/strategies/spherical/ssf.hpp | 3 +-- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/make_qbk.py b/doc/make_qbk.py index 8cdcfc9195..65665cebec 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -78,7 +78,7 @@ def cs_to_quickbook(section): access_functions = ["get", "set", "exterior_ring", "interior_rings" , "num_points", "num_interior_rings", "num_geometries"] -coordinate_systems = ["cartesian", "geographic", "polar", "spherical"] +coordinate_systems = ["cartesian", "geographic", "polar", "spherical", "spherical_equatorial"] core = ["closure", "coordinate_system", "coordinate_type", "cs_tag" , "dimension", "exception", "interior_type" @@ -103,7 +103,7 @@ def cs_to_quickbook(section): , "centroid::bashein_detmer", "centroid::average" , "convex_hull::graham_andrew" , "simplify::douglas_peucker" - , "side::side_by_triangle", "side::side_by_cross_track" + , "side::side_by_triangle", "side::side_by_cross_track", "side::spherical_side_formula" , "transform::inverse_transformer", "transform::map_transformer" , "transform::rotate_transformer", "transform::scale_transformer" , "transform::translate_transformer", "transform::ublas_transformer" diff --git a/doc/quickref.xml b/doc/quickref.xml index 3d596993fa..be41e3513c 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -253,6 +253,7 @@ cs::cartesian cs::spherical + cs::spherical_equatorial cs::geographic @@ -533,6 +534,7 @@ strategy::side::side_by_triangle strategy::side::side_by_cross_track + strategy::side::spherical_side_formula diff --git a/doc/reference.qbk b/doc/reference.qbk index db995b8d4e..392d8b1b3c 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -179,6 +179,7 @@ [section:cs Coordinate Systems] [include generated/cartesian.qbk] [include generated/spherical.qbk] +[include generated/spherical_equatorial.qbk] [include generated/geographic.qbk] [endsect] [/coordinate systems] @@ -244,6 +245,7 @@ [include generated/convex_hull_graham_andrew.qbk] [include generated/side_side_by_triangle.qbk] [include generated/side_side_by_cross_track.qbk] +[include generated/side_spherical_side_formula.qbk] [include generated/simplify_douglas_peucker.qbk] [include generated/transform_inverse_transformer.qbk] [include generated/transform_map_transformer.qbk] diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index da3c3ed775..b4255c8a12 100644 --- a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp @@ -32,8 +32,7 @@ namespace strategy { namespace side /*! \brief Check at which side of a segment a point lies: -\details left of segment (> 0), right of segment (< 0), on segment (0) - In fact this is twice the area of a triangle + left of segment (> 0), right of segment (< 0), on segment (0) \ingroup strategies \tparam CalculationType \tparam_calculation */ diff --git a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp index bbae9df902..e96f2e7e72 100644 --- a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp @@ -54,8 +54,7 @@ static inline double course(Point const& p1, Point const& p2) /*! -\brief Check at which side of a segment a point lies: -\details from a Great Circle segment between two points: +\brief Check at which side of a Great Circle segment a point lies left of segment (> 0), right of segment (< 0), on segment (0) \ingroup strategies \tparam CalculationType \tparam_calculation diff --git a/include/boost/geometry/strategies/spherical/ssf.hpp b/include/boost/geometry/strategies/spherical/ssf.hpp index 96a7c379d6..f0d2334e04 100644 --- a/include/boost/geometry/strategies/spherical/ssf.hpp +++ b/include/boost/geometry/strategies/spherical/ssf.hpp @@ -32,8 +32,7 @@ namespace strategy { namespace side /*! -\brief Check at which side of a segment a point lies: -\details from a Great Circle segment between two points: +\brief Check at which side of a Great Circle segment a point lies left of segment (> 0), right of segment (< 0), on segment (0) \ingroup strategies \tparam CalculationType \tparam_calculation From 772c367507203d330146da1d3f8fff855515cbb1 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 17 Jun 2011 18:47:16 +0000 Subject: [PATCH 025/135] Merged commit 72603 to Release Branch Fixes problem with commented ifdef's (2x) See Boost ML 15-06-2011 19:36 (CET) Authorized by Daniel James [SVN r72656] --- .../algorithms/detail/overlay/handle_tangencies.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp index 61e7378471..c69da9b35d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp @@ -305,9 +305,9 @@ private : debug_consider(0, left, right, header, false, "opp.", ret); return ret; } -//#ifdef BOOST_GEOMETRY_DEBUG_ENRICH +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH std::cout << " iu/iu coming from opposite unhandled" << std::endl; -//#endif +#endif } // We need EXTRA information here: are p/r/s overlapping? @@ -360,10 +360,10 @@ private : } } -//#ifdef BOOST_GEOMETRY_DEBUG_ENRICH +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH std::cout << " iu/iu unhandled" << std::endl; debug_consider(0, left, right, header, false, "unhandled", left.index < right.index); -//#endif +#endif return left.index < right.index; } From b09438434d59b273b9c6736e4805faec69347b95 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 17 Jun 2011 22:07:01 +0000 Subject: [PATCH 026/135] Merged r72657 through r72658 adding macro __boost__ Authorized by Daniel James [SVN r72659] --- doc/geometry.qbk | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/geometry.qbk b/doc/geometry.qbk index bbcf49e1f5..1a8c0276a0 100644 --- a/doc/geometry.qbk +++ b/doc/geometry.qbk @@ -65,6 +65,7 @@ All algorithms in Boost.Geometry will check any geometry arguments against the concept requirements.] +[def __boost__ Boost] [def __boost_geometry__ Boost.Geometry] [def __boost_array__ Boost.Array] [def __boost_fusion__ Boost.Fusion] From a7d945dad221c683a9501ced838a98d0061936c3 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 9 Oct 2011 18:30:04 +0000 Subject: [PATCH 027/135] Merged up to and including change 74761 [SVN r74858] --- doc/Jamfile.v2 | 27 +- doc/introduction.qbk | 15 +- doc/reference/algorithms/convex_hull.qbk | 2 +- .../algorithms/create_svg_overlay.hpp | 2 + .../geometries/adapted/boost_fusion.cpp | 2 +- example/ml01_multipolygon_simplify.cpp | 67 ++++ example/ml01_multipolygon_simplify.vcproj | 171 ++++++++ example/ml02_distance_strategy.cpp | 36 ++ example/ml02_distance_strategy.vcproj | 171 ++++++++ include/boost/geometry/algorithms/assign.hpp | 137 +------ include/boost/geometry/algorithms/convert.hpp | 241 ++++++++--- .../boost/geometry/algorithms/covered_by.hpp | 206 ++++++++++ .../algorithms/detail/assign_box_corners.hpp | 93 +++++ .../detail/assign_indexed_point.hpp | 94 +++++ .../algorithms/detail/assign_values.hpp | 11 +- .../detail/has_self_intersections.hpp | 3 +- .../detail/overlay/append_no_duplicates.hpp | 53 +++ .../detail/overlay/assign_parents.hpp | 13 +- .../detail/overlay/backtrack_check_si.hpp | 181 +++++++++ .../overlay/calculate_distance_policy.hpp | 6 +- .../detail/overlay/clip_linestring.hpp | 7 +- .../detail/overlay/copy_segments.hpp | 11 +- .../detail/overlay/enrichment_info.hpp | 22 +- .../algorithms/detail/overlay/get_turns.hpp | 44 ++- .../detail/overlay/intersection_insert.hpp | 43 ++ .../algorithms/detail/overlay/overlay.hpp | 25 +- .../detail/overlay/ring_properties.hpp | 6 +- .../detail/overlay/select_rings.hpp | 57 +-- .../detail/overlay/self_turn_points.hpp | 112 ++++-- .../algorithms/detail/overlay/traverse.hpp | 374 +++++++----------- .../algorithms/detail/overlay/within_util.hpp | 98 ----- .../detail/sections/sectionalize.hpp | 11 +- include/boost/geometry/algorithms/within.hpp | 246 ++++-------- include/boost/geometry/core/tags.hpp | 16 +- .../geometries/adapted/boost_fusion.hpp | 2 +- .../geometry/geometries/concepts/check.hpp | 2 +- .../geometry/multi/algorithms/convert.hpp | 133 +++++++ .../geometry/multi/algorithms/covered_by.hpp | 68 ++++ .../detail/overlay/select_rings.hpp | 5 +- .../geometry/multi/algorithms/within.hpp | 43 +- include/boost/geometry/multi/core/tags.hpp | 2 +- .../policies/relate/intersection_points.hpp | 11 +- .../agnostic/point_in_box_by_side.hpp | 151 +++++++ .../agnostic/point_in_poly_winding.hpp | 41 +- .../agnostic/simplify_douglas_peucker.hpp | 9 +- .../strategies/cartesian/area_surveyor.hpp | 2 +- .../strategies/cartesian/box_in_box.hpp | 176 +++++++++ .../strategies/cartesian/cart_intersect.hpp | 51 ++- .../strategies/cartesian/point_in_box.hpp | 172 ++++++++ .../strategies/cartesian/side_by_triangle.hpp | 2 +- .../strategies/concepts/distance_concept.hpp | 75 +--- .../strategies/concepts/within_concept.hpp | 255 ++++++++++-- .../boost/geometry/strategies/covered_by.hpp | 72 ++++ .../boost/geometry/strategies/strategies.hpp | 3 + .../strategies/strategy_transform.hpp | 27 ++ include/boost/geometry/strategies/within.hpp | 23 +- .../boost/geometry/util/parameter_type_of.hpp | 75 ++++ include/boost/geometry/util/rational.hpp | 179 +++++++++ test/algorithms/Jamfile.v2 | 1 + test/algorithms/algorithms_tests.sln | 6 + test/algorithms/assign.cpp | 8 + test/algorithms/convert.cpp | 298 ++++++++++---- test/algorithms/covered_by.cpp | 149 +++++++ test/algorithms/covered_by.vcproj | 174 ++++++++ test/algorithms/difference.cpp | 60 ++- test/algorithms/intersection.cpp | 87 +++- test/algorithms/intersects.cpp | 51 +++ test/algorithms/overlay/ccw_traverse.cpp | 6 +- test/algorithms/overlay/get_turns.cpp | 5 + test/algorithms/overlay/overlay_cases.hpp | 27 ++ .../overlay/robustness/intersects.cpp | 181 +++++++++ .../overlay/robustness/intersects.vcproj | 223 +++++++++++ .../overlay/robustness/robustness.sln | 6 + test/algorithms/overlay/select_rings.cpp | 2 +- .../overlay/self_intersection_points.vcproj | 1 + test/algorithms/overlay/traverse.cpp | 6 +- test/algorithms/test_convert.hpp | 64 +++ test/algorithms/test_covered_by.hpp | 123 ++++++ test/algorithms/test_difference.hpp | 4 - test/algorithms/test_intersection.hpp | 44 ++- test/algorithms/test_overlay.hpp | 2 +- test/algorithms/test_union.hpp | 5 - test/algorithms/test_within.hpp | 5 + test/algorithms/union.cpp | 61 ++- test/algorithms/within.cpp | 129 +++++- test/geometry_test_common.hpp | 43 +- test/multi/algorithms/Jamfile.v2 | 2 + test/multi/algorithms/multi_convert.cpp | 99 +++++ test/multi/algorithms/multi_convert.vcproj | 174 ++++++++ test/multi/algorithms/multi_covered_by.cpp | 58 +++ test/multi/algorithms/multi_covered_by.vcproj | 174 ++++++++ test/multi/algorithms/multi_difference.cpp | 2 +- test/multi/algorithms/multi_intersection.cpp | 14 + test/multi/algorithms/multi_simplify.cpp | 9 + test/multi/algorithms/multi_within.cpp | 12 +- test/multi/multi_tests.sln | 12 + test/strategies/within.cpp | 59 ++- test/util/Jamfile.v2 | 1 + test/util/rational.cpp | 61 +++ test/util/rational.vcproj | 174 ++++++++ test/util/util_tests.sln | 6 + 101 files changed, 5650 insertions(+), 1160 deletions(-) create mode 100644 example/ml01_multipolygon_simplify.cpp create mode 100644 example/ml01_multipolygon_simplify.vcproj create mode 100644 example/ml02_distance_strategy.cpp create mode 100644 example/ml02_distance_strategy.vcproj create mode 100644 include/boost/geometry/algorithms/covered_by.hpp create mode 100644 include/boost/geometry/algorithms/detail/assign_box_corners.hpp create mode 100644 include/boost/geometry/algorithms/detail/assign_indexed_point.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp delete mode 100644 include/boost/geometry/algorithms/detail/overlay/within_util.hpp create mode 100644 include/boost/geometry/multi/algorithms/convert.hpp create mode 100644 include/boost/geometry/multi/algorithms/covered_by.hpp create mode 100644 include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp create mode 100644 include/boost/geometry/strategies/cartesian/box_in_box.hpp create mode 100644 include/boost/geometry/strategies/cartesian/point_in_box.hpp create mode 100644 include/boost/geometry/strategies/covered_by.hpp create mode 100644 include/boost/geometry/util/parameter_type_of.hpp create mode 100644 include/boost/geometry/util/rational.hpp create mode 100644 test/algorithms/covered_by.cpp create mode 100644 test/algorithms/covered_by.vcproj create mode 100644 test/algorithms/overlay/robustness/intersects.cpp create mode 100644 test/algorithms/overlay/robustness/intersects.vcproj create mode 100644 test/algorithms/test_convert.hpp create mode 100644 test/algorithms/test_covered_by.hpp create mode 100644 test/multi/algorithms/multi_convert.cpp create mode 100644 test/multi/algorithms/multi_convert.vcproj create mode 100644 test/multi/algorithms/multi_covered_by.cpp create mode 100644 test/multi/algorithms/multi_covered_by.vcproj create mode 100644 test/util/rational.cpp create mode 100644 test/util/rational.vcproj diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 711c331896..511c51402b 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -14,8 +14,10 @@ project geometry/doc ; # Auto-index, experimental. Commented otherwise does not build without. #using auto-index ; -import boostbook ; -import quickbook ; +using quickbook ; + +path-constant here : . ; +path-constant images_location : html ; boostbook geometry @@ -23,18 +25,19 @@ boostbook geometry : Jamfile.v2 quickref.xml generated/point.qbk - : chunk.section.depth=4 + chunk.section.depth=4 # off # on # off # index.on.type=1 - html - chunk.first.sections=1 - toc.section.depth=3 - toc.max.depth=2 - generate.section.toc.level=4 - boost.root=../../../.. - enable_index - ; - +# html + chunk.first.sections=1 + toc.section.depth=3 + toc.max.depth=2 + generate.section.toc.level=4 + boost.root=../../../.. + enable_index + $(here) + pdf:img.src.path=$(images_location)/ +; diff --git a/doc/introduction.qbk b/doc/introduction.qbk index 2669979465..0ccd76ddc2 100644 --- a/doc/introduction.qbk +++ b/doc/introduction.qbk @@ -39,10 +39,17 @@ The library follows existing conventions: * conventions from the std library * conventions and names from one of the __ogc__ standards on geometry -The library can be downloaded from [@http://svn.boost.org/svn/boost/trunk Boost.Trunk], -from [@http://svn.boost.org/svn/boost/branches/release Boost.Release], or will come -to you by the normal Boost distribution process. Note that [*extensions] are -only distributed in Boost.Trunk, and that they are subject to change. +The library was released with Boost 1.47.0 and from that point on it is oficially part of the Boost C++ Libraries. + +Latest stable version of the source code is included in the [@http://www.boost.org/users/download/ Boost packaged releases]. +It can also be downloaded from the current [@http://svn.boost.org/svn/boost/branches/release Boost release branch] +in the Boost Subversion repository. + +The library development upstream is available from the [@http://svn.boost.org/svn/boost/trunk Boost trunk] in the Boost Subversion repository. + +Note that the library [*extensions] are not distributed in the official Boost releases, but only available +in the [@http://svn.boost.org/svn/boost/trunk/boost/geometry/extensions/ Boost trunk] +and that they are subject to change. __boost_geometry__ was accepted by Boost at November 28, 2009 ([@http://permalink.gmane.org/gmane.comp.lib.boost.announce/246 review report]). diff --git a/doc/reference/algorithms/convex_hull.qbk b/doc/reference/algorithms/convex_hull.qbk index 2a1de18920..6916d4066e 100644 --- a/doc/reference/algorithms/convex_hull.qbk +++ b/doc/reference/algorithms/convex_hull.qbk @@ -11,7 +11,7 @@ =============================================================================/] [heading Complexity] -Linear +Logarithmic [heading Example] [convex_hull] diff --git a/doc/src/examples/algorithms/create_svg_overlay.hpp b/doc/src/examples/algorithms/create_svg_overlay.hpp index a8ed47bcf9..add3bb3f6c 100644 --- a/doc/src/examples/algorithms/create_svg_overlay.hpp +++ b/doc/src/examples/algorithms/create_svg_overlay.hpp @@ -12,6 +12,8 @@ #define CREATE_SVG_OVERLAY_HPP #include + +#include #include #if defined(HAVE_SVG) diff --git a/doc/src/examples/geometries/adapted/boost_fusion.cpp b/doc/src/examples/geometries/adapted/boost_fusion.cpp index f13c6bad6c..405e5a970d 100644 --- a/doc/src/examples/geometries/adapted/boost_fusion.cpp +++ b/doc/src/examples/geometries/adapted/boost_fusion.cpp @@ -24,7 +24,7 @@ struct sample_point }; BOOST_FUSION_ADAPT_STRUCT(sample_point, (double, x) (double, y) (double, z)) -BOOST_GEOMETRY_REGISTER_BOOST_FUSION_CS(sample_point) +BOOST_GEOMETRY_REGISTER_BOOST_FUSION_CS(cs::cartesian) int main() { diff --git a/example/ml01_multipolygon_simplify.cpp b/example/ml01_multipolygon_simplify.cpp new file mode 100644 index 0000000000..d423c69834 --- /dev/null +++ b/example/ml01_multipolygon_simplify.cpp @@ -0,0 +1,67 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2009-2011 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) +// +// Multipolygon DP simplification example from the mailing list discussion +// about the DP algorithm issue: +// http://lists.osgeo.org/pipermail/ggl/2011-September/001533.html + +#include +#include +#include +#include +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_xy; + typedef boost::geometry::model::polygon polygon; + typedef boost::geometry::model::ring ring; + typedef boost::geometry::model::multi_polygon multi_polygon; + + multi_polygon original_1; + multi_polygon simplified_1; + + // Values between 0..1 and simplified with 1/2048 + boost::geometry::read_wkt("MULTIPOLYGON(((0.561648 1,1 1,1 0,0.468083 0,0.52758 0.00800554,0.599683 0.0280924,0.601611 0.265374,0.622693 0.316765,0.69507 0.357497,0.695623 0.429711,0.655111 0.502298,0.696467 0.543147,0.840712 0.593546,0.882583 0.66546,0.852357 0.748213,0.84264 0.789567,0.832667 0.841202,0.832667 0.841202,0.740538 0.873004,0.617349 0.905045,0.566576 0.977697,0.561648 1)),((0 0.801979,0.0308575 0.786234,0.0705513 0.631135,0.141616 0.527248,0.233985 0.505872,0.264777 0.526263,0.336631 0.505009,0.356603 0.422321,0.355803 0.350038,0.375252 0.205364,0.415206 0.0709182,0.45479 0,0 0,0 0,0 0.801979)))", original_1); + + std::cout << "Original: \n" << boost::geometry::num_points(original_1) << " points.\n\n"; + + boost::geometry::simplify(original_1, simplified_1, 1.0 / 2048.0); + + std::cout << "Polygon with values 0..1 and simplified with 1.0 / 2048.0 \n" + << "Result: \n" << boost::geometry::wkt(simplified_1) << "\n" << boost::geometry::num_points(simplified_1) << " points.\n\n"; + + // Multiply every points from original_1 by 2047 + multi_polygon original_2(original_1); + BOOST_FOREACH(polygon& p, original_2) + { + BOOST_FOREACH(point_xy& pt, p.outer()) + { + pt.x(pt.x() * 2047.0); + pt.y(pt.y() * 2047.0); + } + + BOOST_FOREACH(ring& r, p.inners()) + { + BOOST_FOREACH(point_xy& pt, r) + { + pt.x(pt.x() * 2047.0); + pt.y(pt.y() * 2047.0); + } + } + } + + multi_polygon simplified_2; + boost::geometry::simplify(original_2, simplified_2, 1.0); + std::cout << "Same values but multiplied by 2047.0 and simplified with 1.0\n" + << "Result: \n" << boost::geometry::wkt(simplified_2) << "\n" << boost::geometry::num_points(simplified_2) << " points.\n"; + + return 0; +} + diff --git a/example/ml01_multipolygon_simplify.vcproj b/example/ml01_multipolygon_simplify.vcproj new file mode 100644 index 0000000000..fe5492da9a --- /dev/null +++ b/example/ml01_multipolygon_simplify.vcproj @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ml02_distance_strategy.cpp b/example/ml02_distance_strategy.cpp new file mode 100644 index 0000000000..3b887d5e47 --- /dev/null +++ b/example/ml02_distance_strategy.cpp @@ -0,0 +1,36 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2009-2011 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) +// +// Multipolygon DP simplification example from the mailing list discussion +// about the DP algorithm issue: +// http://lists.osgeo.org/pipermail/ggl/2011-September/001533.html + +#include +#include +#include +using namespace boost::geometry; + +int main() +{ + typedef model::d2::point_xy point_xy; + + point_xy p1(0.0, 0.0); + point_xy p2(5.0, 0.0); + + // 1) This is direct call to Pythagoras algo + typedef strategy::distance::pythagoras strategy1_type; + strategy1_type strategy1; + strategy1_type ::calculation_type d1 = strategy1.apply(p1, p2); + + // 2) This is what is effectively called by simplify + typedef strategy::distance::comparable::pythagoras strategy2_type; + strategy2_type strategy2; + strategy2_type::calculation_type d2 = strategy2.apply(p1, p2); + + return 0; +} diff --git a/example/ml02_distance_strategy.vcproj b/example/ml02_distance_strategy.vcproj new file mode 100644 index 0000000000..0b04ecfac0 --- /dev/null +++ b/example/ml02_distance_strategy.vcproj @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/boost/geometry/algorithms/assign.hpp b/include/boost/geometry/algorithms/assign.hpp index df5cd663df..74089f95b8 100644 --- a/include/boost/geometry/algorithms/assign.hpp +++ b/include/boost/geometry/algorithms/assign.hpp @@ -25,6 +25,8 @@ #include #include +#include +#include #include #include @@ -122,124 +124,6 @@ inline void assign_zero(Geometry& geometry) >::apply(geometry); } - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ -// Note: this is moved to namespace detail because the names and parameter orders -// are not yet 100% clear. - -/*! -\brief Assign the four points of a 2D box -\ingroup assign -\note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT - so this is how it is implemented. -\tparam Box \tparam_box -\tparam Point \tparam_point -\param box \param_box -\param lower_left point being assigned to lower left coordinates of the box -\param lower_right point being assigned to lower right coordinates of the box -\param upper_left point being assigned to upper left coordinates of the box -\param upper_right point being assigned to upper right coordinates of the box - -\qbk{ -[heading Example] -[assign_box_corners] [assign_box_corners_output] -} -*/ -template -inline void assign_box_corners(Box const& box, - Point& lower_left, Point& lower_right, - Point& upper_left, Point& upper_right) -{ - concept::check(); - concept::check(); - - detail::assign::assign_box_2d_corner - (box, lower_left); - detail::assign::assign_box_2d_corner - (box, lower_right); - detail::assign::assign_box_2d_corner - (box, upper_left); - detail::assign::assign_box_2d_corner - (box, upper_right); -} - -template -inline void assign_box_corners_oriented(Box const& box, Range& corners) -{ - if (Reverse) - { - // make counterclockwise ll,lr,ur,ul - assign_box_corners(box, corners[0], corners[1], corners[3], corners[2]); - } - else - { - // make clockwise ll,ul,ur,lr - assign_box_corners(box, corners[0], corners[3], corners[1], corners[2]); - } -} - - -/*! -\brief Assign a box or segment with the value of a point -\ingroup assign -\tparam Index indicates which box-corner, min_corner (0) or max_corner (1) - or which point of segment (0/1) -\tparam Point \tparam_point -\tparam Geometry \tparam_box_or_segment -\param point \param_point -\param geometry \param_box_or_segment - -\qbk{ -[heading Example] -[assign_point_to_index] [assign_point_to_index_output] -} -*/ -template -inline void assign_point_to_index(Point const& point, Geometry& geometry) -{ - concept::check(); - concept::check(); - - detail::assign::assign_point_to_index - < - Geometry, Point, Index, 0, dimension::type::value - >::apply(point, geometry); -} - - -/*! -\brief Assign a point with a point of a box or segment -\ingroup assign -\tparam Index indicates which box-corner, min_corner (0) or max_corner (1) - or which point of segment (0/1) -\tparam Geometry \tparam_box_or_segment -\tparam Point \tparam_point -\param geometry \param_box_or_segment -\param point \param_point - -\qbk{ -[heading Example] -[assign_point_from_index] [assign_point_from_index_output] -} -*/ -template -inline void assign_point_from_index(Geometry const& geometry, Point& point) -{ - concept::check(); - concept::check(); - - detail::assign::assign_point_from_index - < - Geometry, Point, Index, 0, dimension::type::value - >::apply(geometry, point); -} - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - - /*! \brief Assigns one geometry to another geometry \details The assign algorithm assigns one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only @@ -263,8 +147,25 @@ inline void assign(Geometry1& geometry1, Geometry2 const& geometry2) { concept::check_concepts_and_equal_dimensions(); + bool const same_point_order = + point_order::value == point_order::value; + bool const same_closure = + closure::value == closure::value; + + BOOST_MPL_ASSERT_MSG + ( + same_point_order, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER + , (types) + ); + BOOST_MPL_ASSERT_MSG + ( + same_closure, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE + , (types) + ); + dispatch::convert < + false, typename tag::type, typename tag::type, dimension::type::value, diff --git a/include/boost/geometry/algorithms/convert.hpp b/include/boost/geometry/algorithms/convert.hpp index b90e008c1d..e6f16a77fe 100644 --- a/include/boost/geometry/algorithms/convert.hpp +++ b/include/boost/geometry/algorithms/convert.hpp @@ -11,23 +11,31 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP #include #include #include +#include #include #include #include #include #include +#include +#include #include +#include +#include + #include +#include +#include #include @@ -76,6 +84,123 @@ struct point_to_box {} }; +template +struct box_to_range +{ + static inline void apply(Box const& box, Range& range) + { + traits::resize::apply(range, Close ? 5 : 4); + assign_box_corners_oriented(box, range); + if (Close) + { + range[4] = range[0]; + } + } +}; + +template +struct segment_to_range +{ + static inline void apply(Segment const& segment, Range& range) + { + traits::resize::apply(range, 2); + + typename boost::range_iterator::type it = boost::begin(range); + + assign_point_from_index<0>(segment, *it); + ++it; + assign_point_from_index<1>(segment, *it); + } +}; + +template +< + typename Range1, + typename Range2, + bool Reverse = false +> +struct range_to_range +{ + typedef typename reversible_view + < + Range1 const, + Reverse ? iterate_reverse : iterate_forward + >::type rview_type; + typedef typename closeable_view + < + rview_type const, + geometry::closure::value + >::type view_type; + + static inline void apply(Range1 const& source, Range2& destination) + { + geometry::clear(destination); + + rview_type rview(source); + + // We consider input always as closed, and skip last + // point for open output. + view_type view(rview); + + int n = boost::size(view); + if (geometry::closure::value == geometry::open) + { + n--; + } + + int i = 0; + for (typename boost::range_iterator::type it + = boost::begin(view); + it != boost::end(view) && i < n; + ++it, ++i) + { + geometry::append(destination, *it); + } + } +}; + +template +struct polygon_to_polygon +{ + typedef range_to_range + < + typename geometry::ring_type::type, + typename geometry::ring_type::type, + geometry::point_order::value + != geometry::point_order::value + > per_ring; + + static inline void apply(Polygon1 const& source, Polygon2& destination) + { + // Clearing managed per ring, and in the resizing of interior rings + + per_ring::apply(geometry::exterior_ring(source), + geometry::exterior_ring(destination)); + + // Container should be resizeable + traits::resize + < + typename boost::remove_reference + < + typename traits::interior_mutable_type::type + >::type + >::apply(interior_rings(destination), num_interior_rings(source)); + + typename interior_return_type::type rings_source + = interior_rings(source); + typename interior_return_type::type rings_dest + = interior_rings(destination); + + BOOST_AUTO_TPL(it_source, boost::begin(rings_source)); + BOOST_AUTO_TPL(it_dest, boost::begin(rings_dest)); + + for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest) + { + per_ring::apply(*it_source, *it_dest); + } + } +}; + }} // namespace detail::conversion #endif // DOXYGEN_NO_DETAIL @@ -87,12 +212,18 @@ namespace dispatch template < + bool UseAssignment, typename Tag1, typename Tag2, std::size_t DimensionCount, typename Geometry1, typename Geometry2 > struct convert { + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES + , (types) + ); }; @@ -102,10 +233,9 @@ template std::size_t DimensionCount, typename Geometry1, typename Geometry2 > -struct convert +struct convert { - // Same geometry type -> copy coordinates from G1 to G2 - // Actually: we try now to just copy it + // Same geometry type -> copy whole geometry static inline void apply(Geometry1 const& source, Geometry2& destination) { destination = source; @@ -118,57 +248,51 @@ template std::size_t DimensionCount, typename Geometry1, typename Geometry2 > -struct convert +struct convert : detail::conversion::point_to_point {}; +template +struct convert + : detail::conversion::segment_to_range +{}; -template -struct convert -{ - static inline void apply(Ring1 const& source, Ring2& destination) - { - geometry::clear(destination); - for (typename boost::range_iterator::type it - = boost::begin(source); - it != boost::end(source); - ++it) - { - geometry::append(destination, *it); - } - } -}; - - -template -struct convert -{ - static inline void apply(Box const& box, Ring& ring) - { - // go from box to ring -> add coordinates in correct order - geometry::clear(ring); - typename point_type::type point; - - geometry::assign_values(point, get(box), get(box)); - geometry::append(ring, point); - geometry::assign_values(point, get(box), get(box)); - geometry::append(ring, point); +template +struct convert + : detail::conversion::range_to_range + < + Ring1, + Ring2, + geometry::point_order::value + != geometry::point_order::value + > +{}; - geometry::assign_values(point, get(box), get(box)); - geometry::append(ring, point); +template +struct convert + : detail::conversion::range_to_range +{}; - geometry::assign_values(point, get(box), get(box)); - geometry::append(ring, point); +template +struct convert + : detail::conversion::polygon_to_polygon +{}; - geometry::assign_values(point, get(box), get(box)); - geometry::append(ring, point); - } -}; +template +struct convert + : detail::conversion::box_to_range + < + Box, + Ring, + geometry::closure::value == closed, + geometry::point_order::value == counterclockwise + > +{}; template -struct convert +struct convert { static inline void apply(Box const& box, Polygon& polygon) { @@ -176,7 +300,7 @@ struct convert convert < - box_tag, ring_tag, + false, box_tag, ring_tag, 2, Box, ring_type >::apply(box, exterior_ring(polygon)); } @@ -184,7 +308,7 @@ struct convert template -struct convert +struct convert { static inline void apply(Point const& point, Box& box) { @@ -201,14 +325,14 @@ struct convert template -struct convert +struct convert { static inline void apply(Ring const& ring, Polygon& polygon) { typedef typename ring_type::type ring_type; convert < - ring_tag, ring_tag, DimensionCount, + false, ring_tag, ring_tag, DimensionCount, Ring, ring_type >::apply(ring, exterior_ring(polygon)); } @@ -216,7 +340,7 @@ struct convert template -struct convert +struct convert { static inline void apply(Polygon const& polygon, Ring& ring) { @@ -224,6 +348,7 @@ struct convert convert < + false, ring_tag, ring_tag, DimensionCount, ring_type, Ring >::apply(exterior_ring(polygon), ring); @@ -237,8 +362,11 @@ struct convert /*! \brief Converts one geometry to another geometry -\details The convert algorithm converts one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only -if it is possible and applicable. +\details The convert algorithm converts one geometry, e.g. a BOX, to another +geometry, e.g. a RING. This only if it is possible and applicable. +If the point-order is different, or the closure is different between two +geometry types, it will be converted correctly by explicitly reversing the +points or closing or opening the polygon rings. \ingroup convert \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry @@ -254,8 +382,11 @@ inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) dispatch::convert < - typename tag::type, - typename tag::type, + boost::is_same::value + // && boost::has_assign::value, -- type traits extensions + && ! boost::is_array::value, + typename tag_cast::type, multi_tag>::type, + typename tag_cast::type, multi_tag>::type, dimension::type::value, Geometry1, Geometry2 @@ -266,4 +397,4 @@ inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP diff --git a/include/boost/geometry/algorithms/covered_by.hpp b/include/boost/geometry/algorithms/covered_by.hpp new file mode 100644 index 0000000000..3e099126a9 --- /dev/null +++ b/include/boost/geometry/algorithms/covered_by.hpp @@ -0,0 +1,206 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_COVERED_BY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP + + +#include + + +#include + + +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Tag1, + typename Tag2, + typename Geometry1, + typename Geometry2, + typename Strategy +> +struct covered_by +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (types) + ); +}; + + +template +struct covered_by +{ + static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) + { + return strategy.apply(point, box); + } +}; + +template +struct covered_by +{ + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) + { + assert_dimension_equal(); + return strategy.apply(box1, box2); + } +}; + + + +template +struct covered_by +{ + static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy) + { + return detail::within::point_in_ring + < + Point, + Ring, + order_as_direction::value>::value, + geometry::closure::value, + Strategy + >::apply(point, ring) >= 0; + } +}; + +template +struct covered_by +{ + static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy) + { + return detail::within::point_in_polygon + < + Point, + Polygon, + order_as_direction::value>::value, + geometry::closure::value, + Strategy + >::apply(point, polygon, strategy) >= 0; + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +/*! +\brief \brief_check12{is inside or on border} +\ingroup covered_by +\details \details_check12{covered_by, is inside or on border}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param geometry1 geometry which might be covered_by the second geometry +\param geometry2 geometry which might contain the first geometry +\return true if geometry1 is completely contained covered_by geometry2, + else false +\note The default strategy is used for covered_by detection + + */ +template +inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + concept::check(); + concept::check(); + assert_dimension_equal(); + + typedef typename point_type::type point_type1; + typedef typename point_type::type point_type2; + + typedef typename strategy::covered_by::services::default_strategy + < + typename tag::type, + typename tag::type, + typename tag::type, + typename tag_cast::type, areal_tag>::type, + typename tag_cast + < + typename cs_tag::type, spherical_tag + >::type, + typename tag_cast + < + typename cs_tag::type, spherical_tag + >::type, + Geometry1, + Geometry2 + >::type strategy_type; + + return dispatch::covered_by + < + typename tag::type, + typename tag::type, + Geometry1, + Geometry2, + strategy_type + >::apply(geometry1, geometry2, strategy_type()); +} + +/*! +\brief \brief_check12{is inside or on border} \brief_strategy +\ingroup covered_by +\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param geometry1 \param_geometry geometry which might be covered_by the second geometry +\param geometry2 \param_geometry which might contain the first geometry +\param strategy strategy to be used +\return true if geometry1 is completely contained covered_by geometry2, + else false + +\qbk{distinguish,with strategy} + +*/ +template +inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2, + Strategy const& strategy) +{ + concept::within::check + < + typename tag::type, + typename tag::type, + typename tag_cast::type, areal_tag>::type, + Strategy + >(); + concept::check(); + concept::check(); + assert_dimension_equal(); + + return dispatch::covered_by + < + typename tag::type, + typename tag::type, + Geometry1, + Geometry2, + Strategy + >::apply(geometry1, geometry2, strategy); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP diff --git a/include/boost/geometry/algorithms/detail/assign_box_corners.hpp b/include/boost/geometry/algorithms/detail/assign_box_corners.hpp new file mode 100644 index 0000000000..1262dd6edf --- /dev/null +++ b/include/boost/geometry/algorithms/detail/assign_box_corners.hpp @@ -0,0 +1,93 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP + + +#include + +#include +#include + + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ +// Note: this is moved to namespace detail because the names and parameter orders +// are not yet 100% clear. + +/*! +\brief Assign the four points of a 2D box +\ingroup assign +\note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT + so this is how it is implemented. +\tparam Box \tparam_box +\tparam Point \tparam_point +\param box \param_box +\param lower_left point being assigned to lower left coordinates of the box +\param lower_right point being assigned to lower right coordinates of the box +\param upper_left point being assigned to upper left coordinates of the box +\param upper_right point being assigned to upper right coordinates of the box + +\qbk{ +[heading Example] +[assign_box_corners] [assign_box_corners_output] +} +*/ +template +inline void assign_box_corners(Box const& box, + Point& lower_left, Point& lower_right, + Point& upper_left, Point& upper_right) +{ + concept::check(); + concept::check(); + + detail::assign::assign_box_2d_corner + (box, lower_left); + detail::assign::assign_box_2d_corner + (box, lower_right); + detail::assign::assign_box_2d_corner + (box, upper_left); + detail::assign::assign_box_2d_corner + (box, upper_right); +} + +template +inline void assign_box_corners_oriented(Box const& box, Range& corners) +{ + if (Reverse) + { + // make counterclockwise ll,lr,ur,ul + assign_box_corners(box, corners[0], corners[1], corners[3], corners[2]); + } + else + { + // make clockwise ll,ul,ur,lr + assign_box_corners(box, corners[0], corners[3], corners[1], corners[2]); + } +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP diff --git a/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp b/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp new file mode 100644 index 0000000000..3be2390188 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp @@ -0,0 +1,94 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP + + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +/*! +\brief Assign a box or segment with the value of a point +\ingroup assign +\tparam Index indicates which box-corner, min_corner (0) or max_corner (1) + or which point of segment (0/1) +\tparam Point \tparam_point +\tparam Geometry \tparam_box_or_segment +\param point \param_point +\param geometry \param_box_or_segment + +\qbk{ +[heading Example] +[assign_point_to_index] [assign_point_to_index_output] +} +*/ +template +inline void assign_point_to_index(Point const& point, Geometry& geometry) +{ + concept::check(); + concept::check(); + + detail::assign::assign_point_to_index + < + Geometry, Point, Index, 0, dimension::type::value + >::apply(point, geometry); +} + + +/*! +\brief Assign a point with a point of a box or segment +\ingroup assign +\tparam Index indicates which box-corner, min_corner (0) or max_corner (1) + or which point of segment (0/1) +\tparam Geometry \tparam_box_or_segment +\tparam Point \tparam_point +\param geometry \param_box_or_segment +\param point \param_point + +\qbk{ +[heading Example] +[assign_point_from_index] [assign_point_from_index_output] +} +*/ +template +inline void assign_point_from_index(Geometry const& geometry, Point& point) +{ + concept::check(); + concept::check(); + + detail::assign::assign_point_from_index + < + Geometry, Point, Index, 0, dimension::type::value + >::apply(geometry, point); +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP diff --git a/include/boost/geometry/algorithms/detail/assign_values.hpp b/include/boost/geometry/algorithms/detail/assign_values.hpp index d9c6fc49d6..17f1ac794f 100644 --- a/include/boost/geometry/algorithms/detail/assign_values.hpp +++ b/include/boost/geometry/algorithms/detail/assign_values.hpp @@ -90,14 +90,7 @@ struct assign_inverse_box_or_segment static inline void apply(BoxOrSegment& geometry) { - typedef typename coordinate_type::type coordinate_type; - - typedef typename boost::mpl::if_ - < - typename boost::is_arithmetic::type, - coordinate_type, - double - >::type bound_type; + typedef typename coordinate_type::type bound_type; initialize < @@ -207,7 +200,7 @@ struct assign_point_from_index { geometry::set( point, boost::numeric_cast < - typename coordinate_type::type + typename coordinate_type::type >(geometry::get(geometry))); assign_point_from_index diff --git a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp index 38493878c9..e466b26f8f 100644 --- a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp +++ b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -59,11 +59,10 @@ namespace detail { namespace overlay template inline bool has_self_intersections(Geometry const& geometry) { - using namespace boost::geometry; typedef typename point_type::type point_type; typedef detail::overlay::turn_info turn_info; std::deque turns; - detail::get_turns::no_interrupt_policy policy; + detail::disjoint::disjoint_interrupt_policy policy; geometry::self_turns(geometry, turns, policy); #ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS diff --git a/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp new file mode 100644 index 0000000000..b9b50b238f --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 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_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP + + +#include + +#include +#include + + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +inline void append_no_duplicates(Range& range, Point const& point, bool force = false) +{ + if (boost::size(range) == 0 + || force + || ! geometry::detail::equals::equals_point_point(*(boost::end(range)-1), point)) + { +#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION + std::cout << " add: (" + << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")" + << std::endl; +#endif + geometry::append(range, point); + } +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index 423e051f96..be992ac86f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include @@ -42,23 +42,22 @@ static inline bool within_selected_input(Item const& item2, ring_identifier cons typedef typename geometry::tag::type tag1; typedef typename geometry::tag::type tag2; - int code = -1; switch (ring_id.source_index) { case 0 : - code = point_in_ring(item2.point, + return geometry::within(item2.point, get_ring::apply(ring_id, geometry1)); break; case 1 : - code = point_in_ring(item2.point, + return geometry::within(item2.point, get_ring::apply(ring_id, geometry2)); break; case 2 : - code = point_in_ring(item2.point, + return geometry::within(item2.point, get_ring::apply(ring_id, collection)); break; } - return code == 1; + return false; } @@ -77,7 +76,7 @@ struct ring_info_helper {} inline ring_info_helper(ring_identifier i, area_type a) - : id(i), real_area(a), abs_area(abs(a)) + : id(i), real_area(a), abs_area(geometry::math::abs(a)) {} }; diff --git a/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp new file mode 100644 index 0000000000..ad0b304d31 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp @@ -0,0 +1,181 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 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_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP + + +#include + +#include + +#include + +#include +#include + +# include + + +#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) +# include +# include +#endif + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +inline void clear_visit_info(Turns& turns) +{ + typedef typename boost::range_value::type tp_type; + + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it) + { + for (typename boost::range_iterator + < + typename tp_type::container_type + >::type op_it = boost::begin(it->operations); + op_it != boost::end(it->operations); + ++op_it) + { + op_it->visited.clear(); + } + it->discarded = false; + } +} + +struct backtrack_state +{ + bool m_good; + + inline backtrack_state() : m_good(true) {} + inline void reset() { m_good = true; } + inline bool good() const { return m_good; } +}; + + +template +< + typename Geometry1, + typename Geometry2 +> +class backtrack_check_self_intersections +{ + struct state : public backtrack_state + { + bool m_checked; + inline state() + : m_checked() + {} + }; +public : + typedef state state_type; + + template + static inline void apply(std::size_t size_at_start, + Rings& rings, typename boost::range_value::type& ring, + Turns& turns, Operation& operation, + std::string const& , + Geometry1 const& geometry1, + Geometry2 const& geometry2, + state_type& state + ) + { + state.m_good = false; + + // Check self-intersections and throw exception if appropriate + if (! state.m_checked) + { + state.m_checked = true; + has_self_intersections(geometry1); + has_self_intersections(geometry2); + } + + // Make bad output clean + rings.resize(size_at_start); + ring.clear(); + + // Reject this as a starting point + operation.visited.set_rejected(); + + // And clear all visit info + clear_visit_info(turns); + } +}; + +#ifdef BOOST_GEOMETRY_OVERLAY_REPORT_WKT +template +< + typename Geometry1, + typename Geometry2 +> +class backtrack_debug +{ +public : + typedef backtrack_state state_type; + + template + static inline void apply(std::size_t size_at_start, + Rings& rings, typename boost::range_value::type& ring, + Turns& turns, Operation& operation, + std::string const& reason, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + state_type& state + ) + { + std::cout << " REJECT " << reason << std::endl; + + state.m_good = false; + + rings.resize(size_at_start); + ring.clear(); + operation.visited.set_rejected(); + clear_visit_info(turns); + + int c = 0; + for (int i = 0; i < turns.size(); i++) + { + for (int j = 0; j < 2; j++) + { + if (turns[i].operations[j].visited.rejected()) + { + c++; + } + } + } + std::cout << "BACKTRACK (" << reason << " )" + << " " << c << " of " << turns.size() << " rejected" + << std::endl; + std::cout + << geometry::wkt(geometry1) << std::endl + << geometry::wkt(geometry2) << std::endl; + } +}; +#endif // BOOST_GEOMETRY_OVERLAY_REPORT_WKT + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp b/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp index a88060efb5..5b0c38467b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp @@ -10,7 +10,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP -#include +#include namespace boost { namespace geometry @@ -34,9 +34,9 @@ struct calculate_distance_policy static inline void apply(Info& info, Point1 const& p1, Point2 const& p2) { info.operations[0].enriched.distance - = geometry::distance(info.point, p1); + = geometry::comparable_distance(info.point, p1); info.operations[1].enriched.distance - = geometry::distance(info.point, p2); + = geometry::comparable_distance(info.point, p2); } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp index 6e8a7f6c37..801890a323 100644 --- a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp @@ -11,10 +11,11 @@ #include -#include #include #include +#include + #include #include @@ -215,9 +216,9 @@ OutputIterator clip_range_with_box(Box const& b, Range const& range, // b. Add p1 only if it is the first point, then add p2 if (boost::empty(line_out)) { - geometry::append(line_out, p1); + detail::overlay::append_no_duplicates(line_out, p1, true); } - geometry::append(line_out, p2); + detail::overlay::append_no_duplicates(line_out, p2); // c. If c2 is clipped, finish the line if (c2) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index 36cc9f5fb6..c03f77e9f2 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -27,6 +27,7 @@ #include #include +#include namespace boost { namespace geometry { @@ -92,12 +93,7 @@ struct copy_segments_ring for (size_type i = 0; i < count; ++i, ++it) { -#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION - std::cout << " add: (" - << geometry::get<0>(*it) << ", " << geometry::get<1>(*it) << ")" - << std::endl; -#endif - geometry::append(current_output, *it); + detail::overlay::append_no_duplicates(current_output, *it); } } }; @@ -164,7 +160,8 @@ struct copy_segments_box // (see comments in ring-version) for (int i = 0; i < count; i++, index++) { - geometry::append(current_output, bp[index % 5]); + detail::overlay::append_no_duplicates(current_output, bp[index % 5]); + } } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp index 132b2dbf19..9d838fb496 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp @@ -10,7 +10,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP -#include +#include namespace boost { namespace geometry @@ -23,15 +23,25 @@ namespace detail { namespace overlay /*! - \brief Keeps info to enrich intersection info (per source) - \details Class to keep information necessary for traversal phase (a phase - of the overlay process). The information is gathered during the - enrichment phase +\brief Keeps info to enrich intersection info (per source) +\details Class to keep information necessary for traversal phase (a phase + of the overlay process). The information is gathered during the + enrichment phase */ template struct enrichment_info { - typedef typename default_distance_result::type distance_type; + typedef typename strategy::distance::services::return_type + < + typename strategy::distance::services::comparable_type + < + typename strategy::distance::services::default_strategy + < + point_tag, + P + >::type + >::type + >::type distance_type; inline enrichment_info() : travels_to_vertex_index(-1) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 6b7fbe19d1..e79bf4ed99 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -127,6 +127,31 @@ class get_turns_in_sections >::type range2_iterator; + template + static inline bool neighbouring(Section const& section, + int index1, int index2) + { + // About n-2: + // (square: range_count=5, indices 0,1,2,3 + // -> 0-3 are adjacent, don't check on intersections) + // Also tested for open polygons, and/or duplicates + // About first condition: will be optimized by compiler (static) + // It checks if it is areal (box,ring,(multi)polygon + int const n = int(section.range_count); + return boost::is_same + < + typename tag_cast + < + typename geometry::point_type::type, + areal_tag + >::type, + areal_tag + >::value + && index1 == 0 + && index2 >= n - 2 + ; + } + public : // Returns true if terminated, false if interrupted @@ -196,7 +221,7 @@ public : if (skip) { // If sources are the same (possibly self-intersecting): - // skip if it is a neighbouring sement. + // skip if it is a neighbouring segment. // (including first-last segment // and two segments with one or more degenerate/duplicate // (zero-length) segments in between) @@ -204,12 +229,9 @@ public : // Also skip if index1 < index2 to avoid getting all // intersections twice (only do this on same source!) - // About n-2: - // (square: range_count=5, indices 0,1,2,3 - // -> 0-3 are adjacent) - skip = index2 >= index1 - || ndi1 == ndi2 + 1 - || (index2 == 0 && index1 >= int(sec1.range_count) - 2) + skip = index1 >= index2 + || ndi2 == ndi1 + 1 + || neighbouring(sec1, index1, index2) ; } @@ -492,9 +514,9 @@ struct get_turns_cs next++; next++; - bool first = true; + //bool first = true; - char previous_side[2] = {0, 0}; + //char previous_side[2] = {0, 0}; int index = 0; @@ -505,7 +527,7 @@ struct get_turns_cs segment_identifier seg_id(source_id1, multi_index, ring_index, index); - if (first) + /*if (first) { previous_side[0] = get_side<0>(box, *prev); previous_side[1] = get_side<1>(box, *prev); @@ -519,7 +541,7 @@ struct get_turns_cs // 1) EITHER the two points are lying on one side of the box (! 0 && the same) // 2) OR same in Y-direction // 3) OR all points are inside the box (0) - /*if (! ( + if (! ( (current_side[0] != 0 && current_side[0] == previous_side[0]) || (current_side[1] != 0 && current_side[1] == previous_side[1]) || (current_side[0] == 0 diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index be5efb371f..5ae8f772cc 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -295,6 +295,49 @@ struct intersection_insert } }; +template +< + typename Tag1, typename Tag2, + bool Areal1, bool Areal2, + typename Geometry1, typename Geometry2, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename OutputIterator, typename PointOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + Tag1, Tag2, point_tag, + Areal1, Areal2, false, + Geometry1, Geometry2, + Reverse1, Reverse2, ReverseOut, + OutputIterator, PointOut, + OverlayType, + Strategy + > +{ + static inline OutputIterator apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, OutputIterator out, Strategy const& strategy) + { + + typedef detail::overlay::turn_info turn_info; + std::vector turns; + + detail::get_turns::no_interrupt_policy policy; + geometry::get_turns + < + false, false, detail::overlay::assign_null_policy + >(geometry1, geometry2, turns, policy); + for (typename std::vector::const_iterator it + = turns.begin(); it != turns.end(); ++it) + { + *out++ = it->point; + } + + return out; + } +}; + template < diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index e9233f7645..2b71e54b02 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -9,6 +9,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP + #include #include @@ -25,8 +26,6 @@ #include #include -#include - #include #include @@ -124,7 +123,7 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, std::map empty; std::map all_of_one_of_them; - select_rings(geometry1, geometry2, empty, all_of_one_of_them); + select_rings(geometry1, geometry2, empty, all_of_one_of_them, false); ring_container_type rings; assign_parents(geometry1, geometry2, rings, all_of_one_of_them); return add_rings(all_of_one_of_them, geometry1, geometry2, rings, out); @@ -169,9 +168,6 @@ struct overlay >(geometry1, geometry2, out); } - has_self_intersections(geometry1); - has_self_intersections(geometry2); - container_type turn_points; #ifdef BOOST_GEOMETRY_TIME_OVERLAY @@ -215,11 +211,14 @@ std::cout << "traverse" << std::endl; // Note that these rings are always in clockwise order, even in CCW polygons, // and are marked as "to be reversed" below ring_container_type rings; - geometry::traverse(geometry1, geometry2, - Direction == overlay_union - ? geometry::detail::overlay::operation_union - : geometry::detail::overlay::operation_intersection, - turn_points, rings); + traverse::apply + ( + geometry1, geometry2, + Direction == overlay_union + ? geometry::detail::overlay::operation_union + : geometry::detail::overlay::operation_intersection, + turn_points, rings + ); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "traverse: " << timer.elapsed() << std::endl; @@ -236,7 +235,7 @@ std::cout << "traverse" << std::endl; typedef ring_properties::type> properties; std::map selected; - select_rings(geometry1, geometry2, map, selected); + select_rings(geometry1, geometry2, map, selected, ! turn_points.empty()); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "select_rings: " << timer.elapsed() << std::endl; @@ -251,7 +250,7 @@ std::cout << "traverse" << std::endl; it != boost::end(rings); ++it) { - selected[id] = properties(*it); + selected[id] = properties(*it, true); selected[id].reversed = ReverseOut; id.multi_index++; } diff --git a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp index c6bcaf10bb..d112b71dc9 100644 --- a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp @@ -52,17 +52,17 @@ struct ring_properties {} template - inline ring_properties(RingOrBox const& ring_or_box) + inline ring_properties(RingOrBox const& ring_or_box, bool midpoint) : within_code(-1) , reversed(false) , discarded(false) , parent_area(-1) { this->area = geometry::area(ring_or_box); - geometry::point_on_border(this->point, ring_or_box, true); + geometry::point_on_border(this->point, ring_or_box, midpoint); } - area_type get_area() const + inline area_type get_area() const { return reversed ? -area : area; } diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp index 60ec4c88a6..21dec45ca7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -40,15 +40,17 @@ namespace dispatch struct select_rings { template - static inline void apply(Box const& box, Geometry const& geometry, ring_identifier const& id, Map& map) + static inline void apply(Box const& box, Geometry const& geometry, + ring_identifier const& id, Map& map, bool midpoint) { - map[id] = typename Map::mapped_type(box); + map[id] = typename Map::mapped_type(box, midpoint); } template - static inline void apply(Box const& box, ring_identifier const& id, Map& map) + static inline void apply(Box const& box, + ring_identifier const& id, Map& map, bool midpoint) { - map[id] = typename Map::mapped_type(box); + map[id] = typename Map::mapped_type(box, midpoint); } }; @@ -56,20 +58,22 @@ namespace dispatch struct select_rings { template - static inline void apply(Ring const& ring, Geometry const& geometry, ring_identifier const& id, Map& map) + static inline void apply(Ring const& ring, Geometry const& geometry, + ring_identifier const& id, Map& map, bool midpoint) { if (boost::size(ring) > 0) { - map[id] = typename Map::mapped_type(ring); + map[id] = typename Map::mapped_type(ring, midpoint); } } template - static inline void apply(Ring const& ring, ring_identifier const& id, Map& map) + static inline void apply(Ring const& ring, + ring_identifier const& id, Map& map, bool midpoint) { if (boost::size(ring) > 0) { - map[id] = typename Map::mapped_type(ring); + map[id] = typename Map::mapped_type(ring, midpoint); } } }; @@ -79,36 +83,38 @@ namespace dispatch struct select_rings { template - static inline void apply(Polygon const& polygon, Geometry const& geometry, ring_identifier id, Map& map) + static inline void apply(Polygon const& polygon, Geometry const& geometry, + ring_identifier id, Map& map, bool midpoint) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; - per_ring::apply(exterior_ring(polygon), geometry, id, map); + per_ring::apply(exterior_ring(polygon), geometry, id, map, midpoint); typename interior_return_type::type rings = interior_rings(polygon); for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) { id.ring_index++; - per_ring::apply(*it, geometry, id, map); + per_ring::apply(*it, geometry, id, map, midpoint); } } template - static inline void apply(Polygon const& polygon, ring_identifier id, Map& map) + static inline void apply(Polygon const& polygon, + ring_identifier id, Map& map, bool midpoint) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; - per_ring::apply(exterior_ring(polygon), id, map); + per_ring::apply(exterior_ring(polygon), id, map, midpoint); typename interior_return_type::type rings = interior_rings(polygon); for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) { id.ring_index++; - per_ring::apply(*it, id, map); + per_ring::apply(*it, id, map, midpoint); } } }; @@ -203,7 +209,7 @@ inline void update_selection_map(Geometry1 const& geometry1, bool found = intersection_map.find(it->first) != intersection_map.end(); if (! found) { - ring_identifier id = it->first; + ring_identifier const id = it->first; typename SelectionMap::mapped_type properties = it->second; // Copy by value // Calculate the "within code" (previously this was done earlier but is @@ -242,16 +248,20 @@ template typename IntersectionMap, typename SelectionMap > inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2, - IntersectionMap const& intersection_map, SelectionMap& selection_map) + IntersectionMap const& intersection_map, + SelectionMap& selection_map, bool midpoint) { typedef typename geometry::tag::type tag1; typedef typename geometry::tag::type tag2; SelectionMap map_with_all; - dispatch::select_rings::apply(geometry1, geometry2, ring_identifier(0, -1, -1), map_with_all); - dispatch::select_rings::apply(geometry2, geometry1, ring_identifier(1, -1, -1), map_with_all); + dispatch::select_rings::apply(geometry1, geometry2, + ring_identifier(0, -1, -1), map_with_all, midpoint); + dispatch::select_rings::apply(geometry2, geometry1, + ring_identifier(1, -1, -1), map_with_all, midpoint); - update_selection_map(geometry1, geometry2, intersection_map, map_with_all, selection_map); + update_selection_map(geometry1, geometry2, intersection_map, + map_with_all, selection_map); } template @@ -261,14 +271,17 @@ template typename IntersectionMap, typename SelectionMap > inline void select_rings(Geometry const& geometry, - IntersectionMap const& intersection_map, SelectionMap& selection_map) + IntersectionMap const& intersection_map, + SelectionMap& selection_map, bool midpoint) { typedef typename geometry::tag::type tag; SelectionMap map_with_all; - dispatch::select_rings::apply(geometry, ring_identifier(0, -1, -1), map_with_all); + dispatch::select_rings::apply(geometry, + ring_identifier(0, -1, -1), map_with_all, midpoint); - update_selection_map(intersection_map, map_with_all, selection_map); + update_selection_map(geometry, geometry, intersection_map, + map_with_all, selection_map); } diff --git a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index 62b8ef4846..d4147eac52 100644 --- a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -31,6 +32,60 @@ namespace boost { namespace geometry namespace detail { namespace self_get_turn_points { +class self_ip_exception : public geometry::exception {}; + +template +< + typename Geometry, + typename Turns, + typename TurnPolicy, + typename InterruptPolicy +> +struct self_section_visitor +{ + Geometry const& m_geometry; + Turns& m_turns; + InterruptPolicy& m_interrupt_policy; + + inline self_section_visitor(Geometry const& g, + Turns& turns, InterruptPolicy& ip) + : m_geometry(g) + , m_turns(turns) + , m_interrupt_policy(ip) + {} + + template + inline bool apply(Section const& sec1, Section const& sec2) + { + if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box) + && ! sec1.duplicate + && ! sec2.duplicate) + { + detail::get_turns::get_turns_in_sections + < + Geometry, Geometry, + false, false, + Section, Section, + Turns, TurnPolicy, + InterruptPolicy + >::apply( + 0, m_geometry, sec1, + 0, m_geometry, sec2, + m_turns, m_interrupt_policy); + } + if (m_interrupt_policy.has_intersections) + { + // TODO: we should give partition an interrupt policy. + // Now we throw, and catch below, to stop the partition loop. + throw self_ip_exception(); + } + return true; + } + +}; + + + template < typename Geometry, @@ -45,49 +100,38 @@ struct get_turns Turns& turns, InterruptPolicy& interrupt_policy) { + typedef model::box + < + typename geometry::point_type::type + > box_type; typedef typename geometry::sections < - model::box ::type>, - 1 + box_type, 1 > sections_type; sections_type sec; geometry::sectionalize(geometry, sec); - for (typename boost::range_iterator::type - it1 = sec.begin(); - it1 != sec.end(); - ++it1) + self_section_visitor + < + Geometry, + Turns, TurnPolicy, InterruptPolicy + > visitor(geometry, turns, interrupt_policy); + + try { - for (typename boost::range_iterator::type - it2 = sec.begin(); - it2 != sec.end(); - ++it2) - { - if (! geometry::detail::disjoint::disjoint_box_box( - it1->bounding_box, it2->bounding_box) - && ! it1->duplicate - && ! it2->duplicate - ) - { - if (! geometry::detail::get_turns::get_turns_in_sections - < - Geometry, Geometry, - false, false, - typename boost::range_value::type, - typename boost::range_value::type, - Turns, TurnPolicy, - InterruptPolicy - >::apply( - 0, geometry, *it1, - 0, geometry, *it2, - turns, interrupt_policy)) - { - return false; - } - } - } + geometry::partition + < + box_type, + detail::get_turns::get_section_box, + detail::get_turns::ovelaps_section_box + >::apply(sec, visitor); } + catch(self_ip_exception const& ) + { + return false; + } + return true; } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index d91efa71c0..8edae0f2b4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -14,8 +14,10 @@ #include -#include +#include +#include #include +#include #include #include #include @@ -38,7 +40,8 @@ namespace detail { namespace overlay { template -inline void debug_traverse(Turn const& turn, Operation op, std::string const& header) +inline void debug_traverse(Turn const& turn, Operation op, + std::string const& header) { #ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE std::cout << header @@ -57,30 +60,6 @@ inline void debug_traverse(Turn const& turn, Operation op, std::string const& he } -template -inline void clear_visit_info(Turns& turns) -{ - typedef typename boost::range_value::type tp_type; - - for (typename boost::range_iterator::type - it = boost::begin(turns); - it != boost::end(turns); - ++it) - { - for (typename boost::range_iterator - < - typename tp_type::container_type - >::type op_it = boost::begin(it->operations); - op_it != boost::end(it->operations); - ++op_it) - { - op_it->visited.clear(); - } - it->discarded = false; - } -} - - template inline void set_visited_for_continue(Info& info, Turn const& turn) { @@ -125,7 +104,11 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2, // If there is no next IP on this segment if (info.enriched.next_ip_index < 0) { - if (info.enriched.travels_to_vertex_index < 0 || info.enriched.travels_to_ip_index < 0) return false; + if (info.enriched.travels_to_vertex_index < 0 + || info.enriched.travels_to_ip_index < 0) + { + return false; + } BOOST_ASSERT(info.enriched.travels_to_vertex_index >= 0); BOOST_ASSERT(info.enriched.travels_to_ip_index >= 0); @@ -151,7 +134,7 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2, seg_id = info.seg_id; } - geometry::append(current_output, ip->point); + detail::overlay::append_no_duplicates(current_output, ip->point); return true; } @@ -227,76 +210,6 @@ inline bool select_next_ip(operation_type operation, -template -< - typename Rings, - typename Turns, - typename Operation, - typename Geometry1, - typename Geometry2 -> -inline void backtrack(std::size_t size_at_start, bool& fail, - Rings& rings, typename boost::range_value::type& ring, - Turns& turns, Operation& operation, - -#ifdef BOOST_GEOMETRY_OVERLAY_REPORT_WKT - std::string const& reason, - Geometry1 const& geometry1, - Geometry2 const& geometry2 -#else - std::string const& reason, - Geometry1 const& , - Geometry2 const& -#endif - ) -{ -#ifdef BOOST_GEOMETRY_DEBUG_ENRICH - std::cout << " REJECT " << reason << std::endl; -#endif - fail = true; - - // Make bad output clean - rings.resize(size_at_start); - ring.clear(); - - // Reject this as a starting point - operation.visited.set_rejected(); - - // And clear all visit info - clear_visit_info(turns); - - /*** - int c = 0; - for (int i = 0; i < turns.size(); i++) - { - for (int j = 0; j < 2; j++) - { - if (turns[i].operations[j].visited.rejected()) - { - c++; - } - } - } - std::cout << "BACKTRACK (" << reason << " )" - << " " << c << " of " << turns.size() << " rejected" - << std::endl; - ***/ - - - -#ifdef BOOST_GEOMETRY_OVERLAY_REPORT_WKT - std::cout << " BT (" << reason << " )"; - std::cout - << geometry::wkt(geometry1) << std::endl - << geometry::wkt(geometry2) << std::endl; -#endif - -} - -}} // namespace detail::overlay -#endif // DOXYGEN_NO_DETAIL - - /*! \brief Traverses through intersection points / geometries \ingroup overlay @@ -306,164 +219,173 @@ template bool Reverse1, bool Reverse2, typename Geometry1, typename Geometry2, - typename Turns, - typename Rings + typename Backtrack = backtrack_check_self_intersections > -inline void traverse(Geometry1 const& geometry1, - Geometry2 const& geometry2, - detail::overlay::operation_type operation, - Turns& turns, Rings& rings) +class traverse { - typedef typename boost::range_iterator::type turn_iterator; - typedef typename boost::range_value::type turn_type; - typedef typename boost::range_iterator - < - typename turn_type::container_type - >::type turn_operation_iterator_type; +public : + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + detail::overlay::operation_type operation, + Turns& turns, Rings& rings) + { + typedef typename boost::range_iterator::type turn_iterator; + typedef typename boost::range_value::type turn_type; + typedef typename boost::range_iterator + < + typename turn_type::container_type + >::type turn_operation_iterator_type; - std::size_t size_at_start = boost::size(rings); + std::size_t size_at_start = boost::size(rings); - bool fail = false; - do - { - fail = false; - // Iterate through all unvisited points - for (turn_iterator it = boost::begin(turns); - ! fail && it != boost::end(turns); - ++it) + typename Backtrack::state_type state; + do { - // Skip discarded ones - if (! (it->is_discarded() || it->blocked())) + state.reset(); + + // Iterate through all unvisited points + for (turn_iterator it = boost::begin(turns); + state.good() && it != boost::end(turns); + ++it) { - for (turn_operation_iterator_type iit = boost::begin(it->operations); - ! fail && iit != boost::end(it->operations); - ++iit) + // Skip discarded ones + if (! (it->is_discarded() || it->blocked())) { - if (iit->visited.none() - && ! iit->visited.rejected() - && (iit->operation == operation - || iit->operation == detail::overlay::operation_continue) - ) + for (turn_operation_iterator_type iit = boost::begin(it->operations); + state.good() && iit != boost::end(it->operations); + ++iit) { - set_visited_for_continue(*it, *iit); - - typename boost::range_value::type current_output; - geometry::append(current_output, it->point); - - turn_iterator current = it; - turn_operation_iterator_type current_iit = iit; - segment_identifier current_seg_id; - - if (! detail::overlay::assign_next_ip( - geometry1, geometry2, - turns, - current, current_output, - *iit, current_seg_id)) - { - detail::overlay::backtrack( - size_at_start, fail, - rings, current_output, turns, *current_iit, - "No next IP", - geometry1, geometry2); - } - - if (! detail::overlay::select_next_ip( - operation, - *current, - current_seg_id, - current_iit)) - { - detail::overlay::backtrack( - size_at_start, fail, - rings, current_output, turns, *iit, - "Dead end at start", - geometry1, geometry2); - } - else + if (iit->visited.none() + && ! iit->visited.rejected() + && (iit->operation == operation + || iit->operation == detail::overlay::operation_continue) + ) { + set_visited_for_continue(*it, *iit); - iit->visited.set_started(); - detail::overlay::debug_traverse(*it, *iit, "-> Started"); - detail::overlay::debug_traverse(*current, *current_iit, "Selected "); + typename boost::range_value::type current_output; + detail::overlay::append_no_duplicates(current_output, + it->point, true); + turn_iterator current = it; + turn_operation_iterator_type current_iit = iit; + segment_identifier current_seg_id; - unsigned int i = 0; + if (! detail::overlay::assign_next_ip( + geometry1, geometry2, + turns, + current, current_output, + *iit, current_seg_id)) + { + Backtrack::apply( + size_at_start, + rings, current_output, turns, *current_iit, + "No next IP", + geometry1, geometry2, state); + } - while (current_iit != iit && ! fail) + if (! detail::overlay::select_next_ip( + operation, + *current, + current_seg_id, + current_iit)) + { + Backtrack::apply( + size_at_start, + rings, current_output, turns, *iit, + "Dead end at start", + geometry1, geometry2, state); + } + else { - if (current_iit->visited.visited()) - { - // It visits a visited node again, without passing the start node. - // This makes it suspicious for endless loops - detail::overlay::backtrack( - size_at_start, fail, - rings, current_output, turns, *iit, - "Visit again", - geometry1, geometry2); - } - else - { + iit->visited.set_started(); + detail::overlay::debug_traverse(*it, *iit, "-> Started"); + detail::overlay::debug_traverse(*current, *current_iit, "Selected "); - // We assume clockwise polygons only, non self-intersecting, closed. - // However, the input might be different, and checking validity - // is up to the library user. - // Therefore we make here some sanity checks. If the input - // violates the assumptions, the output polygon will not be correct - // but the routine will stop and output the current polygon, and - // will continue with the next one. + unsigned int i = 0; - // Below three reasons to stop. - detail::overlay::assign_next_ip( - geometry1, geometry2, - turns, current, current_output, - *current_iit, current_seg_id); - - if (! detail::overlay::select_next_ip( - operation, - *current, - current_seg_id, - current_iit)) + while (current_iit != iit && state.good()) + { + if (current_iit->visited.visited()) { - // Should not occur in valid (non-self-intersecting) polygons - // Should not occur in self-intersecting polygons without spikes - // Might occur in polygons with spikes - detail::overlay::backtrack( - size_at_start, fail, + // It visits a visited node again, without passing the start node. + // This makes it suspicious for endless loops + Backtrack::apply( + size_at_start, rings, current_output, turns, *iit, - "Dead end", - geometry1, geometry2); + "Visit again", + geometry1, geometry2, state); } - detail::overlay::debug_traverse(*current, *current_iit, "Selected "); - - if (i++ > 2 + 2 * turns.size()) + else { - // Sanity check: there may be never more loops - // than turn points. - // Turn points marked as "ii" can be visited twice. - detail::overlay::backtrack( - size_at_start, fail, - rings, current_output, turns, *iit, - "Endless loop", - geometry1, geometry2); + + + // We assume clockwise polygons only, non self-intersecting, closed. + // However, the input might be different, and checking validity + // is up to the library user. + + // Therefore we make here some sanity checks. If the input + // violates the assumptions, the output polygon will not be correct + // but the routine will stop and output the current polygon, and + // will continue with the next one. + + // Below three reasons to stop. + detail::overlay::assign_next_ip( + geometry1, geometry2, + turns, current, current_output, + *current_iit, current_seg_id); + + if (! detail::overlay::select_next_ip( + operation, + *current, + current_seg_id, + current_iit)) + { + // Should not occur in valid (non-self-intersecting) polygons + // Should not occur in self-intersecting polygons without spikes + // Might occur in polygons with spikes + Backtrack::apply( + size_at_start, + rings, current_output, turns, *iit, + "Dead end", + geometry1, geometry2, state); + } + detail::overlay::debug_traverse(*current, *current_iit, "Selected "); + + if (i++ > 2 + 2 * turns.size()) + { + // Sanity check: there may be never more loops + // than turn points. + // Turn points marked as "ii" can be visited twice. + Backtrack::apply( + size_at_start, + rings, current_output, turns, *iit, + "Endless loop", + geometry1, geometry2, state); + } } } - } - if (! fail) - { - iit->visited.set_finished(); - detail::overlay::debug_traverse(*current, *iit, "->Finished"); - rings.push_back(current_output); + if (state.good()) + { + iit->visited.set_finished(); + detail::overlay::debug_traverse(*current, *iit, "->Finished"); + rings.push_back(current_output); + } } } } } } - } - } while (fail); -} + } while (! state.good()); + } +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/overlay/within_util.hpp b/include/boost/geometry/algorithms/detail/overlay/within_util.hpp deleted file mode 100644 index 8618b81fe8..0000000000 --- a/include/boost/geometry/algorithms/detail/overlay/within_util.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 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_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP - - - -#include -#include - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace overlay -{ - - -template -struct within_code -{}; - -template -struct within_code -{ - static inline int apply(Point const& point, Box const& box) - { - // 1. Check outside - if (get<0>(point) < get(box) - || get<0>(point) > get(box) - || get<1>(point) < get(box) - || get<1>(point) > get(box)) - { - return -1; - } - // 2. Check border - if (geometry::math::equals(get<0>(point), get(box)) - || geometry::math::equals(get<0>(point), get(box)) - || geometry::math::equals(get<1>(point), get(box)) - || geometry::math::equals(get<1>(point), get(box))) - { - return 0; - } - return 1; - } -}; -template -struct within_code -{ - static inline int apply(Point const& point, Ring const& ring) - { - // Same as point_in_ring but here ALWAYS with winding. - typedef strategy::within::winding strategy_type; - - return detail::within::point_in_ring - < - Point, - Ring, - order_as_direction::value>::value, - geometry::closure::value, - strategy_type - >::apply(point, ring, strategy_type()); - } -}; - - -template -inline int point_in_ring(Point const& point, Geometry const& geometry) -{ - return within_code::type, Point, Geometry> - ::apply(point, geometry); -} - -template -inline bool within_or_touch(Point const& point, Geometry const& geometry) -{ - return within_code::type, Point, Geometry> - ::apply(point, geometry) >= 0; -} - - - -}} // namespace detail::overlay -#endif // DOXYGEN_NO_DETAIL - - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 52cf158667..aea7d17cea 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -189,11 +189,12 @@ struct check_duplicate_loop static inline bool apply(Segment const& seg) { - coordinate_type const diff = - geometry::get<1, Dimension>(seg) - geometry::get<0, Dimension>(seg); - - coordinate_type const zero = 0; - if (! geometry::math::equals(diff, zero)) + if (! geometry::math::equals + ( + geometry::get<0, Dimension>(seg), + geometry::get<1, Dimension>(seg) + ) + ) { return false; } diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index 912ba4bab2..987c6101b3 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -31,10 +31,12 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -48,105 +50,6 @@ namespace detail { namespace within { -/*! - \brief Implementation for boxes - \ingroup boolean_relations - \note Should have strategy for e.g. Wrangel - */ -template -< - typename Point, - typename Box, - typename Strategy, - std::size_t Dimension, - std::size_t DimensionCount -> -struct point_in_box -{ - static inline int apply(Point const& p, Box const& b, Strategy const& s) - { - assert_dimension_equal(); - - if (get(p) <= get(b) - || get(p) >= get(b)) - { - return -1; - } - - return point_in_box - < - Point, - Box, - Strategy, - Dimension + 1, - DimensionCount - >::apply(p, b, s); - } -}; - -template -< - typename Point, - typename Box, - typename Strategy, - std::size_t DimensionCount -> -struct point_in_box -{ - static inline int apply(Point const& , Box const& , Strategy const& ) - { - return 1; - } -}; - - -template -< - typename Box1, - typename Box2, - typename Strategy, - std::size_t Dimension, - std::size_t DimensionCount -> -struct box_in_box -{ - static inline int apply(Box1 const& b1, Box2 const& b2, Strategy const& s) - { - assert_dimension_equal(); - - if (get(b1) <= get(b2) - || get(b1) >= get(b2)) - { - return -1; - } - - return box_in_box - < - Box1, - Box2, - Strategy, - Dimension + 1, - DimensionCount - >::apply(b1, b2, s); - } -}; - -template -< - typename Box1, - typename Box2, - typename Strategy, - std::size_t DimensionCount -> -struct box_in_box -{ - static inline int apply(Box1 const& , Box2 const& , Strategy const&) - { - return 1; - } -}; - - template < typename Point, @@ -157,7 +60,7 @@ template > struct point_in_ring { - BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategy) ); + BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal) ); static inline int apply(Point const& point, Ring const& ring, Strategy const& strategy) @@ -181,13 +84,14 @@ struct point_in_ring iterator_type it = boost::begin(view); iterator_type end = boost::end(view); + bool stop = false; for (iterator_type previous = it++; - it != end; + it != end && ! stop; ++previous, ++it) { if (! strategy.apply(point, *previous, *it, state)) { - return false; + stop = true; } } @@ -196,7 +100,6 @@ struct point_in_ring }; - // Polygon: in exterior ring, and if so, not within interior ring(s) template < @@ -208,7 +111,7 @@ template > struct point_in_polygon { - BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategy) ); + BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal) ); static inline int apply(Point const& point, Polygon const& poly, Strategy const& strategy) @@ -280,84 +183,60 @@ struct within template struct within - : detail::within::point_in_box - < - Point, - Box, - Strategy, - 0, - dimension::type::value - > -{}; +{ + static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) + { + return strategy.apply(point, box); + } +}; template struct within - : detail::within::box_in_box - < - Box1, - Box2, - Strategy, - 0, - dimension::type::value - > -{}; +{ + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) + { + assert_dimension_equal(); + return strategy.apply(box1, box2); + } +}; template struct within - : detail::within::point_in_ring - < - Point, - Ring, - order_as_direction::value>::value, - geometry::closure::value, - Strategy - > -{}; +{ + static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy) + { + return detail::within::point_in_ring + < + Point, + Ring, + order_as_direction::value>::value, + geometry::closure::value, + Strategy + >::apply(point, ring, strategy) == 1; + } +}; template struct within - : detail::within::point_in_polygon - < - Point, - Polygon, - order_as_direction::value>::value, - geometry::closure::value, - Strategy - > -{}; - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -namespace strategy { namespace within { - -/// Strategy for box-in-box (not used but has to be present for default strategy) -struct unused_strategy {}; - -namespace services -{ - -// Specialize for box-in-areal (box-in-box). This is meant to do box-in-box -// but will be catched by box-in-any-areal, which has to change later -// (we might introduce another tag which is not "areal", derived by poly/ring/ -// multi_poly, but NOT by box, and use that here. E.g. "polygonal") -// Using cartesian prevents spherical yet from compiling, which is good. -template -struct default_strategy -{ - typedef unused_strategy type; + static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy) + { + return detail::within::point_in_polygon + < + Point, + Polygon, + order_as_direction::value>::value, + geometry::closure::value, + Strategy + >::apply(point, polygon, strategy) == 1; + } }; -} // namespace services - -}} // namespace strategy::within +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH -#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS /*! \brief \brief_check12{is completely inside} @@ -387,18 +266,27 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2) { concept::check(); concept::check(); + assert_dimension_equal(); typedef typename point_type::type point_type1; typedef typename point_type::type point_type2; typedef typename strategy::within::services::default_strategy < + typename tag::type, + typename tag::type, typename tag::type, typename tag_cast::type, areal_tag>::type, - typename cs_tag::type, - typename cs_tag::type, - point_type1, - point_type2 + typename tag_cast + < + typename cs_tag::type, spherical_tag + >::type, + typename tag_cast + < + typename cs_tag::type, spherical_tag + >::type, + Geometry1, + Geometry2 >::type strategy_type; return dispatch::within @@ -408,7 +296,7 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2) Geometry1, Geometry2, strategy_type - >::apply(geometry1, geometry2, strategy_type()) == 1; + >::apply(geometry1, geometry2, strategy_type()); } /*! @@ -443,12 +331,16 @@ template inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - // Always assume a point-in-polygon strategy here. - // Because for point-in-box, it makes no sense to specify one. - BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategy) ); - + concept::within::check + < + typename tag::type, + typename tag::type, + typename tag_cast::type, areal_tag>::type, + Strategy + >(); concept::check(); concept::check(); + assert_dimension_equal(); return dispatch::within < @@ -457,7 +349,7 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2, Geometry1, Geometry2, Strategy - >::apply(geometry1, geometry2, strategy) == 1; + >::apply(geometry1, geometry2, strategy); } }} // namespace boost::geometry diff --git a/include/boost/geometry/core/tags.hpp b/include/boost/geometry/core/tags.hpp index f110a079ae..8b97398617 100644 --- a/include/boost/geometry/core/tags.hpp +++ b/include/boost/geometry/core/tags.hpp @@ -20,18 +20,21 @@ namespace boost { namespace geometry // Tags defining strategies linked to coordinate systems +/// Tag used for casting spherical/geographic coordinate systems +struct spherical_tag {}; + /// Tag indicating Cartesian coordinate system family (cartesian,epsg) struct cartesian_tag {}; /// Tag indicating Spherical polar coordinate system family -struct spherical_polar_tag {}; +struct spherical_polar_tag : spherical_tag {}; /// Tag indicating Spherical equatorial coordinate system family -struct spherical_equatorial_tag {}; +struct spherical_equatorial_tag : spherical_tag {}; /// Tag indicating Geographic coordinate system family (geographic) -struct geographic_tag {}; +struct geographic_tag : spherical_tag {}; @@ -53,6 +56,9 @@ struct linear_tag {}; /// For areal types (polygon, multi_polygon, box, ring) struct areal_tag {}; +// Subset of areal types (polygon, multi_polygon, ring) +struct polygonal_tag : areal_tag {}; + /// For volume types (also box (?), polyhedron) struct volumetric_tag {}; @@ -70,10 +76,10 @@ struct point_tag : single_tag, pointlike_tag {}; struct linestring_tag : single_tag, linear_tag {}; /// OGC Polygon identifying tag -struct polygon_tag : single_tag, areal_tag {}; +struct polygon_tag : single_tag, polygonal_tag {}; /// Convenience (linear) ring identifying tag -struct ring_tag : single_tag, areal_tag {}; +struct ring_tag : single_tag, polygonal_tag {}; /// Convenience 2D or 3D box (mbr / aabb) identifying tag struct box_tag : single_tag, areal_tag {}; diff --git a/include/boost/geometry/geometries/adapted/boost_fusion.hpp b/include/boost/geometry/geometries/adapted/boost_fusion.hpp index 3c81672f89..4e6c850db0 100644 --- a/include/boost/geometry/geometries/adapted/boost_fusion.hpp +++ b/include/boost/geometry/geometries/adapted/boost_fusion.hpp @@ -165,7 +165,7 @@ struct tag fusion_adapt_detail::is_fusion_sequence \ >::type \ > \ - { typedef cs::cartesian type; }; \ + { typedef CoordinateSystem type; }; \ }}} diff --git a/include/boost/geometry/geometries/concepts/check.hpp b/include/boost/geometry/geometries/concepts/check.hpp index cd913e48bf..e858a6662a 100644 --- a/include/boost/geometry/geometries/concepts/check.hpp +++ b/include/boost/geometry/geometries/concepts/check.hpp @@ -44,7 +44,7 @@ class check BOOST_CONCEPT_ASSERT((Concept )); }; -}} // namespace detail::check +}} // namespace detail::concept_check #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/multi/algorithms/convert.hpp b/include/boost/geometry/multi/algorithms/convert.hpp new file mode 100644 index 0000000000..9d27badec5 --- /dev/null +++ b/include/boost/geometry/multi/algorithms/convert.hpp @@ -0,0 +1,133 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_MULTI_ALGORITHMS_CONVERT_HPP +#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP + + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace conversion +{ + +template +struct single_to_multi +{ + static inline void apply(Single const& single, Multi& multi) + { + traits::resize::apply(multi, 1); + Policy::apply(single, *boost::begin(multi)); + } +}; + + + +template +struct multi_to_multi +{ + static inline void apply(Multi1 const& multi1, Multi2& multi2) + { + traits::resize::apply(multi2, boost::size(multi1)); + + typename boost::range_iterator::type it1 + = boost::begin(multi1); + typename boost::range_iterator::type it2 + = boost::begin(multi2); + + for (; it1 != boost::end(multi1); ++it1, ++it2) + { + Policy::apply(*it1, *it2); + } + } +}; + + +}} // namespace detail::convert +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// Dispatch for multi <-> multi, specifying their single-version as policy. +// Note that, even if the multi-types are mutually different, their single +// version types might be the same and therefore we call boost::is_same again + +template +struct convert + : detail::conversion::multi_to_multi + < + Multi1, + Multi2, + convert + < + boost::is_same + < + typename boost::range_value::type, + typename boost::range_value::type + >::value, + typename single_tag_of + < + typename tag::type + >::type, + typename single_tag_of + < + typename tag::type + >::type, + DimensionCount, + typename boost::range_value::type, + typename boost::range_value::type + > + > +{}; + +template +struct convert + : detail::conversion::single_to_multi + < + Single, + Multi, + convert + < + false, + typename tag::type, + typename single_tag_of + < + typename tag::type + >::type, + DimensionCount, + Single, + typename boost::range_value::type + > + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP diff --git a/include/boost/geometry/multi/algorithms/covered_by.hpp b/include/boost/geometry/multi/algorithms/covered_by.hpp new file mode 100644 index 0000000000..b5eeb782a2 --- /dev/null +++ b/include/boost/geometry/multi/algorithms/covered_by.hpp @@ -0,0 +1,68 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_MULTI_ALGORITHMS_COVERED_BY_HPP +#define BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP + + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct covered_by +{ + static inline bool apply(Point const& point, + MultiPolygon const& multi_polygon, Strategy const& strategy) + { + return detail::within::geometry_multi_within_code + < + Point, + MultiPolygon, + Strategy, + detail::within::point_in_polygon + < + Point, + typename boost::range_value::type, + order_as_direction + < + geometry::point_order::value + >::value, + geometry::closure::value, + Strategy + > + >::apply(point, multi_polygon, strategy) >= 0; + } +}; + + +} // namespace dispatch + + +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP diff --git a/include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp index 6e150cf585..ffe86a36bb 100644 --- a/include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp @@ -30,7 +30,8 @@ namespace dispatch struct select_rings { template - static inline void apply(Multi const& multi, Geometry const& geometry, ring_identifier id, Map& map) + static inline void apply(Multi const& multi, Geometry const& geometry, + ring_identifier id, Map& map, bool midpoint) { typedef typename boost::range_iterator < @@ -43,7 +44,7 @@ namespace dispatch for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it) { id.ring_index = -1; - per_polygon::apply(*it, geometry, id, map); + per_polygon::apply(*it, geometry, id, map, midpoint); id.multi_index++; } } diff --git a/include/boost/geometry/multi/algorithms/within.hpp b/include/boost/geometry/multi/algorithms/within.hpp index e9fcbb65ab..50ec1c1e8d 100644 --- a/include/boost/geometry/multi/algorithms/within.hpp +++ b/include/boost/geometry/multi/algorithms/within.hpp @@ -37,7 +37,7 @@ template typename Strategy, typename Policy > -struct geometry_in_multi +struct geometry_multi_within_code { static inline int apply(Geometry const& geometry, MultiGeometry const& multi, @@ -48,7 +48,8 @@ struct geometry_in_multi it != boost::end(multi); ++it) { - // Geometry within a multi: true if within one of them + // Geometry coding on multi: 1 (within) if within one of them; + // 0 (touch) if on border of one of them int const code = Policy::apply(geometry, *it, strategy); if (code != -1) { @@ -70,21 +71,29 @@ namespace dispatch template struct within - : detail::within::geometry_in_multi - < - Point, - MultiPolygon, - Strategy, - detail::within::point_in_polygon - < - Point, - typename boost::range_value::type, - order_as_direction::value>::value, - geometry::closure::value, - Strategy - > - > -{}; +{ + static inline bool apply(Point const& point, + MultiPolygon const& multi_polygon, Strategy const& strategy) + { + return detail::within::geometry_multi_within_code + < + Point, + MultiPolygon, + Strategy, + detail::within::point_in_polygon + < + Point, + typename boost::range_value::type, + order_as_direction + < + geometry::point_order::value + >::value, + geometry::closure::value, + Strategy + > + >::apply(point, multi_polygon, strategy) == 1; + } +}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/multi/core/tags.hpp b/include/boost/geometry/multi/core/tags.hpp index 69398f7919..c168cfc166 100644 --- a/include/boost/geometry/multi/core/tags.hpp +++ b/include/boost/geometry/multi/core/tags.hpp @@ -27,7 +27,7 @@ struct multi_point_tag : multi_tag, pointlike_tag {}; struct multi_linestring_tag : multi_tag, linear_tag {}; /// OGC Multi polygon identifying tag -struct multi_polygon_tag : multi_tag, areal_tag {}; +struct multi_polygon_tag : multi_tag, polygonal_tag {}; /// OGC Geometry Collection identifying tag struct geometry_collection_tag : multi_tag {}; diff --git a/include/boost/geometry/policies/relate/intersection_points.hpp b/include/boost/geometry/policies/relate/intersection_points.hpp index cb47dedc99..ac5e966806 100644 --- a/include/boost/geometry/policies/relate/intersection_points.hpp +++ b/include/boost/geometry/policies/relate/intersection_points.hpp @@ -70,7 +70,16 @@ struct segments_intersection_points promoted_type const da = (promoted_type(dx2) * wy) - (promoted_type(dy2) * wx); // r: ratio 0-1 where intersection divides A/B - promoted_type const r = da / d; + promoted_type r = da / d; + // Handle robustness issues + if (r < 0) + { + r = 0; + } + else if (r > 1) + { + r = 1; + } result.count = 1; set<0>(result.intersections[0], diff --git a/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp new file mode 100644 index 0000000000..2cda538621 --- /dev/null +++ b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp @@ -0,0 +1,151 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP +#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP + +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry { namespace strategy +{ + +namespace within +{ + +struct decide_within +{ + static inline bool apply(int side, bool& result) + { + if (side != 1) + { + result = false; + return false; + } + return true; // continue + } +}; + +struct decide_covered_by +{ + static inline bool apply(int side, bool& result) + { + if (side != 1) + { + result = side >= 0; + return false; + } + return true; // continue + } +}; + + +template +struct point_in_box_by_side +{ + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy_type; + + static inline bool apply(Point const& point, Box const& box) + { + // Create (counterclockwise) array of points, the fifth one closes it + // Every point should be on the LEFT side (=1), or ON the border (=0), + // So >= 1 or >= 0 + boost::array::type, 5> bp; + geometry::detail::assign_box_corners_oriented(box, bp); + bp[4] = bp[0]; + + bool result = true; + side_strategy_type strategy; + boost::ignore_unused_variable_warning(strategy); + + for (int i = 1; i < 5; i++) + { + int const side = strategy.apply(point, bp[i - 1], bp[i]); + if (! Decide::apply(side, result)) + { + return result; + } + } + + return result; + } +}; + + +} // namespace within + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +namespace within { namespace services +{ + +template +struct default_strategy + < + point_tag, box_tag, + point_tag, areal_tag, + spherical_tag, spherical_tag, + Point, Box + > +{ + typedef within::point_in_box_by_side + < + Point, Box, within::decide_within + > type; +}; + + + +}} // namespace within::services + + +namespace covered_by { namespace services +{ + + +template +struct default_strategy + < + point_tag, box_tag, + point_tag, areal_tag, + spherical_tag, spherical_tag, + Point, Box + > +{ + typedef within::point_in_box_by_side + < + Point, Box, within::decide_covered_by + > type; +}; + + +}} // namespace covered_by::services + + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}}} // namespace boost::geometry::strategy + + +#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index c98de8ab32..fda35cc2ad 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -17,6 +17,7 @@ #include #include +#include #include @@ -181,23 +182,18 @@ namespace services { // Register using "areal_tag" for ring, polygon, multi-polygon -template -struct default_strategy +template +struct default_strategy { - typedef winding type; + typedef winding::type> type; }; -template -struct default_strategy +template +struct default_strategy { - typedef winding type; + typedef winding::type> type; }; -template -struct default_strategy -{ - typedef winding type; -}; } // namespace services @@ -207,6 +203,29 @@ struct default_strategy +struct default_strategy +{ + typedef strategy::within::winding::type> type; +}; + +template +struct default_strategy +{ + typedef strategy::within::winding::type> type; +}; + + +}}} // namespace strategy::covered_by::services +#endif + + }} // namespace boost::geometry diff --git a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp index b4e95b8a40..4ce74e946f 100644 --- a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp +++ b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp @@ -94,7 +94,12 @@ class douglas_peucker { public : - typedef typename strategy::distance::services::comparable_type::type distance_strategy_type; + // See also ticket 5954 https://svn.boost.org/trac/boost/ticket/5954 + // Comparable is currently not possible here because it has to be compared to the squared of max_distance, and more. + // For now we have to take the real distance. + typedef PointDistanceStrategy distance_strategy_type; + // typedef typename strategy::distance::services::comparable_type::type distance_strategy_type; + typedef typename strategy::distance::services::return_type::type return_type; private : @@ -145,7 +150,7 @@ private : #ifdef GL_DEBUG_DOUGLAS_PEUCKER std::cout << "consider " << dsv(it->p) << " at " << double(dist) - << ((dist > max_dist) ? " maybe" : " no") + << ((dist > max_dist) ? " maybe" : " no") << std::endl; #endif diff --git a/include/boost/geometry/strategies/cartesian/area_surveyor.hpp b/include/boost/geometry/strategies/cartesian/area_surveyor.hpp index 033c4a433d..2759466e5d 100644 --- a/include/boost/geometry/strategies/cartesian/area_surveyor.hpp +++ b/include/boost/geometry/strategies/cartesian/area_surveyor.hpp @@ -82,7 +82,7 @@ private : inline return_type area() const { return_type result = sum; - result *= 0.5; + result /= 2; return result; } }; diff --git a/include/boost/geometry/strategies/cartesian/box_in_box.hpp b/include/boost/geometry/strategies/cartesian/box_in_box.hpp new file mode 100644 index 0000000000..85a1caafb0 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/box_in_box.hpp @@ -0,0 +1,176 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP + + +#include +#include +#include +#include + + +namespace boost { namespace geometry { namespace strategy +{ + + +namespace within +{ + +struct box_within_range +{ + template + static inline bool apply(BoxContainedValue const& bed_min + , BoxContainedValue const& bed_max + , BoxContainingValue const& bing_min + , BoxContainingValue const& bing_max) + { + return bed_min > bing_min && bed_max < bing_max; + } +}; + + +struct box_covered_by_range +{ + template + static inline bool apply(BoxContainedValue const& bed_min + , BoxContainedValue const& bed_max + , BoxContainingValue const& bing_min + , BoxContainingValue const& bing_max) + { + return bed_min >= bing_min && bed_max <= bing_max; + } +}; + + +template +< + typename SubStrategy, + typename Box1, + typename Box2, + std::size_t Dimension, + std::size_t DimensionCount +> +struct relate_box_box_loop +{ + static inline bool apply(Box1 const& b_contained, Box2 const& b_containing) + { + assert_dimension_equal(); + + if (! SubStrategy::apply( + get(b_contained), + get(b_contained), + get(b_containing), + get(b_containing) + ) + ) + { + return false; + } + + return relate_box_box_loop + < + SubStrategy, + Box1, Box2, + Dimension + 1, DimensionCount + >::apply(b_contained, b_containing); + } +}; + +template +< + typename SubStrategy, + typename Box1, + typename Box2, + std::size_t DimensionCount +> +struct relate_box_box_loop +{ + static inline bool apply(Box1 const& , Box2 const& ) + { + return true; + } +}; + +template +< + typename Box1, + typename Box2, + typename SubStrategy = box_within_range +> +struct box_in_box +{ + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return relate_box_box_loop + < + SubStrategy, + Box1, Box2, 0, dimension::type::value + >::apply(box1, box2); + } +}; + + +} // namespace within + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +namespace within { namespace services +{ + +template +struct default_strategy + < + box_tag, box_tag, + box_tag, areal_tag, + cartesian_tag, cartesian_tag, + BoxContained, BoxContaining + > +{ + typedef within::box_in_box type; +}; + + +}} // namespace within::services + +namespace covered_by { namespace services +{ + +template +struct default_strategy + < + box_tag, box_tag, + box_tag, areal_tag, + cartesian_tag, cartesian_tag, + BoxContained, BoxContaining + > +{ + typedef within::box_in_box + < + BoxContained, BoxContaining, + within::box_covered_by_range + > type; +}; + +}} // namespace covered_by::services + + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}}} // namespace boost::geometry::strategy + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index 4df6a478ec..b081e19374 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -16,6 +16,8 @@ #include #include +#include + #include #include @@ -54,6 +56,19 @@ struct segment_arrange } }; +template +inline typename geometry::point_type::type get_from_index( + Segment const& segment) +{ + typedef typename geometry::point_type::type point_type; + point_type point; + geometry::detail::assign::assign_point_from_index + < + Segment, point_type, Index, 0, dimension::type::value + >::apply(segment, point); + return point; +} + } #endif @@ -91,10 +106,10 @@ struct relate_cartesian_segments /// Relate segments a and b static inline return_type apply(segment_type1 const& a, segment_type2 const& b) { - coordinate_type dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir - coordinate_type dx_b = get<1, 0>(b) - get<0, 0>(b); - coordinate_type dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir - coordinate_type dy_b = get<1, 1>(b) - get<0, 1>(b); + coordinate_type const dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir + coordinate_type const dx_b = get<1, 0>(b) - get<0, 0>(b); + coordinate_type const dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir + coordinate_type const dy_b = get<1, 1>(b) - get<0, 1>(b); return apply(a, b, dx_a, dy_a, dx_b, dy_b); } @@ -133,8 +148,15 @@ struct relate_cartesian_segments // Note: Do NOT yet calculate the determinant here, but use the SIDE strategy. // Determinant calculation is not robust; side (orient) can be made robust // (and is much robuster even without measures) - sides.set<1>(side::apply(a.first, a.second, b.first), - side::apply(a.first, a.second, b.second)); + sides.set<1> + ( + side::apply(detail::get_from_index<0>(a) + , detail::get_from_index<1>(a) + , detail::get_from_index<0>(b)), + side::apply(detail::get_from_index<0>(a) + , detail::get_from_index<1>(a) + , detail::get_from_index<1>(b)) + ); if (sides.same<1>()) { @@ -143,8 +165,15 @@ struct relate_cartesian_segments } // 2b) For other segment - sides.set<0>(side::apply(b.first, b.second, a.first), - side::apply(b.first, b.second, a.second)); + sides.set<0> + ( + side::apply(detail::get_from_index<0>(b) + , detail::get_from_index<1>(b) + , detail::get_from_index<0>(a)), + side::apply(detail::get_from_index<0>(b) + , detail::get_from_index<1>(b) + , detail::get_from_index<1>(a)) + ); if (sides.same<0>()) { @@ -164,7 +193,7 @@ struct relate_cartesian_segments bool collinear = sides.collinear(); - // Get the same type, but at least a double (also used for divisions + // Get the same type, but at least a double (also used for divisions) typedef typename select_most_precise < coordinate_type, double @@ -347,8 +376,8 @@ private : // In robustness it can occur that a point of A is inside B AND a point of B is inside A, // still while has_common_points is true (so one point equals the other). // If that is the case we select on length. - coordinate_type const length_a = abs(a_1 - a_2); - coordinate_type const length_b = abs(b_1 - b_2); + coordinate_type const length_a = geometry::math::abs(a_1 - a_2); + coordinate_type const length_b = geometry::math::abs(b_1 - b_2); if (length_a > length_b) { a_in_b = false; diff --git a/include/boost/geometry/strategies/cartesian/point_in_box.hpp b/include/boost/geometry/strategies/cartesian/point_in_box.hpp new file mode 100644 index 0000000000..a9450b6c07 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/point_in_box.hpp @@ -0,0 +1,172 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP + + +#include +#include +#include +#include + + +namespace boost { namespace geometry { namespace strategy +{ + +namespace within +{ + + +struct within_range +{ + template + static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) + { + return value > min_value && value < max_value; + } +}; + + +struct covered_by_range +{ + template + static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) + { + return value >= min_value && value <= max_value; + } +}; + + +template +< + typename SubStrategy, + typename Point, + typename Box, + std::size_t Dimension, + std::size_t DimensionCount +> +struct relate_point_box_loop +{ + static inline bool apply(Point const& point, Box const& box) + { + if (! SubStrategy::apply(get(point), + get(box), + get(box)) + ) + { + return false; + } + + return relate_point_box_loop + < + SubStrategy, + Point, Box, + Dimension + 1, DimensionCount + >::apply(point, box); + } +}; + + +template +< + typename SubStrategy, + typename Point, + typename Box, + std::size_t DimensionCount +> +struct relate_point_box_loop +{ + static inline bool apply(Point const& , Box const& ) + { + return true; + } +}; + + +template +< + typename Point, + typename Box, + typename SubStrategy = within_range +> +struct point_in_box +{ + static inline bool apply(Point const& point, Box const& box) + { + return relate_point_box_loop + < + SubStrategy, + Point, Box, + 0, dimension::type::value + >::apply(point, box); + } +}; + + +} // namespace within + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +namespace within { namespace services +{ + +template +struct default_strategy + < + point_tag, box_tag, + point_tag, areal_tag, + cartesian_tag, cartesian_tag, + Point, Box + > +{ + typedef within::point_in_box type; +}; + + +}} // namespace within::services + + +namespace covered_by { namespace services +{ + + +template +struct default_strategy + < + point_tag, box_tag, + point_tag, areal_tag, + cartesian_tag, cartesian_tag, + Point, Box + > +{ + typedef within::point_in_box + < + Point, Box, + within::covered_by_range + > type; +}; + + +}} // namespace covered_by::services + + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}}} // namespace boost::geometry::strategy + + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index b4255c8a12..d3d8b1ff3b 100644 --- a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp @@ -89,7 +89,7 @@ public : promoted_type const s = dx * dpy - dy * dpx; - promoted_type zero = promoted_type(); + promoted_type const zero = promoted_type(); return math::equals(s, zero) ? 0 : s > zero ? 1 : -1; diff --git a/include/boost/geometry/strategies/concepts/distance_concept.hpp b/include/boost/geometry/strategies/concepts/distance_concept.hpp index a29ad63580..5ec23df792 100644 --- a/include/boost/geometry/strategies/concepts/distance_concept.hpp +++ b/include/boost/geometry/strategies/concepts/distance_concept.hpp @@ -19,13 +19,7 @@ #include -#include -#include -#include -#include -#include -#include -#include +#include #include #include @@ -50,40 +44,15 @@ private : template static void apply(ApplyMethod const&) { - namespace ft = boost::function_types; - typedef typename ft::parameter_types - < - ApplyMethod - >::type parameter_types; - - typedef typename boost::mpl::if_ - < - ft::is_member_function_pointer, - boost::mpl::int_<1>, - boost::mpl::int_<0> - >::type base_index; - // 1: inspect and define both arguments of apply - typedef typename boost::remove_reference + typedef typename parameter_type_of < - typename boost::mpl::at - < - parameter_types, - base_index - >::type + ApplyMethod, 0 >::type ptype1; - typedef typename boost::remove_reference + typedef typename parameter_type_of < - typename boost::mpl::at - < - parameter_types, - typename boost::mpl::plus - < - base_index, - boost::mpl::int_<1> - >::type - >::type + ApplyMethod, 1 >::type ptype2; // 2) check if apply-arguments fulfill point concept @@ -177,40 +146,14 @@ private : template static void apply(ApplyMethod const&) { - namespace ft = boost::function_types; - typedef typename ft::parameter_types - < - ApplyMethod - >::type parameter_types; - - typedef typename boost::mpl::if_ - < - ft::is_member_function_pointer, - boost::mpl::int_<1>, - boost::mpl::int_<0> - >::type base_index; - - // 1: inspect and define both arguments of apply - typedef typename boost::remove_reference + typedef typename parameter_type_of < - typename boost::mpl::at - < - parameter_types, - base_index - >::type + ApplyMethod, 0 >::type ptype; - typedef typename boost::remove_reference + typedef typename parameter_type_of < - typename boost::mpl::at - < - parameter_types, - typename boost::mpl::plus - < - base_index, - boost::mpl::int_<1> - >::type - >::type + ApplyMethod, 1 >::type sptype; // 2) check if apply-arguments fulfill point concept diff --git a/include/boost/geometry/strategies/concepts/within_concept.hpp b/include/boost/geometry/strategies/concepts/within_concept.hpp index c1f07bc713..19c6174169 100644 --- a/include/boost/geometry/strategies/concepts/within_concept.hpp +++ b/include/boost/geometry/strategies/concepts/within_concept.hpp @@ -17,6 +17,9 @@ #include +#include + +#include namespace boost { namespace geometry { namespace concept @@ -24,57 +27,265 @@ namespace boost { namespace geometry { namespace concept /*! - \brief Checks strategy for within (point-in-polygon) - \ingroup within +\brief Checks strategy for within (point-in-polygon) +\ingroup within */ template -class WithinStrategy +class WithinStrategyPolygonal { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS - // 1) must define state_type, + // 1) must define state_type typedef typename Strategy::state_type state_type; - // 2) must define point_type (of "point" in poly) - typedef typename Strategy::point_type point_type; + struct checker + { + template + static void apply(ApplyMethod const&, ResultMethod const& ) + { + typedef typename parameter_type_of + < + ApplyMethod, 0 + >::type point_type; + typedef typename parameter_type_of + < + ApplyMethod, 1 + >::type segment_point_type; - // 3) must define point_type, of polygon (segments) - typedef typename Strategy::segment_point_type spoint_type; + // CHECK: apply-arguments should both fulfill point concept + BOOST_CONCEPT_ASSERT + ( + (concept::ConstPoint) + ); + BOOST_CONCEPT_ASSERT + ( + (concept::ConstPoint) + ); - struct check_methods - { - static void apply() - { - Strategy const* str; + // CHECK: return types (result: int, apply: bool) + BOOST_MPL_ASSERT_MSG + ( + (boost::is_same + < + bool, typename boost::function_types::result_type::type + >::type::value), + WRONG_RETURN_TYPE_OF_APPLY + , (bool) + ); + BOOST_MPL_ASSERT_MSG + ( + (boost::is_same + < + int, typename boost::function_types::result_type::type + >::type::value), + WRONG_RETURN_TYPE_OF_RESULT + , (int) + ); + + // CHECK: calling method apply and result + Strategy const* str; state_type* st; point_type const* p; - spoint_type const* sp; - - // 4) must implement a method apply - // having a point, two segment-points, and state - str->apply(*p, *sp, *sp, *st); + segment_point_type const* sp; - // 5) must implement a method result returning int + bool b = str->apply(*p, *sp, *sp, *st); int r = str->result(*st); boost::ignore_unused_variable_warning(r); + boost::ignore_unused_variable_warning(b); boost::ignore_unused_variable_warning(str); } }; public : - BOOST_CONCEPT_USAGE(WithinStrategy) + BOOST_CONCEPT_USAGE(WithinStrategyPolygonal) { - check_methods::apply(); + checker::apply(&Strategy::apply, &Strategy::result); } #endif }; +template +class WithinStrategyPointBox +{ +#ifndef DOXYGEN_NO_CONCEPT_MEMBERS + + struct checker + { + template + static void apply(ApplyMethod const&) + { + typedef typename parameter_type_of + < + ApplyMethod, 0 + >::type point_type; + typedef typename parameter_type_of + < + ApplyMethod, 1 + >::type box_type; + + // CHECK: apply-arguments should fulfill point/box concept + BOOST_CONCEPT_ASSERT + ( + (concept::ConstPoint) + ); + + BOOST_CONCEPT_ASSERT + ( + (concept::ConstBox) + ); + + // CHECK: return types (apply: bool) + BOOST_MPL_ASSERT_MSG + ( + (boost::is_same + < + bool, + typename boost::function_types::result_type::type + >::type::value), + WRONG_RETURN_TYPE + , (bool) + ); + + + // CHECK: calling method apply + Strategy const* str; + point_type const* p; + box_type const* bx; + + bool b = str->apply(*p, *bx); + + boost::ignore_unused_variable_warning(b); + boost::ignore_unused_variable_warning(str); + } + }; + + +public : + BOOST_CONCEPT_USAGE(WithinStrategyPointBox) + { + checker::apply(&Strategy::apply); + } +#endif +}; + +template +class WithinStrategyBoxBox +{ +#ifndef DOXYGEN_NO_CONCEPT_MEMBERS + + struct checker + { + template + static void apply(ApplyMethod const&) + { + typedef typename parameter_type_of + < + ApplyMethod, 0 + >::type box_type1; + typedef typename parameter_type_of + < + ApplyMethod, 1 + >::type box_type2; + + // CHECK: apply-arguments should both fulfill box concept + BOOST_CONCEPT_ASSERT + ( + (concept::ConstBox) + ); + + BOOST_CONCEPT_ASSERT + ( + (concept::ConstBox) + ); + + // CHECK: return types (apply: bool) + BOOST_MPL_ASSERT_MSG + ( + (boost::is_same + < + bool, + typename boost::function_types::result_type::type + >::type::value), + WRONG_RETURN_TYPE + , (bool) + ); + + + // CHECK: calling method apply + Strategy const* str; + box_type1 const* b1; + box_type2 const* b2; + + bool b = str->apply(*b1, *b2); + + boost::ignore_unused_variable_warning(b); + boost::ignore_unused_variable_warning(str); + } + }; + + +public : + BOOST_CONCEPT_USAGE(WithinStrategyBoxBox) + { + checker::apply(&Strategy::apply); + } +#endif +}; + +// So now: boost::geometry::concept::within +namespace within +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct check_within +{}; + + +template +struct check_within +{ + BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal) ); +}; + + +template +struct check_within +{ + BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox) ); +}; + +template +struct check_within +{ + BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox) ); +}; + + +} // namespace dispatch +#endif + + +/*! +\brief Checks, in compile-time, the concept of any within-strategy +\ingroup concepts +*/ +template +inline void check() +{ + dispatch::check_within c; + boost::ignore_unused_variable_warning(c); +} + +}}}} // namespace boost::geometry::concept::within -}}} // namespace boost::geometry::concept #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/covered_by.hpp b/include/boost/geometry/strategies/covered_by.hpp new file mode 100644 index 0000000000..59704eac43 --- /dev/null +++ b/include/boost/geometry/strategies/covered_by.hpp @@ -0,0 +1,72 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_STRATEGIES_COVERED_BY_HPP +#define BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP + +#include + + +namespace boost { namespace geometry +{ + + +namespace strategy { namespace covered_by +{ + + +namespace services +{ + +/*! +\brief Traits class binding a covered_by determination strategy to a coordinate system +\ingroup covered_by +\tparam TagContained tag (possibly casted) of point-type +\tparam TagContained tag (possibly casted) of (possibly) containing type +\tparam CsTagContained tag of coordinate system of point-type +\tparam CsTagContaining tag of coordinate system of (possibly) containing type +\tparam Geometry geometry-type of input (often point, or box) +\tparam GeometryContaining geometry-type of input (possibly) containing type +*/ +template +< + typename TagContained, + typename TagContaining, + typename CastedTagContained, + typename CastedTagContaining, + typename CsTagContained, + typename CsTagContaining, + typename GeometryContained, + typename GeometryContaining +> +struct default_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPES + , (types) + ); +}; + + +} // namespace services + + +}} // namespace strategy::covered_by + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP + diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index 25369a7bfb..7242b3db08 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -28,10 +28,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -43,6 +45,7 @@ #include #include +#include #include #include diff --git a/include/boost/geometry/strategies/strategy_transform.hpp b/include/boost/geometry/strategies/strategy_transform.hpp index 34e19fc774..0410833cad 100644 --- a/include/boost/geometry/strategies/strategy_transform.hpp +++ b/include/boost/geometry/strategies/strategy_transform.hpp @@ -222,6 +222,17 @@ namespace detail set_from_radian<1>(p, acos(z)); return true; } + + template + inline bool cartesian_to_spherical_equatorial2(T x, T y, T z, P& p) + { + assert_dimension(); + + set_from_radian<0>(p, atan2(y, x)); + set_from_radian<1>(p, asin(z)); + return true; + } + template inline bool cartesian_to_spherical3(T x, T y, T z, P& p) @@ -323,6 +334,16 @@ struct from_cartesian_3_to_spherical_polar_2 } }; +template +struct from_cartesian_3_to_spherical_equatorial_2 +{ + inline bool apply(P1 const& p1, P2& p2) const + { + assert_dimension(); + return detail::cartesian_to_spherical_equatorial2(get<0>(p1), get<1>(p1), get<2>(p1), p2); + } +}; + /*! \brief Transformation strategy for 3D cartesian (x,y,z) to 3D spherical (phi,theta,r) @@ -421,6 +442,12 @@ struct default_strategy type; }; +template +struct default_strategy +{ + typedef from_cartesian_3_to_spherical_equatorial_2 type; +}; + /// Specialization to transform from XYZ to sphere(phi,theta,r) template struct default_strategy diff --git a/include/boost/geometry/strategies/within.hpp b/include/boost/geometry/strategies/within.hpp index ca61156b8a..717fe5f15d 100644 --- a/include/boost/geometry/strategies/within.hpp +++ b/include/boost/geometry/strategies/within.hpp @@ -16,7 +16,6 @@ #include -#include namespace boost { namespace geometry { @@ -29,28 +28,32 @@ namespace services { /*! - \brief Traits class binding a within determination strategy to a coordinate system - \ingroup within - \tparam CsTagContained tag of coordinate system of point-type - \tparam CsTagContained tag of coordinate system of segment-type - \tparam Point point-type of input points - \tparam PointContaining point-type of input segment-points +\brief Traits class binding a within determination strategy to a coordinate system +\ingroup within +\tparam TagContained tag (possibly casted) of point-type +\tparam TagContained tag (possibly casted) of (possibly) containing type +\tparam CsTagContained tag of coordinate system of point-type +\tparam CsTagContaining tag of coordinate system of (possibly) containing type +\tparam Geometry geometry-type of input (often point, or box) +\tparam GeometryContaining geometry-type of input (possibly) containing type */ template < typename TagContained, typename TagContaining, + typename CastedTagContained, + typename CastedTagContaining, typename CsTagContained, typename CsTagContaining, - typename Point, - typename PointContaining + typename GeometryContained, + typename GeometryContaining > struct default_strategy { BOOST_MPL_ASSERT_MSG ( false, NOT_IMPLEMENTED_FOR_THIS_TYPES - , (types) + , (types) ); }; diff --git a/include/boost/geometry/util/parameter_type_of.hpp b/include/boost/geometry/util/parameter_type_of.hpp new file mode 100644 index 0000000000..2e82941648 --- /dev/null +++ b/include/boost/geometry/util/parameter_type_of.hpp @@ -0,0 +1,75 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_UTIL_PARAMETER_TYPE_OF_HPP +#define BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP + + +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +/*! +\brief Meta-function selecting a parameter type of a (member) function, by index +\ingroup utility + */ +template +struct parameter_type_of +{ + typedef typename boost::function_types::parameter_types + < + Method + >::type parameter_types; + + typedef typename boost::mpl::if_ + < + boost::function_types::is_member_function_pointer, + boost::mpl::int_<1>, + boost::mpl::int_<0> + >::type base_index_type; + + typedef typename boost::mpl::if_c + < + Index == 0, + base_index_type, + typename boost::mpl::plus + < + base_index_type, + boost::mpl::int_ + >::type + >::type indexed_type; + + typedef typename boost::remove_reference + < + typename boost::mpl::at + < + parameter_types, + indexed_type + >::type + >::type type; +}; + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP diff --git a/include/boost/geometry/util/rational.hpp b/include/boost/geometry/util/rational.hpp new file mode 100644 index 0000000000..d450a84970 --- /dev/null +++ b/include/boost/geometry/util/rational.hpp @@ -0,0 +1,179 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2011-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2011-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2011-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_UTIL_RATIONAL_HPP +#define BOOST_GEOMETRY_UTIL_RATIONAL_HPP + +#include +#include + +#include +#include + + +namespace boost{ namespace geometry +{ + + +// Specialize for Boost.Geometry's coordinate cast +// (from string to coordinate type) +namespace detail +{ + +template +struct coordinate_cast > +{ + static inline void split_parts(std::string const& source, std::string::size_type p, + T& before, T& after, bool& negate, std::string::size_type& len) + { + std::string before_part = source.substr(0, p); + std::string const after_part = source.substr(p + 1); + + negate = false; + + if (before_part.size() > 0 && before_part[0] == '-') + { + negate = true; + before_part.erase(0, 1); + } + before = atol(before_part.c_str()); + after = atol(after_part.c_str()); + len = after_part.length(); + } + + + static inline rational apply(std::string const& source) + { + T before, after; + bool negate; + std::string::size_type len; + + // Note: decimal comma is not (yet) supported, it does (and should) not + // occur in a WKT, where points are comma separated. + std::string::size_type p = source.find("."); + if (p == std::string::npos) + { + p = source.find("/"); + if (p == std::string::npos) + { + return rational(atol(source.c_str())); + } + split_parts(source, p, before, after, negate, len); + + return negate + ? -rational(before, after) + : rational(before, after) + ; + + } + + split_parts(source, p, before, after, negate, len); + + T den = 1; + for (std::string::size_type i = 0; i < len; i++) + { + den *= 10; + } + + return negate + ? -rational(before) - rational(after, den) + : rational(before) + rational(after, den) + ; + } +}; + +} // namespace detail + +// Specialize for Boost.Geometry's select_most_precise +template +struct select_most_precise, boost::rational > +{ + typedef typename boost::rational + < + typename select_most_precise::type + > type; +}; + +template +struct select_most_precise, double> +{ + typedef typename boost::rational type; +}; + + +}} // namespace boost::geometry + + +// Specializes boost::rational to boost::numeric::bounds +namespace boost { namespace numeric +{ + +template +struct bounds > +{ + static inline rational lowest() + { + return rational(bounds::lowest(), 1); + } + static inline rational highest() + { + return rational(bounds::highest(), 1); + } +}; + +}} // namespace boost::numeric + + +// Support for boost::numeric_cast to int and to double (necessary for SVG-mapper) +namespace boost { namespace numeric +{ + +template +< + typename T, + typename Traits, + typename OverflowHandler, + typename Float2IntRounder, + typename RawConverter, + typename UserRangeChecker +> +struct converter, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker> +{ + static inline int convert(rational const& arg) + { + return int(rational_cast(arg)); + } +}; + +template +< + typename T, + typename Traits, + typename OverflowHandler, + typename Float2IntRounder, + typename RawConverter, + typename UserRangeChecker +> +struct converter, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker> +{ + static inline double convert(rational const& arg) + { + return rational_cast(arg); + } +}; + + +}} + + +#endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP diff --git a/test/algorithms/Jamfile.v2 b/test/algorithms/Jamfile.v2 index 7058f6753b..3e37dcaf0f 100644 --- a/test/algorithms/Jamfile.v2 +++ b/test/algorithms/Jamfile.v2 @@ -19,6 +19,7 @@ test-suite boost-geometry-algorithms [ run convex_hull.cpp ] [ run correct.cpp ] [ run convert.cpp ] + [ run covered_by.cpp ] [ run difference.cpp ] [ run disjoint.cpp ] [ run distance.cpp ] diff --git a/test/algorithms/algorithms_tests.sln b/test/algorithms/algorithms_tests.sln index 6880312aa9..124ad8af03 100644 --- a/test/algorithms/algorithms_tests.sln +++ b/test/algorithms/algorithms_tests.sln @@ -56,6 +56,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "comparable_distance", "comp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convert", "convert.vcproj", "{FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "covered_by", "covered_by.vcproj", "{5ABF0B56-F9F1-4D93-B15A-E3972F45D97B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -174,6 +176,10 @@ Global {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Debug|Win32.Build.0 = Debug|Win32 {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Release|Win32.ActiveCfg = Release|Win32 {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Release|Win32.Build.0 = Release|Win32 + {5ABF0B56-F9F1-4D93-B15A-E3972F45D97B}.Debug|Win32.ActiveCfg = Debug|Win32 + {5ABF0B56-F9F1-4D93-B15A-E3972F45D97B}.Debug|Win32.Build.0 = Debug|Win32 + {5ABF0B56-F9F1-4D93-B15A-E3972F45D97B}.Release|Win32.ActiveCfg = Release|Win32 + {5ABF0B56-F9F1-4D93-B15A-E3972F45D97B}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/algorithms/assign.cpp b/test/algorithms/assign.cpp index ad3bef97b3..f99e11a550 100644 --- a/test/algorithms/assign.cpp +++ b/test/algorithms/assign.cpp @@ -162,6 +162,14 @@ void test_assign_conversion() ring_type ring; bg::assign(ring, b); + { + typedef bg::model::ring ring_type_ccw; + ring_type_ccw ring_ccw; + // Should NOT compile (currently): bg::assign(ring_ccw, ring); + + } + + //std::cout << bg::wkt(b) << std::endl; //std::cout << bg::wkt(ring) << std::endl; diff --git a/test/algorithms/convert.cpp b/test/algorithms/convert.cpp index 039922b3be..8b230f8bb1 100644 --- a/test/algorithms/convert.cpp +++ b/test/algorithms/convert.cpp @@ -12,97 +12,237 @@ // 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 -BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) -BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) - - -template -void test_all() +template +void test_mixed_point_types() { - typedef bg::model::box

box_type; - - P p; - bg::assign_values(p, 1, 2); - - box_type b; - bg::convert(p, b); + // Point + test_mixed_identical_result("POINT(1 2)"); + + // Linestring + test_mixed_identical_result + < + bg::model::linestring, + bg::model::linestring + > + ("LINESTRING(1 1,2 2)"); + + // Ring + test_mixed_identical_result + < + bg::model::ring, + bg::model::ring + > + ("POLYGON((1 1,2 2,3 0,1 1))"); + test_mixed_reversible_result + < + bg::model::ring, + bg::model::ring + > + ( + "POLYGON((1 1,2 2,3 0,1 1))", + "POLYGON((1 1,3 0,2 2,1 1))" + ); + test_mixed + < + bg::model::ring, + bg::model::ring + > + ( + "POLYGON((1 1,2 2,3 0,1 1))", + "POLYGON((1 1,2 2,3 0))" + ); + test_mixed + < + bg::model::ring, + bg::model::ring + > + ( + "POLYGON((1 1,2 2,3 0))", + "POLYGON((1 1,2 2,3 0,1 1))" + ); + + // Polygon + test_mixed_reversible_result + < + bg::model::polygon, + bg::model::polygon + > + ( + "POLYGON((0 0,0 5,5 5,5 0,0 0),(1 1,3 2,2 4,1 1))", + "POLYGON((0 0,5 0,5 5,0 5,0 0),(1 1,2 4,3 2,1 1))" + ); + test_mixed + < + bg::model::polygon, + bg::model::polygon + > + ( + "POLYGON((0 0,0 5,5 5,5 0,0 0),(1 1,3 2,2 4,1 1))", + "POLYGON((0 0,5 0,5 5,0 5),(1 1,2 4,3 2))" + ); + // (polygon uses ring, so other tests omitted here) + + // Combinations: + // ring <-> polygon + test_mixed_identical_result + < + bg::model::polygon, + bg::model::ring + > + ("POLYGON((1 1,2 2,3 0,1 1))"); + test_mixed_reversible_result + < + bg::model::polygon, + bg::model::ring + > + ( + "POLYGON((1 1,2 2,3 0,1 1))", + "POLYGON((1 1,3 0,2 2,1 1))" + ); + // Any hole will be omitted going from polygon to ring + test_mixed + < + bg::model::polygon, + bg::model::ring + > + ( + "POLYGON((0 0,0 5,5 5,5 0,0 0),(1 1,3 2,2 4,1 1))", + "POLYGON((0 0,0 5,5 5,5 0,0 0))" + ); + + // point -> box + test_mixed + < + Point1, + bg::model::box + > + ( + "POINT(0 0)", + "POLYGON((0 0,0 0,0 0,0 0,0 0))" + ); + + // segment -> line + test_mixed + < + bg::model::segment, + bg::model::linestring + > + ( + "LINESTRING(0 0,1 1)", + "LINESTRING(0 0,1 1)" + ); + + // box -> ring ( <- is NYI) + test_mixed + < + bg::model::box, + bg::model::ring + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,0 2,2 2,2 0,0 0))" + ); + test_mixed + < + bg::model::box, + bg::model::ring + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,2 0,2 2,0 2,0 0))" + ); + test_mixed + < + bg::model::box, + bg::model::ring + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,0 2,2 2,2 0))" + ); + test_mixed + < + bg::model::box, + bg::model::ring + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,2 0,2 2,0 2))" + ); + + // box -> polygon ( <- is NYI) + test_mixed + < + bg::model::box, + bg::model::polygon + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,0 2,2 2,2 0,0 0))" + ); + test_mixed + < + bg::model::box, + bg::model::polygon + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,2 0,2 2,0 2,0 0))" + ); + test_mixed + < + bg::model::box, + bg::model::polygon + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,0 2,2 2,2 0))" + ); + test_mixed + < + bg::model::box, + bg::model::polygon + > + ( + "BOX(0 0,2 2)", + "POLYGON((0 0,2 0,2 2,0 2))" + ); +} - BOOST_CHECK_CLOSE((bg::get<0, 0>(b)), 1.0, 0.001); - BOOST_CHECK_CLOSE((bg::get<0, 1>(b)), 2.0, 0.001); - BOOST_CHECK_CLOSE((bg::get<1, 0>(b)), 1.0, 0.001); - BOOST_CHECK_CLOSE((bg::get<1, 1>(b)), 2.0, 0.001); +template +void test_mixed_types() +{ + test_mixed_point_types(); + test_mixed_point_types(); } -template -void test_std() +void test_array() { - test_all

(); - - typedef bg::model::box

box_type; - typedef bg::model::ring

ring_type; - typedef bg::model::polygon

polygon_type; - - box_type b; - bg::set(b, 1); - bg::set(b, 2); - bg::set(b, 3); - bg::set(b, 4); - - ring_type ring; - bg::convert(b, ring); - - //std::cout << bg::wkt(b) << std::endl; - //std::cout << bg::wkt(ring) << std::endl; - - typename boost::range_const_iterator::type it = ring.begin(); - BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001); - BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001); - it++; - BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001); - BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001); - it++; - BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001); - BOOST_CHECK_CLOSE(bg::get<1>(*it), 4.0, 0.001); - it++; - BOOST_CHECK_CLOSE(bg::get<0>(*it), 3.0, 0.001); - BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001); - it++; - BOOST_CHECK_CLOSE(bg::get<0>(*it), 1.0, 0.001); - BOOST_CHECK_CLOSE(bg::get<1>(*it), 2.0, 0.001); - - BOOST_CHECK_EQUAL(ring.size(), 5u); - - - polygon_type polygon; - - bg::convert(ring, polygon); - BOOST_CHECK_EQUAL(bg::num_points(polygon), 5u); - - bg::convert(polygon, ring); - BOOST_CHECK_EQUAL(bg::num_points(ring), 5u); + int a[2] = {1, 2}; + int b[2]; + bg::convert(a, b); + BOOST_CHECK_EQUAL(b[0], 1); + BOOST_CHECK_EQUAL(b[1], 2); } int test_main(int, char* []) { - test_std >(); - test_std >(); - test_std >(); - -#ifdef HAVE_TTMATH - test_std >(); -#endif + test_mixed_types + < + bg::model::point, + bg::model::point + >(); + test_mixed_types + < + boost::tuple, + bg::model::point + >(); + + test_array(); return 0; } diff --git a/test/algorithms/covered_by.cpp b/test/algorithms/covered_by.cpp new file mode 100644 index 0000000000..a6cb7aef12 --- /dev/null +++ b/test/algorithms/covered_by.cpp @@ -0,0 +1,149 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright (c) 2007-2011 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) + +#include + + +#include +#include + + +template +void test_all() +{ + /* + // trivial case + test_ring

("POINT(1 1)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", true, false); + + // on border/corner + test_ring

("POINT(0 0)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", false, true); + test_ring

("POINT(0 1)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", false, true); + + // aligned to segment/vertex + test_ring

("POINT(1 1)", "POLYGON((0 0,0 3,3 3,3 1,2 1,2 0,0 0))", true, false); + test_ring

("POINT(1 1)", "POLYGON((0 0,0 3,4 3,3 1,2 2,2 0,0 0))", true, false); + + // same polygon, but point on border + test_ring

("POINT(3 3)", "POLYGON((0 0,0 3,3 3,3 1,2 1,2 0,0 0))", false, true); + test_ring

("POINT(3 3)", "POLYGON((0 0,0 3,4 3,3 1,2 2,2 0,0 0))", false, true); + + // holes + test_geometry >("POINT(2 2)", + "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,3 1,3 3,1 3,1 1))", false); + + */ + + typedef bg::model::box

box_type; + + test_geometry("POINT(1 1)", "BOX(0 0,2 2)", true); + test_geometry("POINT(0 0)", "BOX(0 0,2 2)", true); + test_geometry("POINT(2 2)", "BOX(0 0,2 2)", true); + test_geometry("POINT(0 1)", "BOX(0 0,2 2)", true); + test_geometry("POINT(1 0)", "BOX(0 0,2 2)", true); + test_geometry("POINT(3 3)", "BOX(0 0,2 2)", false); + + test_geometry("BOX(1 1,2 2)", "BOX(0 0,3 3)", true); + test_geometry("BOX(0 0,3 3)", "BOX(1 1,2 2)", false); + test_geometry("BOX(0 0,2 2)", "BOX(0 0,3 3)", true); + test_geometry("BOX(1 1,3 3)", "BOX(0 0,3 3)", true); + test_geometry("BOX(1 2,3 3)", "BOX(0 0,3 3)", true); + test_geometry("BOX(1 1,4 3)", "BOX(0 0,3 3)", false); + + + /* + test_within_code("POINT(1 1)", "BOX(0 0,2 2)", 1); + test_within_code("POINT(1 0)", "BOX(0 0,2 2)", 0); + test_within_code("POINT(0 1)", "BOX(0 0,2 2)", 0); + test_within_code("POINT(0 3)", "BOX(0 0,2 2)", -1); + test_within_code("POINT(3 3)", "BOX(0 0,2 2)", -1); + + test_within_code("BOX(1 1,2 2)", "BOX(0 0,3 3)", 1); + test_within_code("BOX(0 1,2 2)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 0,2 2)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 1,2 3)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 1,3 2)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 1,3 4)", "BOX(0 0,3 3)", -1); + */ +} + + +void test_3d() +{ + typedef boost::geometry::model::point point_type; + typedef boost::geometry::model::box box_type; + box_type box(point_type(0, 0, 0), point_type(4, 4, 4)); + BOOST_CHECK_EQUAL(bg::covered_by(point_type(2, 2, 2), box), true); + BOOST_CHECK_EQUAL(bg::covered_by(point_type(2, 4, 2), box), true); + BOOST_CHECK_EQUAL(bg::covered_by(point_type(2, 2, 4), box), true); + BOOST_CHECK_EQUAL(bg::covered_by(point_type(2, 2, 5), box), false); +} + +template +void test_mixed_of() +{ + typedef boost::geometry::model::polygon polygon_type1; + typedef boost::geometry::model::polygon polygon_type2; + typedef boost::geometry::model::box box_type1; + typedef boost::geometry::model::box box_type2; + + polygon_type1 poly1, poly2; + boost::geometry::read_wkt("POLYGON((0 0,0 5,5 5,5 0,0 0))", poly1); + boost::geometry::read_wkt("POLYGON((0 0,0 5,5 5,5 0,0 0))", poly2); + + box_type1 box1(P1(1, 1), P1(4, 4)); + box_type2 box2(P2(0, 0), P2(5, 5)); + P1 p1(3, 3); + P2 p2(3, 3); + + BOOST_CHECK_EQUAL(bg::covered_by(p1, poly2), true); + BOOST_CHECK_EQUAL(bg::covered_by(p2, poly1), true); + BOOST_CHECK_EQUAL(bg::covered_by(p2, box1), true); + BOOST_CHECK_EQUAL(bg::covered_by(p1, box2), true); + BOOST_CHECK_EQUAL(bg::covered_by(box1, box2), true); + BOOST_CHECK_EQUAL(bg::covered_by(box2, box1), false); +} + + +void test_mixed() +{ + // Mixing point types and coordinate types + test_mixed_of + < + boost::geometry::model::d2::point_xy, + boost::geometry::model::point + >(); + test_mixed_of + < + boost::geometry::model::d2::point_xy, + boost::geometry::model::point + >(); + test_mixed_of + < + boost::geometry::model::d2::point_xy, + boost::geometry::model::d2::point_xy + >(); +} + + +int test_main( int , char* [] ) +{ + test_all >(); + test_all >(); + + //test_spherical > >(); + + test_mixed(); + test_3d(); + + +#if defined(HAVE_TTMATH) + test_all >(); + //test_spherical > >(); +#endif + + return 0; +} diff --git a/test/algorithms/covered_by.vcproj b/test/algorithms/covered_by.vcproj new file mode 100644 index 0000000000..13f41e9300 --- /dev/null +++ b/test/algorithms/covered_by.vcproj @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/algorithms/difference.cpp b/test/algorithms/difference.cpp index 7787dea3d6..1cd2bb8aeb 100644 --- a/test/algorithms/difference.cpp +++ b/test/algorithms/difference.cpp @@ -46,8 +46,7 @@ void test_all() typedef bg::model::polygon

polygon; typedef bg::model::ring

ring; - bool const is_float = - boost::is_same::type, float>::value; + typedef typename bg::coordinate_type

::type ct; test_one("simplex_normal", simplex_normal[0], simplex_normal[1], @@ -93,7 +92,7 @@ void test_all() test_one("distance_zero", distance_zero[0], distance_zero[1], 2, 0, 8.7048386, - is_float ? 1 : 2, // The too small one is discarded for floating point + if_typed(1, 2), // The too small one is discarded for floating point 0, 0.0098387); @@ -200,18 +199,55 @@ void test_all() ***/ #ifdef _MSC_VER - { - // Isovist (submitted by Brandon during Formal Review) - std::string tn = string_from_type::type>::name(); - test_one("isovist", - isovist1[0], isovist1[1], - 4, 0, 0.279121891701124, - 4, 0, 224.889211358929, - 0.01); - } + // Isovist (submitted by Brandon during Formal Review) + test_one("isovist", + isovist1[0], isovist1[1], + 4, 0, 0.279121891701124, + 4, 0, 224.889211358929, + 0.01); + + test_one("ggl_list_20110306_javier", + ggl_list_20110306_javier[0], ggl_list_20110306_javier[1], + 1, 0, 71495.3331, + 2, 0, 8960.49049); #endif + + test_one("ggl_list_20110307_javier", + ggl_list_20110307_javier[0], ggl_list_20110307_javier[1], + 1, 0, 16815.6, + 1, 0, 3200.4, + 0.01); + + test_one("ggl_list_20110716_enrico", + ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1], + 3, 0, 35723.8506317139, + 1, 0, 58456.4964294434 + ); + + test_one("ggl_list_20110820_christophe", + ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1], + 1, 0, 2.8570121719168924, + 1, 0, 64.498061986388564); + +#ifdef _MSC_VER + // 2011-07-02 + // Interesting FP-precision case. + // sql server gives: 6.62295817619452E-05 + // PostGIS gives: 0.0 (no output) + // Boost.Geometry gives results depending on FP-type, and compiler, and operating system. + // For double, it is zero (skipped). On gcc/Linux, for float either. + // Because we cannot predict this, we only test for MSVC + test_one("ggl_list_20110627_phillip", + ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1], + if_typed(0, 1), 0, + if_typed_tt(0.0000000000001105367, 0.0), + 1, 0, 3577.40960816756, + 0.01 + ); +#endif + // Other combi's { test_one( diff --git a/test/algorithms/intersection.cpp b/test/algorithms/intersection.cpp index c4d9ec5c3b..c85ebb877e 100644 --- a/test/algorithms/intersection.cpp +++ b/test/algorithms/intersection.cpp @@ -20,11 +20,15 @@ //#define BOOST_GEOMETRY_DEBUG_IDENTIFIER +#include +#include + +#include + #include #include -#include -#include +#include #include #include @@ -155,17 +159,40 @@ void test_areal() crossed[0], crossed[1], 3, 0, 1.5); + typedef typename bg::coordinate_type::type ct; + #ifdef _MSC_VER - { - // Isovist (submitted by Brandon during Formal Review) - std::string tn = string_from_type::type>::name(); - test_one("isovist", - isovist1[0], isovist1[1], - 1, - tn == std::string("f") ? 19 : tn == std::string("d") ? 22 : 20, - 88.19203, - tn == std::string("f") ? 0.5 : tn == std::string("d") ? 0.1 : 0.01); - } + // Isovist (submitted by Brandon during Formal Review) + test_one("isovist", + isovist1[0], isovist1[1], + 1, + if_typed(19, if_typed(20, 20)), + 88.19203, + if_typed(0.5, if_typed(0.1, 0.01))); +#endif + + //std::cout << typeid(ct).name() << std::endl; + + test_one("ggl_list_20110306_javier", + ggl_list_20110306_javier[0], ggl_list_20110306_javier[1], + 1, if_typed_tt(5, 4), + 0.6649875, + if_typed(1.0, 0.01)); + + test_one("ggl_list_20110307_javier", + ggl_list_20110307_javier[0], ggl_list_20110307_javier[1], + 1, 4, 0.4, 0.01); + + test_one("ggl_list_20110627_phillip", + ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1], + 1, if_typed_tt(6, 5), 11151.6618); + +#ifdef _MSC_VER // gcc/linux behaves differently + test_one("ggl_list_20110716_enrico", + ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1], + 3, + if_typed(19, if_typed(22, 21)), + 35723.8506317139); #endif return; @@ -237,6 +264,23 @@ void test_boxes(std::string const& wkt1, std::string const& wkt2, double expecte } +template +void test_point_output() +{ + typedef bg::model::linestring

linestring; + typedef bg::model::polygon

polygon; + typedef bg::model::box

box; + typedef bg::model::segment

segment; + + test_point_output(simplex_normal[0], simplex_normal[1], 6); + test_point_output("box(1 1,6 4)", simplex_normal[0], 4); + test_point_output("linestring(0 2,6 2)", simplex_normal[0], 2); + // NYI because of sectionize: + // test_point_output("linestring(0 2,6 2)", simplex_normal[0], 2); + // NYI because needs special treatment: + // test_point_output("box(0 0,4 4)", "box(2 2,6 6)", 2); +} + template void test_all() { @@ -311,6 +355,8 @@ void test_all() test_boxes("box(2 2,8 7)", "box(14 4,20 10)", 0, false); test_boxes("box(2 2,4 4)", "box(4 4,8 8)", 0, true); + test_point_output

(); + /* test_one(99, "box(115041.10 471900.10, 118334.60 474523.40)", @@ -375,10 +421,18 @@ void test_exception() BOOST_CHECK_MESSAGE(false, "No exception thrown"); } -int test_main(int, char* []) +template +void test_rational() { - test_exception >(); + typedef bg::model::polygon polygon; + test_one("simplex_normal", + simplex_normal[0], simplex_normal[1], + 1, 7, 5.47363293); +} + +int test_main(int, char* []) +{ test_all >(); #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) @@ -388,9 +442,12 @@ int test_main(int, char* []) test_all >(); #endif - //test_pointer_version(); #endif + test_exception >(); + test_pointer_version(); + test_rational > >(); + return 0; } diff --git a/test/algorithms/intersects.cpp b/test/algorithms/intersects.cpp index 4e71452f22..51e7b8cac8 100644 --- a/test/algorithms/intersects.cpp +++ b/test/algorithms/intersects.cpp @@ -58,6 +58,57 @@ void test_all() // Hole: two intersecting holes test_self_intersects( "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,3 3,3 1,1 1),(2 2,2 3.5,3.5 3.5,3.5 2,2 2))", true); + + // Mail Akira T on [Boost-users] at 27-7-2011 3:17 + test_self_intersects >( + "LINESTRING(0 0,0 4,4 4,2 2,2 5)", true); + + test_self_intersects >( + "LINESTRING(0 4,4 4,2 2,2 5)", true); + + // Test self-intersections at last segment in close/open rings: + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,0 0))", false); + + test_self_intersects >( + "POLYGON((0 0,3 3,4 1))", false); + + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,0 1,0 0))", true); + + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,0 1))", true); + + // Duplicates in first or last + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,0 1,0 1,0 0))", true); + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,0 1,0 0,0 0))", true); + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,0 1,0 1))", true); + test_self_intersects >( + "POLYGON((0 0,0 0,3 3,4 1,0 1,0 1,0 0))", true); + test_self_intersects >( + "POLYGON((0 0,0 0,3 3,4 1,0 1,0 1))", true); + test_self_intersects >( + "POLYGON((0 0,3 3,3 3,4 1,0 1,0 1,0 0))", true); + test_self_intersects >( + "POLYGON((0 0,3 3,3 3,4 1,0 1,0 1))", true); + + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,0 0,0 0))", false); + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,4 1,0 0))", false); + test_self_intersects >( + "POLYGON((0 0,3 3,4 1,4 1))", false); + test_self_intersects >( + "POLYGON((0 0,0 0,3 3,4 1,0 0))", false); + test_self_intersects >( + "POLYGON((0 0,0 0,3 3,4 1))", false); + test_self_intersects >( + "POLYGON((0 0,3 3,3 3,4 1,0 0))", false); + test_self_intersects >( + "POLYGON((0 0,3 3,3 3,4 1))", false); } diff --git a/test/algorithms/overlay/ccw_traverse.cpp b/test/algorithms/overlay/ccw_traverse.cpp index 463ecdbde4..edf9dcb5a7 100644 --- a/test/algorithms/overlay/ccw_traverse.cpp +++ b/test/algorithms/overlay/ccw_traverse.cpp @@ -62,7 +62,11 @@ inline typename bg::coordinate_type::type intersect(Geometry1 const& typedef std::deque out_vector; out_vector v; - bg::traverse::value, rev::value>(g1, g2, op, turns, v); + bg::detail::overlay::traverse + < + rev::value, rev::value, + Geometry1, Geometry2 + >::apply(g1, g2, op, turns, v); typename bg::coordinate_type::type result = 0.0; BOOST_FOREACH(ring_type& ring, v) diff --git a/test/algorithms/overlay/get_turns.cpp b/test/algorithms/overlay/get_turns.cpp index 2ee3a050c2..6ebac44e46 100644 --- a/test/algorithms/overlay/get_turns.cpp +++ b/test/algorithms/overlay/get_turns.cpp @@ -303,6 +303,11 @@ void test_all() 4, ggl_list_20110306_javier[0], ggl_list_20110306_javier[1]); +#ifdef _MSC_VER // gcc returns 14 for float + test_get_turns::apply("ggl_list_20110716_enrico", + 13, + ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1]); +#endif // pies test_get_turns::apply("pie_23_16_16", 3, pie_23_16_16[0], pie_23_16_16[1]); diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index 650a491239..64e5f865a8 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -490,6 +490,33 @@ static std::string ggl_list_20110306_javier[2] = "POLYGON((-2 2,2002 2,2002 -2002,-2 -2002,-2 2),(0 -147.00000000000003,0 -2000,2000 -2000,2000 0,104 0,440 -240,400 -280,0 -147.00000000000003))", "POLYGON((359.99000000000001 -280,0 -182,0 -147,400.00999999999999 -280,359.99000000000001 -280))" }; + +static std::string ggl_list_20110307_javier[2] = + { + "POLYGON((-2 2, 1842 2, 1842 -2362, -2 -2362, -2 2), (0 0, 0 -2360, 1840 -2360, 1840 0, 0 0))", + // "POLYGON((-0.01 -1960, 0 -1960, 0 -1880, 0.01 -1960, -0.01 -1960))" + "POLYGON ((-0.01 -1960, 80.01 -1960, 0 -1880, -0.01 -1960))" + }; + + +static std::string ggl_list_20110627_phillip[2] = + { + "POLYGON((537.99678544791459 124.30517362077681,437.36539413622404 142.02728895075373,456.33031803043468 249.50296671450121,556.96217263181723 231.78347688272990,537.99678544791459 124.30517362077681))", + "POLYGON((437.35 142.03,461.94 281.32,564.5 263.26,539.9 123.97,437.35 142.03))" + }; + +static std::string ggl_list_20110716_enrico[2] = + { + "POLYGON((1.83691e-014 -300,-259.808 -150,-259.808 150,-5.51073e-014 300,259.808 150,259.808 -150,9.18455e-014 -300,1.83691e-014 -300),(7.65379e-014 -250,216.506 -125,216.506 125,-4.59227e-014 250,-216.506 125,-216.506 -125,1.53076e-014 -250,7.65379e-014 -250))", + "POLYGON((1.83691e-014 -300,-259.808 -150,-216.506 -125,-216.506 125,-259.808 150,-5.51073e-014 300,-4.59227e-014 250,216.506 125,259.808 150,259.808 -150,216.506 -125,7.65379e-014 -250,9.18455e-014 -300,1.83691e-014 -300),(6.12303e-014 -200,173.205 -100,173.205 100,-3.67382e-014 200,-173.205 100,-173.205 -100,1.22461e-014 -200,6.12303e-014 -200))" + }; + + +static std::string ggl_list_20110820_christophe[2] = +{ + "POLYGON((17.763942722600319 32.23605727739968,19.192448808558737 30.807551191441263,16.000000000000000 30.000000000000000,17.763942722600319 32.236057277399681))", + "POLYGON((0.24806946917841693 26.015444246572663,31.751930530821582 33.984555753427337,32.248069469178418 30.015444246572663,0.24806946917841693 26.015444246572663))" +}; // GEOS "TestOverlay" test. diff --git a/test/algorithms/overlay/robustness/intersects.cpp b/test/algorithms/overlay/robustness/intersects.cpp new file mode 100644 index 0000000000..8d60f1321f --- /dev/null +++ b/test/algorithms/overlay/robustness/intersects.cpp @@ -0,0 +1,181 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2011 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) + +#include +#include +#include +#include +#include + +#define BOOST_GEOMETRY_REPORT_OVERLAY_ERROR +#define BOOST_GEOMETRY_NO_BOOST_TEST +//#define BOOST_GEOMETRY_TIME_OVERLAY + + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + + +template +inline void make_polygon(MultiPolygon& mp, int count_x, int count_y, int index, int width_x) +{ + typedef typename bg::point_type::type point_type; + + for(int j = 0; j < count_x; ++j) + { + for(int k = 0; k < count_y; ++k) + { + mp.push_back(MultiPolygon::value_type()); + mp.back().outer().push_back(point_type(width_x + j * 10 + 1, k * 10 + 1)); + mp.back().outer().push_back(point_type(width_x + j * 10 + width_x, k * 10 + 5 + index)); + mp.back().outer().push_back(point_type(width_x + j * 10 + 5 + index, k * 10 + 7)); + mp.back().outer().push_back(point_type(width_x + j * 10 + 1, k * 10 + 1)); + } + } +} + + + +template +void test_intersects(int count_x, int count_y, int width_x, p_q_settings const& settings) +{ + MultiPolygon mp; + + make_polygon(mp, count_x, count_y, 0, width_x); + + bool const b = bg::intersects(mp); + if (b) + { + std::cout << " YES"; + } + + if(settings.svg) + { + typedef typename bg::coordinate_type::type coordinate_type; + typedef typename bg::point_type::type point_type; + std::ostringstream filename; + filename << "intersects_" + << string_from_type::name() + << ".svg"; + + std::ofstream svg(filename.str().c_str()); + bg::svg_mapper mapper(svg, 500, 500); + mapper.add(mp); + mapper.map(mp, "fill-opacity:0.5;fill:rgb(153,204,0);" + "stroke:rgb(153,204,0);stroke-width:3"); + } +} + + +template +void test_all(int count, int count_x, int count_y, int width_x, p_q_settings const& settings) +{ + boost::timer t; + + typedef bg::model::polygon + < + bg::model::d2::point_xy, Clockwise, Closed + > polygon; + typedef bg::model::multi_polygon + < + polygon + > multi_polygon; + + + int index = 0; + for(int i = 0; i < count; i++) + { + test_intersects(count_x, count_y, width_x, settings); + } + std::cout + << " type: " << string_from_type::name() + << " time: " << t.elapsed() << std::endl; +} + +int main(int argc, char** argv) +{ + try + { + namespace po = boost::program_options; + po::options_description description("=== intersects ===\nAllowed options"); + + int width_x = 7; + int count = 1; + int count_x = 10; + int count_y = 10; + bool ccw = false; + bool open = false; + p_q_settings settings; + + description.add_options() + ("help", "Help message") + ("count", po::value(&count)->default_value(1), "Number of tests") + ("count_x", po::value(&count_x)->default_value(10), "Triangle count in x-direction") + ("count_y", po::value(&count_y)->default_value(10), "Triangle count in y-direction") + ("width_x", po::value(&width_x)->default_value(7), "Width of triangle in x-direction") + ("ccw", po::value(&ccw)->default_value(false), "Counter clockwise polygons") + ("open", po::value(&open)->default_value(false), "Open polygons") + ("wkt", po::value(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests") + ("svg", po::value(&settings.svg)->default_value(false), "Create a SVG for all tests") + ; + + po::variables_map varmap; + po::store(po::parse_command_line(argc, argv, description), varmap); + po::notify(varmap); + + if (varmap.count("help")) + { + std::cout << description << std::endl; + return 1; + } + + if (ccw && open) + { + test_all(count, count_x, count_y, width_x, settings); + } + else if (ccw) + { + test_all(count, count_x, count_y, width_x, settings); + } + else if (open) + { + test_all(count, count_x, count_y, width_x, settings); + } + else + { + test_all(count, count_x, count_y, width_x, settings); + } + +#if defined(HAVE_TTMATH) + // test_all(seed, count, max, svg, level); +#endif + } + catch(std::exception const& e) + { + std::cout << "Exception " << e.what() << std::endl; + } + catch(...) + { + std::cout << "Other exception" << std::endl; + } + + return 0; +} diff --git a/test/algorithms/overlay/robustness/intersects.vcproj b/test/algorithms/overlay/robustness/intersects.vcproj new file mode 100644 index 0000000000..8331792e5d --- /dev/null +++ b/test/algorithms/overlay/robustness/intersects.vcproj @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/algorithms/overlay/robustness/robustness.sln b/test/algorithms/overlay/robustness/robustness.sln index ccb43ed937..dd6ff88215 100644 --- a/test/algorithms/overlay/robustness/robustness.sln +++ b/test/algorithms/overlay/robustness/robustness.sln @@ -12,6 +12,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "star_comb", "star_comb.vcpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "interior_triangles", "interior_triangles.vcproj", "{7583C2E3-AD74-4C34-8E94-9162F641B215}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intersects", "intersects.vcproj", "{1AC9B120-3ED0-4444-86E5-1916108943C7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -42,6 +44,10 @@ Global {7583C2E3-AD74-4C34-8E94-9162F641B215}.Debug|Win32.Build.0 = Debug|Win32 {7583C2E3-AD74-4C34-8E94-9162F641B215}.Release|Win32.ActiveCfg = Release|Win32 {7583C2E3-AD74-4C34-8E94-9162F641B215}.Release|Win32.Build.0 = Release|Win32 + {1AC9B120-3ED0-4444-86E5-1916108943C7}.Debug|Win32.ActiveCfg = Debug|Win32 + {1AC9B120-3ED0-4444-86E5-1916108943C7}.Debug|Win32.Build.0 = Debug|Win32 + {1AC9B120-3ED0-4444-86E5-1916108943C7}.Release|Win32.ActiveCfg = Release|Win32 + {1AC9B120-3ED0-4444-86E5-1916108943C7}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/algorithms/overlay/select_rings.cpp b/test/algorithms/overlay/select_rings.cpp index e9dcad5e73..af2f18761f 100644 --- a/test/algorithms/overlay/select_rings.cpp +++ b/test/algorithms/overlay/select_rings.cpp @@ -50,7 +50,7 @@ void test_geometry(std::string const& wkt1, std::string const& wkt2, map_type selected; std::map empty; - bg::detail::overlay::select_rings(geometry1, geometry2, empty, selected); + bg::detail::overlay::select_rings(geometry1, geometry2, empty, selected, true); BOOST_CHECK_EQUAL(selected.size(), expected_ids.size()); BOOST_CHECK_EQUAL(selected.size(), expected_withins.size()); diff --git a/test/algorithms/overlay/self_intersection_points.vcproj b/test/algorithms/overlay/self_intersection_points.vcproj index 450ea2270f..a4cdb80498 100644 --- a/test/algorithms/overlay/self_intersection_points.vcproj +++ b/test/algorithms/overlay/self_intersection_points.vcproj @@ -46,6 +46,7 @@ ExceptionHandling="2" RuntimeLibrary="1" UsePrecompiledHeader="0" + DebugInformationFormat="1" /> (g1, g2, Direction, turns, v); + bg::detail::overlay::traverse + < + Reverse1, Reverse2, + G1, G2 + >::apply(g1, g2, Direction, turns, v); // Check number of resulting rings BOOST_CHECK_MESSAGE(expected_count == boost::size(v), diff --git a/test/algorithms/test_convert.hpp b/test/algorithms/test_convert.hpp new file mode 100644 index 0000000000..65e5a73ebe --- /dev/null +++ b/test/algorithms/test_convert.hpp @@ -0,0 +1,64 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2011 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_CONVERT_HPP +#define BOOST_GEOMETRY_TEST_CONVERT_HPP + + +#include +#include +#include +#include + +#include + +#include +#include +#include + + +#include + +#include + +BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + + + +template +void test_mixed(std::string const& wkt, std::string const& expected) +{ + Geometry1 geometry1; + bg::read_wkt(wkt, geometry1); + + Geometry2 geometry2; + bg::convert(geometry1, geometry2); + + std::ostringstream out; + out << bg::wkt(geometry2); + BOOST_CHECK_EQUAL(out.str(), expected); + + // std::cout << bg::area(geometry1) << " " << bg::area(geometry2) << std::endl; +} + +template +void test_mixed_identical_result(std::string const& wkt) +{ + test_mixed(wkt, wkt); + test_mixed(wkt, wkt); +} + +template +void test_mixed_reversible_result(std::string const& wkt1, std::string const& wkt2) +{ + test_mixed(wkt1, wkt2); + test_mixed(wkt2, wkt1); +} + +#endif diff --git a/test/algorithms/test_covered_by.hpp b/test/algorithms/test_covered_by.hpp new file mode 100644 index 0000000000..b99257bbc8 --- /dev/null +++ b/test/algorithms/test_covered_by.hpp @@ -0,0 +1,123 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2011 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_COVERED_BY_HPP +#define BOOST_GEOMETRY_TEST_COVERED_BY_HPP + + +#include + +#include +#include +#include +#include +#include + +#include + + +template +void test_geometry(std::string const& wkt1, + std::string const& wkt2, bool expected) +{ + Geometry1 geometry1; + Geometry2 geometry2; + + bg::read_wkt(wkt1, geometry1); + bg::read_wkt(wkt2, geometry2); + + bool detected = bg::covered_by(geometry1, geometry2); + + BOOST_CHECK_MESSAGE(detected == expected, + "covered_by: " << wkt1 + << " in " << wkt2 + << " -> Expected: " << expected + << " detected: " << detected); +} + +/* + +template +void test_ordered_ring(std::string const& wkt_point, + std::string const& wkt_geometry, bool expected) +{ + typedef bg::model::ring ring_type; + ring_type ring; + Point point; + + bg::read_wkt(wkt_geometry, ring); + if (! Clockwise) + { + std::reverse(boost::begin(ring), boost::end(ring)); + } + if (! Closed) + { + ring.resize(ring.size() - 1); + } + + bg::read_wkt(wkt_point, point); + + bool detected = bg::covered_by(point, ring); + + BOOST_CHECK_MESSAGE(detected == expected, + "covered_by: " << wkt_point + << " in " << wkt_geometry + << " -> Expected: " << expected + << " detected: " << detected + << " clockwise: " << int(Clockwise) + << " closed: " << int(Closed) + ); + + // other strategy (note that this one cannot detect OnBorder + // (without modifications) + + bg::strategy::covered_by::franklin franklin; + detected = bg::covered_by(point, ring, franklin); + if (! on_border) + { + BOOST_CHECK_MESSAGE(detected == expected, + "covered_by: " << wkt_point + << " in " << wkt_geometry + << " -> Expected: " << expected + << " detected: " << detected + << " clockwise: " << int(Clockwise) + << " closed: " << int(Closed) + ); + } + + + bg::strategy::covered_by::crossings_multiply cm; + detected = bg::covered_by(point, ring, cm); + if (! on_border) + { + BOOST_CHECK_MESSAGE(detected == expected, + "covered_by: " << wkt_point + << " in " << wkt_geometry + << " -> Expected: " << expected + << " detected: " << detected + << " clockwise: " << int(Clockwise) + << " closed: " << int(Closed) + ); + } +} + +template +void test_ring(std::string const& wkt_point, + std::string const& wkt_geometry, + bool expected) +{ + test_ordered_ring(wkt_point, wkt_geometry, expected); + test_ordered_ring(wkt_point, wkt_geometry, expected); + test_ordered_ring(wkt_point, wkt_geometry, expected); + test_ordered_ring(wkt_point, wkt_geometry, expected); + test_geometry >(wkt_point, wkt_geometry, expected); +} +*/ + +#endif diff --git a/test/algorithms/test_difference.hpp b/test/algorithms/test_difference.hpp index 30b97bbb23..948b90334b 100644 --- a/test/algorithms/test_difference.hpp +++ b/test/algorithms/test_difference.hpp @@ -23,7 +23,6 @@ #include #include -#include #include @@ -73,9 +72,6 @@ void test_difference(std::string const& caseid, G1 const& g1, G2 const& g2, { if (expected_point_count > 0) { - // Get a correct point-count without duplicate points - // (note that overlay might be adapted to avoid duplicates) - bg::unique(*it); n += bg::num_points(*it); } diff --git a/test/algorithms/test_intersection.hpp b/test/algorithms/test_intersection.hpp index 4dcda0e8e9..2b606a11ab 100644 --- a/test/algorithms/test_intersection.hpp +++ b/test/algorithms/test_intersection.hpp @@ -13,14 +13,12 @@ #include #include -#include #include #include #include #include #include -#include #include @@ -33,7 +31,7 @@ # include #endif - +#include template @@ -41,8 +39,7 @@ typename bg::default_area_result::type test_intersection(std::string const& G1 const& g1, G2 const& g2, std::size_t expected_count = 0, std::size_t expected_point_count = 0, double expected_length_or_area = 0, - double percentage = 0.0001, - bool make_unique = true) + double percentage = 0.0001) { static const bool is_line = bg::geometry_id::type::value == 2; @@ -78,21 +75,11 @@ typename bg::default_area_result::type test_intersection(std::string const& { if (expected_point_count > 0) { - if (make_unique) - { - // Get a correct point-count without duplicate points - // (note that overlay might be adapted to avoid duplicates) - bg::unique(*it); - n += bg::num_points(*it, true); - } - else - { - n += bg::num_points(*it, true); - } + n += bg::num_points(*it, true); } // instead of specialization we check it run-time here - length_or_area += is_line + length_or_area += is_line ? bg::length(*it) : bg::area(*it); @@ -126,7 +113,8 @@ typename bg::default_area_result::type test_intersection(std::string const& ); } - BOOST_CHECK_CLOSE(length_or_area, expected_length_or_area, percentage); + double const detected_length_or_area = boost::numeric_cast(length_or_area); + BOOST_CHECK_CLOSE(detected_length_or_area, expected_length_or_area, percentage); #endif @@ -179,8 +167,7 @@ typename bg::default_area_result::type test_one(std::string const& caseid, std::string const& wkt1, std::string const& wkt2, std::size_t expected_count = 0, std::size_t expected_point_count = 0, double expected_length_or_area = 0, - double percentage = 0.0001, - bool make_unique = true) + double percentage = 0.0001) { G1 g1; bg::read_wkt(wkt1, g1); @@ -194,9 +181,24 @@ typename bg::default_area_result::type test_one(std::string const& caseid, return test_intersection(caseid, g1, g2, expected_count, expected_point_count, - expected_length_or_area, percentage, make_unique); + expected_length_or_area, percentage); } +template +void test_point_output(std::string const& wkt1, std::string const& wkt2, int expected_count) +{ + Geometry1 g1; + bg::read_wkt(wkt1, g1); + bg::correct(g1); + + Geometry2 g2; + bg::read_wkt(wkt2, g2); + bg::correct(g2); + + std::vector::type> points; + bg::intersection(g1, g2, points); + BOOST_CHECK_EQUAL(points.size(), expected_count); +} #endif diff --git a/test/algorithms/test_overlay.hpp b/test/algorithms/test_overlay.hpp index acae98ce29..bece5e1e98 100644 --- a/test/algorithms/test_overlay.hpp +++ b/test/algorithms/test_overlay.hpp @@ -144,7 +144,7 @@ static std::string two_bends[2] = // within each other, having no intersections but many holes within each other static std::string winded[2] = - {"POLYGON((0 0,0 11,11 11,11 0,0 0),(3 3,4 3,4 4,3 4,3 3),(5 3,6 3,6 4,5 4,5 3),(2 6,7 6,7 6,7 9,2 9,2 6),(9 2,10 2,10 5,9 5,9 2))", + {"POLYGON((0 0,0 11,11 11,11 0,0 0),(3 3,4 3,4 4,3 4,3 3),(5 3,6 3,6 4,5 4,5 3),(2 6,7 6,7 9,2 9,2 6),(9 2,10 2,10 5,9 5,9 2))", "POLYGON((1 1,1 10,10 10,10 6,8 6,8 1,1 1),(2 2,7 2,7 5,2 5,2 2),(3 7,4 7,4 8,3 8,3 7),(5 7,6 7,6 8,5 8,5 7),(8 7,9 7,9 8,8 8,8 7))"}; static std::string within_holes_disjoint[2] = diff --git a/test/algorithms/test_union.hpp b/test/algorithms/test_union.hpp index dc316d3498..47a567eb88 100644 --- a/test/algorithms/test_union.hpp +++ b/test/algorithms/test_union.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #include @@ -55,10 +54,6 @@ void test_union(std::string const& caseid, G1 const& g1, G2 const& g2, area += bg::area(*it); holes += bg::num_interior_rings(*it); - // Get a correct point-count without duplicate points - // (note that overlay might be adapted to avoid duplicates) - OutputType simplified; - bg::unique(*it); n += bg::num_points(*it, true); } diff --git a/test/algorithms/test_within.hpp b/test/algorithms/test_within.hpp index c15b0f3e4f..d2c5170091 100644 --- a/test/algorithms/test_within.hpp +++ b/test/algorithms/test_within.hpp @@ -21,6 +21,10 @@ #include +#include +#include +#include + template void test_geometry(std::string const& wkt1, @@ -42,6 +46,7 @@ void test_geometry(std::string const& wkt1, } + template void test_ordered_ring(std::string const& wkt_point, std::string const& wkt_geometry, bool expected, bool on_border) diff --git a/test/algorithms/union.cpp b/test/algorithms/union.cpp index 95d079f1ba..f1b05ca22b 100644 --- a/test/algorithms/union.cpp +++ b/test/algorithms/union.cpp @@ -25,26 +25,12 @@ #include #include -static std::string javier4[2] = - { - "POLYGON((-2 2, 1842 2, 1842 -2362, -2 -2362, -2 2), (0 0, 0 -2360, 1840 -2360, 1840 0, 0 0))", - // "POLYGON((-0.01 -1960, 0 -1960, 0 -1880, 0.01 -1960, -0.01 -1960))" - "POLYGON ((-0.01 -1960, 80.01 -1960, 0 -1880, -0.01 -1960))" - }; - - - - - - template void test_areal() { - test_one("javier4", - javier4[0], javier4[1], - 1, 1, 13, 20016.4); + typedef typename bg::coordinate_type::type ct; test_one("simplex_normal", simplex_normal[0], simplex_normal[1], @@ -63,12 +49,7 @@ void test_areal() // This sample was selected because of the border case, and ttmath generates one point more. test_one("star_poly", example_star, example_polygon, 1, 1, -#if defined(HAVE_TTMATH) - boost::is_same::type, ttmath_big>::value ? 28 : 27, -#else - 27, -#endif - 5.647949); + if_typed_tt(28, 27), 5.647949); // Pseudo-box as Polygon // (note, internally, the intersection points is different, so yes, @@ -237,20 +218,34 @@ void test_areal() test_one("ggl_list_20110306_javier", ggl_list_20110306_javier[0], ggl_list_20110306_javier[1], 1, 1, 16, 80456.4904910401); + + test_one("ggl_list_20110307_javier", + ggl_list_20110307_javier[0], ggl_list_20110307_javier[1], + 1, 1, 13, 20016.4); + + test_one("ggl_list_20110627_phillip", + ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1], + 1, 0, + if_typed(5, if_typed_tt(8, 7)), + 14729.07145); + +#ifdef TEST_ENRICO + test_one("ggl_list_20110716_enrico", + ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1], + 1, 1, + if_typed(18, 17), + 129904.197692871); +#endif #ifdef _MSC_VER - { - // Isovist (submitted by Brandon during Formal Review) - std::string tn = string_from_type::type>::name(); - test_one("isovist", - isovist1[0], isovist1[1], - 1, - 0, - tn == std::string("f") ? 71 - : tn == std::string("d") ? 72 - : 73, - 313.36036462); - } + // Isovist (submitted by Brandon during Formal Review) + test_one("isovist", + isovist1[0], isovist1[1], + 1, + 0, + if_typed(71, + if_typed(70, 73)), + 313.36036462); #endif } diff --git a/test/algorithms/within.cpp b/test/algorithms/within.cpp index b8820f99b1..85c6f13b62 100644 --- a/test/algorithms/within.cpp +++ b/test/algorithms/within.cpp @@ -37,18 +37,28 @@ void test_all() typedef bg::model::box

box_type; test_geometry("POINT(1 1)", "BOX(0 0,2 2)", true); + test_geometry("POINT(0 0)", "BOX(0 0,2 2)", false); + test_geometry("POINT(2 2)", "BOX(0 0,2 2)", false); + test_geometry("POINT(0 1)", "BOX(0 0,2 2)", false); + test_geometry("POINT(1 0)", "BOX(0 0,2 2)", false); test_geometry("BOX(1 1,2 2)", "BOX(0 0,3 3)", true); test_geometry("BOX(0 0,3 3)", "BOX(1 1,2 2)", false); - - // Mixed point types - test_geometry - < - bg::model::d2::point_xy, - bg::model::polygon

- >("POINT(1 1)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", true); - + /* + test_within_code("POINT(1 1)", "BOX(0 0,2 2)", 1); + test_within_code("POINT(1 0)", "BOX(0 0,2 2)", 0); + test_within_code("POINT(0 1)", "BOX(0 0,2 2)", 0); + test_within_code("POINT(0 3)", "BOX(0 0,2 2)", -1); + test_within_code("POINT(3 3)", "BOX(0 0,2 2)", -1); + + test_within_code("BOX(1 1,2 2)", "BOX(0 0,3 3)", 1); + test_within_code("BOX(0 1,2 2)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 0,2 2)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 1,2 3)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 1,3 2)", "BOX(0 0,3 3)", 0); + test_within_code("BOX(1 1,3 4)", "BOX(0 0,3 3)", -1); + */ // Real-life problem (solved now), point is in the middle, 409623 is also a coordinate // on the border, has been wrong in the past (2009) @@ -106,6 +116,105 @@ void test_spherical() BOOST_CHECK_EQUAL(bg::within(Point(7, 52.5), triangle), true); BOOST_CHECK_EQUAL(bg::within(Point(8.0, 51.5), triangle), false); BOOST_CHECK_EQUAL(bg::within(Point(6.0, 51.0), triangle), false); + + // Test spherical boxes + // See also http://www.gcmap.com/mapui?P=1E45N-19E45N-19E55N-1E55N-1E45N,10E55.1N,10E45.1N + bg::model::box box; + bg::read_wkt("POLYGON((1 45,19 55))", box); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.1), box), true); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.2), box), true); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.3), box), true); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.4), box), false); + + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.1), box), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.2), box), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.3), box), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.4), box), true); + + // Crossing the dateline (Near Tuvalu) + // http://www.gcmap.com/mapui?P=178E10S-178W10S-178W6S-178E6S-178E10S,180W5.999S,180E9.999S + // http://en.wikipedia.org/wiki/Tuvalu + + bg::model::box tuvalu(Point(178, -10), Point(-178, -6)); + BOOST_CHECK_EQUAL(bg::within(Point(180, -8), tuvalu), true); + BOOST_CHECK_EQUAL(bg::within(Point(-180, -8), tuvalu), true); + BOOST_CHECK_EQUAL(bg::within(Point(180, -5.999), tuvalu), false); + BOOST_CHECK_EQUAL(bg::within(Point(180, -10.001), tuvalu), true); +} + +void test_3d() +{ + typedef boost::geometry::model::point point_type; + typedef boost::geometry::model::box box_type; + box_type box(point_type(0, 0, 0), point_type(4, 4, 4)); + BOOST_CHECK_EQUAL(bg::within(point_type(2, 2, 2), box), true); + BOOST_CHECK_EQUAL(bg::within(point_type(2, 4, 2), box), false); + BOOST_CHECK_EQUAL(bg::within(point_type(2, 2, 4), box), false); + BOOST_CHECK_EQUAL(bg::within(point_type(2, 2, 5), box), false); +} + +template +void test_mixed_of() +{ + typedef boost::geometry::model::polygon polygon_type1; + typedef boost::geometry::model::polygon polygon_type2; + typedef boost::geometry::model::box box_type1; + typedef boost::geometry::model::box box_type2; + + polygon_type1 poly1, poly2; + boost::geometry::read_wkt("POLYGON((0 0,0 5,5 5,5 0,0 0))", poly1); + boost::geometry::read_wkt("POLYGON((0 0,0 5,5 5,5 0,0 0))", poly2); + + box_type1 box1(P1(1, 1), P1(4, 4)); + box_type2 box2(P2(0, 0), P2(5, 5)); + P1 p1(3, 3); + P2 p2(3, 3); + + BOOST_CHECK_EQUAL(bg::within(p1, poly2), true); + BOOST_CHECK_EQUAL(bg::within(p2, poly1), true); + BOOST_CHECK_EQUAL(bg::within(p2, box1), true); + BOOST_CHECK_EQUAL(bg::within(p1, box2), true); + BOOST_CHECK_EQUAL(bg::within(box1, box2), true); + BOOST_CHECK_EQUAL(bg::within(box2, box1), false); +} + + +void test_mixed() +{ + // Mixing point types and coordinate types + test_mixed_of + < + boost::geometry::model::d2::point_xy, + boost::geometry::model::point + >(); + test_mixed_of + < + boost::geometry::model::d2::point_xy, + boost::geometry::model::point + >(); + test_mixed_of + < + boost::geometry::model::d2::point_xy, + boost::geometry::model::d2::point_xy + >(); +} + +void test_strategy() +{ + // Test by explicitly specifying a strategy + typedef bg::model::d2::point_xy point_type; + typedef bg::model::box box_type; + point_type p(3, 3); + box_type b(point_type(0, 0), point_type(5, 5)); + + bool r = bg::within(p, b, + bg::strategy::within::point_in_box()); + + r = bg::within(b, b, + bg::strategy::within::box_in_box()); + + r = bg::within(p, b, + bg::strategy::within::point_in_box_by_side()); } @@ -116,6 +225,10 @@ int test_main( int , char* [] ) test_spherical > >(); + test_mixed(); + test_3d(); + test_strategy(); + #if defined(HAVE_TTMATH) test_all >(); diff --git a/test/geometry_test_common.hpp b/test/geometry_test_common.hpp index 0af0a83408..2e4a645be9 100644 --- a/test/geometry_test_common.hpp +++ b/test/geometry_test_common.hpp @@ -32,16 +32,28 @@ #endif - #include // Include some always-included-for-testing files #if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST) -# include -# include + +// Until Boost fixes it, silence warning issued by clang: +// warning: unused variable 'check_is_close' [-Wunused-variable] +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-variable" +#endif + +# include +# include //# include -# include +# include + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + #endif @@ -82,6 +94,11 @@ template <> struct string_from_type { static std::string name() { return "t"; } }; #endif +#if defined(BOOST_RATIONAL_HPP) +template struct string_from_type > +{ static std::string name() { return "r"; } }; +#endif + #if defined(HAVE_GMP) template <> struct string_from_type @@ -94,6 +111,24 @@ template <> struct string_from_type #endif +template +inline T if_typed_tt(T value_tt, T value) +{ +#if defined(HAVE_TTMATH) + return boost::is_same::value ? value_tt : value; +#else + return value; +#endif +} + +template +inline T if_typed(T value_typed, T value) +{ + return boost::is_same::value ? value_typed : value; +} + + + struct geographic_policy { diff --git a/test/multi/algorithms/Jamfile.v2 b/test/multi/algorithms/Jamfile.v2 index 9087b7ac3d..1076835aad 100644 --- a/test/multi/algorithms/Jamfile.v2 +++ b/test/multi/algorithms/Jamfile.v2 @@ -12,8 +12,10 @@ test-suite boost-geometry-multi-algorithms : [ run multi_area.cpp ] [ run multi_centroid.cpp ] + [ run multi_convert.cpp ] [ run multi_convex_hull.cpp ] [ run multi_correct.cpp ] + [ run multi_covered_by.cpp ] [ run multi_difference.cpp ] [ run multi_envelope.cpp ] [ run multi_equals.cpp ] diff --git a/test/multi/algorithms/multi_convert.cpp b/test/multi/algorithms/multi_convert.cpp new file mode 100644 index 0000000000..68023aaf9e --- /dev/null +++ b/test/multi/algorithms/multi_convert.cpp @@ -0,0 +1,99 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright (c) 2007-2011 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) + +#include + +#include + +#include +#include +#include + + +template +void test_mixed_point_types() +{ + test_mixed_identical_result + < + bg::model::multi_point, + bg::model::multi_point + > + ("MULTIPOINT((1 1),(2 2),(3 3))"); + + test_mixed_identical_result + < + bg::model::multi_linestring >, + bg::model::multi_linestring > + > + ("MULTILINESTRING((1 1,2 2),(3 3,4 4))"); + + // Single -> multi (always possible) + test_mixed + < + Point1, bg::model::multi_point + > + ( + "POINT(1 1)", + "MULTIPOINT((1 1))" + ); + test_mixed + < + bg::model::linestring, + bg::model::multi_linestring > + > + ( + "LINESTRING(1 1,2 2)", + "MULTILINESTRING((1 1,2 2))" + ); + test_mixed + < + bg::model::segment, + bg::model::multi_linestring > + > + ( + "LINESTRING(1 1,2 2)", + "MULTILINESTRING((1 1,2 2))" + ); + test_mixed + < + bg::model::box, + bg::model::multi_polygon > + > + ( + "BOX(0 0,1 1)", + "MULTIPOLYGON(((0 0,0 1,1 1,1 0,0 0)))" + ); + test_mixed + < + bg::model::ring, + bg::model::multi_polygon > + > + ( + "POLYGON((0 0,0 1,1 1,1 0,0 0))", + "MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)))" + ); + + // Multi -> single: should not compile (because multi often have 0 or >1 elements) +} + +template +void test_mixed_types() +{ + test_mixed_point_types(); + test_mixed_point_types(); +} + +int test_main( int , char* [] ) +{ + test_mixed_types + < + bg::model::point, + bg::model::point + >(); + + return 0; +} diff --git a/test/multi/algorithms/multi_convert.vcproj b/test/multi/algorithms/multi_convert.vcproj new file mode 100644 index 0000000000..4829412bef --- /dev/null +++ b/test/multi/algorithms/multi_convert.vcproj @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/multi/algorithms/multi_covered_by.cpp b/test/multi/algorithms/multi_covered_by.cpp new file mode 100644 index 0000000000..5d937f4ebc --- /dev/null +++ b/test/multi/algorithms/multi_covered_by.cpp @@ -0,0 +1,58 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright (c) 2007-2011 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) + +#include + +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + + +template +void test_all() +{ + typedef bg::model::multi_polygon > mp; + + // test multi-with-one-polygon (trivial case) + test_geometry("POINT(1 1)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", true); + test_geometry("POINT(3 3)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", false); + test_geometry("POINT(0 1)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", true); + test_geometry("POINT(4 4)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", false); + + // test if it is in one of them + std::string multi("MULTIPOLYGON(" + "((0 0,0 2,2 2,2 0,0 0))" + "((3 3,3 6,6 6,6 3,3 3))" + ")"); + test_geometry("POINT(4 4)", multi, true); + test_geometry("POINT(1 1)", multi, true); + test_geometry("POINT(0 1)", multi, true); +} + +int test_main( int , char* [] ) +{ + //test_all >(); + test_all >(); + +#if defined(HAVE_TTMATH) + test_all >(); +#endif + + return 0; +} diff --git a/test/multi/algorithms/multi_covered_by.vcproj b/test/multi/algorithms/multi_covered_by.vcproj new file mode 100644 index 0000000000..87a62a9389 --- /dev/null +++ b/test/multi/algorithms/multi_covered_by.vcproj @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/multi/algorithms/multi_difference.cpp b/test/multi/algorithms/multi_difference.cpp index fe6a8fcd70..f99b566a5f 100644 --- a/test/multi/algorithms/multi_difference.cpp +++ b/test/multi/algorithms/multi_difference.cpp @@ -11,7 +11,7 @@ #include // #define BOOST_GEOMETRY_DEBUG_ASSEMBLE -#define BOOST_GEOMETRY_CHECK_WITH_SQLSERVER +//#define BOOST_GEOMETRY_CHECK_WITH_SQLSERVER #include #include diff --git a/test/multi/algorithms/multi_intersection.cpp b/test/multi/algorithms/multi_intersection.cpp index be8821cd5b..473c1f5a67 100644 --- a/test/multi/algorithms/multi_intersection.cpp +++ b/test/multi/algorithms/multi_intersection.cpp @@ -138,6 +138,19 @@ void test_linear() 2, 4, 2 * std::sqrt(2.0)); } +template +void test_point_output() +{ + typedef bg::model::box

box; + typedef bg::model::linestring

linestring; + typedef bg::model::polygon

polygon; + typedef bg::model::multi_polygon multi_polygon; + + test_point_output(case_multi_simplex[0], case_multi_simplex[1], 10); + test_point_output("linestring(4 0,0 4)", case_multi_simplex[0], 4); + test_point_output("box(3 0,4 6)", case_multi_simplex[0], 8); +} + template void test_all() @@ -174,6 +187,7 @@ void test_all() test_linear(); #endif + test_point_output

(); // linear } diff --git a/test/multi/algorithms/multi_simplify.cpp b/test/multi/algorithms/multi_simplify.cpp index 09a8361780..68424985da 100644 --- a/test/multi/algorithms/multi_simplify.cpp +++ b/test/multi/algorithms/multi_simplify.cpp @@ -44,6 +44,15 @@ void test_all() test_geometry( "MULTIPOLYGON(((4 0,8 2,8 7,4 9,0 7,0 2,2 1,4 0),(7 3,7 6,1 6,1 3,4 3,7 3)))", "MULTIPOLYGON(((4 0,8 2,8 7,4 9,0 7,0 2,4 0),(7 3,7 6,1 6,1 3,7 3)))", 1.0); + + // Ticket 5954 https://svn.boost.org/trac/boost/ticket/5954 + test_geometry( + "MULTIPOLYGON(((0.561648 1,1 1,1 0,0.468083 0,0.52758 0.00800554,0.599683 0.0280924,0.601611 0.265374,0.622693 0.316765,0.69507 0.357497,0.695623 0.429711,0.655111 0.502298,0.696467 0.543147,0.840712 0.593546,0.882583 0.66546,0.852357 0.748213,0.84264 0.789567,0.832667 0.841202,0.832667 0.841202,0.740538 0.873004,0.617349 0.905045,0.566576 0.977697,0.561648 1)),((0 0.801979,0.0308575 0.786234,0.0705513 0.631135,0.141616 0.527248,0.233985 0.505872,0.264777 0.526263,0.336631 0.505009,0.356603 0.422321,0.355803 0.350038,0.375252 0.205364,0.415206 0.0709182,0.45479 0,0 0,0 0,0 0.801979)))", + "MULTIPOLYGON(((0.561648 1,1 1,1 0,0.468083 0,0.52758 0.00800554,0.599683 0.0280924,0.601611 0.265374,0.622693 0.316765,0.69507 0.357497,0.695623 0.429711,0.655111 0.502298,0.696467 0.543147,0.840712 0.593546,0.882583 0.66546,0.852357 0.748213,0.84264 0.789567,0.832667 0.841202,0.740538 0.873004,0.617349 0.905045,0.566576 0.977697,0.561648 1)),((0 0.801979,0.0308575 0.786234,0.0705513 0.631135,0.141616 0.527248,0.233985 0.505872,0.264777 0.526263,0.336631 0.505009,0.356603 0.422321,0.355803 0.350038,0.375252 0.205364,0.415206 0.0709182,0.45479 0,0 0,0 0.801979)))", 1.0 / 2048.0); + test_geometry( + "MULTIPOLYGON(((1149.69 2047,2047 2047,2047 0,958.166 0,1079.96 16.3873,1227.55 57.5051,1231.5 543.221,1274.65 648.418,1422.81 731.796,1423.94 879.618,1341.01 1028.2,1425.67 1111.82,1720.94 1214.99,1806.65 1362.2,1744.77 1531.59,1724.88 1616.24,1704.47 1721.94,1704.47 1721.94,1515.88 1787.04,1263.71 1852.63,1159.78 2001.35,1149.69 2047)),((0 1641.65,63.1653 1609.42,144.419 1291.93,289.888 1079.28,478.967 1035.52,541.999 1077.26,689.084 1033.75,729.966 864.491,728.329 716.528,768.141 420.38,849.927 145.17,930.955 0,0 0,0 0,0 1641.65)))", + "MULTIPOLYGON(((1149.69 2047,2047 2047,2047 0,958.166 0,1079.96 16.3873,1227.55 57.5051,1231.5 543.221,1274.65 648.418,1422.81 731.796,1423.94 879.618,1341.01 1028.2,1425.67 1111.82,1720.94 1214.99,1806.65 1362.2,1744.77 1531.59,1724.88 1616.24,1704.47 1721.94,1515.88 1787.04,1263.71 1852.63,1159.78 2001.35,1149.69 2047)),((0 1641.65,63.1653 1609.42,144.419 1291.93,289.888 1079.28,478.967 1035.52,541.999 1077.26,689.084 1033.75,729.966 864.491,728.329 716.528,768.141 420.38,849.927 145.17,930.955 0,0 0,0 1641.65)))", 1.0); + // End ticket 5954 } int test_main( int , char* [] ) diff --git a/test/multi/algorithms/multi_within.cpp b/test/multi/algorithms/multi_within.cpp index a3815b6862..9c4f64ef69 100644 --- a/test/multi/algorithms/multi_within.cpp +++ b/test/multi/algorithms/multi_within.cpp @@ -29,16 +29,20 @@ void test_all() { typedef bg::model::multi_polygon > mp; - // trivial cases + // test multi-with-one-polygon (trivial case) test_geometry("POINT(1 1)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", true); test_geometry("POINT(3 3)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", false); + test_geometry("POINT(0 1)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", false); + test_geometry("POINT(4 4)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)))", false); // test if it is in one of them - test_geometry("POINT(4 4)", "MULTIPOLYGON(" + std::string multi("MULTIPOLYGON(" "((0 0,0 2,2 2,2 0,0 0))" "((3 3,3 6,6 6,6 3,3 3))" - ")", - true); + ")"); + test_geometry("POINT(4 4)", multi, true); + test_geometry("POINT(1 1)", multi, true); + test_geometry("POINT(0 1)", multi, false); } int test_main( int , char* [] ) diff --git a/test/multi/multi_tests.sln b/test/multi/multi_tests.sln index bc6b4ca80b..57d180722e 100644 --- a/test/multi/multi_tests.sln +++ b/test/multi/multi_tests.sln @@ -42,6 +42,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multi_difference", "algorit EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multi_transform", "algorithms\multi_transform.vcproj", "{64985954-0A74-46F5-908F-865E905C3414}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multi_covered_by", "algorithms\multi_covered_by.vcproj", "{680E56F0-229C-4377-BDC0-80EB9B59314B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multi_convert", "algorithms\multi_convert.vcproj", "{21B7EF55-23C3-4FD2-9F2F-FD8F0F3FE167}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -132,6 +136,14 @@ Global {64985954-0A74-46F5-908F-865E905C3414}.Debug|Win32.Build.0 = Debug|Win32 {64985954-0A74-46F5-908F-865E905C3414}.Release|Win32.ActiveCfg = Release|Win32 {64985954-0A74-46F5-908F-865E905C3414}.Release|Win32.Build.0 = Release|Win32 + {680E56F0-229C-4377-BDC0-80EB9B59314B}.Debug|Win32.ActiveCfg = Debug|Win32 + {680E56F0-229C-4377-BDC0-80EB9B59314B}.Debug|Win32.Build.0 = Debug|Win32 + {680E56F0-229C-4377-BDC0-80EB9B59314B}.Release|Win32.ActiveCfg = Release|Win32 + {680E56F0-229C-4377-BDC0-80EB9B59314B}.Release|Win32.Build.0 = Release|Win32 + {21B7EF55-23C3-4FD2-9F2F-FD8F0F3FE167}.Debug|Win32.ActiveCfg = Debug|Win32 + {21B7EF55-23C3-4FD2-9F2F-FD8F0F3FE167}.Debug|Win32.Build.0 = Debug|Win32 + {21B7EF55-23C3-4FD2-9F2F-FD8F0F3FE167}.Release|Win32.ActiveCfg = Release|Win32 + {21B7EF55-23C3-4FD2-9F2F-FD8F0F3FE167}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/strategies/within.cpp b/test/strategies/within.cpp index ef6b9179c7..6e0cbe955a 100644 --- a/test/strategies/within.cpp +++ b/test/strategies/within.cpp @@ -11,16 +11,21 @@ #include +#include #include #include #include #include +#include +#include +#include #include #include +#include #include #include @@ -36,7 +41,7 @@ void test_point_in_polygon(std::string const& case_id, Strategy const& strategy, std::string const& strategy_id, bool expected) { - BOOST_CONCEPT_ASSERT( (bg::concept::WithinStrategy) ); + BOOST_CONCEPT_ASSERT( (bg::concept::WithinStrategyPolygonal) ); bool detected = bg::within(point, polygon, strategy); BOOST_CHECK_MESSAGE(detected == expected, @@ -68,11 +73,63 @@ void test_geometry(std::string const& case_id, std::string const& wkt_point "cross.mult", boost::contains(deviations, "c") ? !expected : expected); } +template +void test_box_of(std::string const& wkt_point, std::string const& wkt_box, + bool expected_within, bool expected_covered_by) +{ + typedef bg::model::box box_type; + + Point point; + box_type box; + bg::read_wkt(wkt_point, point); + bg::read_wkt(wkt_box, box); + + bool detected_within = bg::within(point, box); + bool detected_covered_by = bg::covered_by(point, box); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + + // Also test with the non-default agnostic side version + namespace wi = bg::strategy::within; + wi::point_in_box_by_side within_strategy; + wi::point_in_box_by_side covered_by_strategy; + + detected_within = bg::within(point, box, within_strategy); + detected_covered_by = bg::covered_by(point, box, covered_by_strategy); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + + // We might exchange strategies between within/covered by. + // So the lines below might seem confusing, but are as intended + detected_within = bg::covered_by(point, box, within_strategy); + detected_covered_by = bg::within(point, box, covered_by_strategy); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + + // Finally we call the strategies directly + detected_within = within_strategy.apply(point, box); + detected_covered_by = covered_by_strategy.apply(point, box); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); +} + +template +void test_box() +{ + test_box_of("POINT(1 1)", "BOX(0 0,2 2)", true, true); + test_box_of("POINT(0 0)", "BOX(0 0,2 2)", false, true); + test_box_of("POINT(2 2)", "BOX(0 0,2 2)", false, true); + test_box_of("POINT(0 1)", "BOX(0 0,2 2)", false, true); + test_box_of("POINT(1 0)", "BOX(0 0,2 2)", false, true); + test_box_of("POINT(3 3)", "BOX(0 0,2 2)", false, false); +} template void test_all() { + test_box(); + typedef bg::model::polygon polygon; std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))"; diff --git a/test/util/Jamfile.v2 b/test/util/Jamfile.v2 index 0ec3e7543f..2b620c50a9 100644 --- a/test/util/Jamfile.v2 +++ b/test/util/Jamfile.v2 @@ -11,6 +11,7 @@ test-suite boost-geometry-util : [ run for_each_coordinate.cpp ] + [ run rational.cpp ] [ run select_most_precise.cpp ] [ run write_dsv.cpp ] ; diff --git a/test/util/rational.cpp b/test/util/rational.cpp new file mode 100644 index 0000000000..20f876caf6 --- /dev/null +++ b/test/util/rational.cpp @@ -0,0 +1,61 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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) + + +#include + +#include +#include +#include + +void test_coordinate_cast(std::string const& s, int expected_nom, int expected_denom) +{ + boost::rational a = bg::detail::coordinate_cast >::apply(s); + BOOST_CHECK_EQUAL(a.numerator(), expected_nom); + BOOST_CHECK_EQUAL(a.denominator(), expected_denom); +} + + +void test_wkt(std::string const& wkt, std::string const expected_wkt) +{ + bg::model::point, 2, bg::cs::cartesian> p; + bg::read_wkt(wkt, p); + std::ostringstream out; + out << bg::wkt(p); + + BOOST_CHECK_EQUAL(out.str(), expected_wkt); +} + +int test_main(int, char* []) +{ + test_coordinate_cast("0", 0, 1); + test_coordinate_cast("1", 1, 1); + test_coordinate_cast("-1", -1, 1); + test_coordinate_cast("-0.5", -1, 2); + test_coordinate_cast("-1.5", -3, 2); + test_coordinate_cast("0.5", 1, 2); + test_coordinate_cast("1.5", 3, 2); + test_coordinate_cast("2.12345", 42469, 20000); + test_coordinate_cast("1.", 1, 1); + + test_coordinate_cast("3/2", 3, 2); + test_coordinate_cast("-3/2", -3, 2); + + test_wkt("POINT(1.5 2.75)", "POINT(3/2 11/4)"); + test_wkt("POINT(3/2 11/4)", "POINT(3/2 11/4)"); + test_wkt("POINT(-1.5 2.75)", "POINT(-3/2 11/4)"); + test_wkt("POINT(-3/2 11/4)", "POINT(-3/2 11/4)"); + + return 0; +} diff --git a/test/util/rational.vcproj b/test/util/rational.vcproj new file mode 100644 index 0000000000..28ad0a237f --- /dev/null +++ b/test/util/rational.vcproj @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/util/util_tests.sln b/test/util/util_tests.sln index a4aa5c1465..fbbb18042b 100644 --- a/test/util/util_tests.sln +++ b/test/util/util_tests.sln @@ -8,6 +8,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "write_dsv", "write_dsv.vcpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "as_range", "as_range.vcproj", "{A36D8426-67EB-405C-B6E8-3FBB3374A59B}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rational", "rational.vcproj", "{6ABF6324-C1DC-4687-9895-B4CE2B27446F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -30,6 +32,10 @@ Global {A36D8426-67EB-405C-B6E8-3FBB3374A59B}.Debug|Win32.Build.0 = Debug|Win32 {A36D8426-67EB-405C-B6E8-3FBB3374A59B}.Release|Win32.ActiveCfg = Release|Win32 {A36D8426-67EB-405C-B6E8-3FBB3374A59B}.Release|Win32.Build.0 = Release|Win32 + {6ABF6324-C1DC-4687-9895-B4CE2B27446F}.Debug|Win32.ActiveCfg = Debug|Win32 + {6ABF6324-C1DC-4687-9895-B4CE2B27446F}.Debug|Win32.Build.0 = Debug|Win32 + {6ABF6324-C1DC-4687-9895-B4CE2B27446F}.Release|Win32.ActiveCfg = Release|Win32 + {6ABF6324-C1DC-4687-9895-B4CE2B27446F}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 2baaa1df1ff7620be3f791861eb48b998cb79e74 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 7 Jan 2012 17:32:00 +0000 Subject: [PATCH 028/135] Added new io folder to release branch [SVN r76340] --- include/boost/geometry/algorithms/append.hpp | 9 +- include/boost/geometry/algorithms/area.hpp | 22 +- include/boost/geometry/algorithms/assign.hpp | 15 +- include/boost/geometry/algorithms/convert.hpp | 115 +++--- .../boost/geometry/algorithms/covered_by.hpp | 2 +- .../detail/convert_indexed_to_indexed.hpp | 80 ++++ .../detail/has_self_intersections.hpp | 2 +- .../detail/overlay/backtrack_check_si.hpp | 17 +- .../detail/overlay/copy_segments.hpp | 50 +++ .../overlay/enrich_intersection_points.hpp | 10 +- .../algorithms/detail/overlay/follow.hpp | 356 ++++++++++++++++++ .../algorithms/detail/overlay/get_turns.hpp | 2 +- .../detail/overlay/intersection_insert.hpp | 152 ++++++++ .../algorithms/detail/overlay/overlay.hpp | 2 +- .../algorithms/detail/overlay/traverse.hpp | 15 +- .../boost/geometry/algorithms/difference.hpp | 22 +- .../boost/geometry/algorithms/distance.hpp | 218 ++++++----- .../geometry/algorithms/not_implemented.hpp | 117 ++++++ .../geometry/algorithms/sym_difference.hpp | 36 +- include/boost/geometry/geometry.hpp | 6 +- 20 files changed, 1022 insertions(+), 226 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/follow.hpp create mode 100644 include/boost/geometry/algorithms/not_implemented.hpp diff --git a/include/boost/geometry/algorithms/append.hpp b/include/boost/geometry/algorithms/append.hpp index ad315e47f2..badf33e79f 100644 --- a/include/boost/geometry/algorithms/append.hpp +++ b/include/boost/geometry/algorithms/append.hpp @@ -178,14 +178,18 @@ struct append_range // Default: append a range (or linestring or ring or whatever) to any geometry -template +template +< + typename Geometry, typename RangeOrPoint, + typename TagRangeOrPoint = typename tag::type +> struct append : splitted_dispatch::append_range::type, Geometry, RangeOrPoint> {}; // Specialization for point to append a point to any geometry template -struct append +struct append : splitted_dispatch::append_point::type, Geometry, RangeOrPoint> {}; @@ -217,7 +221,6 @@ inline void append(Geometry& geometry, RangeOrPoint const& range_or_point, dispatch::append < - typename tag::type, Geometry, RangeOrPoint >::apply(geometry, range_or_point, ring_index, multi_index); diff --git a/include/boost/geometry/algorithms/area.hpp b/include/boost/geometry/algorithms/area.hpp index 641d9adfba..32010d6f97 100644 --- a/include/boost/geometry/algorithms/area.hpp +++ b/include/boost/geometry/algorithms/area.hpp @@ -135,9 +135,16 @@ namespace dispatch template < - typename Tag, typename Geometry, - typename Strategy + typename Strategy = typename strategy::area::services::default_strategy + < + typename cs_tag + < + typename point_type::type + >::type, + typename point_type::type + >::type, + typename Tag = typename tag::type > struct area : detail::calculate_null @@ -153,7 +160,7 @@ template typename Geometry, typename Strategy > -struct area +struct area : detail::area::box_area {}; @@ -163,7 +170,7 @@ template typename Ring, typename Strategy > -struct area +struct area : detail::area::ring_area < Ring, @@ -179,7 +186,7 @@ template typename Polygon, typename Strategy > -struct area +struct area : detail::calculate_polygon_sum < typename Strategy::return_type, @@ -236,9 +243,7 @@ inline typename default_area_result::type area(Geometry const& geometr return dispatch::area < - typename tag::type, - Geometry, - strategy_type + Geometry >::apply(geometry, strategy_type()); } @@ -274,7 +279,6 @@ inline typename Strategy::return_type area( return dispatch::area < - typename tag::type, Geometry, Strategy >::apply(geometry, strategy); diff --git a/include/boost/geometry/algorithms/assign.hpp b/include/boost/geometry/algorithms/assign.hpp index 74089f95b8..25c1699de4 100644 --- a/include/boost/geometry/algorithms/assign.hpp +++ b/include/boost/geometry/algorithms/assign.hpp @@ -29,20 +29,17 @@ #include #include #include - -#include #include #include +#include #include #include #include #include - #include - namespace boost { namespace geometry { @@ -163,15 +160,7 @@ inline void assign(Geometry1& geometry1, Geometry2 const& geometry2) , (types) ); - dispatch::convert - < - false, - typename tag::type, - typename tag::type, - dimension::type::value, - Geometry2, - Geometry1 - >::apply(geometry2, geometry1); + dispatch::convert::apply(geometry2, geometry1); } diff --git a/include/boost/geometry/algorithms/convert.hpp b/include/boost/geometry/algorithms/convert.hpp index e6f16a77fe..bad386cb0d 100644 --- a/include/boost/geometry/algorithms/convert.hpp +++ b/include/boost/geometry/algorithms/convert.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include @@ -212,28 +214,24 @@ namespace dispatch template < - bool UseAssignment, - typename Tag1, typename Tag2, - std::size_t DimensionCount, - typename Geometry1, typename Geometry2 + typename Geometry1, typename Geometry2, + typename Tag1 = typename tag_cast::type, multi_tag>::type, + typename Tag2 = typename tag_cast::type, multi_tag>::type, + std::size_t DimensionCount = dimension::type::value, + bool UseAssignment = boost::is_same::value + && !boost::is_array::value > -struct convert -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES - , (types) - ); -}; +struct convert: not_implemented > +{}; template < + typename Geometry1, typename Geometry2, typename Tag, - std::size_t DimensionCount, - typename Geometry1, typename Geometry2 + std::size_t DimensionCount > -struct convert +struct convert { // Same geometry type -> copy whole geometry static inline void apply(Geometry1 const& source, Geometry2& destination) @@ -245,21 +243,42 @@ struct convert template < - std::size_t DimensionCount, - typename Geometry1, typename Geometry2 + typename Geometry1, typename Geometry2, + std::size_t DimensionCount > -struct convert +struct convert : detail::conversion::point_to_point {}; -template -struct convert + +template +< + typename Box1, typename Box2, + std::size_t DimensionCount +> +struct convert + : detail::conversion::indexed_to_indexed +{}; + + +template +< + typename Segment1, typename Segment2, + std::size_t DimensionCount +> +struct convert + : detail::conversion::indexed_to_indexed +{}; + + +template +struct convert : detail::conversion::segment_to_range {}; -template -struct convert +template +struct convert : detail::conversion::range_to_range < Ring1, @@ -269,18 +288,18 @@ struct convert > {}; -template -struct convert +template +struct convert : detail::conversion::range_to_range {}; -template -struct convert +template +struct convert : detail::conversion::polygon_to_polygon {}; template -struct convert +struct convert : detail::conversion::box_to_range < Box, @@ -292,7 +311,7 @@ struct convert template -struct convert +struct convert { static inline void apply(Box const& box, Polygon& polygon) { @@ -300,15 +319,16 @@ struct convert convert < - false, box_tag, ring_tag, - 2, Box, ring_type + Box, ring_type, + box_tag, ring_tag, + 2, false >::apply(box, exterior_ring(polygon)); } }; -template -struct convert +template +struct convert { static inline void apply(Point const& point, Box& box) { @@ -324,23 +344,24 @@ struct convert }; -template -struct convert +template +struct convert { static inline void apply(Ring const& ring, Polygon& polygon) { typedef typename ring_type::type ring_type; convert < - false, ring_tag, ring_tag, DimensionCount, - Ring, ring_type + Ring, ring_type, + ring_tag, ring_tag, + DimensionCount, false >::apply(ring, exterior_ring(polygon)); } }; -template -struct convert +template +struct convert { static inline void apply(Polygon const& polygon, Ring& ring) { @@ -348,9 +369,9 @@ struct convert convert < - false, - ring_tag, ring_tag, DimensionCount, - ring_type, Ring + ring_type, Ring, + ring_tag, ring_tag, + DimensionCount, false >::apply(exterior_ring(polygon), ring); } }; @@ -380,17 +401,7 @@ inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) { concept::check_concepts_and_equal_dimensions(); - dispatch::convert - < - boost::is_same::value - // && boost::has_assign::value, -- type traits extensions - && ! boost::is_array::value, - typename tag_cast::type, multi_tag>::type, - typename tag_cast::type, multi_tag>::type, - dimension::type::value, - Geometry1, - Geometry2 - >::apply(geometry1, geometry2); + dispatch::convert::apply(geometry1, geometry2); } diff --git a/include/boost/geometry/algorithms/covered_by.hpp b/include/boost/geometry/algorithms/covered_by.hpp index 3e099126a9..fdb78edc1d 100644 --- a/include/boost/geometry/algorithms/covered_by.hpp +++ b/include/boost/geometry/algorithms/covered_by.hpp @@ -170,7 +170,7 @@ inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2) \param geometry1 \param_geometry geometry which might be covered_by the second geometry \param geometry2 \param_geometry which might contain the first geometry \param strategy strategy to be used -\return true if geometry1 is completely contained covered_by geometry2, +\return true if geometry1 is inside of or on the border of geometry2, else false \qbk{distinguish,with strategy} diff --git a/include/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp b/include/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp new file mode 100644 index 0000000000..3dc4d5c2f5 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp @@ -0,0 +1,80 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP + + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace conversion +{ + + +template +< + typename Source, + typename Destination, + std::size_t Dimension, + std::size_t DimensionCount +> +struct indexed_to_indexed +{ + static inline void apply(Source const& source, Destination& destination) + { + typedef typename coordinate_type::type coordinate_type; + + geometry::set(destination, + boost::numeric_cast( + geometry::get(source))); + geometry::set(destination, + boost::numeric_cast( + geometry::get(source))); + + indexed_to_indexed + < + Source, Destination, + Dimension + 1, DimensionCount + >::apply(source, destination); + } +}; + +template +< + typename Source, + typename Destination, + std::size_t DimensionCount +> +struct indexed_to_indexed +{ + static inline void apply(Source const& , Destination& ) + {} +}; + + +}} // namespace detail::conversion +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP diff --git a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp index e466b26f8f..2ea2e4cc01 100644 --- a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp +++ b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -21,7 +21,7 @@ #ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS # include -# include +# include #endif diff --git a/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp index ad0b304d31..7762afed4e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp @@ -9,34 +9,26 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP - #include - #include #include -#include #include - -# include - - +#include +#include #if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) # include -# include +# include #endif - namespace boost { namespace geometry { - #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay { - template inline void clear_visit_info(Turns& turns) { @@ -170,12 +162,9 @@ public : }; #endif // BOOST_GEOMETRY_OVERLAY_REPORT_WKT - }} // namespace detail::overlay #endif // DOXYGEN_NO_DETAIL - }} // namespace boost::geometry - #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index c03f77e9f2..920d4c2c80 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -98,6 +98,41 @@ struct copy_segments_ring } }; +template +< + typename LineString, + bool Reverse, + typename SegmentIdentifier, + typename RangeOut +> +struct copy_segments_linestring +{ + + typedef typename boost::range_iterator::type iterator; + + static inline void apply(LineString const& ls, + SegmentIdentifier const& seg_id, int to_index, + RangeOut& current_output) + { + int const from_index = seg_id.segment_index + 1; + + // Sanity check + if (from_index > to_index || from_index < 0 || to_index >= boost::size(ls)) + { + return; + } + + typedef typename boost::range_difference::type size_type; + size_type const count = to_index - from_index + 1; + + typename boost::range_iterator::type it = boost::begin(ls) + from_index; + + for (size_type i = 0; i < count; ++i, ++it) + { + detail::overlay::append_no_duplicates(current_output, *it); + } + } +}; template < @@ -208,6 +243,21 @@ struct copy_segments {}; + +template +< + typename LineString, + bool Reverse, + typename SegmentIdentifier, + typename RangeOut +> +struct copy_segments + : detail::copy_segments::copy_segments_linestring + < + LineString, Reverse, SegmentIdentifier, RangeOut + > +{}; + template < typename Polygon, diff --git a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index 5a13b52404..77f5cfb50e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -9,7 +9,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP - #include #include #include @@ -19,26 +18,21 @@ #ifdef BOOST_GEOMETRY_DEBUG_ENRICH # include # include -# include +# include # define BOOST_GEOMETRY_DEBUG_IDENTIFIER #endif #include #include - - #include #include #include - #include - #ifdef BOOST_GEOMETRY_DEBUG_ENRICH # include #endif - namespace boost { namespace geometry { @@ -524,8 +518,6 @@ inline void enrich_intersection_points(TurnPoints& turn_points, } - }} // namespace boost::geometry - #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/follow.hpp b/include/boost/geometry/algorithms/detail/overlay/follow.hpp new file mode 100644 index 0000000000..084a335cb6 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -0,0 +1,356 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 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_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP + +#include + +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +namespace following +{ + +template +static inline bool is_entering(Turn const& turn, Operation const& op) +{ + // (Blocked means: blocked for polygon/polygon intersection, because + // they are reversed. But for polygon/line it is similar to continue) + return op.operation == operation_intersection + || op.operation == operation_continue + || op.operation == operation_blocked + ; +} + +template +< + typename Turn, + typename Operation, + typename LineString, + typename Polygon +> +static inline bool is_leaving(Turn const& turn, Operation const& op, + bool entered, bool first, + LineString const& linestring, Polygon const& polygon) +{ + if (op.operation == operation_union) + { + return entered + || turn.method == method_crosses + || (first && geometry::within(linestring[0], polygon)) + ; + } + return false; +} + + +template +< + typename Turn, + typename Operation, + typename LineString, + typename Polygon +> +static inline bool is_staying_inside(Turn const& turn, Operation const& op, + bool entered, bool first, + LineString const& linestring, Polygon const& polygon) +{ + if (turn.method == method_crosses) + { + // The normal case, this is completely covered with entering/leaving + // so stay out of this time consuming "within" + return false; + } + + if (is_entering(turn, op)) + { + return entered || (first && geometry::within(linestring[0], polygon)); + } + + return false; +} + +template +static inline bool was_entered(Turn const& turn, bool first) +{ + if (first && (turn.method == method_collinear || turn.method == method_equal)) + { + // If it is the very first point, and either equal or collinear, there is only one + // IP generated (on purpose). So consider this as having entered. + // Maybe it will leave immediately after that (u/i) but that is checked later. + return true; + } + return false; +} + + +// Template specialization structure to call the right actions for the right type +template +struct action_selector +{ + // If you get here the overlay type is not intersection or difference + // BOOST_MPL_ASSERT(false); +}; + +// Specialization for intersection, containing the implementation +template<> +struct action_selector +{ + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation + > + static inline void enter(LineStringOut& current_piece, + LineString const& linestring, + segment_identifier& segment_id, + int index, Point const& point, + Operation const& operation, OutputIterator& out) + { + // On enter, append the intersection point and remember starting point + detail::overlay::append_no_duplicates(current_piece, point); + segment_id = operation.seg_id; + } + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation + > + static inline void leave(LineStringOut& current_piece, + LineString const& linestring, + segment_identifier& segment_id, + int index, Point const& point, + Operation const& operation, OutputIterator& out) + { + // On leave, copy all segments from starting point, append the intersection point + // and add the output piece + geometry::copy_segments(linestring, segment_id, index, current_piece); + detail::overlay::append_no_duplicates(current_piece, point); + if (! current_piece.empty()) + { + *out++ = current_piece; + current_piece.clear(); + } + } + + static inline bool is_entered(bool entered) + { + return entered; + } + + template + static inline bool included(Point const& point, Geometry const& geometry) + { + return geometry::within(point, geometry); + } + +}; + +// Specialization for difference, which reverses these actions +template<> +struct action_selector +{ + typedef action_selector normal_action; + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation + > + static inline void enter(LineStringOut& current_piece, + LineString const& linestring, + segment_identifier& segment_id, + int index, Point const& point, + Operation const& operation, OutputIterator& out) + { + normal_action::leave(current_piece, linestring, segment_id, index, + point, operation, out); + } + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation + > + static inline void leave(LineStringOut& current_piece, + LineString const& linestring, + segment_identifier& segment_id, + int index, Point const& point, + Operation const& operation, OutputIterator& out) + { + normal_action::enter(current_piece, linestring, segment_id, index, + point, operation, out); + } + + static inline bool is_entered(bool entered) + { + return ! normal_action::is_entered(entered); + } + + template + static inline bool included(Point const& point, Geometry const& geometry) + { + return ! normal_action::included(point, geometry); + } + +}; + +} + +/*! +\brief Follows a linestring from intersection point to intersection point, outputting which + is inside, or outside, a ring or polygon +\ingroup overlay + */ +template +< + typename LineStringOut, + typename LineString, + typename Polygon, + overlay_type OverlayType +> +class follow +{ + + template + struct sort_on_segment + { + inline bool operator()(Turn const& left, Turn const& right) const + { + segment_identifier const& sl = left.operations[0].seg_id; + segment_identifier const& sr = right.operations[0].seg_id; + + return sl == sr + ? left.operations[0].enriched.distance < right.operations[0].enriched.distance + : sl < sr; + + } + }; + + + +public : + + template + static inline bool included(Point const& point, Geometry const& geometry) + { + return following::action_selector::included(point, geometry); + } + + template + static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon, + detail::overlay::operation_type operation, + Turns& turns, OutputIterator out) + { + typedef typename boost::range_iterator::type turn_iterator; + typedef typename boost::range_value::type turn_type; + typedef typename boost::range_iterator + < + typename turn_type::container_type + >::type turn_operation_iterator_type; + + typedef following::action_selector action; + + // Sort intersection points on segments-along-linestring, and distance + // (like in enrich is done for poly/poly) + std::sort(boost::begin(turns), boost::end(turns), sort_on_segment()); + + LineStringOut current_piece; + geometry::segment_identifier current_segment_id(0, -1, -1, -1); + + // Iterate through all intersection points (they are ordered along the line) + bool entered = false; + bool first = true; + for (turn_iterator it = boost::begin(turns); it != boost::end(turns); ++it) + { + turn_operation_iterator_type iit = boost::begin(it->operations); + + if (following::was_entered(*it, first)) + { + debug_traverse(*it, *iit, "-> Was entered"); + entered = true; + } + + if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon)) + { + debug_traverse(*it, *iit, "-> Staying inside"); + + entered = true; + } + else if (following::is_entering(*it, *iit)) + { + debug_traverse(*it, *iit, "-> Entering"); + + entered = true; + action::enter(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out); + } + else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon)) + { + debug_traverse(*it, *iit, "-> Leaving"); + + entered = false; + action::leave(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out); + } + first = false; + } + + if (action::is_entered(entered)) + { + geometry::copy_segments(linestring, current_segment_id, + boost::size(linestring) - 1, + current_piece); + } + + // Output the last one, if applicable + if (! current_piece.empty()) + { + *out++ = current_piece; + } + return out; + } + +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index e79bf4ed99..5c762d4035 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -58,7 +58,7 @@ #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION # include -# include +# include #endif diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 5ae8f772cc..644e091402 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -26,8 +26,12 @@ #include #include #include +#include #include +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) +#include +#endif namespace boost { namespace geometry { @@ -102,6 +106,98 @@ struct intersection_linestring_linestring_point } }; +/*! +\brief Version of linestring with an areal feature (polygon or multipolygon) +*/ +template +< + typename LineString, typename Areal, + bool ReverseAreal, + typename OutputIterator, typename LineStringOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_of_linestring_with_areal +{ + typedef detail::overlay::follow + < + LineStringOut, + LineString, + Areal, + OverlayType + > follower; + +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) + template + static inline void debug_follow(Turn const& turn, Operation op, + int index) + { + std::cout << index + << " at " << op.seg_id + << " meth: " << method_char(turn.method) + << " op: " << operation_char(op.operation) + << " vis: " << visited_char(op.visited) + << " of: " << operation_char(turn.operations[0].operation) + << operation_char(turn.operations[1].operation) + << " " << geometry::wkt(turn.point) + << std::endl; + } +#endif + + static inline OutputIterator apply(LineString const& linestring, Areal const& areal, + OutputIterator out, + Strategy const& strategy) + { + if (boost::size(linestring) == 0) + { + return out; + } + + typedef typename point_type::type point_type; + + typedef detail::overlay::traversal_turn_info turn_info; + std::deque turns; + + detail::get_turns::no_interrupt_policy policy; + geometry::get_turns + < + false, + (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal), + detail::overlay::calculate_distance_policy + >(linestring, areal, turns, policy); + + if (turns.empty()) + { + // No intersection points, it is either completely + // inside (interior + borders) + // or completely outside + if (follower::included(*boost::begin(linestring), areal)) + { + LineStringOut copy; + geometry::convert(linestring, copy); + *out++ = copy; + } + return out; + } + +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) + int index = 0; + BOOST_FOREACH(turn_info const& turn, turns) + { + debug_follow(turn, turn.operations[0], index++); + } +#endif + + return follower::apply + ( + linestring, areal, + geometry::detail::overlay::operation_intersection, + turns, out + ); + } +}; + + }} // namespace detail::intersection #endif // DOXYGEN_NO_DETAIL @@ -264,6 +360,62 @@ struct intersection_insert } }; + +template +< + typename Linestring, typename Polygon, + bool ReverseLinestring, bool ReversePolygon, bool ReverseOut, + typename OutputIterator, typename GeometryOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + linestring_tag, polygon_tag, linestring_tag, + false, true, false, + Linestring, Polygon, + ReverseLinestring, ReversePolygon, ReverseOut, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > : detail::intersection::intersection_of_linestring_with_areal + < + Linestring, Polygon, + ReversePolygon, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > +{}; + + +template +< + typename Linestring, typename Ring, + bool ReverseLinestring, bool ReverseRing, bool ReverseOut, + typename OutputIterator, typename GeometryOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + linestring_tag, ring_tag, linestring_tag, + false, true, false, + Linestring, Ring, + ReverseLinestring, ReverseRing, ReverseOut, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > : detail::intersection::intersection_of_linestring_with_areal + < + Linestring, Ring, + ReverseRing, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > +{}; + template < typename Segment, typename Box, diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index 2b71e54b02..9fefa17d77 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -37,7 +37,7 @@ #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -# include +# include #endif diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index 8edae0f2b4..34b2c0e07e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -9,7 +9,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP - #include #include @@ -22,19 +21,17 @@ #include #include - -#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) +#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) \ + || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) \ + || defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) # include # include -# include +# include #endif - - namespace boost { namespace geometry { - #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay { @@ -46,10 +43,12 @@ inline void debug_traverse(Turn const& turn, Operation op, #ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE std::cout << header << " at " << op.seg_id + << " meth: " << method_char(turn.method) << " op: " << operation_char(op.operation) << " vis: " << visited_char(op.visited) << " of: " << operation_char(turn.operations[0].operation) << operation_char(turn.operations[1].operation) + << " " << geometry::wkt(turn.point) << std::endl; if (boost::contains(header, "Finished")) @@ -387,8 +386,6 @@ public : }} // namespace detail::overlay #endif // DOXYGEN_NO_DETAIL - }} // namespace boost::geometry - #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP diff --git a/include/boost/geometry/algorithms/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index 230ef512e0..87715b8097 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -53,11 +53,23 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, concept::check(); concept::check(); concept::check(); - - return detail::intersection::insert( - geometry1, geometry2, - out, - strategy); + + return geometry::dispatch::intersection_insert + < + typename geometry::tag::type, + typename geometry::tag::type, + typename geometry::tag::type, + geometry::is_areal::value, + geometry::is_areal::value, + geometry::is_areal::value, + Geometry1, Geometry2, + geometry::detail::overlay::do_reverse::value>::value, + geometry::detail::overlay::do_reverse::value, true>::value, + geometry::detail::overlay::do_reverse::value>::value, + OutputIterator, GeometryOut, + overlay_difference, + Strategy + >::apply(geometry1, geometry2, out, strategy); } /*! diff --git a/include/boost/geometry/algorithms/distance.hpp b/include/boost/geometry/algorithms/distance.hpp index c28d4a6c0e..5a9e6abd2f 100644 --- a/include/boost/geometry/algorithms/distance.hpp +++ b/include/boost/geometry/algorithms/distance.hpp @@ -19,15 +19,13 @@ #include #include -#include - -#include - #include #include #include #include +#include + #include #include @@ -236,6 +234,18 @@ struct point_to_polygon }; +// Helper metafunction for default strategy retrieval +template +struct default_strategy + : strategy::distance::services::default_strategy + < + point_tag, + typename point_type::type, + typename point_type::type + > +{}; + + }} // namespace detail::distance #endif // DOXYGEN_NO_DETAIL @@ -244,31 +254,97 @@ struct point_to_polygon namespace dispatch { + using strategy::distance::services::return_type; template < - typename GeometryTag1, typename GeometryTag2, typename Geometry1, typename Geometry2, - typename StrategyTag, typename Strategy + typename Strategy = typename detail::distance::default_strategy::type, + typename Tag1 = typename tag_cast::type, multi_tag>::type, + typename Tag2 = typename tag_cast::type, multi_tag>::type, + typename StrategyTag = typename strategy::distance::services::tag::type, + bool Reverse = reverse_dispatch::type::value +> +struct distance: not_implemented +{}; + + +// If reversal is needed, perform it +template +< + typename Geometry1, typename Geometry2, typename Strategy, + typename Tag1, typename Tag2, typename StrategyTag +> +struct distance +< + Geometry1, Geometry2, Strategy, + Tag1, Tag2, StrategyTag, + true +> + : distance +{ + static inline typename return_type::type apply( + Geometry1 const& g1, + Geometry2 const& g2, + Strategy const& strategy) + { + return distance + < + Geometry2, Geometry1, Strategy, + Tag2, Tag1, StrategyTag, + false + >::apply(g2, g1, strategy); + } +}; + +// If reversal is needed and we got the strategy by default, invert it before +// proceeding to the reversal. +template +< + typename Geometry1, typename Geometry2, + typename Tag1, typename Tag2, typename StrategyTag > struct distance +< + Geometry1, Geometry2, + typename detail::distance::default_strategy::type, + Tag1, Tag2, StrategyTag, + true +> + : distance + < + Geometry2, Geometry1, + typename detail::distance::default_strategy::type, + Tag2, Tag1, StrategyTag, + false + > { - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); + typedef typename detail::distance::default_strategy::type reversed_strategy; + + static inline typename strategy::distance::services::return_type::type apply( + Geometry1 const& g1, + Geometry2 const& g2, + typename detail::distance::default_strategy::type const&) + { + return distance + < + Geometry2, Geometry1, reversed_strategy, + Tag2, Tag1, StrategyTag, + false + >::apply(g2, g1, reversed_strategy()); + } }; +// Point-point template struct distance < - point_tag, point_tag, - P1, P2, - strategy_tag_distance_point_point, Strategy + P1, P2, Strategy, + point_tag, point_tag, strategy_tag_distance_point_point, + false > : detail::distance::point_to_point {}; @@ -278,9 +354,9 @@ struct distance template struct distance < - point_tag, linestring_tag, - Point, Linestring, - strategy_tag_distance_point_point, Strategy + Point, Linestring, Strategy, + point_tag, linestring_tag, strategy_tag_distance_point_point, + false > { @@ -307,9 +383,9 @@ struct distance template struct distance < - point_tag, linestring_tag, - Point, Linestring, - strategy_tag_distance_point_segment, Strategy + Point, Linestring, Strategy, + point_tag, linestring_tag, strategy_tag_distance_point_segment, + false > { static inline typename return_type::type apply(Point const& point, @@ -328,9 +404,9 @@ struct distance template struct distance < - point_tag, ring_tag, - Point, Ring, - strategy_tag_distance_point_point, Strategy + Point, Ring, Strategy, + point_tag, ring_tag, strategy_tag_distance_point_point, + false > { typedef typename return_type::type return_type; @@ -363,9 +439,9 @@ struct distance template struct distance < - point_tag, polygon_tag, - Point, Polygon, - strategy_tag_distance_point_point, Strategy + Point, Polygon, Strategy, + point_tag, polygon_tag, strategy_tag_distance_point_point, + false > { typedef typename return_type::type return_type; @@ -399,9 +475,9 @@ struct distance template struct distance < - point_tag, segment_tag, - Point, Segment, - strategy_tag_distance_point_point, Strategy + Point, Segment, Strategy, + point_tag, segment_tag, strategy_tag_distance_point_point, + false > : detail::distance::point_to_segment {}; @@ -409,9 +485,9 @@ struct distance template struct distance < - point_tag, segment_tag, - Point, Segment, - strategy_tag_distance_point_segment, Strategy + Point, Segment, Strategy, + point_tag, segment_tag, strategy_tag_distance_point_segment, + false > { static inline typename return_type::type apply(Point const& point, @@ -427,27 +503,6 @@ struct distance -// Strictly spoken this might be in namespace again -template -< - typename GeometryTag1, typename GeometryTag2, - typename G1, typename G2, - typename StrategyTag, typename Strategy -> -struct distance_reversed -{ - static inline typename return_type::type apply(G1 const& g1, - G2 const& g2, Strategy const& strategy) - { - return distance - < - GeometryTag2, GeometryTag1, - G2, G1, - StrategyTag, Strategy - >::apply(g2, g1, strategy); - } -}; - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -489,34 +544,18 @@ for return_type<...> for your strategy. */ template inline typename strategy::distance::services::return_type::type distance( - Geometry1 const& geometry1, - Geometry2 const& geometry2, Strategy const& strategy) + Geometry1 const& geometry1, Geometry2 const& geometry2, + Strategy const& strategy) { concept::check(); concept::check(); - return boost::mpl::if_ - < - typename geometry::reverse_dispatch::type, - dispatch::distance_reversed - < - typename tag_cast::type, multi_tag>::type, - typename tag_cast::type, multi_tag>::type, - Geometry1, - Geometry2, - typename strategy::distance::services::tag::type, - Strategy - >, - dispatch::distance - < - typename tag_cast::type, multi_tag>::type, - typename tag_cast::type, multi_tag>::type, - Geometry1, - Geometry2, - typename strategy::distance::services::tag::type, - Strategy - > - >::type::apply(geometry1, geometry2, strategy); + return dispatch::distance + < + Geometry1, + Geometry2, + Strategy + >::apply(geometry1, geometry2, strategy); } @@ -539,29 +578,8 @@ inline typename default_distance_result::type distance( concept::check(); concept::check(); - typedef typename point_type::type point1_type; - typedef typename point_type::type point2_type; - - // Define a point-point-distance-strategy - // for either the normal case, either the reversed case - typedef typename boost::mpl::if_c - < - geometry::reverse_dispatch::type::value, - typename strategy::distance::services::default_strategy - < - point_tag, - point2_type, - point1_type - >::type, - typename strategy::distance::services::default_strategy - < - point_tag, - point1_type, - point2_type - >::type - >::type strategy; - - return distance(geometry1, geometry2, strategy()); + return distance(geometry1, geometry2, + typename detail::distance::default_strategy::type()); } }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/not_implemented.hpp b/include/boost/geometry/algorithms/not_implemented.hpp new file mode 100644 index 0000000000..2ccf2d74b6 --- /dev/null +++ b/include/boost/geometry/algorithms/not_implemented.hpp @@ -0,0 +1,117 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_NOT_IMPLEMENTED_HPP +#define BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP + + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +namespace info +{ + struct UNRECOGNIZED_GEOMETRY_TYPE {}; + struct POINT {}; + struct LINESTRING {}; + struct POLYGON {}; + struct RING {}; + struct BOX {}; + struct SEGMENT {}; + struct MULTI_POINT {}; + struct MULTI_LINESTRING {}; + struct MULTI_POLYGON {}; + struct GEOMETRY_COLLECTION {}; + template struct DIMENSION {}; +} + + +namespace nyi +{ + + +struct not_implemented_tag {}; + +template +< + typename Term1, + typename Term2, + typename Term3 +> +struct not_implemented_error +{ + +#ifndef BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD +# define BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD false +#endif + + BOOST_MPL_ASSERT_MSG + ( + BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD, + THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED, + ( + types + ) + ); +}; + +template +struct tag_to_term +{ + typedef Tag type; +}; + +template <> struct tag_to_term { typedef info::UNRECOGNIZED_GEOMETRY_TYPE type; }; +template <> struct tag_to_term { typedef info::POINT type; }; +template <> struct tag_to_term { typedef info::LINESTRING type; }; +template <> struct tag_to_term { typedef info::POLYGON type; }; +template <> struct tag_to_term { typedef info::RING type; }; +template <> struct tag_to_term { typedef info::BOX type; }; +template <> struct tag_to_term { typedef info::SEGMENT type; }; +template <> struct tag_to_term { typedef info::MULTI_POINT type; }; +template <> struct tag_to_term { typedef info::MULTI_LINESTRING type; }; +template <> struct tag_to_term { typedef info::MULTI_POLYGON type; }; +template <> struct tag_to_term { typedef info::GEOMETRY_COLLECTION type; }; +template struct tag_to_term > { typedef info::DIMENSION type; }; + + +} + + +template +< + typename Term1 = void, + typename Term2 = void, + typename Term3 = void +> +struct not_implemented + : nyi::not_implemented_tag, + nyi::not_implemented_error + < + typename mpl::identity::type>::type, + typename mpl::identity::type>::type, + typename mpl::identity::type>::type + > +{}; + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index d228f056ad..d312e04e48 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -57,10 +57,38 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, concept::check(); concept::check(); - out = detail::intersection::insert( - geometry1, geometry2, out, strategy); - out = detail::intersection::insert( - geometry2, geometry1, out, strategy); + out = geometry::dispatch::intersection_insert + < + typename geometry::tag::type, + typename geometry::tag::type, + typename geometry::tag::type, + geometry::is_areal::value, + geometry::is_areal::value, + geometry::is_areal::value, + Geometry1, Geometry2, + geometry::detail::overlay::do_reverse::value>::value, + geometry::detail::overlay::do_reverse::value, true>::value, + geometry::detail::overlay::do_reverse::value>::value, + OutputIterator, GeometryOut, + overlay_difference, + Strategy + >::apply(geometry1, geometry2, out, strategy); + out = geometry::dispatch::intersection_insert + < + typename geometry::tag::type, + typename geometry::tag::type, + typename geometry::tag::type, + geometry::is_areal::value, + geometry::is_areal::value, + geometry::is_areal::value, + Geometry2, Geometry1, + geometry::detail::overlay::do_reverse::value>::value, + geometry::detail::overlay::do_reverse::value, true>::value, + geometry::detail::overlay::do_reverse::value>::value, + OutputIterator, GeometryOut, + overlay_difference, + Strategy + >::apply(geometry2, geometry1, out, strategy); return out; } diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp index 694659785e..daddbf4191 100644 --- a/include/boost/geometry/geometry.hpp +++ b/include/boost/geometry/geometry.hpp @@ -16,7 +16,6 @@ // Shortcut to include all header files - #include #include #include @@ -76,12 +75,11 @@ #include #include #include -#include +#include #include #include -#include - +#include #endif // BOOST_GEOMETRY_GEOMETRY_HPP From 121d5c11c3cfd687d033314619d14ab21efdfcb4 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 7 Jan 2012 17:58:37 +0000 Subject: [PATCH 029/135] Merged Geometry headerfiles [SVN r76342] --- include/boost/geometry/domains/gis/io/io.hpp | 8 +- .../domains/gis/io/wkt/detail/wkt_multi.hpp | 2 +- .../gis/io/wkt/{read_wkt.hpp => read.hpp} | 6 +- .../{read_wkt_multi.hpp => read_multi.hpp} | 8 +- .../boost/geometry/domains/gis/io/wkt/wkt.hpp | 10 +- .../gis/io/wkt/{write_wkt.hpp => write.hpp} | 6 +- .../{write_wkt_multi.hpp => write_multi.hpp} | 10 +- .../boost/geometry/io/wkt/detail/prefix.hpp | 45 ++ .../geometry/io/wkt/detail/wkt_multi.hpp | 57 ++ include/boost/geometry/io/wkt/iomanip.hpp | 46 ++ include/boost/geometry/io/wkt/read.hpp | 686 ++++++++++++++++++ include/boost/geometry/io/wkt/wkt.hpp | 21 + include/boost/geometry/io/wkt/write.hpp | 376 ++++++++++ .../boost/geometry/multi/algorithms/area.hpp | 6 +- .../geometry/multi/algorithms/convert.hpp | 25 +- .../geometry/multi/algorithms/distance.hpp | 18 +- .../multi/algorithms/intersection.hpp | 205 ++++++ .../geometry/multi/io/wkt/detail/prefix.hpp | 51 ++ include/boost/geometry/multi/io/wkt/read.hpp | 105 +++ include/boost/geometry/multi/io/wkt/wkt.hpp | 20 + include/boost/geometry/multi/io/wkt/write.hpp | 108 +++ .../boost/geometry/multi/util/write_dsv.hpp | 2 +- .../agnostic/simplify_douglas_peucker.hpp | 2 +- .../spherical/distance_cross_track.hpp | 2 +- include/boost/geometry/util/write_dsv.hpp | 396 ---------- 25 files changed, 1773 insertions(+), 448 deletions(-) rename include/boost/geometry/domains/gis/io/wkt/{read_wkt.hpp => read.hpp} (99%) rename include/boost/geometry/domains/gis/io/wkt/{read_wkt_multi.hpp => read_multi.hpp} (92%) rename include/boost/geometry/domains/gis/io/wkt/{write_wkt.hpp => write.hpp} (98%) rename include/boost/geometry/domains/gis/io/wkt/{write_wkt_multi.hpp => write_multi.hpp} (91%) create mode 100644 include/boost/geometry/io/wkt/detail/prefix.hpp create mode 100644 include/boost/geometry/io/wkt/detail/wkt_multi.hpp create mode 100644 include/boost/geometry/io/wkt/iomanip.hpp create mode 100644 include/boost/geometry/io/wkt/read.hpp create mode 100644 include/boost/geometry/io/wkt/wkt.hpp create mode 100644 include/boost/geometry/io/wkt/write.hpp create mode 100644 include/boost/geometry/multi/io/wkt/detail/prefix.hpp create mode 100644 include/boost/geometry/multi/io/wkt/read.hpp create mode 100644 include/boost/geometry/multi/io/wkt/wkt.hpp create mode 100644 include/boost/geometry/multi/io/wkt/write.hpp delete mode 100644 include/boost/geometry/util/write_dsv.hpp diff --git a/include/boost/geometry/domains/gis/io/io.hpp b/include/boost/geometry/domains/gis/io/io.hpp index 39703e3c3e..d1c06234cf 100644 --- a/include/boost/geometry/domains/gis/io/io.hpp +++ b/include/boost/geometry/domains/gis/io/io.hpp @@ -15,11 +15,11 @@ #define BOOST_GEOMETRY_DOMAINS_GIS_IO_HPP -#include -#include +#include +#include -#include -#include +#include +#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp b/include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp index abfbd28534..4cf7bc00a0 100644 --- a/include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp @@ -15,7 +15,7 @@ #define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP -#include +#include #include diff --git a/include/boost/geometry/domains/gis/io/wkt/read_wkt.hpp b/include/boost/geometry/domains/gis/io/wkt/read.hpp similarity index 99% rename from include/boost/geometry/domains/gis/io/wkt/read_wkt.hpp rename to include/boost/geometry/domains/gis/io/wkt/read.hpp index bc534a2113..6ae5f3b875 100644 --- a/include/boost/geometry/domains/gis/io/wkt/read_wkt.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/read.hpp @@ -11,8 +11,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_WKT_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_WKT_HPP +#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_HPP +#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_HPP #include @@ -689,4 +689,4 @@ inline void read_wkt(std::string const& wkt, Geometry& geometry) }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_WKT_HPP +#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/read_wkt_multi.hpp b/include/boost/geometry/domains/gis/io/wkt/read_multi.hpp similarity index 92% rename from include/boost/geometry/domains/gis/io/wkt/read_wkt_multi.hpp rename to include/boost/geometry/domains/gis/io/wkt/read_multi.hpp index 379a9fa154..0d9a2b649c 100644 --- a/include/boost/geometry/domains/gis/io/wkt/read_wkt_multi.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/read_multi.hpp @@ -11,8 +11,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_WKT_MULTI_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_WKT_MULTI_HPP +#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_MULTI_HPP +#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_MULTI_HPP #include @@ -20,7 +20,7 @@ #include #include -#include +#include #include @@ -109,4 +109,4 @@ struct read_wkt }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_WKT_MULTI_HPP +#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_MULTI_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/wkt.hpp b/include/boost/geometry/domains/gis/io/wkt/wkt.hpp index 420e816ccc..662012b1d7 100644 --- a/include/boost/geometry/domains/gis/io/wkt/wkt.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/wkt.hpp @@ -14,12 +14,10 @@ #ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WKT_HPP #define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WKT_HPP +#include +#include -#include -#include - -#include -#include - +#include +#include #endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WKT_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp b/include/boost/geometry/domains/gis/io/wkt/write.hpp similarity index 98% rename from include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp rename to include/boost/geometry/domains/gis/io/wkt/write.hpp index 7bf52c13c6..0f1dbb9094 100644 --- a/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/write.hpp @@ -11,8 +11,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_WKT_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_WKT_HPP +#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_HPP +#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_HPP #include #include @@ -391,4 +391,4 @@ inline wkt_manipulator wkt(Geometry const& geometry) }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_WKT_HPP +#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/write_wkt_multi.hpp b/include/boost/geometry/domains/gis/io/wkt/write_multi.hpp similarity index 91% rename from include/boost/geometry/domains/gis/io/wkt/write_wkt_multi.hpp rename to include/boost/geometry/domains/gis/io/wkt/write_multi.hpp index f7ee47dcd7..a8810a8153 100644 --- a/include/boost/geometry/domains/gis/io/wkt/write_wkt_multi.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/write_multi.hpp @@ -11,14 +11,12 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP - - +#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_MULTI_HPP +#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_MULTI_HPP #include -#include +#include #include @@ -114,4 +112,4 @@ struct wkt }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP +#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_MULTI_HPP diff --git a/include/boost/geometry/io/wkt/detail/prefix.hpp b/include/boost/geometry/io/wkt/detail/prefix.hpp new file mode 100644 index 0000000000..e31da6dfd9 --- /dev/null +++ b/include/boost/geometry/io/wkt/detail/prefix.hpp @@ -0,0 +1,45 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_IO_WKT_DETAIL_PREFIX_HPP +#define BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace wkt +{ + +struct prefix_point +{ + static inline const char* apply() { return "POINT"; } +}; + +struct prefix_polygon +{ + static inline const char* apply() { return "POLYGON"; } +}; + +struct prefix_linestring +{ + static inline const char* apply() { return "LINESTRING"; } +}; + +}} // namespace wkt::impl +#endif + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP diff --git a/include/boost/geometry/io/wkt/detail/wkt_multi.hpp b/include/boost/geometry/io/wkt/detail/wkt_multi.hpp new file mode 100644 index 0000000000..d698bc1edd --- /dev/null +++ b/include/boost/geometry/io/wkt/detail/wkt_multi.hpp @@ -0,0 +1,57 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP +#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace wkt +{ + +struct prefix_null +{ + static inline const char* apply() { return ""; } +}; + +struct prefix_multipoint +{ + static inline const char* apply() { return "MULTIPOINT"; } +}; + +struct prefix_multilinestring +{ + static inline const char* apply() { return "MULTILINESTRING"; } +}; + +struct prefix_multipolygon +{ + static inline const char* apply() { return "MULTIPOLYGON"; } +}; + + + +}} // namespace wkt::impl +#endif + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP diff --git a/include/boost/geometry/io/wkt/iomanip.hpp b/include/boost/geometry/io/wkt/iomanip.hpp new file mode 100644 index 0000000000..b26694193a --- /dev/null +++ b/include/boost/geometry/io/wkt/iomanip.hpp @@ -0,0 +1,46 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_IO_WKT_IOMANIP_HPP +#define BOOST_GEOMETRY_IO_WKT_IOMANIP_HPP + +#include + +// This short file contains only one manipulator, streaming as WKT +// Don't move contents to as_wkt, developers must be able to choose how to stream + +// Don't use namespace boost::geometry, to enable the library to stream custom geometries which +// are living outside the namespace boost { namespace geometry + +//namespace boost { namespace geometry +//{ + + +/*! +\brief Streams a geometry as Well-Known Text +\ingroup wkt +*/ +template +inline std::basic_ostream& operator<< + ( + std::basic_ostream &os, + Geometry const& geom + ) +{ + os << boost::geometry::wkt(geom); + return os; +} + +//}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_IO_WKT_IOMANIP_HPP diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp new file mode 100644 index 0000000000..78c127c4f3 --- /dev/null +++ b/include/boost/geometry/io/wkt/read.hpp @@ -0,0 +1,686 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_IO_WKT_READ_HPP +#define BOOST_GEOMETRY_IO_WKT_READ_HPP + +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +/*! +\brief Exception showing things wrong with WKT parsing +\ingroup wkt +*/ +struct read_wkt_exception : public geometry::exception +{ + template + read_wkt_exception(std::string const& msg, + Iterator const& it, Iterator const& end, std::string const& wkt) + : message(msg) + , wkt(wkt) + { + if (it != end) + { + source = " at '"; + source += it->c_str(); + source += "'"; + } + complete = message + source + " in '" + wkt.substr(0, 100) + "'"; + } + + read_wkt_exception(std::string const& msg, std::string const& wkt) + : message(msg) + , wkt(wkt) + { + complete = message + "' in (" + wkt.substr(0, 100) + ")"; + } + + virtual ~read_wkt_exception() throw() {} + + virtual const char* what() const throw() + { + return complete.c_str(); + } +private : + std::string source; + std::string message; + std::string wkt; + std::string complete; +}; + + +#ifndef DOXYGEN_NO_DETAIL +// (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostGIS)) +namespace detail { namespace wkt +{ + +typedef boost::tokenizer > tokenizer; + +template +struct parsing_assigner +{ + static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, + Point& point, std::string const& wkt) + { + typedef typename coordinate_type::type coordinate_type; + + // Stop at end of tokens, or at "," ot ")" + bool finished = (it == end || *it == "," || *it == ")"); + + try + { + // Initialize missing coordinates to default constructor (zero) + // OR + // Use lexical_cast for conversion to double/int + // Note that it is much slower than atof. However, it is more standard + // and in parsing the change in performance falls probably away against + // the tokenizing + set(point, finished + ? coordinate_type() + : coordinate_cast::apply(*it)); + } + catch(boost::bad_lexical_cast const& blc) + { + throw read_wkt_exception(blc.what(), it, end, wkt); + } + catch(std::exception const& e) + { + throw read_wkt_exception(e.what(), it, end, wkt); + } + catch(...) + { + throw read_wkt_exception("", it, end, wkt); + } + + parsing_assigner::apply( + (finished ? it : ++it), end, point, wkt); + } +}; + +template +struct parsing_assigner +{ + static inline void apply(tokenizer::iterator&, tokenizer::iterator, Point&, + std::string const&) + { + } +}; + + + +template +inline void handle_open_parenthesis(Iterator& it, + Iterator const& end, std::string const& wkt) +{ + if (it == end || *it != "(") + { + throw read_wkt_exception("Expected '('", it, end, wkt); + } + ++it; +} + + +template +inline void handle_close_parenthesis(Iterator& it, + Iterator const& end, std::string const& wkt) +{ + if (it != end && *it == ")") + { + ++it; + } + else + { + throw read_wkt_exception("Expected ')'", it, end, wkt); + } +} + +template +inline void check_end(Iterator& it, + Iterator const& end, std::string const& wkt) +{ + if (it != end) + { + throw read_wkt_exception("Too much tokens", it, end, wkt); + } +} + +/*! +\brief Internal, parses coordinate sequences, strings are formated like "(1 2,3 4,...)" +\param it token-iterator, should be pre-positioned at "(", is post-positions after last ")" +\param end end-token-iterator +\param out Output itererator receiving coordinates +*/ +template +struct container_inserter +{ + // Version with output iterator + template + static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, + std::string const& wkt, OutputIterator out) + { + handle_open_parenthesis(it, end, wkt); + + Point point; + + // Parse points until closing parenthesis + + while (it != end && *it != ")") + { + parsing_assigner + < + Point, + 0, + dimension::value + >::apply(it, end, point, wkt); + out = point; + ++out; + if (it != end && *it == ",") + { + ++it; + } + } + + handle_close_parenthesis(it, end, wkt); + } +}; + + +// Geometry is a value-type or reference-type +template +struct container_appender +{ + typedef typename geometry::point_type + < + typename boost::remove_reference::type + >::type point_type; + + static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, + std::string const& wkt, Geometry out) + { + handle_open_parenthesis(it, end, wkt); + + point_type point; + + // Parse points until closing parenthesis + + while (it != end && *it != ")") + { + parsing_assigner + < + point_type, + 0, + dimension::value + >::apply(it, end, point, wkt); + + geometry::append(out, point); + if (it != end && *it == ",") + { + ++it; + } + } + + handle_close_parenthesis(it, end, wkt); + } +}; + +/*! +\brief Internal, parses a point from a string like this "(x y)" +\note used for parsing points and multi-points +*/ +template +struct point_parser +{ + static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, + std::string const& wkt, P& point) + { + handle_open_parenthesis(it, end, wkt); + parsing_assigner::value>::apply(it, end, point, wkt); + handle_close_parenthesis(it, end, wkt); + } +}; + + +template +struct linestring_parser +{ + static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, + std::string const& wkt, Geometry& geometry) + { + container_appender::apply(it, end, wkt, geometry); + } +}; + + +template +struct ring_parser +{ + static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, + std::string const& wkt, Ring& ring) + { + // A ring should look like polygon((x y,x y,x y...)) + // So handle the extra opening/closing parentheses + // and in between parse using the container-inserter + handle_open_parenthesis(it, end, wkt); + container_appender::apply(it, end, wkt, ring); + handle_close_parenthesis(it, end, wkt); + } +}; + + + + +/*! +\brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))" +\note used for parsing polygons and multi-polygons +*/ +template +struct polygon_parser +{ + typedef typename ring_return_type::type ring_return_type; + typedef container_appender appender; + + static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, + std::string const& wkt, Polygon& poly) + { + + handle_open_parenthesis(it, end, wkt); + + int n = -1; + + // Stop at ")" + while (it != end && *it != ")") + { + // Parse ring + if (++n == 0) + { + appender::apply(it, end, wkt, exterior_ring(poly)); + } + else + { + typename ring_type::type ring; + appender::apply(it, end, wkt, ring); + traits::push_back + < + typename boost::remove_reference + < + typename traits::interior_mutable_type::type + >::type + >::apply(interior_rings(poly), ring); + } + + if (it != end && *it == ",") + { + // Skip "," after ring is parsed + ++it; + } + } + + handle_close_parenthesis(it, end, wkt); + } +}; + +inline bool one_of(tokenizer::iterator const& it, std::string const& value, + bool& is_present) +{ + if (boost::iequals(*it, value)) + { + is_present = true; + return true; + } + return false; +} + +inline bool one_of(tokenizer::iterator const& it, std::string const& value, + bool& present1, bool& present2) +{ + if (boost::iequals(*it, value)) + { + present1 = true; + present2 = true; + return true; + } + return false; +} + + +inline void handle_empty_z_m(tokenizer::iterator& it, tokenizer::iterator end, + bool& has_empty, bool& has_z, bool& has_m) +{ + has_empty = false; + has_z = false; + has_m = false; + + // WKT can optionally have Z and M (measured) values as in + // POINT ZM (1 1 5 60), POINT M (1 1 80), POINT Z (1 1 5) + // GGL supports any of them as coordinate values, but is not aware + // of any Measured value. + while (it != end + && (one_of(it, "M", has_m) + || one_of(it, "Z", has_z) + || one_of(it, "EMPTY", has_empty) + || one_of(it, "MZ", has_m, has_z) + || one_of(it, "ZM", has_z, has_m) + ) + ) + { + ++it; + } +} + +/*! +\brief Internal, starts parsing +\param tokens boost tokens, parsed with separator " " and keeping separator "()" +\param geometry string to compare with first token +*/ +template +inline bool initialize(tokenizer const& tokens, + std::string const& geometry_name, std::string const& wkt, + tokenizer::iterator& it) +{ + it = tokens.begin(); + if (it != tokens.end() && boost::iequals(*it++, geometry_name)) + { + bool has_empty, has_z, has_m; + + handle_empty_z_m(it, tokens.end(), has_empty, has_z, has_m); + + if (has_z && dimension::type::value < 3) + { + throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt); + } + if (has_empty) + { + check_end(it, tokens.end(), wkt); + return false; + } + // M is ignored at all. + + return true; + } + throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt); +} + + +template class Parser, typename PrefixPolicy> +struct geometry_parser +{ + static inline void apply(std::string const& wkt, Geometry& geometry) + { + geometry::clear(geometry); + + tokenizer tokens(wkt, boost::char_separator(" ", ",()")); + tokenizer::iterator it; + if (initialize(tokens, PrefixPolicy::apply(), wkt, it)) + { + Parser::apply(it, tokens.end(), wkt, geometry); + check_end(it, tokens.end(), wkt); + } + } +}; + + + + + +/*! +\brief Supports box parsing +\note OGC does not define the box geometry, and WKT does not support boxes. + However, to be generic GGL supports reading and writing from and to boxes. + Boxes are outputted as a standard POLYGON. GGL can read boxes from + a standard POLYGON, from a POLYGON with 2 points of from a BOX +\tparam Box the box +*/ +template +struct box_parser +{ + static inline void apply(std::string const& wkt, Box& box) + { + bool should_close = false; + tokenizer tokens(wkt, boost::char_separator(" ", ",()")); + tokenizer::iterator it = tokens.begin(); + tokenizer::iterator end = tokens.end(); + if (it != end && boost::iequals(*it, "POLYGON")) + { + ++it; + bool has_empty, has_z, has_m; + handle_empty_z_m(it, end, has_empty, has_z, has_m); + if (has_empty) + { + assign_zero(box); + return; + } + handle_open_parenthesis(it, end, wkt); + should_close = true; + } + else if (it != end && boost::iequals(*it, "BOX")) + { + ++it; + } + else + { + throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt); + } + + typedef typename point_type::type point_type; + std::vector points; + container_inserter::apply(it, end, wkt, std::back_inserter(points)); + + if (should_close) + { + handle_close_parenthesis(it, end, wkt); + } + check_end(it, end, wkt); + + int index = 0; + int n = boost::size(points); + if (n == 2) + { + index = 1; + } + else if (n == 4 || n == 5) + { + // In case of 4 or 5 points, we do not check the other ones, just + // take the opposite corner which is always 2 + index = 2; + } + else + { + throw read_wkt_exception("Box should have 2,4 or 5 points", wkt); + } + + geometry::detail::assign_point_to_index(points.front(), box); + geometry::detail::assign_point_to_index(points[index], box); + } +}; + + +/*! +\brief Supports segment parsing +\note OGC does not define the segment, and WKT does not support segmentes. + However, it is useful to implement it, also for testing purposes +\tparam Segment the segment +*/ +template +struct segment_parser +{ + static inline void apply(std::string const& wkt, Segment& segment) + { + tokenizer tokens(wkt, boost::char_separator(" ", ",()")); + tokenizer::iterator it = tokens.begin(); + tokenizer::iterator end = tokens.end(); + if (it != end && + (boost::iequals(*it, "SEGMENT") + || boost::iequals(*it, "LINESTRING") )) + { + ++it; + } + else + { + throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt); + } + + typedef typename point_type::type point_type; + std::vector points; + container_inserter::apply(it, end, wkt, std::back_inserter(points)); + + check_end(it, end, wkt); + + if (boost::size(points) == 2) + { + geometry::detail::assign_point_to_index<0>(points.front(), segment); + geometry::detail::assign_point_to_index<1>(points.back(), segment); + } + else + { + throw read_wkt_exception("Segment should have 2 points", wkt); + } + + } +}; + + + +}} // namespace detail::wkt +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct read_wkt {}; + + +template +struct read_wkt + : detail::wkt::geometry_parser + < + Point, + detail::wkt::point_parser, + detail::wkt::prefix_point + > +{}; + + +template +struct read_wkt + : detail::wkt::geometry_parser + < + L, + detail::wkt::linestring_parser, + detail::wkt::prefix_linestring + > +{}; + +template +struct read_wkt + : detail::wkt::geometry_parser + < + Ring, + detail::wkt::ring_parser, + detail::wkt::prefix_polygon + > +{}; + +template +struct read_wkt + : detail::wkt::geometry_parser + < + Geometry, + detail::wkt::polygon_parser, + detail::wkt::prefix_polygon + > +{}; + + +// Box (Non-OGC) +template +struct read_wkt + : detail::wkt::box_parser +{}; + +// Segment (Non-OGC) +template +struct read_wkt + : detail::wkt::segment_parser +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +/*! +\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry) +\ingroup wkt +\param wkt string containing \ref WKT +\param geometry output geometry +\par Example: +\note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz" +\note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())" +Small example showing how to use read_wkt to build a point +\dontinclude doxygen_1.cpp +\skip example_from_wkt_point +\line { +\until } +\par Example: +Small example showing how to use read_wkt to build a linestring +\dontinclude doxygen_1.cpp +\skip example_from_wkt_linestring +\line { +\until } +\par Example: +Small example showing how to use read_wkt to build a polygon +\dontinclude doxygen_1.cpp +\skip example_from_wkt_polygon +\line { +\until } +*/ +template +inline void read_wkt(std::string const& wkt, Geometry& geometry) +{ + geometry::concept::check(); + dispatch::read_wkt::type, Geometry>::apply(wkt, geometry); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_IO_WKT_READ_HPP diff --git a/include/boost/geometry/io/wkt/wkt.hpp b/include/boost/geometry/io/wkt/wkt.hpp new file mode 100644 index 0000000000..b231f4f8f7 --- /dev/null +++ b/include/boost/geometry/io/wkt/wkt.hpp @@ -0,0 +1,21 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_IO_WKT_WKT_HPP +#define BOOST_GEOMETRY_IO_WKT_WKT_HPP + +#include +#include +#include + +#endif // BOOST_GEOMETRY_IO_WKT_WKT_HPP diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp new file mode 100644 index 0000000000..5b59a78b19 --- /dev/null +++ b/include/boost/geometry/io/wkt/write.hpp @@ -0,0 +1,376 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_IO_WKT_WRITE_HPP +#define BOOST_GEOMETRY_IO_WKT_WRITE_HPP + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace wkt +{ + +template +struct stream_coordinate +{ + template + static inline void apply(std::basic_ostream& os, P const& p) + { + os << (I > 0 ? " " : "") << get(p); + stream_coordinate::apply(os, p); + } +}; + +template +struct stream_coordinate +{ + template + static inline void apply(std::basic_ostream&, P const&) + {} +}; + +struct prefix_linestring_par +{ + static inline const char* apply() { return "LINESTRING("; } +}; + +struct prefix_ring_par_par +{ + // Note, double parentheses are intentional, indicating WKT ring begin/end + static inline const char* apply() { return "POLYGON(("; } +}; + +struct opening_parenthesis +{ + static inline const char* apply() { return "("; } +}; + +struct closing_parenthesis +{ + static inline const char* apply() { return ")"; } +}; + +struct double_closing_parenthesis +{ + static inline const char* apply() { return "))"; } +}; + +/*! +\brief Stream points as \ref WKT +*/ +template +struct wkt_point +{ + template + static inline void apply(std::basic_ostream& os, Point const& p) + { + os << Policy::apply() << "("; + stream_coordinate::type::value>::apply(os, p); + os << ")"; + } +}; + +/*! +\brief Stream ranges as WKT +\note policy is used to stream prefix/postfix, enabling derived classes to override this +*/ +template +struct wkt_range +{ + template + static inline void apply(std::basic_ostream& os, + Range const& range) + { + typedef typename boost::range_iterator::type iterator_type; + + bool first = true; + + os << PrefixPolicy::apply(); + + // TODO: check EMPTY here + + for (iterator_type it = boost::begin(range); + it != boost::end(range); + ++it) + { + os << (first ? "" : ","); + stream_coordinate + < + point_type, 0, dimension::type::value + >::apply(os, *it); + first = false; + } + + os << SuffixPolicy::apply(); + } + +private: + typedef typename boost::range_value::type point_type; +}; + +/*! +\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4) +\note Used in polygon, all multi-geometries +*/ +template +struct wkt_sequence + : wkt_range + < + Range, + opening_parenthesis, + closing_parenthesis + > +{}; + +template +struct wkt_poly +{ + template + static inline void apply(std::basic_ostream& os, + Polygon const& poly) + { + typedef typename ring_type::type ring; + + os << PrefixPolicy::apply(); + // TODO: check EMPTY here + os << "("; + wkt_sequence::apply(os, exterior_ring(poly)); + + typename interior_return_type::type rings + = interior_rings(poly); + for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) + { + os << ","; + wkt_sequence::apply(os, *it); + } + os << ")"; + } +}; + +template +struct wkt_box +{ + typedef typename point_type::type point_type; + + template + static inline void apply(std::basic_ostream& os, + Box const& box) + { + // Convert to ring, then stream + typedef model::ring ring_type; + ring_type ring; + geometry::convert(box, ring); + os << "POLYGON("; + wkt_sequence::apply(os, ring); + os << ")"; + } + + private: + + inline wkt_box() + { + // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron! + //assert_dimension(); + } +}; + + +template +struct wkt_segment +{ + typedef typename point_type::type point_type; + + template + static inline void apply(std::basic_ostream& os, + Segment const& segment) + { + // Convert to two points, then stream + typedef boost::array sequence; + + sequence points; + geometry::detail::assign_point_from_index<0>(segment, points[0]); + geometry::detail::assign_point_from_index<1>(segment, points[1]); + + // In Boost.Geometry a segment is represented + // in WKT-format like (for 2D): LINESTRING(x y,x y) + os << "LINESTRING"; + wkt_sequence::apply(os, points); + } + + private: + + inline wkt_segment() + {} +}; + +}} // namespace detail::wkt +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct wkt +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (types) + ); +}; + +template +struct wkt + : detail::wkt::wkt_point + < + Point, + detail::wkt::prefix_point + > +{}; + +template +struct wkt + : detail::wkt::wkt_range + < + Linestring, + detail::wkt::prefix_linestring_par, + detail::wkt::closing_parenthesis + > +{}; + +/*! +\brief Specialization to stream a box as WKT +\details A "box" does not exist in WKT. +It is therefore streamed as a polygon +*/ +template +struct wkt + : detail::wkt::wkt_box +{}; + +template +struct wkt + : detail::wkt::wkt_segment +{}; + +/*! +\brief Specialization to stream a ring as WKT +\details A ring or "linear_ring" does not exist in WKT. +A ring is equivalent to a polygon without inner rings +It is therefore streamed as a polygon +*/ +template +struct wkt + : detail::wkt::wkt_range + < + Ring, + detail::wkt::prefix_ring_par_par, + detail::wkt::double_closing_parenthesis + > +{}; + +/*! +\brief Specialization to stream polygon as WKT +*/ +template +struct wkt + : detail::wkt::wkt_poly + < + Polygon, + detail::wkt::prefix_polygon + > +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +/*! +\brief Generic geometry template manipulator class, takes corresponding output class from traits class +\ingroup wkt +\details Stream manipulator, streams geometry classes as \ref WKT streams +\par Example: +Small example showing how to use the wkt class +\dontinclude doxygen_1.cpp +\skip example_as_wkt_point +\line { +\until } +*/ +template +class wkt_manipulator +{ +public: + + inline wkt_manipulator(Geometry const& g) + : m_geometry(g) + {} + + template + inline friend std::basic_ostream& operator<<( + std::basic_ostream& os, + wkt_manipulator const& m) + { + dispatch::wkt + < + typename tag::type, + Geometry + >::apply(os, m.m_geometry); + os.flush(); + return os; + } + +private: + Geometry const& m_geometry; +}; + +/*! +\brief Main WKT-streaming function +\ingroup wkt +\par Example: +Small example showing how to use the wkt helper function +\dontinclude doxygen_1.cpp +\skip example_as_wkt_vector +\line { +\until } +*/ +template +inline wkt_manipulator wkt(Geometry const& geometry) +{ + concept::check(); + + return wkt_manipulator(geometry); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_IO_WKT_WRITE_HPP diff --git a/include/boost/geometry/multi/algorithms/area.hpp b/include/boost/geometry/multi/algorithms/area.hpp index c0f6870f9d..8a0f66e7ca 100644 --- a/include/boost/geometry/multi/algorithms/area.hpp +++ b/include/boost/geometry/multi/algorithms/area.hpp @@ -30,7 +30,7 @@ namespace boost { namespace geometry namespace dispatch { template -struct area +struct area : detail::multi_sum < typename Strategy::return_type, @@ -38,9 +38,9 @@ struct area Strategy, area < - polygon_tag, typename boost::range_value::type, - Strategy + Strategy, + polygon_tag > > {}; diff --git a/include/boost/geometry/multi/algorithms/convert.hpp b/include/boost/geometry/multi/algorithms/convert.hpp index 9d27badec5..ebd58dedd4 100644 --- a/include/boost/geometry/multi/algorithms/convert.hpp +++ b/include/boost/geometry/multi/algorithms/convert.hpp @@ -73,19 +73,16 @@ namespace dispatch // Note that, even if the multi-types are mutually different, their single // version types might be the same and therefore we call boost::is_same again -template -struct convert +template +struct convert : detail::conversion::multi_to_multi < Multi1, Multi2, convert < - boost::is_same - < - typename boost::range_value::type, - typename boost::range_value::type - >::value, + typename boost::range_value::type, + typename boost::range_value::type, typename single_tag_of < typename tag::type @@ -94,30 +91,28 @@ struct convert < typename tag::type >::type, - DimensionCount, - typename boost::range_value::type, - typename boost::range_value::type + DimensionCount > > {}; -template -struct convert +template +struct convert : detail::conversion::single_to_multi < Single, Multi, convert < - false, + Single, + typename boost::range_value::type, typename tag::type, typename single_tag_of < typename tag::type >::type, DimensionCount, - Single, - typename boost::range_value::type + false > > {}; diff --git a/include/boost/geometry/multi/algorithms/distance.hpp b/include/boost/geometry/multi/algorithms/distance.hpp index e59ab63ce8..95660b9696 100644 --- a/include/boost/geometry/multi/algorithms/distance.hpp +++ b/include/boost/geometry/multi/algorithms/distance.hpp @@ -105,17 +105,27 @@ namespace dispatch template < - typename SingleGeometryTag, typename G1, typename G2, - typename Strategy + typename Strategy, + typename SingleGeometryTag +> +struct distance +< + G1, G2, Strategy, + SingleGeometryTag, multi_tag, strategy_tag_distance_point_point, + false > -struct distance : detail::distance::distance_single_to_multi {}; template -struct distance +struct distance +< + G1, G2, Strategy, + multi_tag, multi_tag, strategy_tag_distance_point_point, + false +> : detail::distance::distance_multi_to_multi {}; diff --git a/include/boost/geometry/multi/algorithms/intersection.hpp b/include/boost/geometry/multi/algorithms/intersection.hpp index 870a1b2ab4..15cb053713 100644 --- a/include/boost/geometry/multi/algorithms/intersection.hpp +++ b/include/boost/geometry/multi/algorithms/intersection.hpp @@ -109,6 +109,69 @@ struct intersection_linestring_multi_linestring_point }; +// This loop is quite similar to the loop above, but beacuse the iterator +// is second (above) or first (below) argument, it is not trivial to merge them. +template +< + typename MultiLinestring, typename Areal, + bool ReverseAreal, + typename OutputIterator, typename LineStringOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_of_multi_linestring_with_areal +{ + static inline OutputIterator apply(MultiLinestring const& ml, Areal const& areal, + OutputIterator out, + Strategy const& strategy) + { + for (typename boost::range_iterator + < + MultiLinestring const + >::type it = boost::begin(ml); + it != boost::end(ml); + ++it) + { + out = intersection_of_linestring_with_areal + < + typename boost::range_value::type, + Areal, ReverseAreal, + OutputIterator, LineStringOut, OverlayType, Strategy + >::apply(*it, areal, out, strategy); + } + + return out; + + } +}; + +// This one calls the one above with reversed arguments +template +< + typename Areal, typename MultiLinestring, + bool ReverseAreal, + typename OutputIterator, typename LineStringOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_of_areal_with_multi_linestring +{ + static inline OutputIterator apply(Areal const& areal, MultiLinestring const& ml, + OutputIterator out, + Strategy const& strategy) + { + return intersection_of_multi_linestring_with_areal + < + MultiLinestring, Areal, ReverseAreal, + OutputIterator, LineStringOut, + OverlayType, + Strategy + >::apply(ml, areal, out, strategy); + } +}; + + + template < typename MultiLinestring, typename Box, @@ -222,6 +285,148 @@ struct intersection_insert {}; +template +< + typename Linestring, typename MultiPolygon, + bool ReverseLinestring, bool ReverseMultiPolygon, bool ReverseOut, + typename OutputIterator, typename GeometryOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + linestring_tag, multi_polygon_tag, linestring_tag, + false, true, false, + Linestring, MultiPolygon, + ReverseLinestring, ReverseMultiPolygon, ReverseOut, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > : detail::intersection::intersection_of_linestring_with_areal + < + Linestring, MultiPolygon, + ReverseMultiPolygon, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > +{}; + + +// Derives from areal/mls because runtime arguments are in that order. +// areal/mls reverses it itself to mls/areal +template +< + typename Polygon, typename MultiLinestring, + bool ReversePolygon, bool ReverseMultiLinestring, bool ReverseOut, + typename OutputIterator, typename GeometryOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + polygon_tag, multi_linestring_tag, linestring_tag, + true, false, false, + Polygon, MultiLinestring, + ReversePolygon, ReverseMultiLinestring, ReverseOut, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > : detail::intersection::intersection_of_areal_with_multi_linestring + < + Polygon, MultiLinestring, + ReversePolygon, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > +{}; + + +template +< + typename MultiLinestring, typename Ring, + bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut, + typename OutputIterator, typename GeometryOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + multi_linestring_tag, ring_tag, linestring_tag, + false, true, false, + MultiLinestring, Ring, + ReverseMultiLinestring, ReverseRing, ReverseOut, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > : detail::intersection::intersection_of_multi_linestring_with_areal + < + MultiLinestring, Ring, + ReverseRing, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > +{}; + +template +< + typename MultiLinestring, typename Polygon, + bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut, + typename OutputIterator, typename GeometryOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + multi_linestring_tag, polygon_tag, linestring_tag, + false, true, false, + MultiLinestring, Polygon, + ReverseMultiLinestring, ReverseRing, ReverseOut, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > : detail::intersection::intersection_of_multi_linestring_with_areal + < + MultiLinestring, Polygon, + ReverseRing, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > +{}; + + + +template +< + typename MultiLinestring, typename MultiPolygon, + bool ReverseMultiLinestring, bool ReverseMultiPolygon, bool ReverseOut, + typename OutputIterator, typename GeometryOut, + overlay_type OverlayType, + typename Strategy +> +struct intersection_insert + < + multi_linestring_tag, multi_polygon_tag, linestring_tag, + false, true, false, + MultiLinestring, MultiPolygon, + ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > : detail::intersection::intersection_of_multi_linestring_with_areal + < + MultiLinestring, MultiPolygon, + ReverseMultiPolygon, + OutputIterator, GeometryOut, + OverlayType, + Strategy + > +{}; + + } // namespace dispatch #endif diff --git a/include/boost/geometry/multi/io/wkt/detail/prefix.hpp b/include/boost/geometry/multi/io/wkt/detail/prefix.hpp new file mode 100644 index 0000000000..f9be7f71e4 --- /dev/null +++ b/include/boost/geometry/multi/io/wkt/detail/prefix.hpp @@ -0,0 +1,51 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_MULTI_IO_WKT_DETAIL_PREFIX_HPP +#define BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace wkt +{ + +struct prefix_null +{ + static inline const char* apply() { return ""; } +}; + +struct prefix_multipoint +{ + static inline const char* apply() { return "MULTIPOINT"; } +}; + +struct prefix_multilinestring +{ + static inline const char* apply() { return "MULTILINESTRING"; } +}; + +struct prefix_multipolygon +{ + static inline const char* apply() { return "MULTIPOLYGON"; } +}; + +}} // namespace wkt::impl +#endif + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP diff --git a/include/boost/geometry/multi/io/wkt/read.hpp b/include/boost/geometry/multi/io/wkt/read.hpp new file mode 100644 index 0000000000..eba0f803df --- /dev/null +++ b/include/boost/geometry/multi/io/wkt/read.hpp @@ -0,0 +1,105 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_MULTI_IO_WKT_READ_MULTI_HPP +#define BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP + +#include + +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace detail { namespace wkt +{ + +template class Parser, typename PrefixPolicy> +struct multi_parser +{ + static inline void apply(std::string const& wkt, MultiGeometry& geometry) + { + traits::clear::apply(geometry); + + tokenizer tokens(wkt, boost::char_separator(" ", ",()")); + tokenizer::iterator it; + if (initialize(tokens, PrefixPolicy::apply(), wkt, it)) + { + handle_open_parenthesis(it, tokens.end(), wkt); + + // Parse sub-geometries + while(it != tokens.end() && *it != ")") + { + traits::resize::apply(geometry, boost::size(geometry) + 1); + Parser + < + typename boost::range_value::type + >::apply(it, tokens.end(), wkt, geometry.back()); + if (it != tokens.end() && *it == ",") + { + // Skip "," after multi-element is parsed + ++it; + } + } + + handle_close_parenthesis(it, tokens.end(), wkt); + } + } +}; + +}} // namespace detail::wkt + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct read_wkt + : detail::wkt::multi_parser + < + MultiGeometry, + detail::wkt::point_parser, + detail::wkt::prefix_multipoint + > +{}; + +template +struct read_wkt + : detail::wkt::multi_parser + < + MultiGeometry, + detail::wkt::linestring_parser, + detail::wkt::prefix_multilinestring + > +{}; + +template +struct read_wkt + : detail::wkt::multi_parser + < + MultiGeometry, + detail::wkt::polygon_parser, + detail::wkt::prefix_multipolygon + > +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP diff --git a/include/boost/geometry/multi/io/wkt/wkt.hpp b/include/boost/geometry/multi/io/wkt/wkt.hpp new file mode 100644 index 0000000000..d948b7f252 --- /dev/null +++ b/include/boost/geometry/multi/io/wkt/wkt.hpp @@ -0,0 +1,20 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_MULTI_IO_WKT_WKT_HPP +#define BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP + +#include +#include + +#endif // BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP diff --git a/include/boost/geometry/multi/io/wkt/write.hpp b/include/boost/geometry/multi/io/wkt/write.hpp new file mode 100644 index 0000000000..91030b3a2b --- /dev/null +++ b/include/boost/geometry/multi/io/wkt/write.hpp @@ -0,0 +1,108 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_MULTI_IO_WKT_WRITE_HPP +#define BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace wkt +{ + +template +struct wkt_multi +{ + template + static inline void apply(std::basic_ostream& os, + Multi const& geometry) + { + os << PrefixPolicy::apply(); + // TODO: check EMPTY here + os << "("; + + for (typename boost::range_iterator::type + it = boost::begin(geometry); + it != boost::end(geometry); + ++it) + { + if (it != boost::begin(geometry)) + { + os << ","; + } + StreamPolicy::apply(os, *it); + } + + os << ")"; + } +}; + +}} // namespace wkt::impl +#endif + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct wkt + : detail::wkt::wkt_multi + < + Multi, + detail::wkt::wkt_point + < + typename boost::range_value::type, + detail::wkt::prefix_null + >, + detail::wkt::prefix_multipoint + > +{}; + +template +struct wkt + : detail::wkt::wkt_multi + < + Multi, + detail::wkt::wkt_sequence + < + typename boost::range_value::type + >, + detail::wkt::prefix_multilinestring + > +{}; + +template +struct wkt + : detail::wkt::wkt_multi + < + Multi, + detail::wkt::wkt_poly + < + typename boost::range_value::type, + detail::wkt::prefix_null + >, + detail::wkt::prefix_multipolygon + > +{}; + +} // namespace dispatch +#endif + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP diff --git a/include/boost/geometry/multi/util/write_dsv.hpp b/include/boost/geometry/multi/util/write_dsv.hpp index 31c96116bd..4989620cd1 100644 --- a/include/boost/geometry/multi/util/write_dsv.hpp +++ b/include/boost/geometry/multi/util/write_dsv.hpp @@ -16,7 +16,7 @@ #include -#include +#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp index 4ce74e946f..b5fc78dcd0 100644 --- a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp +++ b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp @@ -27,7 +27,7 @@ //#define GL_DEBUG_DOUGLAS_PEUCKER #ifdef GL_DEBUG_DOUGLAS_PEUCKER -#include +#include #endif diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp index f902591bfa..623aa4cfc4 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -26,7 +26,7 @@ #include #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK -# include +# include #endif diff --git a/include/boost/geometry/util/write_dsv.hpp b/include/boost/geometry/util/write_dsv.hpp deleted file mode 100644 index 3fef63e778..0000000000 --- a/include/boost/geometry/util/write_dsv.hpp +++ /dev/null @@ -1,396 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_UTIL_WRITE_DSV_HPP -#define BOOST_GEOMETRY_UTIL_WRITE_DSV_HPP - - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace dsv -{ - - -struct dsv_settings -{ - std::string coordinate_separator; - std::string point_open; - std::string point_close; - std::string point_separator; - std::string list_open; - std::string list_close; - std::string list_separator; - - dsv_settings(std::string const& sep - , std::string const& open - , std::string const& close - , std::string const& psep - , std::string const& lopen - , std::string const& lclose - , std::string const& lsep - ) - : coordinate_separator(sep) - , point_open(open) - , point_close(close) - , point_separator(psep) - , list_open(lopen) - , list_close(lclose) - , list_separator(lsep) - {} -}; - -/*! -\brief Stream coordinate of a point as \ref DSV -*/ -template -struct stream_coordinate -{ - template - static inline void apply(std::basic_ostream& os, - Point const& point, - dsv_settings const& settings) - { - os << (Dimension > 0 ? settings.coordinate_separator : "") - << get(point); - - stream_coordinate - < - Point, Dimension + 1, Count - >::apply(os, point, settings); - } -}; - -template -struct stream_coordinate -{ - template - static inline void apply(std::basic_ostream&, - Point const&, - dsv_settings const& ) - { - } -}; - - -/*! -\brief Stream indexed coordinate of a box/segment as \ref DSV -*/ -template -< - typename Geometry, - std::size_t Index, - std::size_t Dimension, - std::size_t Count -> -struct stream_indexed -{ - template - static inline void apply(std::basic_ostream& os, - Geometry const& geometry, - dsv_settings const& settings) - { - os << (Dimension > 0 ? settings.coordinate_separator : "") - << get(geometry); - stream_indexed - < - Geometry, Index, Dimension + 1, Count - >::apply(os, geometry, settings); - } -}; - -template -struct stream_indexed -{ - template - static inline void apply(std::basic_ostream&, Geometry const&, - dsv_settings const& ) - { - } -}; - - - -/*! -\brief Stream points as \ref DSV -*/ -template -struct dsv_point -{ - template - static inline void apply(std::basic_ostream& os, - Point const& p, - dsv_settings const& settings) - { - os << settings.point_open; - stream_coordinate::type::value>::apply(os, p, settings); - os << settings.point_close; - } -}; - -/*! -\brief Stream ranges as DSV -\note policy is used to stream prefix/postfix, enabling derived classes to override this -*/ -template -struct dsv_range -{ - template - static inline void apply(std::basic_ostream& os, - Range const& range, - dsv_settings const& settings) - { - typedef typename boost::range_iterator::type iterator_type; - - bool first = true; - - os << settings.list_open; - - for (iterator_type it = boost::begin(range); - it != boost::end(range); - ++it) - { - os << (first ? "" : settings.point_separator) - << settings.point_open; - - stream_coordinate - < - point_type, 0, dimension::type::value - >::apply(os, *it, settings); - os << settings.point_close; - - first = false; - } - - os << settings.list_close; - } - -private: - typedef typename boost::range_value::type point_type; -}; - -/*! -\brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4) -\note Used in polygon, all multi-geometries -*/ - - -template -struct dsv_poly -{ - template - static inline void apply(std::basic_ostream& os, - Polygon const& poly, - dsv_settings const& settings) - { - typedef typename ring_type::type ring; - - os << settings.list_open; - - dsv_range::apply(os, exterior_ring(poly), settings); - - typename interior_return_type::type rings - = interior_rings(poly); - for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) - { - os << settings.list_separator; - dsv_range::apply(os, *it, settings); - } - os << settings.list_close; - } -}; - -template -struct dsv_per_index -{ - typedef typename point_type::type point_type; - - template - static inline void apply(std::basic_ostream& os, - Geometry const& geometry, - dsv_settings const& settings) - { - os << settings.point_open; - stream_indexed - < - Geometry, Index, 0, dimension::type::value - >::apply(os, geometry, settings); - os << settings.point_close; - } -}; - - -template -struct dsv_indexed -{ - typedef typename point_type::type point_type; - - template - static inline void apply(std::basic_ostream& os, - Geometry const& geometry, - dsv_settings const& settings) - { - os << settings.list_open; - dsv_per_index::apply(os, geometry, settings); - os << settings.point_separator; - dsv_per_index::apply(os, geometry, settings); - os << settings.list_close; - } -}; - -}} // namespace detail::dsv -#endif // DOXYGEN_NO_DETAIL - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -struct dsv {}; - - -template -struct dsv - : detail::dsv::dsv_point -{}; - - -template -struct dsv - : detail::dsv::dsv_range -{}; - - -template -struct dsv - : detail::dsv::dsv_indexed -{}; - -template -struct dsv - : detail::dsv::dsv_indexed -{}; - - -template -struct dsv - : detail::dsv::dsv_range -{}; - - -template -struct dsv - : detail::dsv::dsv_poly -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace dsv -{ - - -// FIXME: This class is not copyable/assignable but it is used as such --mloskot -template -class dsv_manipulator -{ -public: - - inline dsv_manipulator(Geometry const& g, - dsv_settings const& settings) - : m_geometry(g) - , m_settings(settings) - {} - - template - inline friend std::basic_ostream& operator<<( - std::basic_ostream& os, - dsv_manipulator const& m) - { - dispatch::dsv - < - typename tag_cast - < - typename tag::type, - multi_tag - >::type, - Geometry - >::apply(os, m.m_geometry, m.m_settings); - os.flush(); - return os; - } - -private: - Geometry const& m_geometry; - dsv_settings m_settings; -}; - - -}} // namespace detail::dsv -#endif // DOXYGEN_NO_DETAIL - - -/*! -\brief Main DSV-streaming function -\details DSV stands for Delimiter Separated Values. Geometries can be streamed - as DSV. There are defaults for all separators. -\note Useful for examples and testing purposes -\note With this function GeoJSON objects can be created, using the right - delimiters -\ingroup utility -*/ -template -inline detail::dsv::dsv_manipulator dsv(Geometry const& geometry - , std::string const& coordinate_separator = ", " - , std::string const& point_open = "(" - , std::string const& point_close = ")" - , std::string const& point_separator = ", " - , std::string const& list_open = "(" - , std::string const& list_close = ")" - , std::string const& list_separator = ", " - ) -{ - concept::check(); - - return detail::dsv::dsv_manipulator(geometry, - detail::dsv::dsv_settings(coordinate_separator, - point_open, point_close, point_separator, - list_open, list_close, list_separator)); -} - - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_UTIL_WRITE_DSV_HPP From 145efff55364e3309ea8e39c97a5eea2c1a75f95 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 7 Jan 2012 18:02:59 +0000 Subject: [PATCH 030/135] Merged - added missing io/dsv/write.hpp file [SVN r76343] --- include/boost/geometry/io/dsv/write.hpp | 375 ++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 include/boost/geometry/io/dsv/write.hpp diff --git a/include/boost/geometry/io/dsv/write.hpp b/include/boost/geometry/io/dsv/write.hpp new file mode 100644 index 0000000000..0df047b05a --- /dev/null +++ b/include/boost/geometry/io/dsv/write.hpp @@ -0,0 +1,375 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_IO_DSV_WRITE_HPP +#define BOOST_GEOMETRY_IO_DSV_WRITE_HPP + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace dsv +{ + +struct dsv_settings +{ + std::string coordinate_separator; + std::string point_open; + std::string point_close; + std::string point_separator; + std::string list_open; + std::string list_close; + std::string list_separator; + + dsv_settings(std::string const& sep + , std::string const& open + , std::string const& close + , std::string const& psep + , std::string const& lopen + , std::string const& lclose + , std::string const& lsep + ) + : coordinate_separator(sep) + , point_open(open) + , point_close(close) + , point_separator(psep) + , list_open(lopen) + , list_close(lclose) + , list_separator(lsep) + {} +}; + +/*! +\brief Stream coordinate of a point as \ref DSV +*/ +template +struct stream_coordinate +{ + template + static inline void apply(std::basic_ostream& os, + Point const& point, + dsv_settings const& settings) + { + os << (Dimension > 0 ? settings.coordinate_separator : "") + << get(point); + + stream_coordinate + < + Point, Dimension + 1, Count + >::apply(os, point, settings); + } +}; + +template +struct stream_coordinate +{ + template + static inline void apply(std::basic_ostream&, + Point const&, + dsv_settings const& ) + { + } +}; + +/*! +\brief Stream indexed coordinate of a box/segment as \ref DSV +*/ +template +< + typename Geometry, + std::size_t Index, + std::size_t Dimension, + std::size_t Count +> +struct stream_indexed +{ + template + static inline void apply(std::basic_ostream& os, + Geometry const& geometry, + dsv_settings const& settings) + { + os << (Dimension > 0 ? settings.coordinate_separator : "") + << get(geometry); + stream_indexed + < + Geometry, Index, Dimension + 1, Count + >::apply(os, geometry, settings); + } +}; + +template +struct stream_indexed +{ + template + static inline void apply(std::basic_ostream&, Geometry const&, + dsv_settings const& ) + { + } +}; + +/*! +\brief Stream points as \ref DSV +*/ +template +struct dsv_point +{ + template + static inline void apply(std::basic_ostream& os, + Point const& p, + dsv_settings const& settings) + { + os << settings.point_open; + stream_coordinate::type::value>::apply(os, p, settings); + os << settings.point_close; + } +}; + +/*! +\brief Stream ranges as DSV +\note policy is used to stream prefix/postfix, enabling derived classes to override this +*/ +template +struct dsv_range +{ + template + static inline void apply(std::basic_ostream& os, + Range const& range, + dsv_settings const& settings) + { + typedef typename boost::range_iterator::type iterator_type; + + bool first = true; + + os << settings.list_open; + + for (iterator_type it = boost::begin(range); + it != boost::end(range); + ++it) + { + os << (first ? "" : settings.point_separator) + << settings.point_open; + + stream_coordinate + < + point_type, 0, dimension::type::value + >::apply(os, *it, settings); + os << settings.point_close; + + first = false; + } + + os << settings.list_close; + } + +private: + typedef typename boost::range_value::type point_type; +}; + +/*! +\brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4) +\note Used in polygon, all multi-geometries +*/ + +template +struct dsv_poly +{ + template + static inline void apply(std::basic_ostream& os, + Polygon const& poly, + dsv_settings const& settings) + { + typedef typename ring_type::type ring; + + os << settings.list_open; + + dsv_range::apply(os, exterior_ring(poly), settings); + + typename interior_return_type::type rings + = interior_rings(poly); + for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) + { + os << settings.list_separator; + dsv_range::apply(os, *it, settings); + } + os << settings.list_close; + } +}; + +template +struct dsv_per_index +{ + typedef typename point_type::type point_type; + + template + static inline void apply(std::basic_ostream& os, + Geometry const& geometry, + dsv_settings const& settings) + { + os << settings.point_open; + stream_indexed + < + Geometry, Index, 0, dimension::type::value + >::apply(os, geometry, settings); + os << settings.point_close; + } +}; + +template +struct dsv_indexed +{ + typedef typename point_type::type point_type; + + template + static inline void apply(std::basic_ostream& os, + Geometry const& geometry, + dsv_settings const& settings) + { + os << settings.list_open; + dsv_per_index::apply(os, geometry, settings); + os << settings.point_separator; + dsv_per_index::apply(os, geometry, settings); + os << settings.list_close; + } +}; + +}} // namespace detail::dsv +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct dsv {}; + +template +struct dsv + : detail::dsv::dsv_point +{}; + +template +struct dsv + : detail::dsv::dsv_range +{}; + +template +struct dsv + : detail::dsv::dsv_indexed +{}; + +template +struct dsv + : detail::dsv::dsv_indexed +{}; + +template +struct dsv + : detail::dsv::dsv_range +{}; + +template +struct dsv + : detail::dsv::dsv_poly +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace dsv +{ + +// FIXME: This class is not copyable/assignable but it is used as such --mloskot +template +class dsv_manipulator +{ +public: + + inline dsv_manipulator(Geometry const& g, + dsv_settings const& settings) + : m_geometry(g) + , m_settings(settings) + {} + + template + inline friend std::basic_ostream& operator<<( + std::basic_ostream& os, + dsv_manipulator const& m) + { + dispatch::dsv + < + typename tag_cast + < + typename tag::type, + multi_tag + >::type, + Geometry + >::apply(os, m.m_geometry, m.m_settings); + os.flush(); + return os; + } + +private: + Geometry const& m_geometry; + dsv_settings m_settings; +}; + +}} // namespace detail::dsv +#endif // DOXYGEN_NO_DETAIL + +/*! +\brief Main DSV-streaming function +\details DSV stands for Delimiter Separated Values. Geometries can be streamed + as DSV. There are defaults for all separators. +\note Useful for examples and testing purposes +\note With this function GeoJSON objects can be created, using the right + delimiters +\ingroup utility +*/ +template +inline detail::dsv::dsv_manipulator dsv(Geometry const& geometry + , std::string const& coordinate_separator = ", " + , std::string const& point_open = "(" + , std::string const& point_close = ")" + , std::string const& point_separator = ", " + , std::string const& list_open = "(" + , std::string const& list_close = ")" + , std::string const& list_separator = ", " + ) +{ + concept::check(); + + return detail::dsv::dsv_manipulator(geometry, + detail::dsv::dsv_settings(coordinate_separator, + point_open, point_close, point_separator, + list_open, list_close, list_separator)); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP From 66affa3646bd66f66e267edcc5786303ec67e95a Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 7 Jan 2012 18:05:53 +0000 Subject: [PATCH 031/135] Merged - added missing io/io.hpp [SVN r76344] --- include/boost/geometry/io/io.hpp | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 include/boost/geometry/io/io.hpp diff --git a/include/boost/geometry/io/io.hpp b/include/boost/geometry/io/io.hpp new file mode 100644 index 0000000000..947ca022c6 --- /dev/null +++ b/include/boost/geometry/io/io.hpp @@ -0,0 +1,58 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_IO_HPP +#define BOOST_GEOMETRY_IO_HPP + +#include +#include + +namespace boost { namespace geometry +{ + +struct format_wkt {}; +struct format_wkb {}; // TODO +struct format_dsv {}; // TODO + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ +template +struct read +{ +}; + +template +struct read +{ + static inline void apply(Geometry& geometry, std::string const& wkt) + { + read_wkt::type, Geometry>::apply(wkt, geometry); + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +template +inline void read(Geometry& geometry, std::string const& wkt) +{ + geometry::concept::check(); + dispatch::read::apply(geometry, wkt); +} + +// TODO: wriite + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_IO_HPP From 745744df374beaeb0fb4e63d59bbc11e94c96cc7 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 8 Jan 2012 00:33:36 +0000 Subject: [PATCH 032/135] Merge - after merge edits for Geometry [SVN r76354] --- include/boost/geometry/domains/gis/io/io.hpp | 65 -- .../domains/gis/io/wkt/detail/wkt.hpp | 49 -- .../domains/gis/io/wkt/detail/wkt_multi.hpp | 56 -- .../geometry/domains/gis/io/wkt/read.hpp | 692 ------------------ .../domains/gis/io/wkt/read_multi.hpp | 112 --- .../geometry/domains/gis/io/wkt/write.hpp | 394 ---------- .../domains/gis/io/wkt/write_multi.hpp | 115 --- .../geometries/multi_geometries.hpp} | 14 +- 8 files changed, 6 insertions(+), 1491 deletions(-) delete mode 100644 include/boost/geometry/domains/gis/io/io.hpp delete mode 100644 include/boost/geometry/domains/gis/io/wkt/detail/wkt.hpp delete mode 100644 include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp delete mode 100644 include/boost/geometry/domains/gis/io/wkt/read.hpp delete mode 100644 include/boost/geometry/domains/gis/io/wkt/read_multi.hpp delete mode 100644 include/boost/geometry/domains/gis/io/wkt/write.hpp delete mode 100644 include/boost/geometry/domains/gis/io/wkt/write_multi.hpp rename include/boost/geometry/{domains/gis/io/wkt/wkt.hpp => multi/geometries/multi_geometries.hpp} (60%) diff --git a/include/boost/geometry/domains/gis/io/io.hpp b/include/boost/geometry/domains/gis/io/io.hpp deleted file mode 100644 index d1c06234cf..0000000000 --- a/include/boost/geometry/domains/gis/io/io.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_HPP - - -#include -#include - -#include -#include - -namespace boost { namespace geometry -{ - -struct format_wkt {}; -struct format_wkb {}; -struct format_dsv {}; - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -struct read -{ -}; - -template -struct read -{ - static inline void apply(Geometry& geometry, std::string const& wkt) - { - read_wkt::type, Geometry>::apply(wkt, geometry); - } -}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - - -template -inline void read(Geometry& geometry, std::string const& wkt) -{ - geometry::concept::check(); - dispatch::read::apply(geometry, wkt); -} - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/detail/wkt.hpp b/include/boost/geometry/domains/gis/io/wkt/detail/wkt.hpp deleted file mode 100644 index 576a1688fb..0000000000 --- a/include/boost/geometry/domains/gis/io/wkt/detail/wkt.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_WKT_DETAIL_WKT_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_HPP - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace wkt { - - -struct prefix_point -{ - static inline const char* apply() { return "POINT"; } -}; - -struct prefix_polygon -{ - static inline const char* apply() { return "POLYGON"; } -}; - -struct prefix_linestring -{ - static inline const char* apply() { return "LINESTRING"; } -}; - - - -}} // namespace wkt::impl -#endif - - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp b/include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp deleted file mode 100644 index 4cf7bc00a0..0000000000 --- a/include/boost/geometry/domains/gis/io/wkt/detail/wkt_multi.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP - - -#include -#include - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace wkt { - -struct prefix_null -{ - static inline const char* apply() { return ""; } -}; - -struct prefix_multipoint -{ - static inline const char* apply() { return "MULTIPOINT"; } -}; - -struct prefix_multilinestring -{ - static inline const char* apply() { return "MULTILINESTRING"; } -}; - -struct prefix_multipolygon -{ - static inline const char* apply() { return "MULTIPOLYGON"; } -}; - - - -}} // namespace wkt::impl -#endif - - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/read.hpp b/include/boost/geometry/domains/gis/io/wkt/read.hpp deleted file mode 100644 index 6ae5f3b875..0000000000 --- a/include/boost/geometry/domains/gis/io/wkt/read.hpp +++ /dev/null @@ -1,692 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_WKT_READ_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_HPP - -#include - -#include -#include - -#include -#include -#include - - -#include - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -namespace boost { namespace geometry -{ - - - -/*! -\brief Exception showing things wrong with WKT parsing -\ingroup wkt -*/ -struct read_wkt_exception : public geometry::exception -{ - template - read_wkt_exception(std::string const& msg, - Iterator const& it, Iterator const& end, std::string const& wkt) - : message(msg) - , wkt(wkt) - { - if (it != end) - { - source = " at '"; - source += it->c_str(); - source += "'"; - } - complete = message + source + " in '" + wkt.substr(0, 100) + "'"; - } - - read_wkt_exception(std::string const& msg, std::string const& wkt) - : message(msg) - , wkt(wkt) - { - complete = message + "' in (" + wkt.substr(0, 100) + ")"; - } - - virtual ~read_wkt_exception() throw() {} - - virtual const char* what() const throw() - { - return complete.c_str(); - } -private : - std::string source; - std::string message; - std::string wkt; - std::string complete; -}; - - - -#ifndef DOXYGEN_NO_DETAIL -// (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostGIS)) -namespace detail { namespace wkt { - -typedef boost::tokenizer > tokenizer; - -template -struct parsing_assigner -{ - static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, - Point& point, std::string const& wkt) - { - typedef typename coordinate_type::type coordinate_type; - - // Stop at end of tokens, or at "," ot ")" - bool finished = (it == end || *it == "," || *it == ")"); - - try - { - // Initialize missing coordinates to default constructor (zero) - // OR - // Use lexical_cast for conversion to double/int - // Note that it is much slower than atof. However, it is more standard - // and in parsing the change in performance falls probably away against - // the tokenizing - set(point, finished - ? coordinate_type() - : coordinate_cast::apply(*it)); - } - catch(boost::bad_lexical_cast const& blc) - { - throw read_wkt_exception(blc.what(), it, end, wkt); - } - catch(std::exception const& e) - { - throw read_wkt_exception(e.what(), it, end, wkt); - } - catch(...) - { - throw read_wkt_exception("", it, end, wkt); - } - - parsing_assigner::apply( - (finished ? it : ++it), end, point, wkt); - } -}; - -template -struct parsing_assigner -{ - static inline void apply(tokenizer::iterator&, tokenizer::iterator, Point&, - std::string const&) - { - } -}; - - - -template -inline void handle_open_parenthesis(Iterator& it, - Iterator const& end, std::string const& wkt) -{ - if (it == end || *it != "(") - { - throw read_wkt_exception("Expected '('", it, end, wkt); - } - ++it; -} - - -template -inline void handle_close_parenthesis(Iterator& it, - Iterator const& end, std::string const& wkt) -{ - if (it != end && *it == ")") - { - ++it; - } - else - { - throw read_wkt_exception("Expected ')'", it, end, wkt); - } -} - -template -inline void check_end(Iterator& it, - Iterator const& end, std::string const& wkt) -{ - if (it != end) - { - throw read_wkt_exception("Too much tokens", it, end, wkt); - } -} - -/*! -\brief Internal, parses coordinate sequences, strings are formated like "(1 2,3 4,...)" -\param it token-iterator, should be pre-positioned at "(", is post-positions after last ")" -\param end end-token-iterator -\param out Output itererator receiving coordinates -*/ -template -struct container_inserter -{ - // Version with output iterator - template - static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, - std::string const& wkt, OutputIterator out) - { - handle_open_parenthesis(it, end, wkt); - - Point point; - - // Parse points until closing parenthesis - - while (it != end && *it != ")") - { - parsing_assigner - < - Point, - 0, - dimension::value - >::apply(it, end, point, wkt); - out = point; - ++out; - if (it != end && *it == ",") - { - ++it; - } - } - - handle_close_parenthesis(it, end, wkt); - } -}; - - -// Geometry is a value-type or reference-type -template -struct container_appender -{ - typedef typename geometry::point_type - < - typename boost::remove_reference::type - >::type point_type; - - static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, - std::string const& wkt, Geometry out) - { - handle_open_parenthesis(it, end, wkt); - - point_type point; - - // Parse points until closing parenthesis - - while (it != end && *it != ")") - { - parsing_assigner - < - point_type, - 0, - dimension::value - >::apply(it, end, point, wkt); - - geometry::append(out, point); - if (it != end && *it == ",") - { - ++it; - } - } - - handle_close_parenthesis(it, end, wkt); - } -}; - -/*! -\brief Internal, parses a point from a string like this "(x y)" -\note used for parsing points and multi-points -*/ -template -struct point_parser -{ - static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, - std::string const& wkt, P& point) - { - handle_open_parenthesis(it, end, wkt); - parsing_assigner::value>::apply(it, end, point, wkt); - handle_close_parenthesis(it, end, wkt); - } -}; - - -template -struct linestring_parser -{ - static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, - std::string const& wkt, Geometry& geometry) - { - container_appender::apply(it, end, wkt, geometry); - } -}; - - -template -struct ring_parser -{ - static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, - std::string const& wkt, Ring& ring) - { - // A ring should look like polygon((x y,x y,x y...)) - // So handle the extra opening/closing parentheses - // and in between parse using the container-inserter - handle_open_parenthesis(it, end, wkt); - container_appender::apply(it, end, wkt, ring); - handle_close_parenthesis(it, end, wkt); - } -}; - - - - -/*! -\brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))" -\note used for parsing polygons and multi-polygons -*/ -template -struct polygon_parser -{ - typedef typename ring_return_type::type ring_return_type; - typedef container_appender appender; - - static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, - std::string const& wkt, Polygon& poly) - { - - handle_open_parenthesis(it, end, wkt); - - int n = -1; - - // Stop at ")" - while (it != end && *it != ")") - { - // Parse ring - if (++n == 0) - { - appender::apply(it, end, wkt, exterior_ring(poly)); - } - else - { - typename ring_type::type ring; - appender::apply(it, end, wkt, ring); - traits::push_back - < - typename boost::remove_reference - < - typename traits::interior_mutable_type::type - >::type - >::apply(interior_rings(poly), ring); - } - - if (it != end && *it == ",") - { - // Skip "," after ring is parsed - ++it; - } - } - - handle_close_parenthesis(it, end, wkt); - } -}; - -inline bool one_of(tokenizer::iterator const& it, std::string const& value, - bool& is_present) -{ - if (boost::iequals(*it, value)) - { - is_present = true; - return true; - } - return false; -} - -inline bool one_of(tokenizer::iterator const& it, std::string const& value, - bool& present1, bool& present2) -{ - if (boost::iequals(*it, value)) - { - present1 = true; - present2 = true; - return true; - } - return false; -} - - -inline void handle_empty_z_m(tokenizer::iterator& it, tokenizer::iterator end, - bool& has_empty, bool& has_z, bool& has_m) -{ - has_empty = false; - has_z = false; - has_m = false; - - // WKT can optionally have Z and M (measured) values as in - // POINT ZM (1 1 5 60), POINT M (1 1 80), POINT Z (1 1 5) - // GGL supports any of them as coordinate values, but is not aware - // of any Measured value. - while (it != end - && (one_of(it, "M", has_m) - || one_of(it, "Z", has_z) - || one_of(it, "EMPTY", has_empty) - || one_of(it, "MZ", has_m, has_z) - || one_of(it, "ZM", has_z, has_m) - ) - ) - { - ++it; - } -} - -/*! -\brief Internal, starts parsing -\param tokens boost tokens, parsed with separator " " and keeping separator "()" -\param geometry string to compare with first token -*/ -template -inline bool initialize(tokenizer const& tokens, - std::string const& geometry_name, std::string const& wkt, - tokenizer::iterator& it) -{ - it = tokens.begin(); - if (it != tokens.end() && boost::iequals(*it++, geometry_name)) - { - bool has_empty, has_z, has_m; - - handle_empty_z_m(it, tokens.end(), has_empty, has_z, has_m); - - if (has_z && dimension::type::value < 3) - { - throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt); - } - if (has_empty) - { - check_end(it, tokens.end(), wkt); - return false; - } - // M is ignored at all. - - return true; - } - throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt); -} - - -template class Parser, typename PrefixPolicy> -struct geometry_parser -{ - static inline void apply(std::string const& wkt, Geometry& geometry) - { - geometry::clear(geometry); - - tokenizer tokens(wkt, boost::char_separator(" ", ",()")); - tokenizer::iterator it; - if (initialize(tokens, PrefixPolicy::apply(), wkt, it)) - { - Parser::apply(it, tokens.end(), wkt, geometry); - check_end(it, tokens.end(), wkt); - } - } -}; - - - - - -/*! -\brief Supports box parsing -\note OGC does not define the box geometry, and WKT does not support boxes. - However, to be generic GGL supports reading and writing from and to boxes. - Boxes are outputted as a standard POLYGON. GGL can read boxes from - a standard POLYGON, from a POLYGON with 2 points of from a BOX -\tparam Box the box -*/ -template -struct box_parser -{ - static inline void apply(std::string const& wkt, Box& box) - { - bool should_close = false; - tokenizer tokens(wkt, boost::char_separator(" ", ",()")); - tokenizer::iterator it = tokens.begin(); - tokenizer::iterator end = tokens.end(); - if (it != end && boost::iequals(*it, "POLYGON")) - { - ++it; - bool has_empty, has_z, has_m; - handle_empty_z_m(it, end, has_empty, has_z, has_m); - if (has_empty) - { - assign_zero(box); - return; - } - handle_open_parenthesis(it, end, wkt); - should_close = true; - } - else if (it != end && boost::iequals(*it, "BOX")) - { - ++it; - } - else - { - throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt); - } - - typedef typename point_type::type point_type; - std::vector points; - container_inserter::apply(it, end, wkt, std::back_inserter(points)); - - if (should_close) - { - handle_close_parenthesis(it, end, wkt); - } - check_end(it, end, wkt); - - int index = 0; - int n = boost::size(points); - if (n == 2) - { - index = 1; - } - else if (n == 4 || n == 5) - { - // In case of 4 or 5 points, we do not check the other ones, just - // take the opposite corner which is always 2 - index = 2; - } - else - { - throw read_wkt_exception("Box should have 2,4 or 5 points", wkt); - } - - geometry::detail::assign_point_to_index(points.front(), box); - geometry::detail::assign_point_to_index(points[index], box); - } -}; - - -/*! -\brief Supports segment parsing -\note OGC does not define the segment, and WKT does not support segmentes. - However, it is useful to implement it, also for testing purposes -\tparam Segment the segment -*/ -template -struct segment_parser -{ - static inline void apply(std::string const& wkt, Segment& segment) - { - tokenizer tokens(wkt, boost::char_separator(" ", ",()")); - tokenizer::iterator it = tokens.begin(); - tokenizer::iterator end = tokens.end(); - if (it != end && - (boost::iequals(*it, "SEGMENT") - || boost::iequals(*it, "LINESTRING") )) - { - ++it; - } - else - { - throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt); - } - - typedef typename point_type::type point_type; - std::vector points; - container_inserter::apply(it, end, wkt, std::back_inserter(points)); - - check_end(it, end, wkt); - - if (boost::size(points) == 2) - { - geometry::detail::assign_point_to_index<0>(points.front(), segment); - geometry::detail::assign_point_to_index<1>(points.back(), segment); - } - else - { - throw read_wkt_exception("Segment should have 2 points", wkt); - } - - } -}; - - - -}} // namespace detail::wkt -#endif // DOXYGEN_NO_DETAIL - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -struct read_wkt {}; - - -template -struct read_wkt - : detail::wkt::geometry_parser - < - Point, - detail::wkt::point_parser, - detail::wkt::prefix_point - > -{}; - - -template -struct read_wkt - : detail::wkt::geometry_parser - < - L, - detail::wkt::linestring_parser, - detail::wkt::prefix_linestring - > -{}; - -template -struct read_wkt - : detail::wkt::geometry_parser - < - Ring, - detail::wkt::ring_parser, - detail::wkt::prefix_polygon - > -{}; - -template -struct read_wkt - : detail::wkt::geometry_parser - < - Geometry, - detail::wkt::polygon_parser, - detail::wkt::prefix_polygon - > -{}; - - -// Box (Non-OGC) -template -struct read_wkt - : detail::wkt::box_parser -{}; - -// Segment (Non-OGC) -template -struct read_wkt - : detail::wkt::segment_parser -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -/*! -\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry) -\ingroup wkt -\param wkt string containing \ref WKT -\param geometry output geometry -\par Example: -\note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz" -\note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())" -Small example showing how to use read_wkt to build a point -\dontinclude doxygen_1.cpp -\skip example_from_wkt_point -\line { -\until } -\par Example: -Small example showing how to use read_wkt to build a linestring -\dontinclude doxygen_1.cpp -\skip example_from_wkt_linestring -\line { -\until } -\par Example: -Small example showing how to use read_wkt to build a polygon -\dontinclude doxygen_1.cpp -\skip example_from_wkt_polygon -\line { -\until } -*/ -template -inline void read_wkt(std::string const& wkt, Geometry& geometry) -{ - geometry::concept::check(); - dispatch::read_wkt::type, Geometry>::apply(wkt, geometry); -} - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/read_multi.hpp b/include/boost/geometry/domains/gis/io/wkt/read_multi.hpp deleted file mode 100644 index 0d9a2b649c..0000000000 --- a/include/boost/geometry/domains/gis/io/wkt/read_multi.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_WKT_READ_MULTI_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_MULTI_HPP - -#include - -#include -#include -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -namespace detail { namespace wkt { - -template class Parser, typename PrefixPolicy> -struct multi_parser -{ - static inline void apply(std::string const& wkt, MultiGeometry& geometry) - { - traits::clear::apply(geometry); - - tokenizer tokens(wkt, boost::char_separator(" ", ",()")); - tokenizer::iterator it; - if (initialize(tokens, PrefixPolicy::apply(), wkt, it)) - { - handle_open_parenthesis(it, tokens.end(), wkt); - - // Parse sub-geometries - while(it != tokens.end() && *it != ")") - { - traits::resize::apply(geometry, boost::size(geometry) + 1); - Parser - < - typename boost::range_value::type - >::apply(it, tokens.end(), wkt, geometry.back()); - if (it != tokens.end() && *it == ",") - { - // Skip "," after multi-element is parsed - ++it; - } - } - - handle_close_parenthesis(it, tokens.end(), wkt); - } - } -}; - - - - -}} // namespace detail::wkt - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -struct read_wkt - : detail::wkt::multi_parser - < - MultiGeometry, - detail::wkt::point_parser, - detail::wkt::prefix_multipoint - > -{}; - - -template -struct read_wkt - : detail::wkt::multi_parser - < - MultiGeometry, - detail::wkt::linestring_parser, - detail::wkt::prefix_multilinestring - > -{}; - - -template -struct read_wkt - : detail::wkt::multi_parser - < - MultiGeometry, - detail::wkt::polygon_parser, - detail::wkt::prefix_multipolygon - > -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_READ_MULTI_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/write.hpp b/include/boost/geometry/domains/gis/io/wkt/write.hpp deleted file mode 100644 index 0f1dbb9094..0000000000 --- a/include/boost/geometry/domains/gis/io/wkt/write.hpp +++ /dev/null @@ -1,394 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_WKT_WRITE_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_HPP - -#include -#include - -#include -#include -#include -#include - - -#include -#include -#include -#include -#include - -#include -#include - -#include - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace wkt -{ - -template -struct stream_coordinate -{ - template - static inline void apply(std::basic_ostream& os, P const& p) - { - os << (I > 0 ? " " : "") << get(p); - stream_coordinate::apply(os, p); - } -}; - -template -struct stream_coordinate -{ - template - static inline void apply(std::basic_ostream&, P const&) - {} -}; - -struct prefix_linestring_par -{ - static inline const char* apply() { return "LINESTRING("; } -}; - -struct prefix_ring_par_par -{ - // Note, double parentheses are intentional, indicating WKT ring begin/end - static inline const char* apply() { return "POLYGON(("; } -}; - -struct opening_parenthesis -{ - static inline const char* apply() { return "("; } -}; - -struct closing_parenthesis -{ - static inline const char* apply() { return ")"; } -}; - -struct double_closing_parenthesis -{ - static inline const char* apply() { return "))"; } -}; - - - - -/*! -\brief Stream points as \ref WKT -*/ -template -struct wkt_point -{ - template - static inline void apply(std::basic_ostream& os, Point const& p) - { - os << Policy::apply() << "("; - stream_coordinate::type::value>::apply(os, p); - os << ")"; - } -}; - -/*! -\brief Stream ranges as WKT -\note policy is used to stream prefix/postfix, enabling derived classes to override this -*/ -template -struct wkt_range -{ - template - static inline void apply(std::basic_ostream& os, - Range const& range) - { - typedef typename boost::range_iterator::type iterator_type; - - bool first = true; - - os << PrefixPolicy::apply(); - - // TODO: check EMPTY here - - for (iterator_type it = boost::begin(range); - it != boost::end(range); - ++it) - { - os << (first ? "" : ","); - stream_coordinate - < - point_type, 0, dimension::type::value - >::apply(os, *it); - first = false; - } - - os << SuffixPolicy::apply(); - } - -private: - typedef typename boost::range_value::type point_type; -}; - -/*! -\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4) -\note Used in polygon, all multi-geometries -*/ - - - -template -struct wkt_sequence - : wkt_range - < - Range, - opening_parenthesis, - closing_parenthesis - > -{}; - - -template -struct wkt_poly -{ - template - static inline void apply(std::basic_ostream& os, - Polygon const& poly) - { - typedef typename ring_type::type ring; - - os << PrefixPolicy::apply(); - // TODO: check EMPTY here - os << "("; - wkt_sequence::apply(os, exterior_ring(poly)); - - typename interior_return_type::type rings - = interior_rings(poly); - for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) - { - os << ","; - wkt_sequence::apply(os, *it); - } - os << ")"; - } -}; - - -template -struct wkt_box -{ - typedef typename point_type::type point_type; - - template - static inline void apply(std::basic_ostream& os, - Box const& box) - { - // Convert to ring, then stream - typedef model::ring ring_type; - ring_type ring; - geometry::convert(box, ring); - os << "POLYGON("; - wkt_sequence::apply(os, ring); - os << ")"; - } - - private: - - inline wkt_box() - { - // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron! - //assert_dimension(); - } -}; - - -template -struct wkt_segment -{ - typedef typename point_type::type point_type; - - template - static inline void apply(std::basic_ostream& os, - Segment const& segment) - { - // Convert to two points, then stream - typedef boost::array sequence; - - sequence points; - geometry::detail::assign_point_from_index<0>(segment, points[0]); - geometry::detail::assign_point_from_index<1>(segment, points[1]); - - // In Boost.Geometry a segment is represented - // in WKT-format like (for 2D): LINESTRING(x y,x y) - os << "LINESTRING"; - wkt_sequence::apply(os, points); - } - - private: - - inline wkt_segment() - {} -}; - -}} // namespace detail::wkt -#endif // DOXYGEN_NO_DETAIL - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -struct wkt -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; - - -template -struct wkt - : detail::wkt::wkt_point - < - Point, - detail::wkt::prefix_point - > -{}; - - -template -struct wkt - : detail::wkt::wkt_range - < - Linestring, - detail::wkt::prefix_linestring_par, - detail::wkt::closing_parenthesis - > -{}; - - -/*! -\brief Specialization to stream a box as WKT -\details A "box" does not exist in WKT. -It is therefore streamed as a polygon -*/ -template -struct wkt - : detail::wkt::wkt_box -{}; - -template -struct wkt - : detail::wkt::wkt_segment -{}; - - -/*! -\brief Specialization to stream a ring as WKT -\details A ring or "linear_ring" does not exist in WKT. -A ring is equivalent to a polygon without inner rings -It is therefore streamed as a polygon -*/ -template -struct wkt - : detail::wkt::wkt_range - < - Ring, - detail::wkt::prefix_ring_par_par, - detail::wkt::double_closing_parenthesis - > -{}; - - -/*! -\brief Specialization to stream polygon as WKT -*/ -template -struct wkt - : detail::wkt::wkt_poly - < - Polygon, - detail::wkt::prefix_polygon - > -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -/*! -\brief Generic geometry template manipulator class, takes corresponding output class from traits class -\ingroup wkt -\details Stream manipulator, streams geometry classes as \ref WKT streams -\par Example: -Small example showing how to use the wkt class -\dontinclude doxygen_1.cpp -\skip example_as_wkt_point -\line { -\until } -*/ -template -class wkt_manipulator -{ -public: - - inline wkt_manipulator(Geometry const& g) - : m_geometry(g) - {} - - template - inline friend std::basic_ostream& operator<<( - std::basic_ostream& os, - wkt_manipulator const& m) - { - dispatch::wkt - < - typename tag::type, - Geometry - >::apply(os, m.m_geometry); - os.flush(); - return os; - } - -private: - Geometry const& m_geometry; -}; - -/*! -\brief Main WKT-streaming function -\ingroup wkt -\par Example: -Small example showing how to use the wkt helper function -\dontinclude doxygen_1.cpp -\skip example_as_wkt_vector -\line { -\until } -*/ -template -inline wkt_manipulator wkt(Geometry const& geometry) -{ - concept::check(); - - return wkt_manipulator(geometry); -} - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/write_multi.hpp b/include/boost/geometry/domains/gis/io/wkt/write_multi.hpp deleted file mode 100644 index a8810a8153..0000000000 --- a/include/boost/geometry/domains/gis/io/wkt/write_multi.hpp +++ /dev/null @@ -1,115 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_DOMAINS_GIS_IO_WKT_WRITE_MULTI_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_MULTI_HPP - -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace wkt -{ - - -template -struct wkt_multi -{ - template - static inline void apply(std::basic_ostream& os, - Multi const& geometry) - { - os << PrefixPolicy::apply(); - // TODO: check EMPTY here - os << "("; - - for (typename boost::range_iterator::type - it = boost::begin(geometry); - it != boost::end(geometry); - ++it) - { - if (it != boost::begin(geometry)) - { - os << ","; - } - StreamPolicy::apply(os, *it); - } - - os << ")"; - } -}; - -}} // namespace wkt::impl -#endif - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - - -template -struct wkt - : detail::wkt::wkt_multi - < - Multi, - detail::wkt::wkt_point - < - typename boost::range_value::type, - detail::wkt::prefix_null - >, - detail::wkt::prefix_multipoint - > -{}; - - -template -struct wkt - : detail::wkt::wkt_multi - < - Multi, - detail::wkt::wkt_sequence - < - typename boost::range_value::type - >, - detail::wkt::prefix_multilinestring - > -{}; - - -template -struct wkt - : detail::wkt::wkt_multi - < - Multi, - detail::wkt::wkt_poly - < - typename boost::range_value::type, - detail::wkt::prefix_null - >, - detail::wkt::prefix_multipolygon - > -{}; - -} // namespace dispatch -#endif - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WRITE_MULTI_HPP diff --git a/include/boost/geometry/domains/gis/io/wkt/wkt.hpp b/include/boost/geometry/multi/geometries/multi_geometries.hpp similarity index 60% rename from include/boost/geometry/domains/gis/io/wkt/wkt.hpp rename to include/boost/geometry/multi/geometries/multi_geometries.hpp index 662012b1d7..0e98b22fb8 100644 --- a/include/boost/geometry/domains/gis/io/wkt/wkt.hpp +++ b/include/boost/geometry/multi/geometries/multi_geometries.hpp @@ -11,13 +11,11 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WKT_HPP -#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WKT_HPP +#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP +#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP -#include -#include +#include +#include +#include -#include -#include - -#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_WKT_HPP +#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP From 47f78e4e05df63d2f24bd945b9d94251a121ee3d Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 8 Jan 2012 10:49:28 +0000 Subject: [PATCH 033/135] Merge for Boost.Geometry [SVN r76363] --- include/boost/geometry/io/dsv/write.hpp | 6 +++--- .../geometry/multi/algorithms/distance.hpp | 20 ++++++++++++++++++- .../multi/geometries/multi_geometries.hpp | 6 +++--- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/include/boost/geometry/io/dsv/write.hpp b/include/boost/geometry/io/dsv/write.hpp index 0df047b05a..62929f8073 100644 --- a/include/boost/geometry/io/dsv/write.hpp +++ b/include/boost/geometry/io/dsv/write.hpp @@ -1,8 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. diff --git a/include/boost/geometry/multi/algorithms/distance.hpp b/include/boost/geometry/multi/algorithms/distance.hpp index 95660b9696..c2e584d969 100644 --- a/include/boost/geometry/multi/algorithms/distance.hpp +++ b/include/boost/geometry/multi/algorithms/distance.hpp @@ -36,6 +36,12 @@ namespace detail { namespace distance template struct distance_single_to_multi + : private dispatch::distance + < + Geometry, + typename range_value::type, + Strategy + > { typedef typename strategy::distance::services::return_type::type return_type; @@ -50,7 +56,13 @@ struct distance_single_to_multi it != boost::end(multi); ++it) { - return_type dist = geometry::distance(geometry, *it); + return_type dist = dispatch::distance + < + Geometry, + typename range_value::type, + Strategy + >::apply(geometry, *it, strategy); + if (first || dist < mindist) { mindist = dist; @@ -64,6 +76,12 @@ struct distance_single_to_multi template struct distance_multi_to_multi + : private distance_single_to_multi + < + typename range_value::type, + Multi2, + Strategy + > { typedef typename strategy::distance::services::return_type::type return_type; diff --git a/include/boost/geometry/multi/geometries/multi_geometries.hpp b/include/boost/geometry/multi/geometries/multi_geometries.hpp index 0e98b22fb8..90cf85a0f6 100644 --- a/include/boost/geometry/multi/geometries/multi_geometries.hpp +++ b/include/boost/geometry/multi/geometries/multi_geometries.hpp @@ -1,8 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. From f3a5c659ec0d15f4c2875650acf23208401a2075 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 8 Jan 2012 11:46:35 +0000 Subject: [PATCH 034/135] Manually synchronized 6 more files and deleted ranges/domains [SVN r76366] --- example/Jamfile.v2 | 2 +- example/c03_custom_linestring_example.cpp | 87 +++++++ example/with_external_libs/x02_gd_example.cpp | 146 +++++++++++ .../with_external_libs/x03_c_soci_example.cpp | 118 +++++++++ .../with_external_libs/x03_d_soci_example.cpp | 83 +++++++ test/domains/Jamfile.v2 | 11 - test/domains/gis/Jamfile.v2 | 11 - test/domains/gis/io/Jamfile.v2 | 11 - test/domains/gis/io/wkt/Jamfile.v2 | 16 -- test/domains/gis/io/wkt/io_wkt_tests.sln | 29 --- test/domains/gis/io/wkt/multi_wkt.cpp | 88 ------- test/domains/gis/io/wkt/multi_wkt.vcproj | 174 ------------- test/domains/gis/io/wkt/wkt.cpp | 232 ------------------ test/domains/gis/io/wkt/wkt.vcproj | 174 ------------- test/geometries/adapted.cpp | 9 +- 15 files changed, 441 insertions(+), 750 deletions(-) create mode 100644 example/c03_custom_linestring_example.cpp create mode 100644 example/with_external_libs/x02_gd_example.cpp create mode 100644 example/with_external_libs/x03_c_soci_example.cpp create mode 100644 example/with_external_libs/x03_d_soci_example.cpp delete mode 100644 test/domains/Jamfile.v2 delete mode 100644 test/domains/gis/Jamfile.v2 delete mode 100644 test/domains/gis/io/Jamfile.v2 delete mode 100644 test/domains/gis/io/wkt/Jamfile.v2 delete mode 100644 test/domains/gis/io/wkt/io_wkt_tests.sln delete mode 100644 test/domains/gis/io/wkt/multi_wkt.cpp delete mode 100644 test/domains/gis/io/wkt/multi_wkt.vcproj delete mode 100644 test/domains/gis/io/wkt/wkt.cpp delete mode 100644 test/domains/gis/io/wkt/wkt.vcproj diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 8f12d888a1..141ee1537b 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -26,7 +26,7 @@ exe 07_b_graph_route_example : 07_b_graph_route_example.cpp ; exe c01_custom_point_example : c01_custom_point_example.cpp ; exe c02_custom_box_example : c02_custom_box_example.cpp ; -# exe c03_custom_linestring_example : c03_custom_linestring_example.cpp ; +exe c03_custom_linestring_example : c03_custom_linestring_example.cpp ; exe c04_a_custom_triangle_example : c04_a_custom_triangle_example.cpp ; exe c04_b_custom_triangle_example : c04_b_custom_triangle_example.cpp ; exe c06_custom_polygon_example : c06_custom_polygon_example.cpp ; diff --git a/example/c03_custom_linestring_example.cpp b/example/c03_custom_linestring_example.cpp new file mode 100644 index 0000000000..1561d1b54d --- /dev/null +++ b/example/c03_custom_linestring_example.cpp @@ -0,0 +1,87 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 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) +// +// Custom Linestring Example + +#include +#include +#include + +#include +#include +#include + +// To register the 'geographic' distance function to calculate distance over the earth: +#include +#include + +// Define a GPS point with coordinates in latitude/longitude and some additional values +struct gps_point +{ + double latitude, longitude, height; + double speed; + // Date/time, heading, etc could be added + + // The default constructor is required if being used in a vector + gps_point() {} + + // Define a constructor to create the point in one line. Order of latitude/longitude + // does not matter as long as "E", "N", etc are included + gps_point(std::string const& c1, std::string const& c2, double h, double s) + : height(h) + , speed(s) + { + boost::geometry::parse(*this, c1, c2); + } +}; + +// Declare a custom linestring which will have the GPS points +struct gps_track : std::vector +{ + std::string owner; + int route_identifier; + // etc + + gps_track(int i, std::string const& o) + : owner(o) + , route_identifier(i) + {} +}; + + +// Register this point as being a recognizable point by Boost.Geometry +BOOST_GEOMETRY_REGISTER_POINT_2D(gps_point, double, cs::geographic, longitude, latitude) + +// Register the track as well, as being a "linestring" +BOOST_GEOMETRY_REGISTER_LINESTRING(gps_track) + + +int main() +{ + // Declare a "GPS Track" and add some GPS points + gps_track track(23, "Mister G"); + track.push_back(gps_point("52 22 23 N", "4 53 32 E", 50, 180)); + track.push_back(gps_point("52 10 00 N", "4 59 59 E", 110, 170)); + track.push_back(gps_point("52 5 20 N", "5 6 56 E", 0, 90)); + + std::cout + << "track: " << track.route_identifier << std::endl + << "from: " << track.owner << std::endl + << "as wkt: " << boost::geometry::dsv(track) << std::endl + << "length: " << boost::geometry::length(track)/1000.0 << " km" << std::endl; + + // Above gives the idea, shows that custom linestrings can be useful. + // We could of course do anything with this track which the library can handle, e.g.: + // - simplify it + // - calculate distance of point-to-line + // - project it to UTM, then transform it to a GIF image (see p03_example) + + return 0; +} diff --git a/example/with_external_libs/x02_gd_example.cpp b/example/with_external_libs/x02_gd_example.cpp new file mode 100644 index 0000000000..d740829f5f --- /dev/null +++ b/example/with_external_libs/x02_gd_example.cpp @@ -0,0 +1,146 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright (c) 2007-2011 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) +// +// GD example + +// GD is a well-known and often used graphic library to write GIF (and other formats) + +// To build and run this example: +// 1) download GD from http://www.libgd.org (currently gd-2.0.35 is assumed) +// 2) add 11 files +// gd.c, gd_gd.c, gd_gif_out.c, gd_io*.c, gd_security.c, gd_topal.c, gdhelpers.c, gdtables.c +// to the project or makefile or jamfile +// 3) for windows, add define NONDLL to indicate GD is not used as a DLL +// (Note that steps 2 and 3 are done in the MSVC gd_example project file and property sheets) + +#include +#include +#include + +#include +#include + + +#include + +#include +#include +#include +#include +#include + +#include + + +#include + +namespace bg = boost::geometry; + + +// ---------------------------------------------------------------------------- +// Read an ASCII file containing WKT's +// (note this function is shared by various examples) +// ---------------------------------------------------------------------------- +template +inline void read_wkt(std::string const& filename, std::vector& geometries) +{ + std::ifstream cpp_file(filename.c_str()); + if (cpp_file.is_open()) + { + while (! cpp_file.eof() ) + { + std::string line; + std::getline(cpp_file, line); + if (! line.empty()) + { + Geometry geometry; + bg::read_wkt(line, geometry); + geometries.push_back(geometry); + } + } + } +} + + +int main() +{ + // Adapt if necessary + std::string filename = "../data/world.wkt"; + + + // The world is measured in latlong (degrees), so latlong is appropriate. + // We ignore holes in this sample (below) + typedef bg::model::ll::point point_type; + typedef bg::model::polygon polygon_type; + typedef bg::model::multi_polygon country_type; + + std::vector countries; + + // Read (for example) world countries + read_wkt(filename, countries); + + + // Create a GD image. + // A world map, as world.shp, is usually mapped in latitude-longitude (-180..180 and -90..90) + // For this example we use a very simple "transformation" + // mapping to 0..720 and 0..360 + const double factor = 2.0; + gdImagePtr im = gdImageCreateTrueColor(int(360 * factor), int(180 * factor)); + + // Allocate three colors + int blue = gdImageColorResolve(im, 0, 52, 255); + int green = gdImageColorResolve(im, 0, 255, 0); + int black = gdImageColorResolve(im, 0, 0, 0); + + // Paint background in blue + gdImageFilledRectangle(im, 0, 0, im->sx, im->sy, blue); + + // Paint all countries in green + BOOST_FOREACH(country_type const& country, countries) + { + BOOST_FOREACH(polygon_type const& polygon, country) + { + // Ignore holes, so take only exterior ring + bg::model::ring const& ring = bg::exterior_ring(polygon); + + // If wished, suppress too small polygons. + // (Note that even in latlong, area is calculated in square meters) + double const a = bg::area(ring); + if (std::fabs(a) > 5000.0e6) + { + int const n = ring.size(); + gdPoint* points = new gdPoint[n]; + + for (int i = 0; i < n; i++) + { + // Translate lon/lat or x/y to GD x/y points + points[i].x = int(factor * (bg::get<0>(ring[i]) + 180.0)); + points[i].y = im->sy - int(factor * (bg::get<1>(ring[i]) + 90.0)); + } + + // Draw the polygon... + gdImageFilledPolygon(im, points, n, green); + // .. and the outline in black... + gdImagePolygon(im, points, n, black); + + delete[] points; + } + } + } + + // Use GD to create a GIF file + std::FILE* out = std::fopen("world.gif", "wb"); + if (out != NULL) + { + gdImageGif(im, out); + std::fclose(out); + } + + gdImageDestroy(im); + + return 0; +} diff --git a/example/with_external_libs/x03_c_soci_example.cpp b/example/with_external_libs/x03_c_soci_example.cpp new file mode 100644 index 0000000000..0f8a0d69b6 --- /dev/null +++ b/example/with_external_libs/x03_c_soci_example.cpp @@ -0,0 +1,118 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright (c) 2009-2011 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) +// Boost.Geometry (aka GGL, Generic Geometry Library) +// SOCI example + +// c: using WKB to retrieve geometries + +// SOCI is a generic C++ template interface to access relational databases + +// To build and run this example, see comments in example a +// Alternatively compile composing and executing compiler command directoy in examples directory, +// for example using GCC compiler: +// g++ -I../../../boost -I/home/mloskot/usr/include/soci \ +// -I /home/mloskot/usr/include/soci/postgresql -I/usr/include/postgresql \ +// -L/home/mloskot/usr/lib -lsoci_core-gcc-3_0 -lsoci_postgresql-gcc-3_0 x03_c_soci_example.cpp + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// user-defined type with GGL geometry +struct tree +{ + int id; + boost::geometry::model::point > location; +}; + +// conversion of row of result to user-defined type - performs WKB parsing +namespace soci +{ + template <> + struct type_conversion + { + typedef soci::values base_type; + + static void from_base(base_type const& v, soci::indicator ind, tree& value) + { + try + { + value.id = v.get("id"); + + // intermediate step: hex-encoded binary string to raw WKB + std::string const& hex = v.get("wkb"); + std::vector wkb; + if (!boost::geometry::hex2wkb(hex, std::back_inserter(wkb))) + throw std::runtime_error("hex2wkb translation failed"); + + // parse WKB and construct point geometry + if (!boost::geometry::read_wkb(wkb.begin(), wkb.end(), value.location)) + throw std::runtime_error("read_wkb failed"); + } + catch(const std::exception& e) + { + std::cout << e.what() << std::endl; + } + } + + static void to_base(tree const& value, base_type& v, soci::indicator& ind) + { + throw std::runtime_error("todo: wkb writer not yet implemented"); + } + }; +} + +int main() +{ + try + { + // establish database connection + soci::session sql(soci::postgresql, "dbname=ggl user=ggl password=ggl"); + + // construct schema of table for trees (point geometries) + sql << "DELETE FROM geometry_columns WHERE f_table_name = 'trees'"; + sql << "DROP TABLE IF EXISTS trees CASCADE"; + sql << "CREATE TABLE trees (id INTEGER)"; + sql << "SELECT AddGeometryColumn('trees', 'geom', -1, 'POINT', 2)"; + + // insert sample data using plain WKT input + sql << "INSERT INTO trees VALUES(1, ST_GeomFromText('POINT(1.23 2.34)', -1))"; + sql << "INSERT INTO trees VALUES(2, ST_GeomFromText('POINT(3.45 4.56)', -1))"; + sql << "INSERT INTO trees VALUES(3, ST_GeomFromText('POINT(5.67 6.78)', -1))"; + sql << "INSERT INTO trees VALUES(4, ST_GeomFromText('POINT(7.89 9.01)', -1))"; + + // query data in WKB form and read to geometry object + typedef std::vector trees_t; + soci::rowset rows = (sql.prepare << "SELECT id, encode(ST_AsBinary(geom), 'hex') AS wkb FROM trees"); + trees_t trees; + std::copy(rows.begin(), rows.end(), std::back_inserter(trees)); + + // print trees output + for (trees_t::const_iterator it = trees.begin(); it != trees.end(); ++it) + { + std::cout << "Tree #" << it->id << " located at\t" << boost::geometry::wkt(it->location) << std::endl; + } + } + catch (std::exception const &e) + { + std::cerr << "Error: " << e.what() << '\n'; + } + return 0; +} + diff --git a/example/with_external_libs/x03_d_soci_example.cpp b/example/with_external_libs/x03_d_soci_example.cpp new file mode 100644 index 0000000000..b3dbd69d1c --- /dev/null +++ b/example/with_external_libs/x03_d_soci_example.cpp @@ -0,0 +1,83 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright (c) 2009-2011 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) +// Boost.Geometry (aka GGL, Generic Geometry Library) +// SOCI example + +// d: using WKB to retrieve geometries + +// SOCI is a generic C++ template interface to access relational databases + +// To build and run this example, see comments in example a +// Alternatively compile composing and executing compiler command directoy in examples directory, +// for example using GCC compiler: +// g++ -I../../../boost -I/home/mloskot/usr/include/soci \ +// -I /home/mloskot/usr/include/soci/postgresql -I/usr/include/postgresql \ +// -L/home/mloskot/usr/lib -lsoci_core-gcc-3_0 -lsoci_postgresql-gcc-3_0 x03_c_soci_example.cpp + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int main() +{ + try + { + // establish database connection + soci::session sql(soci::postgresql, "dbname=ggl user=ggl password=ggl"); + + // construct schema of table for trees (point geometries) + sql << "DELETE FROM geometry_columns WHERE f_table_name = 'parcels'"; + sql << "DROP TABLE IF EXISTS parcels CASCADE"; + sql << "CREATE TABLE parcels (id INTEGER)"; + sql << "SELECT AddGeometryColumn('parcels', 'geom', -1, 'GEOMETRY', 2)"; + + // insert sample data using plain WKT input + sql << "INSERT INTO parcels VALUES(1, ST_GeomFromText('POLYGON ((10 10, 10 20, 20 20, 20 15, 10 10))', -1))"; + sql << "INSERT INTO parcels VALUES(2, ST_GeomFromText('POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', -1))"; + sql << "INSERT INTO parcels VALUES(3, ST_GeomFromText('POLYGON((1 1,2 1,2 2,1 2,1 1))', -1))"; + + // query data in WKB form and read to geometry object + soci::rowset rows = (sql.prepare << "SELECT encode(ST_AsBinary(geom), 'hex') AS wkb FROM parcels"); + + // calculate area of each parcel + for (soci::rowset::iterator it = rows.begin(); it != rows.end(); ++it) + { + // parse WKB and construct geometry object + std::string const& hex = *it; + std::vector wkb; + if (!boost::geometry::hex2wkb(*it, std::back_inserter(wkb))) + throw std::runtime_error("hex2wkb translation failed"); + + boost::geometry::model::d2::polygon parcel; + if (!boost::geometry::read_wkb(wkb.begin(), wkb.end(), parcel)) + throw std::runtime_error("read_wkb failed"); + + double a = boost::geometry::area(parcel); + std::cout << "Parcel geometry: " << boost::geometry::wkt(parcel) << std::endl + << "\thas area is " << a << " in coordinate units" << std::endl; + } + } + catch (std::exception const &e) + { + std::cerr << "Error: " << e.what() << '\n'; + } + return 0; +} + diff --git a/test/domains/Jamfile.v2 b/test/domains/Jamfile.v2 deleted file mode 100644 index 6ec8a24637..0000000000 --- a/test/domains/Jamfile.v2 +++ /dev/null @@ -1,11 +0,0 @@ -# Boost.Geometry (aka GGL, Generic Geometry Library) - -# Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2011 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) - -build-project gis ; \ No newline at end of file diff --git a/test/domains/gis/Jamfile.v2 b/test/domains/gis/Jamfile.v2 deleted file mode 100644 index edbc115ffc..0000000000 --- a/test/domains/gis/Jamfile.v2 +++ /dev/null @@ -1,11 +0,0 @@ -# Boost.Geometry (aka GGL, Generic Geometry Library) -# -# Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2011 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) - -build-project io ; \ No newline at end of file diff --git a/test/domains/gis/io/Jamfile.v2 b/test/domains/gis/io/Jamfile.v2 deleted file mode 100644 index 1e0fa6ed67..0000000000 --- a/test/domains/gis/io/Jamfile.v2 +++ /dev/null @@ -1,11 +0,0 @@ -# Boost.Geometry (aka GGL, Generic Geometry Library) -# -# Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2011 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) - -build-project wkt ; \ No newline at end of file diff --git a/test/domains/gis/io/wkt/Jamfile.v2 b/test/domains/gis/io/wkt/Jamfile.v2 deleted file mode 100644 index f93c637f86..0000000000 --- a/test/domains/gis/io/wkt/Jamfile.v2 +++ /dev/null @@ -1,16 +0,0 @@ -# Boost.Geometry (aka GGL, Generic Geometry Library) -# -# Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2011 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) - -test-suite boost-geometry-domains-gis-io-wkt - : - [ run wkt.cpp ] - [ run multi_wkt.cpp ] - ; - diff --git a/test/domains/gis/io/wkt/io_wkt_tests.sln b/test/domains/gis/io/wkt/io_wkt_tests.sln deleted file mode 100644 index 79c6e993ec..0000000000 --- a/test/domains/gis/io/wkt/io_wkt_tests.sln +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wkt", "wkt.vcproj", "{1FA2ADE2-F649-4245-951E-A8F5935E7127}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multi_wkt", "multi_wkt.vcproj", "{CA8D5E44-7D8F-44A1-900C-35C28890299B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1FA2ADE2-F649-4245-951E-A8F5935E7127}.Debug|Win32.ActiveCfg = Debug|Win32 - {1FA2ADE2-F649-4245-951E-A8F5935E7127}.Debug|Win32.Build.0 = Debug|Win32 - {1FA2ADE2-F649-4245-951E-A8F5935E7127}.Release|Win32.ActiveCfg = Release|Win32 - {1FA2ADE2-F649-4245-951E-A8F5935E7127}.Release|Win32.Build.0 = Release|Win32 - {F2A680B0-F6FC-479E-9988-24CF6851C13C}.Debug|Win32.ActiveCfg = Debug|Win32 - {F2A680B0-F6FC-479E-9988-24CF6851C13C}.Debug|Win32.Build.0 = Debug|Win32 - {F2A680B0-F6FC-479E-9988-24CF6851C13C}.Release|Win32.ActiveCfg = Release|Win32 - {F2A680B0-F6FC-479E-9988-24CF6851C13C}.Release|Win32.Build.0 = Release|Win32 - {CA8D5E44-7D8F-44A1-900C-35C28890299B}.Debug|Win32.ActiveCfg = Debug|Win32 - {CA8D5E44-7D8F-44A1-900C-35C28890299B}.Debug|Win32.Build.0 = Debug|Win32 - {CA8D5E44-7D8F-44A1-900C-35C28890299B}.Release|Win32.ActiveCfg = Release|Win32 - {CA8D5E44-7D8F-44A1-900C-35C28890299B}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/test/domains/gis/io/wkt/multi_wkt.cpp b/test/domains/gis/io/wkt/multi_wkt.cpp deleted file mode 100644 index 9e8e13c420..0000000000 --- a/test/domains/gis/io/wkt/multi_wkt.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// Unit Test - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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) - -//#include -#include -#include - -#include -#include - -#include -#include - -#include - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -template -void test_all(); - - -// Include the single test -#define GEOMETRY_TEST_MULTI -#include "domains/gis/io/wkt/wkt.cpp" - - - -template -void test_all() -{ - using namespace boost::geometry; - typedef bg::model::point P; - - test_wkt >("multipoint((1 2),(3 4))", 2); - test_wkt > >("multilinestring((1 1,2 2,3 3),(4 4,5 5,6 6))", 6, 4 * sqrt(2.0)); - test_wkt > >("multipolygon(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))", 15, 0, 21, 28); - - test_wrong_wkt > >( - "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),(0 0,0 4,4 4,4 0,0 0)))", - "expected '('"); -} - - - -/* - -... see comments in "wkt.cpp" - -union select 13,'# mpoint',npoints(geomfromtext('MULTIPOINT((1 2),(3 4))')) -union select 14,'length mpoint',length(geomfromtext('MULTIPOINT((1 2),(3 4))')) -union select 15,'peri mpoint',perimeter(geomfromtext('MULTIPOINT((1 2),(3 4))')) -union select 16,'area mpoint',area(geomfromtext('MULTIPOINT((1 2),(3 4))')) - -union select 17,'# mls',npoints(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))')) -union select 18,'length mls',length(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))')) -union select 19,'peri mls',perimeter(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))')) -union select 20,'area mls',area(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))')) - -union select 21,'# mpoly',npoints(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))')) -union select 22,'length mpoly',length(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))')) -union select 23,'peri mpoly',perimeter(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))')) -union select 24,'area mpoly',area(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))')) - -*/ diff --git a/test/domains/gis/io/wkt/multi_wkt.vcproj b/test/domains/gis/io/wkt/multi_wkt.vcproj deleted file mode 100644 index 366b2d8a4e..0000000000 --- a/test/domains/gis/io/wkt/multi_wkt.vcproj +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/domains/gis/io/wkt/wkt.cpp b/test/domains/gis/io/wkt/wkt.cpp deleted file mode 100644 index bb50e04163..0000000000 --- a/test/domains/gis/io/wkt/wkt.cpp +++ /dev/null @@ -1,232 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// Unit Test - -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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) - -//#include -#include -#include - -#include - -#include - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -template -void test_wkt(std::string const& wkt, std::size_t n, double len = 0, - double ar = 0, double peri = 0) -{ - G geometry; - - bg::read_wkt(wkt, geometry); - - /* - std::cout << "n=" << bg::num_points(geometry) - << " dim=" << bg::topological_dimension::value - << " length=" << bg::length(geometry) - << " area=" << bg::area(geometry) - << " perimeter=" << bg::perimeter(geometry) - << std::endl << "\t\tgeometry=" << dsv(geometry) - << std::endl; - */ - - BOOST_CHECK_EQUAL(bg::num_points(geometry), n); - BOOST_CHECK_CLOSE(double(bg::length(geometry)), len, 0.0001); - BOOST_CHECK_CLOSE(double(bg::area(geometry)), ar, 0.0001); - BOOST_CHECK_CLOSE(double(bg::perimeter(geometry)), peri, 0.0001); - - // String comparison: only for int/double/float etc - // GMP/CLN add +e01, L0, etc - if (boost::is_fundamental - < - typename bg::coordinate_type::type - >::type::value) - { - std::ostringstream out; - out << bg::wkt(geometry); - BOOST_CHECK_EQUAL(boost::to_upper_copy(out.str()), - boost::to_upper_copy(wkt)); - } -} - -template -void test_relaxed_wkt(std::string const& wkt, std::string const& expected) -{ - if (boost::is_fundamental - < - typename bg::coordinate_type::type - >::type::value) - { - std::string e; - G geometry; - bg::read_wkt(wkt, geometry); - std::ostringstream out; - out << bg::wkt(geometry); - - BOOST_CHECK_EQUAL(boost::to_upper_copy(out.str()), boost::to_upper_copy(expected)); - } -} - - - -template -void test_wrong_wkt(std::string const& wkt, std::string const& start) -{ - std::string e("no exception"); - G geometry; - try - { - bg::read_wkt(wkt, geometry); - } - catch(bg::read_wkt_exception const& ex) - { - e = ex.what(); - boost::to_lower(e); - } - BOOST_CHECK_MESSAGE(boost::starts_with(e, start), " Expected:" - << start << " Got:" << e << " with WKT: " << wkt); -} - -template -void test_wkt_output_iterator(std::string const& wkt) -{ - G geometry; - bg::read_wkt(wkt, std::back_inserter(geometry)); -} - - - -#ifndef GEOMETRY_TEST_MULTI -template -void test_all() -{ - using namespace boost::geometry; - typedef bg::model::point P; - - test_wkt

("POINT(1 2)", 1); - test_wkt >("LINESTRING(1 1,2 2,3 3)", 3, 2 * sqrt(2.0)); - test_wkt >("POLYGON((0 0,0 4,4 4,4 0,0 0)" - ",(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))", 15, 0, 18, 24); - - // Non OGC: a box defined by a polygon - //test_wkt >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 4, 0, 1, 4); - test_wkt >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 5, 0, 1, 4); - - // We accept empty sequences as well (much better than EMPTY)... - // ...or even POINT() (see below) - test_wkt >("LINESTRING()", 0, 0); - test_wkt >("POLYGON(())", 0); - // ... or even with empty holes - test_wkt >("POLYGON((),(),())", 0); - // which all make no valid geometries, but they can exist. - - // These WKT's are incomplete or abnormal but they are considered OK - test_relaxed_wkt

("POINT(1)", "POINT(1 0)"); - test_relaxed_wkt

("POINT()", "POINT(0 0)"); - test_relaxed_wkt >("LINESTRING(1,2,3)", - "LINESTRING(1 0,2 0,3 0)"); - test_relaxed_wkt

("POINT ( 1 2) ", "POINT(1 2)"); - test_relaxed_wkt

("POINT M ( 1 2)", "POINT(1 2)"); - test_relaxed_wkt >("BOX(1 1,2 2)", "POLYGON((1 1,1 2,2 2,2 1,1 1))"); - - test_relaxed_wkt >("LINESTRING EMPTY", "LINESTRING()"); - - test_relaxed_wkt >("POLYGON( ( ) , ( ) , ( ) )", - "POLYGON((),(),())"); - - // Wrong WKT's - test_wrong_wkt

("POINT(1 2", "expected ')'"); - test_wrong_wkt

("POINT 1 2)", "expected '('"); - test_wrong_wkt

("POINT(1 2,)", "expected ')'"); - test_wrong_wkt

("POINT(1 2)foo", "too much tokens at 'foo'"); - test_wrong_wkt

("POINT(1 2 3)", "expected ')'"); - test_wrong_wkt

("POINT(a 2 3)", "bad lexical cast"); - test_wrong_wkt

("POINT 2 3", "expected '('"); - test_wrong_wkt

("POINT Z (1 2 3)", "z only allowed"); - - test_wrong_wkt

("PIONT (1 2)", "should start with 'point'"); - - test_wrong_wkt >("LINESTRING())", "too much tokens"); - - test_wrong_wkt >("POLYGON((1 1,1 4,4 4,4 1,1 1)" - ",((2 2,2 3,3 3,3 2,2 2))", "bad lexical cast"); - - test_wrong_wkt >("BOX(1 1,2 2,3 3)", "box should have 2"); - test_wrong_wkt >("BOX(1 1,2 2) )", "too much tokens"); - - if (boost::is_floating_point::type::value - || ! boost::is_fundamental::type::value) - { - test_wkt

("POINT(1.1 2.1)", 1); - } - - // Deprecated: - // test_wkt_output_iterator >("LINESTRING(1 1,2 2,3 3)"); - // test_wkt_output_iterator >("POLYGON((1 1,2 2,3 3))"); -} -#endif - - -int test_main(int, char* []) -{ - test_all(); - test_all(); - -#if defined(HAVE_TTMATH) - test_all(); -#endif - - return 0; -} - -/* - -Results can be checked in PostGIS by query below, -or by MySQL (but replace length by glength and remove the perimeter) - -Note: -- PostGIS gives "3" for a numpoints of a multi-linestring of 6 points in total (!) - --> "npoints" should be taken for all geometries -- SQL Server 2008 gives "6" - select geometry::STGeomFromText('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))',0).STNumPoints() -- MySQL gives "NULL" - -select 1 as code,'np p' as header,npoints(geomfromtext('POINT(1 2)')) as contents -union select 2,'length point', length(geomfromtext('POINT(1 2)')) -union select 3,'peri point', perimeter(geomfromtext('POINT(1 2)')) -union select 4,'area point',area(geomfromtext('POINT(1 2)')) - - -union select 5,'# ls',npoints(geomfromtext('LINESTRING(1 1,2 2,3 3)')) -union select 6,'length ls',length(geomfromtext('LINESTRING(1 1,2 2,3 3)')) -union select 7,'peri ls',perimeter(geomfromtext('LINESTRING(1 1,2 2,3 3)')) -union select 8,'aera ls',area(geomfromtext('LINESTRING(1 1,2 2,3 3)')) - -union select 9,'# poly',npoints(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))')) -union select 10,'length poly',length(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))')) -union select 11,'peri poly',perimeter(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))')) -union select 12,'area poly',area(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))')) - -*/ diff --git a/test/domains/gis/io/wkt/wkt.vcproj b/test/domains/gis/io/wkt/wkt.vcproj deleted file mode 100644 index ebee61d151..0000000000 --- a/test/domains/gis/io/wkt/wkt.vcproj +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/geometries/adapted.cpp b/test/geometries/adapted.cpp index 2b5099e9b7..8c831f5519 100644 --- a/test/geometries/adapted.cpp +++ b/test/geometries/adapted.cpp @@ -95,15 +95,18 @@ void test_all() int test_main(int, char* []) { -/* test_all(); + test_all(); test_all >(); test_all >(); test_all >(); test_all >(); test_all >(); -*/ + + test_all >(); test_all >(); - //test_all >(); + test_all >(); + + test_all >(); return 0; } From 0be8dce98d1929f4cf2a55cfd8ef1488eea5e2a8 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 8 Jan 2012 12:07:33 +0000 Subject: [PATCH 035/135] Boost.Geometry merge after sync [SVN r76368] --- example/Jamfile.v2 | 6 +++--- example/c03_custom_linestring_example.cpp | 6 +++--- example/with_external_libs/x02_gd_example.cpp | 2 +- example/with_external_libs/x03_c_soci_example.cpp | 2 +- example/with_external_libs/x03_d_soci_example.cpp | 2 +- test/geometries/adapted.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 141ee1537b..7a17e84250 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -1,9 +1,9 @@ # Boost.Geometry (aka GGL, Generic Geometry Library) # Controls building of Boost.Geometry examples # -# Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2011 Mateusz Loskot, London, UK. +# Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +# 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 diff --git a/example/c03_custom_linestring_example.cpp b/example/c03_custom_linestring_example.cpp index 1561d1b54d..8c6fd36972 100644 --- a/example/c03_custom_linestring_example.cpp +++ b/example/c03_custom_linestring_example.cpp @@ -1,8 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// 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 diff --git a/example/with_external_libs/x02_gd_example.cpp b/example/with_external_libs/x02_gd_example.cpp index d740829f5f..2cc9cbae6d 100644 --- a/example/with_external_libs/x02_gd_example.cpp +++ b/example/with_external_libs/x02_gd_example.cpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2012 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) diff --git a/example/with_external_libs/x03_c_soci_example.cpp b/example/with_external_libs/x03_c_soci_example.cpp index 0f8a0d69b6..d9739763f4 100644 --- a/example/with_external_libs/x03_c_soci_example.cpp +++ b/example/with_external_libs/x03_c_soci_example.cpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. +// 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 diff --git a/example/with_external_libs/x03_d_soci_example.cpp b/example/with_external_libs/x03_d_soci_example.cpp index b3dbd69d1c..9f9c5096ae 100644 --- a/example/with_external_libs/x03_d_soci_example.cpp +++ b/example/with_external_libs/x03_d_soci_example.cpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. +// 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 diff --git a/test/geometries/adapted.cpp b/test/geometries/adapted.cpp index 8c831f5519..f1e7ed3a9e 100644 --- a/test/geometries/adapted.cpp +++ b/test/geometries/adapted.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2012 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 From 2c176018e34dbb3e171c70407b821f0fac9dbea7 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 15 Jan 2012 16:26:56 +0000 Subject: [PATCH 036/135] [Geometry] Merge / dsv only [SVN r76523] --- include/boost/geometry/multi/util/write_dsv.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/multi/util/write_dsv.hpp b/include/boost/geometry/multi/util/write_dsv.hpp index 4989620cd1..2ab97df8a5 100644 --- a/include/boost/geometry/multi/util/write_dsv.hpp +++ b/include/boost/geometry/multi/util/write_dsv.hpp @@ -1,8 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. From b9d85b89d5c7943307531ade3292c67b16fc249f Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 5 Feb 2012 18:47:13 +0000 Subject: [PATCH 037/135] Merged geometry fixes since 2011-01-15 [SVN r76904] --- include/boost/geometry/algorithms/append.hpp | 2 +- include/boost/geometry/algorithms/buffer.hpp | 2 +- .../boost/geometry/algorithms/centroid.hpp | 6 +- include/boost/geometry/algorithms/correct.hpp | 39 ++-- .../boost/geometry/algorithms/covered_by.hpp | 50 ++-- .../overlay/calculate_distance_policy.hpp | 3 + .../overlay/enrich_intersection_points.hpp | 6 +- .../algorithms/detail/overlay/follow.hpp | 12 +- .../overlay/get_intersection_points.hpp | 2 +- .../detail/overlay/get_turn_info.hpp | 93 ++++++-- .../detail/overlay/handle_tangencies.hpp | 24 +- .../detail/overlay/intersection_insert.hpp | 12 +- .../algorithms/detail/overlay/overlay.hpp | 21 +- .../detail/overlay/select_rings.hpp | 8 +- .../algorithms/detail/overlay/traverse.hpp | 8 +- .../detail/sections/range_by_section.hpp | 2 +- .../boost/geometry/algorithms/disjoint.hpp | 21 +- .../boost/geometry/algorithms/distance.hpp | 2 +- .../boost/geometry/algorithms/for_each.hpp | 4 +- .../boost/geometry/algorithms/simplify.hpp | 4 +- include/boost/geometry/algorithms/within.hpp | 47 ++-- .../geometry/arithmetic/cross_product.hpp | 110 +++++++++ .../boost/geometry/arithmetic/determinant.hpp | 76 +++++++ include/boost/geometry/io/wkt/iomanip.hpp | 14 +- include/boost/geometry/io/wkt/wkt.hpp | 6 +- .../geometry/multi/algorithms/convert.hpp | 4 +- .../geometry/multi/algorithms/correct.hpp | 6 +- .../geometry/multi/algorithms/covered_by.hpp | 6 +- .../multi/algorithms/intersection.hpp | 2 +- .../geometry/multi/algorithms/within.hpp | 5 +- include/boost/geometry/multi/multi.hpp | 6 +- .../boost/geometry/policies/relate/de9im.hpp | 8 - .../geometry/policies/relate/direction.hpp | 48 ++-- .../policies/relate/intersection_points.hpp | 31 ++- .../intersection_points_determinant.hpp | 176 --------------- .../relate/intersection_points_slope.hpp | 213 ------------------ .../boost/geometry/policies/relate/tupled.hpp | 9 - .../agnostic/hull_graham_andrew.hpp | 73 ++---- .../agnostic/simplify_douglas_peucker.hpp | 3 +- .../strategies/cartesian/area_surveyor.hpp | 11 +- .../strategies/cartesian/cart_intersect.hpp | 17 +- .../cartesian/centroid_bashein_detmer.hpp | 5 +- .../cartesian/distance_pythagoras.hpp | 22 +- .../strategies/cartesian/side_by_triangle.hpp | 11 +- .../strategies/strategy_transform.hpp | 2 +- .../transform/matrix_transformers.hpp | 4 +- .../boost/geometry/util/calculation_type.hpp | 176 +++++++++++++++ .../geometry/util/for_each_coordinate.hpp | 2 +- 48 files changed, 709 insertions(+), 705 deletions(-) create mode 100644 include/boost/geometry/arithmetic/cross_product.hpp create mode 100644 include/boost/geometry/arithmetic/determinant.hpp delete mode 100644 include/boost/geometry/policies/relate/intersection_points_determinant.hpp delete mode 100644 include/boost/geometry/policies/relate/intersection_points_slope.hpp create mode 100644 include/boost/geometry/util/calculation_type.hpp diff --git a/include/boost/geometry/algorithms/append.hpp b/include/boost/geometry/algorithms/append.hpp index 2ceae718d5..72b2bbadab 100644 --- a/include/boost/geometry/algorithms/append.hpp +++ b/include/boost/geometry/algorithms/append.hpp @@ -38,7 +38,7 @@ namespace detail { namespace append template struct append_no_action { - static inline void apply(Geometry& geometry, Point const& point, + static inline void apply(Geometry& , Point const& , int = 0, int = 0) { } diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index 7133acc730..e22e36addc 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -83,7 +83,7 @@ template struct buffer { static inline void apply(BoxIn const& box_in, T const& distance, - T const& chord_length, BoxIn& box_out) + T const& , BoxIn& box_out) { detail::buffer::buffer_box(box_in, distance, box_out); } diff --git a/include/boost/geometry/algorithms/centroid.hpp b/include/boost/geometry/algorithms/centroid.hpp index 473b54b708..69ad9fe829 100644 --- a/include/boost/geometry/algorithms/centroid.hpp +++ b/include/boost/geometry/algorithms/centroid.hpp @@ -191,7 +191,7 @@ struct centroid_range_state it != end; ++previous, ++it) { - Strategy::apply(*previous, *it, state); + strategy.apply(*previous, *it, state); } } }; @@ -211,7 +211,7 @@ struct centroid_range Closure, Strategy >::apply(range, strategy, state); - Strategy::result(state, centroid); + strategy.result(state, centroid); } } }; @@ -262,7 +262,7 @@ struct centroid_polygon Polygon, Strategy >::apply(poly, strategy, state); - Strategy::result(state, centroid); + strategy.result(state, centroid); } } }; diff --git a/include/boost/geometry/algorithms/correct.hpp b/include/boost/geometry/algorithms/correct.hpp index 9d2083238e..583e395f8e 100644 --- a/include/boost/geometry/algorithms/correct.hpp +++ b/include/boost/geometry/algorithms/correct.hpp @@ -80,7 +80,7 @@ struct correct_box_loop template struct correct_box_loop { - static inline void apply(Box& box) + static inline void apply(Box& ) {} }; @@ -147,7 +147,8 @@ struct correct_ring } // Check area Predicate predicate; - coordinate_type const zero = 0; + typedef typename default_area_result::type area_result_type; + area_result_type const zero = area_result_type(); if (predicate(ring_area_type::apply(r, strategy_type()), zero)) { std::reverse(boost::begin(r), boost::end(r)); @@ -161,14 +162,14 @@ template struct correct_polygon { typedef typename ring_type::type ring_type; - typedef typename coordinate_type::type coordinate_type; + typedef typename default_area_result::type area_result_type; static inline void apply(Polygon& poly) { correct_ring < ring_type, - std::less + std::less >::apply(exterior_ring(poly)); typename interior_return_type::type rings @@ -178,7 +179,7 @@ struct correct_polygon correct_ring < ring_type, - std::greater + std::greater >::apply(*it); } } @@ -193,48 +194,42 @@ struct correct_polygon namespace dispatch { -template -struct correct -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; +template ::type> +struct correct: not_implemented +{}; template -struct correct +struct correct : detail::correct::correct_nop {}; template -struct correct +struct correct : detail::correct::correct_nop {}; template -struct correct +struct correct : detail::correct::correct_nop {}; template -struct correct +struct correct : detail::correct::correct_box {}; template -struct correct +struct correct : detail::correct::correct_ring < Ring, - std::less::type> + std::less::type> > {}; template -struct correct +struct correct : detail::correct::correct_polygon {}; @@ -260,7 +255,7 @@ inline void correct(Geometry& geometry) { concept::check(); - dispatch::correct::type, Geometry>::apply(geometry); + dispatch::correct::apply(geometry); } diff --git a/include/boost/geometry/algorithms/covered_by.hpp b/include/boost/geometry/algorithms/covered_by.hpp index 6769bcd73d..8b1ddfc664 100644 --- a/include/boost/geometry/algorithms/covered_by.hpp +++ b/include/boost/geometry/algorithms/covered_by.hpp @@ -17,10 +17,9 @@ #include - +#include #include - #include #include @@ -33,34 +32,29 @@ namespace dispatch template < - typename Tag1, - typename Tag2, typename Geometry1, typename Geometry2, - typename Strategy + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type > -struct covered_by -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; +struct covered_by: not_implemented +{}; -template -struct covered_by +template +struct covered_by { + template static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { return strategy.apply(point, box); } }; -template -struct covered_by +template +struct covered_by { + template static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal(); @@ -70,10 +64,11 @@ struct covered_by -template -struct covered_by +template +struct covered_by { - static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy) + template + static inline bool apply(Point const& point, Ring const& ring, Strategy const& ) { return detail::within::point_in_ring < @@ -86,9 +81,10 @@ struct covered_by } }; -template -struct covered_by +template +struct covered_by { + template static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy) { return detail::within::point_in_polygon @@ -151,11 +147,8 @@ inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2) return dispatch::covered_by < - typename tag::type, - typename tag::type, Geometry1, - Geometry2, - strategy_type + Geometry2 >::apply(geometry1, geometry2, strategy_type()); } @@ -193,11 +186,8 @@ inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2, return dispatch::covered_by < - typename tag::type, - typename tag::type, Geometry1, - Geometry2, - Strategy + Geometry2 >::apply(geometry1, geometry2, strategy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp b/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp index 6cfdbe1b8d..3e6a8897f5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp @@ -30,6 +30,9 @@ namespace detail { namespace overlay */ struct calculate_distance_policy { + static bool const include_no_turn = false; + static bool const include_degenerate = false; + template static inline void apply(Info& info, Point1 const& p1, Point2 const& p2) { diff --git a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index 2193104c21..e4842d35f1 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -294,9 +294,9 @@ template > inline void enrich_assign(Container& operations, TurnPoints& turn_points, - operation_type for_operation, - Geometry1 const& geometry1, Geometry2 const& geometry2, - Strategy const& strategy) + operation_type , + Geometry1 const& , Geometry2 const& , + Strategy const& ) { typedef typename IndexType::type operations_type; typedef typename boost::range_iterator::type iterator_type; diff --git a/include/boost/geometry/algorithms/detail/overlay/follow.hpp b/include/boost/geometry/algorithms/detail/overlay/follow.hpp index 925c3edfa5..274cc47b8a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/follow.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -33,7 +33,7 @@ namespace following { template -static inline bool is_entering(Turn const& turn, Operation const& op) +static inline bool is_entering(Turn const& /* TODO remove this parameter */, Operation const& op) { // (Blocked means: blocked for polygon/polygon intersection, because // they are reversed. But for polygon/line it is similar to continue) @@ -126,10 +126,10 @@ struct action_selector typename Operation > static inline void enter(LineStringOut& current_piece, - LineString const& linestring, + LineString const& , segment_identifier& segment_id, - int index, Point const& point, - Operation const& operation, OutputIterator& out) + int , Point const& point, + Operation const& operation, OutputIterator& ) { // On enter, append the intersection point and remember starting point detail::overlay::append_no_duplicates(current_piece, point); @@ -148,7 +148,7 @@ struct action_selector LineString const& linestring, segment_identifier& segment_id, int index, Point const& point, - Operation const& operation, OutputIterator& out) + Operation const& , OutputIterator& out) { // On leave, copy all segments from starting point, append the intersection point // and add the output piece @@ -273,7 +273,7 @@ public : template static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon, - detail::overlay::operation_type operation, + detail::overlay::operation_type , // TODO: this parameter might be redundant Turns& turns, OutputIterator out) { typedef typename boost::range_iterator::type turn_iterator; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index 5456c0cb34..019c3ba3f9 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -51,7 +51,7 @@ struct get_turn_without_info static inline OutputIterator apply( Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, - TurnInfo const& tp_model, + TurnInfo const& , OutputIterator out) { typedef model::referring_segment segment_type1; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 82798c9fad..663d70d9af 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -23,6 +23,28 @@ namespace boost { namespace geometry { +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) +class turn_info_exception : public geometry::exception +{ + std::string message; +public: + + // NOTE: "char" will be replaced by enum in future version + inline turn_info_exception(char const method) + { + message = "Boost.Geometry Turn exception: "; + message += method; + } + + virtual ~turn_info_exception() throw() + {} + + virtual char const* what() const throw() + { + return message.c_str(); + } +}; +#endif #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay @@ -89,7 +111,7 @@ struct touch_interior : public base_turn_handler typename DirInfo > static inline void apply( - Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point1 const& pi, Point1 const& pj, Point1 const& , Point2 const& qi, Point2 const& qj, Point2 const& qk, TurnInfo& ti, IntersectionInfo const& intersection_info, @@ -399,10 +421,10 @@ struct equal : public base_turn_handler > static inline void apply( Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + Point2 const& , Point2 const& qj, Point2 const& qk, TurnInfo& ti, IntersectionInfo const& intersection_info, - DirInfo const& dir_info) + DirInfo const& ) { ti.method = method_equal; // Copy the SECOND intersection point @@ -656,8 +678,8 @@ struct crosses : public base_turn_handler typename DirInfo > static inline void apply( - Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + Point1 const& , Point1 const& , Point1 const& , + Point2 const& , Point2 const& , Point2 const& , TurnInfo& ti, IntersectionInfo const& intersection_info, DirInfo const& dir_info) @@ -677,6 +699,18 @@ struct crosses : public base_turn_handler } }; +template +struct only_convert +{ + template + static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info) + { + ti.method = method_collinear; + geometry::convert(intersection_info.intersections[0], ti.point); + ti.operations[0].operation = operation_continue; + ti.operations[1].operation = operation_continue; + } +}; /*! \brief Policy doing nothing @@ -686,8 +720,11 @@ struct crosses : public base_turn_handler */ struct assign_null_policy { + static bool const include_no_turn = false; + static bool const include_degenerate = false; + template - static inline void apply(Info& info, Point1 const& p1, Point2 const& p2) + static inline void apply(Info& , Point1 const& , Point2 const& ) {} }; @@ -703,14 +740,16 @@ struct assign_null_policy \tparam TurnInfo type of class getting intersection and turn info \tparam AssignPolicy policy to assign extra info, e.g. to calculate distance from segment's first points - to intersection points + to intersection points. + It also defines if a certain class of points + (degenerate, non-turns) should be included. */ template < typename Point1, typename Point2, typename TurnInfo, - typename AssignPolicy = assign_null_policy + typename AssignPolicy > struct get_turn_info { @@ -749,10 +788,20 @@ struct get_turn_info // Select method and apply switch(method) { - case 'a' : - case 'f' : - case 's' : - case 'd' : + case 'a' : // collinear, "at" + case 'f' : // collinear, "from" + case 's' : // starts from the middle + if (AssignPolicy::include_no_turn + && result.template get<0>().count > 0) + { + only_convert::apply(tp, + result.template get<0>()); + AssignPolicy::apply(tp, pi, qi); + *out++ = tp; + } + break; + + case 'd' : // disjoint: never do anything break; case 'm' : @@ -873,13 +922,23 @@ struct get_turn_info } break; case '0' : - // degenerate points - break; + { + // degenerate points + if (AssignPolicy::include_degenerate) + { + only_convert::apply(tp, result.template get<0>()); + AssignPolicy::apply(tp, pi, qi); + *out++ = tp; + } + } + break; default : -#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS - std::cout << "get_turns, nyi: " << method << std::endl; + { +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + throw turn_info_exception(method); #endif - break; + } + break; } return out; diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp index 11dde19749..1e878ca525 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp @@ -93,6 +93,7 @@ private : } +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH inline void debug_consider(int order, Indexed const& left, Indexed const& right, std::string const& header, bool skip = true, @@ -101,8 +102,6 @@ private : { if (skip) return; - -#ifdef BOOST_GEOMETRY_DEBUG_ENRICH point_type pi, pj, ri, rj, si, sj; geometry::copy_segment_points(m_geometry1, m_geometry2, left.subject.seg_id, @@ -151,14 +150,21 @@ private : std::cout << " " << extra << " " << (ret ? "true" : "false"); } std::cout << std::endl; -#endif } +#else + inline void debug_consider(int, Indexed const& , + Indexed const& , std::string const& , + bool = true, + std::string const& = "", bool = false + ) const + {} +#endif // ux/ux inline bool consider_ux_ux(Indexed const& left, Indexed const& right - , std::string const& header + , std::string const& // header ) const { bool ret = left.index < right.index; @@ -190,7 +196,7 @@ private : inline bool consider_iu_ux(Indexed const& left, Indexed const& right, int order // 1: iu first, -1: ux first - , std::string const& header + , std::string const& // header ) const { bool ret = false; @@ -234,7 +240,7 @@ private : inline bool consider_iu_ix(Indexed const& left, Indexed const& right, int order // 1: iu first, -1: ix first - , std::string const& header + , std::string const& // header ) const { //debug_consider(order, left, right, header, false, "iu/ix"); @@ -507,9 +513,9 @@ template > inline void inspect_cluster(Iterator begin_cluster, Iterator end_cluster, TurnPoints& turn_points, - operation_type for_operation, - Geometry1 const& geometry1, Geometry2 const& geometry2, - Strategy const& strategy) + operation_type , + Geometry1 const& , Geometry2 const& , + Strategy const& ) { int count = 0; diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 70a3653c4d..45324fc79e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -50,7 +50,7 @@ struct intersection_segment_segment_point { static inline OutputIterator apply(Segment1 const& segment1, Segment2 const& segment2, OutputIterator out, - Strategy const& strategy) + Strategy const& ) { typedef typename point_type::type point_type; @@ -86,7 +86,7 @@ struct intersection_linestring_linestring_point { static inline OutputIterator apply(Linestring1 const& linestring1, Linestring2 const& linestring2, OutputIterator out, - Strategy const& strategy) + Strategy const& ) { typedef typename point_type::type point_type; @@ -146,7 +146,7 @@ struct intersection_of_linestring_with_areal static inline OutputIterator apply(LineString const& linestring, Areal const& areal, OutputIterator out, - Strategy const& strategy) + Strategy const& ) { if (boost::size(linestring) == 0) { @@ -351,7 +351,7 @@ struct intersection_insert > { static inline OutputIterator apply(Linestring const& linestring, - Box const& box, OutputIterator out, Strategy const& strategy) + Box const& box, OutputIterator out, Strategy const& ) { typedef typename point_type::type point_type; strategy::intersection::liang_barsky lb_strategy; @@ -436,7 +436,7 @@ struct intersection_insert > { static inline OutputIterator apply(Segment const& segment, - Box const& box, OutputIterator out, Strategy const& strategy) + Box const& box, OutputIterator out, Strategy const& ) { geometry::segment_view range(segment); @@ -469,7 +469,7 @@ struct intersection_insert > { static inline OutputIterator apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, OutputIterator out, Strategy const& strategy) + Geometry2 const& geometry2, OutputIterator out, Strategy const& ) { typedef detail::overlay::turn_info turn_info; diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index 94f867df4c..ab5b6d123d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -145,11 +145,21 @@ struct overlay OutputIterator out, Strategy const& ) { - if (geometry::num_points(geometry1) == 0 && geometry::num_points(geometry2) == 0) + if (geometry::num_points(geometry1) == 0 + && geometry::num_points(geometry2) == 0) { return out; } + if (geometry::num_points(geometry1) == 0 + || geometry::num_points(geometry2) == 0) + { + return return_if_one_input_is_empty + < + GeometryOut, Direction, ReverseOut + >(geometry1, geometry2, out); + } + typedef typename geometry::point_type::type point_type; typedef detail::overlay::traversal_turn_info turn_info; typedef std::deque container_type; @@ -159,15 +169,6 @@ struct overlay typename geometry::ring_type::type > ring_container_type; - if (geometry::num_points(geometry1) == 0 - || geometry::num_points(geometry2) == 0) - { - return return_if_one_input_is_empty - < - GeometryOut, Direction, ReverseOut - >(geometry1, geometry2, out); - } - container_type turn_points; #ifdef BOOST_GEOMETRY_TIME_OVERLAY diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp index bde9262cfc..f664b19514 100644 --- a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -40,7 +40,7 @@ namespace dispatch struct select_rings { template - static inline void apply(Box const& box, Geometry const& geometry, + static inline void apply(Box const& box, Geometry const& , ring_identifier const& id, Map& map, bool midpoint) { map[id] = typename Map::mapped_type(box, midpoint); @@ -58,7 +58,7 @@ namespace dispatch struct select_rings { template - static inline void apply(Ring const& ring, Geometry const& geometry, + static inline void apply(Ring const& ring, Geometry const& , ring_identifier const& id, Map& map, bool midpoint) { if (boost::size(ring) > 0) @@ -129,7 +129,7 @@ template<> struct decide { template - static bool include(ring_identifier const& id, Code const& code) + static bool include(ring_identifier const& , Code const& code) { return code.within_code * -1 == 1; } @@ -162,7 +162,7 @@ template<> struct decide { template - static bool include(ring_identifier const& id, Code const& code) + static bool include(ring_identifier const& , Code const& code) { return code.within_code * 1 == 1; } diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index ab594e93e4..12daafa0cf 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -37,10 +37,10 @@ namespace detail { namespace overlay { template +#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE inline void debug_traverse(Turn const& turn, Operation op, std::string const& header) { -#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE std::cout << header << " at " << op.seg_id << " meth: " << method_char(turn.method) @@ -55,8 +55,12 @@ inline void debug_traverse(Turn const& turn, Operation op, { std::cout << std::endl; } -#endif } +#else +inline void debug_traverse(Turn const& , Operation, std::string const& ) +{ +} +#endif template diff --git a/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp b/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp index 24a8895166..ad62f232bd 100644 --- a/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp +++ b/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp @@ -36,7 +36,7 @@ namespace detail { namespace section template struct full_section_range { - static inline Range const& apply(Range const& range, Section const& section) + static inline Range const& apply(Range const& range, Section const& ) { return range; } diff --git a/include/boost/geometry/algorithms/disjoint.hpp b/include/boost/geometry/algorithms/disjoint.hpp index 67cba36a2d..8e378510f4 100644 --- a/include/boost/geometry/algorithms/disjoint.hpp +++ b/include/boost/geometry/algorithms/disjoint.hpp @@ -44,6 +44,19 @@ namespace boost { namespace geometry namespace detail { namespace disjoint { +struct assign_disjoint_policy +{ + // We want to include all points: + static bool const include_no_turn = true; + static bool const include_degenerate = true; + + // We don't assign extra info: + template + static inline void apply(Info& , Point1 const& , Point2 const& ) + {} +}; + + template struct disjoint_linear { @@ -54,12 +67,14 @@ struct disjoint_linear typedef overlay::turn_info turn_info; std::deque turns; - // Get (and stop on) any intersection + // Specify two policies: + // 1) Stop at any intersection + // 2) In assignment, include also degenerate points (which are normally skipped) disjoint_interrupt_policy policy; geometry::get_turns < - false, false, - overlay::assign_null_policy + false, false, + assign_disjoint_policy >(geometry1, geometry2, turns, policy); if (policy.has_intersections) { diff --git a/include/boost/geometry/algorithms/distance.hpp b/include/boost/geometry/algorithms/distance.hpp index 9b4a6476b3..eca3b03c7b 100644 --- a/include/boost/geometry/algorithms/distance.hpp +++ b/include/boost/geometry/algorithms/distance.hpp @@ -64,7 +64,7 @@ template struct point_to_segment { static inline typename return_type::type apply(Point const& point, - Segment const& segment, Strategy const& strategy) + Segment const& segment, Strategy const& ) { typename strategy::distance::services::default_strategy < diff --git a/include/boost/geometry/algorithms/for_each.hpp b/include/boost/geometry/algorithms/for_each.hpp index 10e1ee7e1b..c1e65459e4 100644 --- a/include/boost/geometry/algorithms/for_each.hpp +++ b/include/boost/geometry/algorithms/for_each.hpp @@ -55,8 +55,10 @@ template struct fe_point_per_segment { static inline Functor apply( - typename add_const_if_c::type& point, Functor f) + typename add_const_if_c::type& , Functor f) { + // TODO: if non-const, we should extract the points from the segment + // and call the functor on those two points return f; } }; diff --git a/include/boost/geometry/algorithms/simplify.hpp b/include/boost/geometry/algorithms/simplify.hpp index ff93e714f5..225321d303 100644 --- a/include/boost/geometry/algorithms/simplify.hpp +++ b/include/boost/geometry/algorithms/simplify.hpp @@ -67,7 +67,7 @@ struct simplify_copy { template static inline void apply(Range const& range, Range& out, - Distance const& max_distance, Strategy const& strategy) + Distance const& , Strategy const& ) { std::copy ( @@ -179,7 +179,7 @@ struct simplify { template static inline void apply(Point const& point, Point& out, - Distance const& max_distance, Strategy const& strategy) + Distance const& , Strategy const& ) { geometry::convert(point, out); } diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index d6fdb9b7ea..bff292422a 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -17,11 +17,11 @@ #include -#include #include #include #include +#include #include #include @@ -165,34 +165,29 @@ namespace dispatch template < - typename Tag1, - typename Tag2, typename Geometry1, typename Geometry2, - typename Strategy + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type > -struct within -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; +struct within: not_implemented +{}; -template -struct within +template +struct within { + template static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { return strategy.apply(point, box); } }; -template -struct within +template +struct within { + template static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal(); @@ -202,9 +197,10 @@ struct within -template -struct within +template +struct within { + template static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy) { return detail::within::point_in_ring @@ -218,9 +214,10 @@ struct within } }; -template -struct within +template +struct within { + template static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy) { return detail::within::point_in_polygon @@ -291,11 +288,8 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2) return dispatch::within < - typename tag::type, - typename tag::type, Geometry1, - Geometry2, - strategy_type + Geometry2 >::apply(geometry1, geometry2, strategy_type()); } @@ -344,11 +338,8 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2, return dispatch::within < - typename tag::type, - typename tag::type, Geometry1, - Geometry2, - Strategy + Geometry2 >::apply(geometry1, geometry2, strategy); } diff --git a/include/boost/geometry/arithmetic/cross_product.hpp b/include/boost/geometry/arithmetic/cross_product.hpp new file mode 100644 index 0000000000..47e7fe1056 --- /dev/null +++ b/include/boost/geometry/arithmetic/cross_product.hpp @@ -0,0 +1,110 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-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) + +#ifndef BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP +#define BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP + + +#include + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct cross_product +{ + // We define cross product only for 2d (see Wolfram) and 3d. + // In Math, it is also well-defined for 7-dimension. + // Generalisation of cross product to n-dimension is defined as + // wedge product but it is not direct analogue to binary cross product. +}; + +template +struct cross_product +{ + typedef P1 return_type; + + static inline return_type apply(P1 const& p1, P2 const& p2) + { + assert_dimension(); + assert_dimension(); + + // For 2-dimensions, analog of the cross product U(x,y) and V(x,y) is + // Ux * Vy - Uy * Vx + // which is returned as 0-component (or X) of 2d vector, 1-component is undefined. + return_type v; + set<0>(v, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2)); + return v; + } +}; + +template +struct cross_product +{ + typedef P1 return_type; + + static inline return_type apply(P1 const& p1, P2 const& p2) + { + assert_dimension(); + assert_dimension(); + + return_type v; + set<0>(v, get<1>(p1) * get<2>(p2) - get<2>(p1) * get<1>(p2)); + set<1>(v, get<2>(p1) * get<0>(p2) - get<0>(p1) * get<2>(p2)); + set<2>(v, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2)); + return v; + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +// TODO: This is a simple draft. If relevant, it can be extended to: +// - accept vectors of different coordinate_type, but common coordinate_system +// - if vectors are of mixed 2d and 3d, lower dimension is used +// - define result_type that will generate type of vector based on: +// -- select_coordinate_type +// -- selection of lower dimension + +/*! +\brief Computes the cross product of two vectors. +\details Both vectors shall be of the same type. + This type also determines type of result vector. +\ingroup arithmetic +\param p1 first vector +\param p2 second vector +\return the cross product vector + */ +template +inline P1 cross_product(P1 const& p1, P2 const& p2) +{ + BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + + return detail::cross_product + < + P1, P2, + dimension::type::value + >::apply(p1, p2); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP diff --git a/include/boost/geometry/arithmetic/determinant.hpp b/include/boost/geometry/arithmetic/determinant.hpp new file mode 100644 index 0000000000..db3b867096 --- /dev/null +++ b/include/boost/geometry/arithmetic/determinant.hpp @@ -0,0 +1,76 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-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) + +#ifndef BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP +#define BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP + + +#include + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +class calculate_determinant +{ + template + static inline ReturnType rt(T const& v) + { + return boost::numeric_cast(v); + } + +public : + + static inline ReturnType apply(U const& ux, U const& uy + , V const& vx, V const& vy) + { + return rt(ux) * rt(vy) - rt(uy) * rt(vx); + } +}; + +template +inline ReturnType determinant(U const& ux, U const& uy + , V const& vx, V const& vy) +{ + return calculate_determinant + < + ReturnType, U, V + >::apply(ux, uy, vx, vy); +} + + +template +inline ReturnType determinant(U const& u, V const& v) +{ + BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + + return calculate_determinant + < + ReturnType, + typename geometry::coordinate_type::type, + typename geometry::coordinate_type::type + >::apply(get<0>(u), get<1>(u), get<0>(v), get<1>(v)); +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP diff --git a/include/boost/geometry/io/wkt/iomanip.hpp b/include/boost/geometry/io/wkt/iomanip.hpp index 4221a1ef15..e7d65def36 100644 --- a/include/boost/geometry/io/wkt/iomanip.hpp +++ b/include/boost/geometry/io/wkt/iomanip.hpp @@ -17,23 +17,19 @@ #include // This short file contains only one manipulator, streaming as WKT -// Don't move contents to as_wkt, developers must be able to choose how to stream +// Don't include this in any standard-included header file. // Don't use namespace boost::geometry, to enable the library to stream custom geometries which -// are living outside the namespace boost { namespace geometry - -//namespace boost { namespace geometry -//{ - +// are living outside the namespace boost::geometry /*! \brief Streams a geometry as Well-Known Text \ingroup wkt */ template -inline std::basic_ostream& operator<< +inline std::basic_ostream& operator<< ( - std::basic_ostream &os, + std::basic_ostream &os, Geometry const& geom ) { @@ -41,6 +37,4 @@ inline std::basic_ostream& operator<< return os; } -//}} // namespace boost::geometry - #endif // BOOST_GEOMETRY_IO_WKT_IOMANIP_HPP diff --git a/include/boost/geometry/io/wkt/wkt.hpp b/include/boost/geometry/io/wkt/wkt.hpp index be388e3769..1efbc477d6 100644 --- a/include/boost/geometry/io/wkt/wkt.hpp +++ b/include/boost/geometry/io/wkt/wkt.hpp @@ -16,6 +16,10 @@ #include #include -#include + +// BSG 2011-02-03 +// We don't include iomanip by default. That tries to stream anything not known +// by default (such as ttmath) and reports errors. +// Users can include iomanip themselves (if they want to) #endif // BOOST_GEOMETRY_IO_WKT_WKT_HPP diff --git a/include/boost/geometry/multi/algorithms/convert.hpp b/include/boost/geometry/multi/algorithms/convert.hpp index 8d1007d2dd..4745791135 100644 --- a/include/boost/geometry/multi/algorithms/convert.hpp +++ b/include/boost/geometry/multi/algorithms/convert.hpp @@ -30,7 +30,7 @@ namespace detail { namespace conversion { template -struct single_to_multi +struct single_to_multi: private Policy { static inline void apply(Single const& single, Multi& multi) { @@ -42,7 +42,7 @@ struct single_to_multi template -struct multi_to_multi +struct multi_to_multi: private Policy { static inline void apply(Multi1 const& multi1, Multi2& multi2) { diff --git a/include/boost/geometry/multi/algorithms/correct.hpp b/include/boost/geometry/multi/algorithms/correct.hpp index feb99decac..d0c3e10753 100644 --- a/include/boost/geometry/multi/algorithms/correct.hpp +++ b/include/boost/geometry/multi/algorithms/correct.hpp @@ -32,19 +32,19 @@ namespace dispatch { template -struct correct +struct correct : detail::correct::correct_nop {}; template -struct correct +struct correct : detail::correct::correct_nop {}; template -struct correct +struct correct : detail::multi_modify < Geometry, diff --git a/include/boost/geometry/multi/algorithms/covered_by.hpp b/include/boost/geometry/multi/algorithms/covered_by.hpp index 0495662f61..ba398c0f42 100644 --- a/include/boost/geometry/multi/algorithms/covered_by.hpp +++ b/include/boost/geometry/multi/algorithms/covered_by.hpp @@ -15,6 +15,7 @@ #define BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP +#include #include #include #include @@ -29,9 +30,10 @@ namespace boost { namespace geometry namespace dispatch { -template -struct covered_by +template +struct covered_by { + template static inline bool apply(Point const& point, MultiPolygon const& multi_polygon, Strategy const& strategy) { diff --git a/include/boost/geometry/multi/algorithms/intersection.hpp b/include/boost/geometry/multi/algorithms/intersection.hpp index c918fcde00..e50292e60f 100644 --- a/include/boost/geometry/multi/algorithms/intersection.hpp +++ b/include/boost/geometry/multi/algorithms/intersection.hpp @@ -181,7 +181,7 @@ template struct clip_multi_linestring { static inline OutputIterator apply(MultiLinestring const& multi_linestring, - Box const& box, OutputIterator out, Strategy const& strategy) + Box const& box, OutputIterator out, Strategy const& ) { typedef typename point_type::type point_type; strategy::intersection::liang_barsky lb_strategy; diff --git a/include/boost/geometry/multi/algorithms/within.hpp b/include/boost/geometry/multi/algorithms/within.hpp index 9cb8523059..a3ec7514b7 100644 --- a/include/boost/geometry/multi/algorithms/within.hpp +++ b/include/boost/geometry/multi/algorithms/within.hpp @@ -69,9 +69,10 @@ struct geometry_multi_within_code namespace dispatch { -template -struct within +template +struct within { + template static inline bool apply(Point const& point, MultiPolygon const& multi_polygon, Strategy const& strategy) { diff --git a/include/boost/geometry/multi/multi.hpp b/include/boost/geometry/multi/multi.hpp index d9f836b69f..db33a9dd03 100644 --- a/include/boost/geometry/multi/multi.hpp +++ b/include/boost/geometry/multi/multi.hpp @@ -17,20 +17,21 @@ #include #include -#include #include +#include #include #include #include #include #include - +#include #include #include #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/geometry/policies/relate/de9im.hpp b/include/boost/geometry/policies/relate/de9im.hpp index a4ceb0630b..766d80b220 100644 --- a/include/boost/geometry/policies/relate/de9im.hpp +++ b/include/boost/geometry/policies/relate/de9im.hpp @@ -167,14 +167,6 @@ struct segments_de9im true); } - - static inline return_type parallel() - { - return de9im_segment(0,0, - -1, -1, 1, - -1, -1, 0, - 1, 0, 2, false, false, true); - } }; diff --git a/include/boost/geometry/policies/relate/direction.hpp b/include/boost/geometry/policies/relate/direction.hpp index 2ed1cc6087..9090d8b51e 100644 --- a/include/boost/geometry/policies/relate/direction.hpp +++ b/include/boost/geometry/policies/relate/direction.hpp @@ -15,6 +15,7 @@ #include +#include #include #include @@ -31,6 +32,8 @@ namespace policies { namespace relate struct direction_type { + // NOTE: "char" will be replaced by enum in future version + inline direction_type(side_info const& s, char h, int ha, int hb, int da = 0, int db = 0, @@ -60,6 +63,8 @@ struct direction_type } + // TODO: replace this + // NOTE: "char" will be replaced by enum in future version // "How" is the intersection formed? char how; @@ -235,20 +240,31 @@ struct segments_direction return return_type('d', false); } - - static inline return_type parallel() - { - return return_type('p', false); - } - - static inline return_type error(std::string const& msg) + static inline return_type error(std::string const&) { - // msg - return return_type('d', false); + // Return "E" to denote error + // This will throw an error in get_turn_info + // TODO: change to enum or similar + return return_type('E', false); } private : + static inline bool is_left + ( + coordinate_type const& ux, + coordinate_type const& uy, + coordinate_type const& vx, + coordinate_type const& vy + ) + { + // This is a "side calculation" as in the strategies, but here terms are precalculated + // We might merge this with side, offering a pre-calculated term (in fact already done using cross-product) + // Waiting for implementing spherical... + + rtype const zero = rtype(); + return geometry::detail::determinant(ux, uy, vx, vy) > zero; + } template static inline return_type calculate_side(side_info const& sides, @@ -259,11 +275,7 @@ private : coordinate_type dpx = get(s2) - get<0, 0>(s1); coordinate_type dpy = get(s2) - get<0, 1>(s1); - // This is a "side calculation" as in the strategies, but here two terms are precalculated - // We might merge this with side, offering a pre-calculated term - // Waiting for implementing spherical... - - return dx1 * dpy - dy1 * dpx > 0 + return is_left(dx1, dy1, dpx, dpy) ? return_type(sides, how, how_a, how_b, -1, 1) : return_type(sides, how, how_a, how_b, 1, -1); } @@ -277,7 +289,7 @@ private : coordinate_type dpx = get(s2) - get<0, 0>(s1); coordinate_type dpy = get(s2) - get<0, 1>(s1); - return dx1 * dpy - dy1 * dpx > 0 + return is_left(dx1, dy1, dpx, dpy) ? return_type(sides, how, how_a, how_b, 1, 1) : return_type(sides, how, how_a, how_b, -1, -1); } @@ -293,7 +305,7 @@ private : coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1); coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1); - int dir = dx1 * dpy - dy1 * dpx > 0 ? 1 : -1; + int dir = is_left(dx1, dy1, dpx, dpy) ? 1 : -1; // From other perspective, then reverse bool const is_a = which == 'A'; @@ -321,7 +333,7 @@ private : // Ending at the middle, one ARRIVES, the other one is NEUTRAL // (because it both "arrives" and "departs" there - return dx * dpy - dy * dpx > 0 + return is_left(dx, dy, dpx, dpy) ? return_type(sides, 'm', 1, 0, 1, 1) : return_type(sides, 'm', 1, 0, -1, -1); } @@ -334,7 +346,7 @@ private : coordinate_type dpx = get<1, 0>(s1) - get<0, 0>(s2); coordinate_type dpy = get<1, 1>(s1) - get<0, 1>(s2); - return dx * dpy - dy * dpx > 0 + return is_left(dx, dy, dpx, dpy) ? return_type(sides, 'm', 0, 1, 1, 1) : return_type(sides, 'm', 0, 1, -1, -1); } diff --git a/include/boost/geometry/policies/relate/intersection_points.hpp b/include/boost/geometry/policies/relate/intersection_points.hpp index 2c15f1e1d4..afd1dde501 100644 --- a/include/boost/geometry/policies/relate/intersection_points.hpp +++ b/include/boost/geometry/policies/relate/intersection_points.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -40,9 +41,6 @@ struct segments_intersection_points S1, S2, CalculationType >::type coordinate_type; - // Get the same type, but at least a double - typedef typename select_most_precise::type rtype; - static inline return_type segments_intersect(side_info const&, coordinate_type const& dx1, coordinate_type const& dy1, coordinate_type const& dx2, coordinate_type const& dy2, @@ -54,7 +52,7 @@ struct segments_intersection_points typename return_type::point_type >::type coordinate_type; - // Get the same type, but at least a double (also used for divisions + // Get the same type, but at least a double (also used for divisions) typedef typename select_most_precise < coordinate_type, double @@ -66,19 +64,21 @@ struct segments_intersection_points // Calculate other determinants - Cramers rule promoted_type const wx = get<0, 0>(s1) - get<0, 0>(s2); promoted_type const wy = get<0, 1>(s1) - get<0, 1>(s2); - promoted_type const d = (dy2 * dx1) - (dx2 * dy1); - promoted_type const da = (promoted_type(dx2) * wy) - (promoted_type(dy2) * wx); + promoted_type const d = detail::determinant(dx1, dy1, dx2, dy2); + promoted_type const da = detail::determinant(dx2, dy2, wx, wy); // r: ratio 0-1 where intersection divides A/B promoted_type r = da / d; + promoted_type const zero = promoted_type(); + promoted_type const one = 1; // Handle robustness issues - if (r < 0) + if (r < zero) { - r = 0; + r = zero; } - else if (r > 1) + else if (r > one) { - r = 1; + r = one; } result.count = 1; @@ -120,7 +120,7 @@ struct segments_intersection_points return collinear_inside(s, index1, 1 - index1); } - static inline return_type collinear_a_in_b(S1 const& s, bool opposite) + static inline return_type collinear_a_in_b(S1 const& s, bool) { return collinear_inside(s); } @@ -144,7 +144,7 @@ struct segments_intersection_points return result; } - static inline return_type segment_equal(S1 const& s, bool opposite) + static inline return_type segment_equal(S1 const& s, bool) { return_type result; result.count = 2; @@ -160,7 +160,7 @@ struct segments_intersection_points { return return_type(); } - static inline return_type error(std::string const& msg) + static inline return_type error(std::string const&) { return return_type(); } @@ -169,10 +169,7 @@ struct segments_intersection_points { return return_type(); } - static inline return_type parallel() - { - return return_type(); - } + static inline return_type degenerate(S1 const& s, bool) { return_type result; diff --git a/include/boost/geometry/policies/relate/intersection_points_determinant.hpp b/include/boost/geometry/policies/relate/intersection_points_determinant.hpp deleted file mode 100644 index bf43ef5c03..0000000000 --- a/include/boost/geometry/policies/relate/intersection_points_determinant.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 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_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP -#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP - - -#include - -#include -#include - -#include -#include -#include -#include - - -namespace boost { namespace geometry -{ - -namespace policies { namespace relate -{ - - -template -struct segments_intersection_points -{ - typedef ReturnType return_type; - typedef S1 segment_type1; - typedef S2 segment_type2; - typedef typename select_calculation_type - < - S1, S2, CalculationType - >::type coordinate_type; - - // Get the same type, but at least a double - typedef typename select_most_precise::type rtype; - - static inline return_type segments_intersect(side_info const&, - coordinate_type const& dx1, coordinate_type const& dy1, - coordinate_type const& dx2, coordinate_type const& dy2, - S1 const& s1, S2 const& s2) - { - return_type result; - typedef typename geometry::coordinate_type - < - typename return_type::point_type - >::type coordinate_type; - - // Get the same type, but at least a double (also used for divisions - typedef typename select_most_precise - < - coordinate_type, double - >::type promoted_type; - - coordinate_type const s1x = get<0, 0>(s1); - coordinate_type const s1y = get<0, 1>(s1); - - // Calculate other determinants - Cramers rule - promoted_type const wx = get<0, 0>(s1) - get<0, 0>(s2); - promoted_type const wy = get<0, 1>(s1) - get<0, 1>(s2); - promoted_type const d = (dy2 * dx1) - (dx2 * dy1); - promoted_type const da = (dx2 * wy) - (dy2 * wx); - - // r: ratio 0-1 where intersection divides A/B - promoted_type const r = da / d; - - result.count = 1; - set<0>(result.intersections[0], - boost::numeric_cast(s1x + r * dx1)); - set<1>(result.intersections[0], - boost::numeric_cast(s1y + r * dy1)); - - return result; - } - - static inline return_type collinear_touch(coordinate_type const& x, - coordinate_type const& y, bool, char) - { - return_type result; - result.count = 1; - set<0>(result.intersections[0], x); - set<1>(result.intersections[0], y); - return result; - } - - template - static inline return_type collinear_inside(S const& s) - { - return_type result; - result.count = 2; - set<0>(result.intersections[0], get<0, 0>(s)); - set<1>(result.intersections[0], get<0, 1>(s)); - set<0>(result.intersections[1], get<1, 0>(s)); - set<1>(result.intersections[1], get<1, 1>(s)); - return result; - } - - template - static inline return_type collinear_interior_boundary_intersect(S const& s, bool, bool) - { - return collinear_inside(s); - } - - static inline return_type collinear_a_in_b(S1 const& s, bool) - { - return collinear_inside(s); - } - static inline return_type collinear_b_in_a(S2 const& s, bool) - { - return collinear_inside(s); - } - - static inline return_type collinear_overlaps( - coordinate_type const& x1, coordinate_type const& y1, - coordinate_type const& x2, coordinate_type const& y2, bool) - { - return_type result; - result.count = 2; - set<0>(result.intersections[0], x1); - set<1>(result.intersections[0], y1); - set<0>(result.intersections[1], x2); - set<1>(result.intersections[1], y2); - return result; - } - - static inline return_type segment_equal(S1 const& s, bool) - { - return_type result; - result.count = 2; - set<0>(result.intersections[0], get<0, 0>(s)); - set<1>(result.intersections[0], get<0, 1>(s)); - set<0>(result.intersections[1], get<1, 0>(s)); - set<1>(result.intersections[1], get<1, 1>(s)); - return result; - } - - static inline return_type disjoint() - { - return return_type(); - } - static inline return_type error(std::string const& msg) - { - return return_type(); - } - - static inline return_type collinear_disjoint() - { - return return_type(); - } - static inline return_type parallel() - { - return return_type(); - } - static inline return_type degenerate(S1 const& s, bool) - { - return_type result; - result.count = 1; - set<0>(result.intersections[0], get<0, 0>(s)); - set<1>(result.intersections[0], get<0, 1>(s)); - return result; - } -}; - - -}} // namespace policies::relate - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP diff --git a/include/boost/geometry/policies/relate/intersection_points_slope.hpp b/include/boost/geometry/policies/relate/intersection_points_slope.hpp deleted file mode 100644 index b5c9922cde..0000000000 --- a/include/boost/geometry/policies/relate/intersection_points_slope.hpp +++ /dev/null @@ -1,213 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 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_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP -#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP - - -#include - -#include -#include - -#include -#include -#include -#include - - -namespace boost { namespace geometry -{ - -namespace policies { namespace relate -{ - - -template -struct segments_intersection_points -{ - typedef ReturnType return_type; - typedef S1 segment_type1; - typedef S2 segment_type2; - typedef typename select_calculation_type - < - S1, S2, CalculationType - >::type coordinate_type; - - // Get the same type, but at least a double (also used for divisions - typedef typename select_most_precise - < - coordinate_type, double - >::type promoted_type; - - template - static inline return_type rico( - coordinate_type const& dm1, coordinate_type const& dn1, - coordinate_type const& dm2, coordinate_type const& dn2, - S1 const& s1, S2 const& s2) - { - promoted_type const a1 = dn1 / dm1; - promoted_type const a2 = dn2 / dm2; - promoted_type const da = a1 - a2; - - if (math::equals(da, 0)) - { - return rico<1 - Dimension>(dn1, dm1, dn2, dm2, s1, s2); - } - - promoted_type const b1 = get<0, Dimension>(s1) - a1 * get<0, 1 - Dimension>(s1); - promoted_type const b2 = get<0, Dimension>(s2) - a2 * get<0, 1 - Dimension>(s2); - - promoted_type const v = (b2 - b1) / da; - - return_type result; - result.count = 1; - set<1 - Dimension>(result.intersections[0], - boost::numeric_cast(v)); - set(result.intersections[0], - boost::numeric_cast(a1 * v + b1)); - return result; - } - - static inline return_type cross(S1 const& s1, S2 const& s2) - { - // Take one of first segment, and one of second segment - return_type result; - result.count = 1; - set<0>(result.intersections[0], get<0, 0>(s1)); - set<1>(result.intersections[0], get<0, 1>(s2)); - return result; - } - - - static inline return_type segments_intersect(side_info const& sides, - coordinate_type const& dx1, coordinate_type const& dy1, - coordinate_type const& dx2, coordinate_type const& dy2, - S1 const& s1, S2 const& s2) - { - bool vertical1 = math::equals(dx1, 0); - bool horizontal2 = math::equals(dy2, 0); - if (vertical1 && horizontal2) - { - return cross(s1, s2); - } - - bool vertical2 = math::equals(dx2, 0); - bool horizontal1 = math::equals(dy1, 0); - if (horizontal1 && vertical2) - { - return cross(s2, s1); - } - if (vertical1 || vertical2) - { - return rico<0>(dy1, dx1, dy2, dx2, s1, s2); - } - else - { - // Not crossing, take the most reasonable choice. - // We want to divide by the largest one. - //if ( - - return rico<1>(dx1, dy1, dx2, dy2, s1, s2); - } - } - - static inline return_type collinear_touch(coordinate_type const& x, - coordinate_type const& y, bool, char) - { - return_type result; - result.count = 1; - set<0>(result.intersections[0], x); - set<1>(result.intersections[0], y); - return result; - } - - template - static inline return_type collinear_inside(S const& s) - { - return_type result; - result.count = 2; - set<0>(result.intersections[0], get<0, 0>(s)); - set<1>(result.intersections[0], get<0, 1>(s)); - set<0>(result.intersections[1], get<1, 0>(s)); - set<1>(result.intersections[1], get<1, 1>(s)); - return result; - } - - template - static inline return_type collinear_interior_boundary_intersect(S const& s, bool, bool) - { - return collinear_inside(s); - } - - static inline return_type collinear_a_in_b(S1 const& s, bool) - { - return collinear_inside(s); - } - static inline return_type collinear_b_in_a(S2 const& s, bool) - { - return collinear_inside(s); - } - - static inline return_type collinear_overlaps( - coordinate_type const& x1, coordinate_type const& y1, - coordinate_type const& x2, coordinate_type const& y2, bool) - { - return_type result; - result.count = 2; - set<0>(result.intersections[0], x1); - set<1>(result.intersections[0], y1); - set<0>(result.intersections[1], x2); - set<1>(result.intersections[1], y2); - return result; - } - - static inline return_type segment_equal(S1 const& s, bool) - { - return_type result; - result.count = 2; - set<0>(result.intersections[0], get<0, 0>(s)); - set<1>(result.intersections[0], get<0, 1>(s)); - set<0>(result.intersections[1], get<1, 0>(s)); - set<1>(result.intersections[1], get<1, 1>(s)); - return result; - } - - static inline return_type disjoint() - { - return return_type(); - } - static inline return_type error(std::string const& msg) - { - return return_type(); - } - - static inline return_type collinear_disjoint() - { - return return_type(); - } - static inline return_type parallel() - { - return return_type(); - } - static inline return_type degenerate(S1 const& s, bool) - { - return_type result; - result.count = 1; - set<0>(result.intersections[0], get<0, 0>(s)); - set<1>(result.intersections[0], get<0, 1>(s)); - return result; - } -}; - - -}} // namespace policies::relate - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP diff --git a/include/boost/geometry/policies/relate/tupled.hpp b/include/boost/geometry/policies/relate/tupled.hpp index f74e667ed1..853a8a26a8 100644 --- a/include/boost/geometry/policies/relate/tupled.hpp +++ b/include/boost/geometry/policies/relate/tupled.hpp @@ -164,15 +164,6 @@ struct segments_tupled ); } - - static inline return_type parallel() - { - return boost::make_tuple - ( - Policy1::parallel(), - Policy2::parallel() - ); - } }; }} // namespace policies::relate diff --git a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp index 8ea91f006e..747c140754 100644 --- a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp +++ b/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp @@ -31,13 +31,6 @@ #include -// Temporary, comparing sorting, this can be removed in the end -//#define BOOST_GEOMETRY_USE_FLEX_SORT -//#define BOOST_GEOMETRY_USE_FLEX_SORT2 -#if defined(BOOST_GEOMETRY_USE_FLEX_SORT) -# include -#endif - namespace boost { namespace geometry { @@ -103,7 +96,7 @@ struct get_extremes } // Then compare with earlier - if (first && boost::size(range) > 0) + if (first) { // First time, assign left/right left = *left_it; @@ -178,62 +171,15 @@ struct assign_range } }; - template static inline void sort(Range& range) { typedef typename boost::range_value::type point_type; typedef geometry::less comparator; -#if defined(GGL_USE_FLEX_SORT) - - #if defined(GGL_USE_FLEX_SORT1) - typedef boost::detail::default_predicate - < - boost::sort_filter_cutoff - < - 18, - boost::detail::insert_sort_core, - boost::sort_filter_ground - < - 30, - boost::detail::heap_sort_core, - boost::detail::quick_sort_core - < - boost::pivot_median_of_three, - boost::default_partitionner - > - > - >, - comparator> my_sort; - my_sort sort; - #elif defined(GGL_USE_FLEX_SORT2) - - // 1, 5, 9, 18, 25: 0.75 - // 50: 0.81 - - typedef boost::detail::default_predicate - >, comparator - > barend_sort; - - barend_sort sort; - #else - #error Define sub-flex-sort - #endif - - sort(boost::begin(range), boost::end(range)); - -#else - std::sort - (boost::begin(range), boost::end(range), comparator()); -#endif + std::sort(boost::begin(range), boost::end(range), comparator()); } - } // namespace detail #endif // DOXYGEN_NO_DETAIL @@ -279,8 +225,15 @@ public : { // First pass. // Get min/max (in most cases left / right) points - // This makes use of the geometry::less/greater predicates with the optional - // direction template parameter to indicate x direction + // This makes use of the geometry::less/greater predicates + + // For the left boundary it is important that multiple points + // are sorted from bottom to top. Therefore the less predicate + // does not take the x-only template parameter (this fixes ticket #6019. + // For the right boundary it is not necessary (though also not harmful), + // because points are sorted from bottom to top in a later stage. + // For symmetry and to get often more balanced lower/upper halves + // we keep it. typedef typename geometry::detail::range_type::type range_type; @@ -293,8 +246,8 @@ public : < range_type, range_iterator, - geometry::less, - geometry::greater + geometry::less, + geometry::greater > extremes; geometry::detail::for_each_range(geometry, extremes); diff --git a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp index 76a00d6f98..4a1a22d1cf 100644 --- a/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp +++ b/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp @@ -60,8 +60,7 @@ namespace detail {} // Necessary for proper compilation - inline douglas_peucker_point operator=( - douglas_peucker_point const& other) + inline douglas_peucker_point operator=(douglas_peucker_point const& ) { return douglas_peucker_point(*this); } diff --git a/include/boost/geometry/strategies/cartesian/area_surveyor.hpp b/include/boost/geometry/strategies/cartesian/area_surveyor.hpp index c9a3e22c4c..74b63532c0 100644 --- a/include/boost/geometry/strategies/cartesian/area_surveyor.hpp +++ b/include/boost/geometry/strategies/cartesian/area_surveyor.hpp @@ -16,9 +16,11 @@ #include -#include -#include +#include +#include +#include +#include namespace boost { namespace geometry @@ -82,7 +84,8 @@ private : inline return_type area() const { return_type result = sum; - result /= 2; + return_type const two = 2; + result /= two; return result; } }; @@ -96,7 +99,7 @@ public : summation& state) { // SUM += x2 * y1 - x1 * y2; - state.sum += get<0>(p2) * get<1>(p1) - get<0>(p1) * get<1>(p2); + state.sum += detail::determinant(p2, p1); } static inline return_type result(summation const& state) diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index d0beeae5ca..2bf7b77676 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -120,7 +121,7 @@ struct relate_cartesian_segments coordinate_type const& dx_a, coordinate_type const& dy_a, coordinate_type const& dx_b, coordinate_type const& dy_b) { - // 1) Handle "disjoint", probably common case. + // 1) Handle "disjoint", common case. // per dimension, 2 cases: a_1----------a_2 b_1-------b_2 or B left of A coordinate_type ax_1, ax_2, bx_1, bx_2; bool ax_swapped = false, bx_swapped = false; @@ -136,7 +137,7 @@ struct relate_cartesian_segments bool ay_swapped = false, by_swapped = false; detail::segment_arrange::apply(a, ay_1, ay_2, ay_swapped); detail::segment_arrange::apply(b, by_1, by_2, by_swapped); - if (ay_2 < ay_1 || ay_1 > by_2) + if (ay_2 < by_1 || ay_1 > by_2) { return Policy::disjoint(); } @@ -199,13 +200,19 @@ struct relate_cartesian_segments coordinate_type, double >::type promoted_type; + // Calculate the determinant/2D cross product + // (Note, because we only check on zero, + // the order a/b does not care) + promoted_type const d = geometry::detail::determinant + < + promoted_type + >(dx_a, dy_a, dx_b, dy_b); - promoted_type const d = (dy_b * dx_a) - (dx_b * dy_a); // Determinant d should be nonzero. // If it is zero, we have an robustness issue here, // (and besides that we cannot divide by it) - if(math::equals(d, zero) && ! collinear) - //if(! collinear && sides.as_collinear()) + promoted_type const pt_zero = promoted_type(); + if(math::equals(d, pt_zero) && ! collinear) { #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION std::cout << "Determinant zero? Type : " diff --git a/include/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp b/include/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp index e696581cd4..8b42715e0b 100644 --- a/include/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp +++ b/include/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -177,7 +178,7 @@ public : calculation_type const y1 = boost::numeric_cast(get<1>(p1)); calculation_type const x2 = boost::numeric_cast(get<0>(p2)); calculation_type const y2 = boost::numeric_cast(get<1>(p2)); - calculation_type const ai = x1 * y2 - x2 * y1; + calculation_type const ai = geometry::detail::determinant(p1, p2); state.count++; state.sum_a2 += ai; state.sum_x += ai * (x1 + x2); @@ -187,7 +188,7 @@ public : static inline bool result(sums const& state, Point& centroid) { calculation_type const zero = calculation_type(); - if (state.count > 0 && state.sum_a2 != zero) + if (state.count > 0 && ! math::equals(state.sum_a2, zero)) { calculation_type const v3 = 3; calculation_type const a3 = v3 * state.sum_a2; diff --git a/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp b/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp index b8d5c453e5..51d2722663 100644 --- a/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp @@ -22,8 +22,7 @@ #include -#include -#include +#include @@ -82,7 +81,8 @@ template class pythagoras { public : - typedef typename select_calculation_type + + typedef typename util::calculation_type::geometric::binary < Point1, Point2, @@ -136,10 +136,14 @@ class pythagoras { typedef comparable::pythagoras comparable_type; public : - typedef typename promote_floating_point - < - typename services::return_type::type - >::type calculation_type; + typedef typename util::calculation_type::geometric::binary + < + Point1, + Point2, + CalculationType, + double, + double // promote integer to double + >::type calculation_type; /*! \brief applies the distance calculation using pythagoras @@ -219,7 +223,7 @@ struct get_comparable > { typedef comparable::pythagoras comparable_type; public : - static inline comparable_type apply(pythagoras const& input) + static inline comparable_type apply(pythagoras const& ) { return comparable_type(); } @@ -303,7 +307,7 @@ struct get_comparable > { typedef comparable::pythagoras comparable_type; public : - static inline comparable_type apply(comparable::pythagoras const& input) + static inline comparable_type apply(comparable::pythagoras const& ) { return comparable_type(); } diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index 7c4a9d6519..967090c50a 100644 --- a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp @@ -17,10 +17,9 @@ #include #include +#include #include - #include - #include @@ -66,7 +65,6 @@ public : CalculationType >::type coordinate_type; -//std::cout << "side: " << typeid(coordinate_type).name() << std::endl; coordinate_type const x = get<0>(p); coordinate_type const y = get<1>(p); @@ -87,7 +85,12 @@ public : promoted_type const dpx = x - sx1; promoted_type const dpy = y - sy1; - promoted_type const s = dx * dpy - dy * dpx; + promoted_type const s + = geometry::detail::determinant + ( + dx, dy, + dpx, dpy + ); promoted_type const zero = promoted_type(); return math::equals(s, zero) ? 0 diff --git a/include/boost/geometry/strategies/strategy_transform.hpp b/include/boost/geometry/strategies/strategy_transform.hpp index 550b41f366..7a1f060169 100644 --- a/include/boost/geometry/strategies/strategy_transform.hpp +++ b/include/boost/geometry/strategies/strategy_transform.hpp @@ -66,7 +66,7 @@ template struct transform_coordinates { template - static inline void transform(Src const& source, Dst& dest, T value) + static inline void transform(Src const& , Dst& , T ) { } }; diff --git a/include/boost/geometry/strategies/transform/matrix_transformers.hpp b/include/boost/geometry/strategies/transform/matrix_transformers.hpp index 32e3d07e40..68da240934 100644 --- a/include/boost/geometry/strategies/transform/matrix_transformers.hpp +++ b/include/boost/geometry/strategies/transform/matrix_transformers.hpp @@ -218,7 +218,7 @@ public : // constructor takes an optional third argument doing nothing. inline translate_transformer(coordinate_type const& translate_x, coordinate_type const& translate_y, - coordinate_type const& dummy = 0) + coordinate_type const& = 0) : ublas_transformer( 1, 0, translate_x, 0, 1, translate_y, @@ -275,7 +275,7 @@ class scale_transformer : public ublas_transformer public : inline scale_transformer(coordinate_type const& scale_x, coordinate_type const& scale_y, - coordinate_type const& dummy = 0) + coordinate_type const& = 0) : ublas_transformer( scale_x, 0, 0, 0, scale_y, 0, diff --git a/include/boost/geometry/util/calculation_type.hpp b/include/boost/geometry/util/calculation_type.hpp new file mode 100644 index 0000000000..aef58909e7 --- /dev/null +++ b/include/boost/geometry/util/calculation_type.hpp @@ -0,0 +1,176 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012 Bruno Lalande, Paris, France. +// Copyright (c) 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) + +#ifndef BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP +#define BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP + +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace util +{ + +namespace detail +{ + +struct default_integral +{ +#ifdef BOOST_HAS_LONG_LONG + typedef boost::long_long_type type; +#else + typedef int type; +#endif +}; + +/*! +\details Selects the most appropriate: + - if calculation type is specified (not void), that one is used + - else if type is non-fundamental (user defined e.g. ttmath), that one + - else if type is floating point, the specified default FP is used + - else it is integral and the specified default integral is used + */ +template +< + typename Type, + typename CalculationType, + typename DefaultFloatingPointCalculationType, + typename DefaultIntegralCalculationType +> +struct calculation_type +{ + BOOST_STATIC_ASSERT(( + boost::is_fundamental + < + DefaultFloatingPointCalculationType + >::type::value + )); + BOOST_STATIC_ASSERT(( + boost::is_fundamental + < + DefaultIntegralCalculationType + >::type::value + )); + + + typedef typename boost::mpl::if_ + < + boost::is_void, + typename boost::mpl::if_ + < + boost::is_floating_point, + typename select_most_precise + < + DefaultFloatingPointCalculationType, + Type + >::type, + typename select_most_precise + < + DefaultIntegralCalculationType, + Type + >::type + >::type, + CalculationType + >::type type; +}; + +} // namespace detail + + +namespace calculation_type +{ + +namespace geometric +{ + +template +< + typename Geometry, + typename CalculationType, + typename DefaultFloatingPointCalculationType = double, + typename DefaultIntegralCalculationType = detail::default_integral::type +> +struct unary +{ + typedef typename detail::calculation_type + < + typename geometry::coordinate_type::type, + CalculationType, + DefaultFloatingPointCalculationType, + DefaultIntegralCalculationType + >::type type; +}; + +template +< + typename Geometry1, + typename Geometry2, + typename CalculationType, + typename DefaultFloatingPointCalculationType = double, + typename DefaultIntegralCalculationType = detail::default_integral::type +> +struct binary +{ + typedef typename detail::calculation_type + < + typename select_coordinate_type::type, + CalculationType, + DefaultFloatingPointCalculationType, + DefaultIntegralCalculationType + >::type type; +}; + + +/*! +\brief calculation type (ternary, for three geometry types) + */ +template +< + typename Geometry1, + typename Geometry2, + typename Geometry3, + typename CalculationType, + typename DefaultFloatingPointCalculationType = double, + typename DefaultIntegralCalculationType = detail::default_integral::type +> +struct ternary +{ + typedef typename detail::calculation_type + < + typename select_most_precise + < + typename coordinate_type::type, + typename select_coordinate_type + < + Geometry2, + Geometry3 + >::type + >::type, + CalculationType, + DefaultFloatingPointCalculationType, + DefaultIntegralCalculationType + >::type type; +}; + +}} // namespace calculation_type::geometric + +} // namespace util + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP diff --git a/include/boost/geometry/util/for_each_coordinate.hpp b/include/boost/geometry/util/for_each_coordinate.hpp index 2726d50cd9..7a1f55b00b 100644 --- a/include/boost/geometry/util/for_each_coordinate.hpp +++ b/include/boost/geometry/util/for_each_coordinate.hpp @@ -54,7 +54,7 @@ struct coordinates_scanner < IsConst, Point - >::type& point, Op operation) + >::type& , Op operation) { return operation; } From c8bc3cc1e182690852630f76d2029b70fba59ced Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 12 Feb 2012 18:01:22 +0000 Subject: [PATCH 038/135] Boost.Geometry merge doc updates [SVN r77001] --- doc/compiling.qbk | 6 ++-- doc/concept/linestring.qbk | 12 ++++++- doc/concept/polygon.qbk | 2 +- doc/concept/ring.qbk | 1 + doc/generated/append_status.qbk | 5 +-- doc/geometry.qbk | 34 ++++++++++++++++--- doc/html/index.html | 18 +++++----- doc/introduction.qbk | 5 ++- doc/reference/algorithms/append.qbk | 6 ++++ doc/reference/algorithms/area.qbk | 4 +++ doc/reference/algorithms/buffer.qbk | 7 ++++ doc/reference/algorithms/centroid.qbk | 4 +++ doc/reference/algorithms/clear.qbk | 4 +++ .../algorithms/comparable_distance.qbk | 4 +++ doc/reference/algorithms/convert.qbk | 9 ++--- doc/reference/algorithms/convex_hull.qbk | 4 +++ doc/reference/algorithms/correct.qbk | 7 ++-- doc/reference/algorithms/covered_by.qbk | 13 ++++--- doc/reference/algorithms/difference.qbk | 4 +++ doc/reference/algorithms/disjoint.qbk | 15 ++++++++ doc/reference/algorithms/distance.qbk | 4 +++ doc/reference/algorithms/envelope.qbk | 15 ++++++++ doc/reference/algorithms/equals.qbk | 4 +++ doc/reference/algorithms/expand.qbk | 5 ++- doc/reference/algorithms/for_each_point.qbk | 16 +++++++++ doc/reference/algorithms/for_each_segment.qbk | 16 +++++++++ doc/reference/algorithms/intersection.qbk | 4 +++ doc/reference/algorithms/intersects.qbk | 5 +++ doc/reference/algorithms/length.qbk | 4 +++ doc/reference/algorithms/num_geometries.qbk | 4 +++ .../algorithms/num_interior_rings.qbk | 5 +++ doc/reference/algorithms/num_points.qbk | 6 ++++ doc/reference/algorithms/overlaps.qbk | 15 ++++++++ doc/reference/algorithms/perimeter.qbk | 8 +++++ doc/reference/algorithms/reverse.qbk | 6 ++-- doc/reference/algorithms/simplify.qbk | 17 ++++++++++ doc/reference/algorithms/sym_difference.qbk | 4 +++ doc/reference/algorithms/transform.qbk | 4 +++ doc/reference/algorithms/union.qbk | 5 +++ doc/reference/algorithms/unique.qbk | 6 ++-- doc/reference/algorithms/within.qbk | 5 +++ doc/reference/geometries/point.qbk | 3 ++ .../geometries/point_assign_warning.qbk | 16 +++++++++ doc/release_notes.qbk | 9 +++-- doc/src/examples/algorithms/append.cpp | 4 +-- .../boost/geometry/algorithms/disjoint.hpp | 4 ++- .../boost/geometry/algorithms/envelope.hpp | 10 ++---- .../boost/geometry/algorithms/for_each.hpp | 5 +++ .../boost/geometry/algorithms/intersects.hpp | 1 + .../boost/geometry/algorithms/overlaps.hpp | 4 ++- .../boost/geometry/geometries/point_xy.hpp | 3 ++ 51 files changed, 327 insertions(+), 54 deletions(-) create mode 100644 doc/reference/algorithms/disjoint.qbk create mode 100644 doc/reference/algorithms/envelope.qbk create mode 100644 doc/reference/algorithms/for_each_point.qbk create mode 100644 doc/reference/algorithms/for_each_segment.qbk create mode 100644 doc/reference/algorithms/overlaps.qbk create mode 100644 doc/reference/geometries/point_assign_warning.qbk diff --git a/doc/compiling.qbk b/doc/compiling.qbk index f1084deca6..f549fabd05 100644 --- a/doc/compiling.qbk +++ b/doc/compiling.qbk @@ -39,9 +39,11 @@ compilers: * 9.0 (__msvc__ 2008) [/reported by Trunk report May 8, 2011] * 8.0 (__msvc__ 2005) [/reported by Trunk report May 8, 2011] * gcc + * gcc 4.7.0 [/reported by Trunk report February 12, 2012] + * gcc 4.6.2 [/reported by Trunk report February 12, 2012] * gcc 4.6.1 [/reported by Trunk report May 8, 2011] - * gcc 4.6.0 (including C++0x) [/reported by Trunk report May 8, 2011] - * gcc 4.5.2 (including C++0x) [/reported by Trunk report May 8, 2011] + * gcc 4.6.0 [/reported by Trunk report May 8, 2011] + * gcc 4.5.2 [/reported by Trunk report May 8, 2011] * gcc 4.4.0 [/reported by Trunk report May 8, 2011] * gcc 4.3.4 [/reported by Trunk report March 26, 2011] * gcc 4.2.1 [/reported by Trunk report May 8, 2011] diff --git a/doc/concept/linestring.qbk b/doc/concept/linestring.qbk index 7d9902bc55..0cf21b7235 100644 --- a/doc/concept/linestring.qbk +++ b/doc/concept/linestring.qbk @@ -16,7 +16,7 @@ [concept Linestring..linestring] A linestring is ['a Curve with linear interpolation between Points]. -([@http://portal.opengeospatial.org/files/?artifact_id=25355 opengeospatial]). +(__ogc_sf__). [heading Concept Definition] @@ -27,9 +27,19 @@ The Linestring Concept is defined as following: * The type defined by the metafunction `range_value<...>::type` must fulfill the [link geometry.reference.concepts.concept_point Point Concept] +[heading Rules] + +Besides the Concepts, which are checks on compile-time, there are rules that +valid linestrings must fulfill. Most algorithms work on any linestring, so either +self-crossing or not. However, for correct results using the overlay algorithms +(intersection and difference algorithms in combination with a polygon) +self-intersections can disturb the process and result in incorrect results. + [heading Available Models] * [link geometry.reference.models.model_linestring model::linestring] * a std::vector (requires registration) * a std::deque (requires registration) +[see_boost_range_sample Linestring] + [endsect] diff --git a/doc/concept/polygon.qbk b/doc/concept/polygon.qbk index 9de46d8245..14f040ce8c 100644 --- a/doc/concept/polygon.qbk +++ b/doc/concept/polygon.qbk @@ -16,7 +16,7 @@ [concept Polygon..polygon] A polygon is ['A polygon is a planar surface defined by one exterior boundary and zero or more interior boundaries] -([@http://portal.opengeospatial.org/files/?artifact_id=25355 opengeospatial]). +(__ogc_sf__). So the definition of a Boost.Geometry polygon differs a bit from e.g. Wiki, where a polygon does not have holes. A polygon of Boost.Geometry is a polygon with or without holes. diff --git a/doc/concept/ring.qbk b/doc/concept/ring.qbk index 63c121d34a..67bc2d0cb4 100644 --- a/doc/concept/ring.qbk +++ b/doc/concept/ring.qbk @@ -41,5 +41,6 @@ on the rules a polygon (and also a ring) must fulfill. * a std::vector (requires `#include boost/geometry/geometries/adapted/std_as_ring.hpp>`) * a std::deque (requires `#include boost/geometry/geometries/adapted/std_as_ring.hpp>`) +[see_boost_range_sample Ring] [endsect] diff --git a/doc/generated/append_status.qbk b/doc/generated/append_status.qbk index ba69252021..51329f887d 100644 --- a/doc/generated/append_status.qbk +++ b/doc/generated/append_status.qbk @@ -1,3 +1,4 @@ +[/NOTE: adapted manually, multi-linestring/multi-polygon do compile but not run!] [heading Supported geometries] [table [[ ][Point][Range]] @@ -8,6 +9,6 @@ [[Ring][ [$img/ok.png] ][ [$img/ok.png] ]] [[Polygon][ [$img/ok.png] ][ [$img/ok.png] ]] [[MultiPoint][ [$img/ok.png] ][ [$img/ok.png] ]] -[[MultiLinestring][ [$img/ok.png] ][ [$img/ok.png] ]] -[[MultiPolygon][ [$img/ok.png] ][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPolygon][ [$img/nyi.png] ][ [$img/nyi.png] ]] ] diff --git a/doc/geometry.qbk b/doc/geometry.qbk index b492272653..8297e3de7c 100644 --- a/doc/geometry.qbk +++ b/doc/geometry.qbk @@ -12,7 +12,6 @@ [library Geometry [quickbook 1.5] - [version 1.49] [authors [Gehrels, Barend], [Lalande, Bruno], [Loskot, Mateusz]] [copyright 2009-2012 Barend Gehrels, Bruno Lalande, Mateusz Loskot] [purpose Documentation of Boost.Geometry library] @@ -61,10 +60,6 @@ [template qbk_ret[what] Returns [what]] [template qbk_out[what] GeometryOut is a [what]] -[template concept[name type] The [name] Concept describes the requirements for a [type] type. -All algorithms in Boost.Geometry will check any geometry arguments against the concept requirements.] - - [def __boost__ Boost] [def __boost_geometry__ Boost.Geometry] [def __boost_array__ Boost.Array] @@ -78,6 +73,35 @@ All algorithms in Boost.Geometry will check any geometry arguments against the c [def __ttmath__ [@http://www.ttmath.org/ ttmath]] [def __ogc__ [@http://www.opengeospatial.org OGC]] +[def __ogc_sf__ [@http://www.opengeospatial.org/standards/sfa OGC Simple Feature Specification]] + +[/Templates] +[template concept[name type] +The [name] Concept describes the requirements for a [type] type. +All algorithms in Boost.Geometry will check any geometry arguments against the concept requirements. +] + +[template heading_conformance_no_ogc[function] +[heading Conformance] +The function [function] is not defined by OGC. +] + +[template heading_conformance_ogc[function ogc_function] +[heading Conformance] +The function [function] implements function [ogc_function] from the __ogc_sf__. +] + +[template conformance_std[function std_function] +The function [function] conforms to the [std_function] of the C++ std-library. +] + +[template see_boost_range_sample[concept] +[note See also the sample in the [@../../../range/doc/html/range/reference/extending/method_2.html Boost.Range documentation] + showing how a type can be adapted to a Boost.Range to fulfill the concept of a [concept] +] +] + + [heading Contributions] Boost.Geometry contains contributions by: diff --git a/doc/html/index.html b/doc/html/index.html index 09c4188c77..7ed18f667c 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -1,10 +1,10 @@ -Chapter 1. Geometry 1.49 +Chapter 1. Geometry - + @@ -21,7 +21,7 @@

-Chapter 1. Geometry 1.49

+Chapter 1. Geometry

Barend Gehrels

@@ -34,7 +34,7 @@
-

+

Distributed under 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)

@@ -89,24 +89,24 @@ Alfredo Correa (adaption of Boost.Array)
  • - Adam Wulkiewicz (spatial indexes) [1] + Adam Wulkiewicz (spatial indexes) [1]
  • - Federico Fernández (spatial indexes) [2] + Federico Fernández (spatial indexes) [2]


  • -

    [1] +

    [1] Currently an extension

    -

    [2] +

    [2] Currently an extension

    - +

    Last revised: February 12, 2012 at 12:12:26 GMT

    Last revised: February 12, 2012 at 17:59:04 GMT


    diff --git a/doc/introduction.qbk b/doc/introduction.qbk index d368a39d7b..dfac965d50 100644 --- a/doc/introduction.qbk +++ b/doc/introduction.qbk @@ -38,10 +38,9 @@ The library follows existing conventions: * conventions from boost * conventions from the std library * conventions and names from one of the __ogc__ standards on geometry and, more - specificly, from the - [@http://portal.opengeospatial.org/files/?artifact_id=25355 Simple Feature Specification] + specificly, from the __ogc_sf__ -The library was released with Boost 1.47.0 and from that point on it is +The library was first released with Boost 1.47.0 and from that point on it is officially part of the Boost C++ Libraries. Latest stable version of the source code is included in the diff --git a/doc/reference/algorithms/append.qbk b/doc/reference/algorithms/append.qbk index d69335d724..3582dfbf44 100644 --- a/doc/reference/algorithms/append.qbk +++ b/doc/reference/algorithms/append.qbk @@ -10,6 +10,12 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ append] + +[heading_conformance_no_ogc __this_function__] + +[include generated/append_status.qbk] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/area.qbk b/doc/reference/algorithms/area.qbk index 225dbe05fc..e459ee5da5 100644 --- a/doc/reference/algorithms/area.qbk +++ b/doc/reference/algorithms/area.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ area] + +[heading_conformance_ogc __this_function__..Area] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/buffer.qbk b/doc/reference/algorithms/buffer.qbk index f4fdc639f1..c798daaabf 100644 --- a/doc/reference/algorithms/buffer.qbk +++ b/doc/reference/algorithms/buffer.qbk @@ -10,6 +10,13 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ buffer] + +[heading_conformance_ogc __this_function__..Buffer] +[note The current implemetation only enlarges a box, which is not defined by OGC. + A next version of the library will contain a more complete implementation +] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/centroid.qbk b/doc/reference/algorithms/centroid.qbk index 2b4cbf7549..12152cb46f 100644 --- a/doc/reference/algorithms/centroid.qbk +++ b/doc/reference/algorithms/centroid.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ centroid] + +[heading_conformance_ogc __this_function__..Centroid] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/clear.qbk b/doc/reference/algorithms/clear.qbk index 5b037500e2..969d6df84f 100644 --- a/doc/reference/algorithms/clear.qbk +++ b/doc/reference/algorithms/clear.qbk @@ -11,6 +11,10 @@ =============================================================================/] [def __is_cleared__ is cleared] +[def __this_function__ clear] + +[heading_conformance_no_ogc __this_function__] +[conformance_std __this_function__..__this_function__() method] [include generated/clear_status.qbk] diff --git a/doc/reference/algorithms/comparable_distance.qbk b/doc/reference/algorithms/comparable_distance.qbk index eec25f5008..99a6b372d5 100644 --- a/doc/reference/algorithms/comparable_distance.qbk +++ b/doc/reference/algorithms/comparable_distance.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ comparable_distance] + +[heading_conformance_no_ogc __this_function__] + [heading Behaviour] There is no (not yet) version with a strategy. diff --git a/doc/reference/algorithms/convert.qbk b/doc/reference/algorithms/convert.qbk index 981fb288e8..f5704cc0fe 100644 --- a/doc/reference/algorithms/convert.qbk +++ b/doc/reference/algorithms/convert.qbk @@ -10,9 +10,9 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] -[note convert is not defined within OGC or ISO] -[note convert is modelled as source -> target - (where assign is modelled as target := source)] +[def __this_function__ convert] + +[heading_conformance_no_ogc __this_function__] [include generated/convert_status.qbk] [note In this status matrix above: columns are source types @@ -29,4 +29,5 @@ Linear [heading See also] * [link geometry.reference.algorithms.assign.assign assign] - +[note convert is modelled as source -> target + (where assign is modelled as target := source)] diff --git a/doc/reference/algorithms/convex_hull.qbk b/doc/reference/algorithms/convex_hull.qbk index df428d95c9..492c99a5a2 100644 --- a/doc/reference/algorithms/convex_hull.qbk +++ b/doc/reference/algorithms/convex_hull.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ convex_hull] + +[heading_conformance_ogc __this_function__..ConvexHull()] + [include generated/convex_hull_status.qbk] [heading Complexity] diff --git a/doc/reference/algorithms/correct.qbk b/doc/reference/algorithms/correct.qbk index 6b547b9337..cb3f6d9027 100644 --- a/doc/reference/algorithms/correct.qbk +++ b/doc/reference/algorithms/correct.qbk @@ -11,6 +11,11 @@ =============================================================================/] [def __corrected__ is corrected] +[def __this_function__ correct] + +[heading_conformance_no_ogc __this_function__] + +[include generated/correct_status.qbk] [heading Behavior] [table @@ -22,8 +27,6 @@ [[__other__][__does_nothing__]] ] -[tip Correct is not defined within OGC or ISO] - [heading Complexity] Linear diff --git a/doc/reference/algorithms/covered_by.qbk b/doc/reference/algorithms/covered_by.qbk index 461aee8e24..0fb187f092 100644 --- a/doc/reference/algorithms/covered_by.qbk +++ b/doc/reference/algorithms/covered_by.qbk @@ -10,17 +10,20 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ covered_by] + +[heading_conformance_no_ogc __this_function__] +[note Both PostGIS and Oracle contain an algorithm with the same name and the + same functionality. + See the [@http://www.postgis.org/docs/ST_CoveredBy.html PostGIS documentation]. +] + [include generated/covered_by_status.qbk] [note In this status matrix above: columns are types of first parameter and rows are types of second parameter. So a point can be checked to be covered by a polygon, but not vice versa. ] -[note convert is not defined within OGC or ISO. However, both PostGIS - and Oracle contain an algorithm with the same name and the same functionality. - See the [@http://www.postgis.org/docs/ST_CoveredBy.html PostGIS documentation]. -] - [heading Complexity] Linear diff --git a/doc/reference/algorithms/difference.qbk b/doc/reference/algorithms/difference.qbk index e49e8332fd..3aaf54efdc 100644 --- a/doc/reference/algorithms/difference.qbk +++ b/doc/reference/algorithms/difference.qbk @@ -8,6 +8,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ difference] + +[heading_conformance_ogc __this_function__..Difference] + [include reference/algorithms/difference_behavior.qbk] [include reference/algorithms/geometry_rules.qbk] diff --git a/doc/reference/algorithms/disjoint.qbk b/doc/reference/algorithms/disjoint.qbk new file mode 100644 index 0000000000..6f5c8ef494 --- /dev/null +++ b/doc/reference/algorithms/disjoint.qbk @@ -0,0 +1,15 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + Copyright (c) 2009-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) +=============================================================================/] + +[def __this_function__ disjoint] + +[heading_conformance_ogc __this_function__..Disjoint] diff --git a/doc/reference/algorithms/distance.qbk b/doc/reference/algorithms/distance.qbk index dbb7592a41..d9c448cfe3 100644 --- a/doc/reference/algorithms/distance.qbk +++ b/doc/reference/algorithms/distance.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ distance] + +[heading_conformance_ogc __this_function__..Distance] + [include generated/distance_status.qbk] [heading Complexity] diff --git a/doc/reference/algorithms/envelope.qbk b/doc/reference/algorithms/envelope.qbk new file mode 100644 index 0000000000..97209a394e --- /dev/null +++ b/doc/reference/algorithms/envelope.qbk @@ -0,0 +1,15 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + Copyright (c) 2009-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) +=============================================================================/] + +[def __this_function__ envelope] + +[heading_conformance_ogc __this_function__..Envelope] diff --git a/doc/reference/algorithms/equals.qbk b/doc/reference/algorithms/equals.qbk index c5fd87baf2..b0159a90a7 100644 --- a/doc/reference/algorithms/equals.qbk +++ b/doc/reference/algorithms/equals.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ equals] + +[heading_conformance_ogc __this_function__..Equals] + [include generated/equals_status.qbk] [heading Complexity] diff --git a/doc/reference/algorithms/expand.qbk b/doc/reference/algorithms/expand.qbk index ce6fdaa2db..0b1c14bd77 100644 --- a/doc/reference/algorithms/expand.qbk +++ b/doc/reference/algorithms/expand.qbk @@ -10,8 +10,12 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ expand] [def __apply_expand__ Box is expanded to include the specified] +[heading_conformance_no_ogc __this_function__] + + [heading Behavior] [table [[Case] [Behavior] ] @@ -20,7 +24,6 @@ [[__box__ / __other__][__nyiversion__]] ] -[tip Expand is not defined within OGC or ISO] [note To use expand with another geometry type then specified, use expand(make_envelope(geometry)] [heading Complexity] diff --git a/doc/reference/algorithms/for_each_point.qbk b/doc/reference/algorithms/for_each_point.qbk new file mode 100644 index 0000000000..a48becbdaf --- /dev/null +++ b/doc/reference/algorithms/for_each_point.qbk @@ -0,0 +1,16 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + Copyright (c) 2009-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) +=============================================================================/] + +[def __this_function__ for_each_point] + +[heading_conformance_no_ogc __this_function__] +[conformance_std __this_function__..std::for_each function] diff --git a/doc/reference/algorithms/for_each_segment.qbk b/doc/reference/algorithms/for_each_segment.qbk new file mode 100644 index 0000000000..fbb9fc6218 --- /dev/null +++ b/doc/reference/algorithms/for_each_segment.qbk @@ -0,0 +1,16 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + Copyright (c) 2009-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) +=============================================================================/] + +[def __this_function__ for_each_segment] + +[heading_conformance_no_ogc __this_function__] +[conformance_std __this_function__..std::for_each function] diff --git a/doc/reference/algorithms/intersection.qbk b/doc/reference/algorithms/intersection.qbk index 88ead046ed..a4d2c9fbf2 100644 --- a/doc/reference/algorithms/intersection.qbk +++ b/doc/reference/algorithms/intersection.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ intersection] + +[heading_conformance_ogc __this_function__..Intersection] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/intersects.qbk b/doc/reference/algorithms/intersects.qbk index 7717f43b96..49aea23223 100644 --- a/doc/reference/algorithms/intersects.qbk +++ b/doc/reference/algorithms/intersects.qbk @@ -10,6 +10,11 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ intersects] + +[heading_conformance_ogc __this_function__..Intersects] +[? __one_parameter__ The version with one parameter is additional and not described in the OGC standard] + [heading Examples] [intersects_linestring] [intersects_linestring_output] diff --git a/doc/reference/algorithms/length.qbk b/doc/reference/algorithms/length.qbk index 98fbc5619b..c349f56e4f 100644 --- a/doc/reference/algorithms/length.qbk +++ b/doc/reference/algorithms/length.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ length] + +[heading_conformance_ogc __this_function__..Length] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/num_geometries.qbk b/doc/reference/algorithms/num_geometries.qbk index 7c7235753b..998d0b1552 100644 --- a/doc/reference/algorithms/num_geometries.qbk +++ b/doc/reference/algorithms/num_geometries.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ num_geometries] + +[heading_conformance_ogc __this_function__..NumGeometries] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/num_interior_rings.qbk b/doc/reference/algorithms/num_interior_rings.qbk index 8fdc0b08b4..abbe59e45c 100644 --- a/doc/reference/algorithms/num_interior_rings.qbk +++ b/doc/reference/algorithms/num_interior_rings.qbk @@ -10,6 +10,11 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ num_interior_ring] + +[heading_conformance_ogc __this_function__..NumInteriorRing] +[note __boost_geometry__ adds an "s"] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/num_points.qbk b/doc/reference/algorithms/num_points.qbk index 54865df288..b59ea1b09e 100644 --- a/doc/reference/algorithms/num_points.qbk +++ b/doc/reference/algorithms/num_points.qbk @@ -10,6 +10,12 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ num_points] + +[heading_conformance_ogc __this_function__..NumPoints] +[note __this_function__ can be called for any geometry and not just linestrings +(as the standard describes)] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/overlaps.qbk b/doc/reference/algorithms/overlaps.qbk new file mode 100644 index 0000000000..9f1a75265c --- /dev/null +++ b/doc/reference/algorithms/overlaps.qbk @@ -0,0 +1,15 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + Copyright (c) 2009-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) +=============================================================================/] + +[def __this_function__ overlaps] + +[heading_conformance_ogc __this_function__..Overlaps] diff --git a/doc/reference/algorithms/perimeter.qbk b/doc/reference/algorithms/perimeter.qbk index 69bace93f4..66d924542c 100644 --- a/doc/reference/algorithms/perimeter.qbk +++ b/doc/reference/algorithms/perimeter.qbk @@ -10,6 +10,14 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ perimeter] + +[heading_conformance_no_ogc __this_function__] +[note PostGIS contains an algorithm with the same name and the + same functionality. + See the [@http://www.postgis.org/docs/ST_Perimeter.html PostGIS documentation]. +] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/reverse.qbk b/doc/reference/algorithms/reverse.qbk index 9221d343d8..282964e298 100644 --- a/doc/reference/algorithms/reverse.qbk +++ b/doc/reference/algorithms/reverse.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ reverse] + +[heading_conformance_no_ogc __this_function__] +[conformance_std __this_function__..std::__this_function__ function] [heading Behavior] [table @@ -27,8 +31,6 @@ [note The reverse of a (multi)polygon or ring might make a valid geometry invalid because the (counter)clockwise orientation reverses.] -[tip Conforms to std::reverse functionality. It is not defined within OGC or ISO] - [heading Complexity] Linear diff --git a/doc/reference/algorithms/simplify.qbk b/doc/reference/algorithms/simplify.qbk index ed72d50eb3..9d0b718bd4 100644 --- a/doc/reference/algorithms/simplify.qbk +++ b/doc/reference/algorithms/simplify.qbk @@ -10,6 +10,23 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ simplify] + +[heading_conformance_no_ogc __this_function__] +[note PostGIS contains an algorithm with the same name and the + same functionality. + See the [@http://www.postgis.org/docs/ST_Simplify.html PostGIS documentation]. +] +[note SQL Server contains an algorithm Reduce() with the same functionality. + See the [@http://msdn.microsoft.com/en-us/library/bb933814.aspx MSDN documentation]. +] + +[heading Behavior] +Simplification is done using [@http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm Douglas-Peucker] (if the default strategy is used). +[note Geometries might become invalid by using simplify. The simplification +process might create self-intersections. +] + [heading Examples] [simplify] [simplify_output] diff --git a/doc/reference/algorithms/sym_difference.qbk b/doc/reference/algorithms/sym_difference.qbk index 9aee1e1281..549f077ae7 100644 --- a/doc/reference/algorithms/sym_difference.qbk +++ b/doc/reference/algorithms/sym_difference.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ sym_difference] + +[heading_conformance_ogc __this_function__..SymDifference] + [include reference/algorithms/difference_behavior.qbk] [include reference/algorithms/geometry_rules.qbk] diff --git a/doc/reference/algorithms/transform.qbk b/doc/reference/algorithms/transform.qbk index 470f170cb4..6b404b1174 100644 --- a/doc/reference/algorithms/transform.qbk +++ b/doc/reference/algorithms/transform.qbk @@ -10,6 +10,10 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ transform] + +[heading_conformance_no_ogc __this_function__] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/union.qbk b/doc/reference/algorithms/union.qbk index 9873d3a670..0a7a1099a8 100644 --- a/doc/reference/algorithms/union.qbk +++ b/doc/reference/algorithms/union.qbk @@ -10,6 +10,11 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ union] + +[heading_conformance_ogc __this_function__..Union] +[note __boost_geometry__ adds an underscore to avoid using the `union` keyword] + [heading Behavior] [table [[Case] [Behavior] ] diff --git a/doc/reference/algorithms/unique.qbk b/doc/reference/algorithms/unique.qbk index be6e03da94..92144dbf11 100644 --- a/doc/reference/algorithms/unique.qbk +++ b/doc/reference/algorithms/unique.qbk @@ -11,6 +11,10 @@ =============================================================================/] [def __applies_unique__ Removes all consecutive duplicate points] +[def __this_function__ unique] + +[heading_conformance_no_ogc __this_function__] +[conformance_std __this_function__..std::__this_function__ function] [heading Behavior] [table @@ -26,8 +30,6 @@ [[__multi_polygon__][__applies_unique__ in all contained polygons (all rings)]] ] -[tip Conforms to std::unique functionality. It is not defined within OGC or ISO] - [heading Complexity] Linear diff --git a/doc/reference/algorithms/within.qbk b/doc/reference/algorithms/within.qbk index 4eea2c448f..db63e07e33 100644 --- a/doc/reference/algorithms/within.qbk +++ b/doc/reference/algorithms/within.qbk @@ -10,6 +10,11 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] +[def __this_function__ within] + +[heading_conformance_ogc __this_function__..Within] +[note OGC defines within as completely within and not on the border. See the notes for within / on the border] + [include generated/within_status.qbk] [note In this status matrix above: columns are types of first parameter and rows are types of second parameter. So a point can be checked to be diff --git a/doc/reference/geometries/point.qbk b/doc/reference/geometries/point.qbk index d168fd5171..0d756a2b73 100644 --- a/doc/reference/geometries/point.qbk +++ b/doc/reference/geometries/point.qbk @@ -13,3 +13,6 @@ [heading Examples] [point] [point_output] + +[include reference/geometries/point_assign_warning.qbk] + diff --git a/doc/reference/geometries/point_assign_warning.qbk b/doc/reference/geometries/point_assign_warning.qbk new file mode 100644 index 0000000000..0ab0bc6c78 --- /dev/null +++ b/doc/reference/geometries/point_assign_warning.qbk @@ -0,0 +1,16 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + Copyright (c) 2009-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) +=============================================================================/] + +[heading Notes] +[note Coordinates are not initialized. If the constructor with parameters is not +called and points are not assigned using `set` or `assign` then the coordinate +values will contain garbage] diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 2385692149..752616e690 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -23,13 +23,14 @@ [*Bugfixes] * bugfix: distance for multi-geometries ignored specified distance strategy. Fixed -* bugfix in difference for polygon/multi_polygon (reported 2011/10/24 on GGL-list) +* bugfix: difference for polygon/multi_polygon (reported 2011/10/24 on GGL-list) * bugfix: raise exception for calculation of distances of multi-geometrie(s) where one of them is empty * bugfix: multi DSV did not correctly use settings, fixed * bugfix: self-intersections could sometimes be missed (introduced in 1.48), fixed * bugfix: convex hull crashed on empty range (e.g. empty multi point), fixed * bugfix: area/centroid/side/intersection/distance did not work for "int" type filled with large (but not overflowing) integers. Fixed. * bugfix: disjoint/intersect did not work for degenerate linestrings. Fixed. +* bugfix: covered_by did not compile for a ring. Fixed. [*Solved tickets] @@ -43,18 +44,20 @@ * support for line/polygon intersections and differences * support for convert of segment/box of different point types * support for append for multi point -* scalar functions (distance, area, length, perimeter) now throw an empty_input_exception on empty input +* the scalar function distance now throws an empty_input_exception on empty input [*Documentation] * updated support status in several algorithms +* updated conformance to OGC or std +* other updates and fixes [*Internal changes] * updates in specializations/not_implemented for distance/convert/assign/area/with/covered_by * move of wkt/dsv to io folder, making domains redundant * warnings: strategy concepts assigned to zero to avoid clang warnings (patched by Vishnu) -* warnings: there were several unused parameters, for which gcc/clang warned. Fixed. +* warnings: there were several unused parameters, for which gcc/clang warned (patched by Christophe) [/=================] [heading Boost 1.48] diff --git a/doc/src/examples/algorithms/append.cpp b/doc/src/examples/algorithms/append.cpp index b4a662bbac..f5a3085b5b 100644 --- a/doc/src/examples/algorithms/append.cpp +++ b/doc/src/examples/algorithms/append.cpp @@ -32,14 +32,14 @@ int main() // Append a range append(poly, tuple_list_of(0, 0)(0, 10)(11, 11)(10, 0)); /*< tuple_list_of delivers a range and can therefore be used in boost::geometry::append >*/ - // Append a point (in this case the closing point + // Append a point (in this case the closing point) append(poly, make_tuple(0, 0)); // Create an interior ring (append does not do this automatically) boost::geometry::interior_rings(poly).resize(1); // Append a range to the interior ring - append(poly, tuple_list_of(2, 2)(2, 5)(6, 6)(5, 2), 0); + append(poly, tuple_list_of(2, 2)(2, 5)(6, 6)(5, 2), 0); /*< The last parameter ring_index 0 denotes the first interior ring >*/ // Append a point to the first interior ring append(poly, make_tuple(2, 2), 0); diff --git a/include/boost/geometry/algorithms/disjoint.hpp b/include/boost/geometry/algorithms/disjoint.hpp index 8e378510f4..f36b8dbdd0 100644 --- a/include/boost/geometry/algorithms/disjoint.hpp +++ b/include/boost/geometry/algorithms/disjoint.hpp @@ -228,7 +228,9 @@ struct disjoint_reversed \param geometry1 \param_geometry \param geometry2 \param_geometry \return \return_check2{are disjoint} - */ + +\qbk{[include reference/algorithms/disjoint.qbk]} +*/ template inline bool disjoint(Geometry1 const& geometry1, Geometry2 const& geometry2) diff --git a/include/boost/geometry/algorithms/envelope.hpp b/include/boost/geometry/algorithms/envelope.hpp index 612541be14..da34f6a783 100644 --- a/include/boost/geometry/algorithms/envelope.hpp +++ b/include/boost/geometry/algorithms/envelope.hpp @@ -216,14 +216,7 @@ struct envelope \param geometry \param_geometry \param mbr \param_box \param_set{envelope} -\par Example: -Example showing envelope calculation, using point_ll latlong points -\dontinclude doxygen_1.cpp -\skip example_envelope_polygon -\line { -\until } - - +\qbk{[include reference/algorithms/envelope.qbk]} \qbk{ [heading Example] [envelope] [envelope_output] @@ -253,6 +246,7 @@ inline void envelope(Geometry const& geometry, Box& mbr) \param geometry \param_geometry \return \return_calc{envelope} +\qbk{[include reference/algorithms/envelope.qbk]} \qbk{ [heading Example] [return_envelope] [return_envelope_output] diff --git a/include/boost/geometry/algorithms/for_each.hpp b/include/boost/geometry/algorithms/for_each.hpp index c1e65459e4..671f26a70d 100644 --- a/include/boost/geometry/algorithms/for_each.hpp +++ b/include/boost/geometry/algorithms/for_each.hpp @@ -250,6 +250,7 @@ struct for_each_segment \tparam Functor \tparam_functor \qbk{distinguish,const version} +\qbk{[include reference/algorithms/for_each_point.qbk]} \qbk{[heading Example]} \qbk{[for_each_point_const] [for_each_point_const_output]} */ @@ -277,6 +278,7 @@ inline Functor for_each_point(Geometry const& geometry, Functor f) \tparam Geometry \tparam_geometry \tparam Functor \tparam_functor +\qbk{[include reference/algorithms/for_each_point.qbk]} \qbk{[heading Example]} \qbk{[for_each_point] [for_each_point_output]} */ @@ -305,6 +307,7 @@ inline Functor for_each_point(Geometry& geometry, Functor f) \tparam Functor \tparam_functor \qbk{distinguish,const version} +\qbk{[include reference/algorithms/for_each_segment.qbk]} \qbk{[heading Example]} \qbk{[for_each_segment_const] [for_each_segment_const_output]} */ @@ -331,6 +334,8 @@ inline Functor for_each_segment(Geometry const& geometry, Functor f) \param f \par_for_each_f{segment} \tparam Geometry \tparam_geometry \tparam Functor \tparam_functor + +\qbk{[include reference/algorithms/for_each_segment.qbk]} */ template inline Functor for_each_segment(Geometry& geometry, Functor f) diff --git a/include/boost/geometry/algorithms/intersects.hpp b/include/boost/geometry/algorithms/intersects.hpp index a319750aaa..f367f2e258 100644 --- a/include/boost/geometry/algorithms/intersects.hpp +++ b/include/boost/geometry/algorithms/intersects.hpp @@ -35,6 +35,7 @@ namespace boost { namespace geometry \return \return_check{is self-intersecting} \qbk{distinguish,one geometry} +\qbk{[def __one_parameter__]} \qbk{[include reference/algorithms/intersects.qbk]} */ template diff --git a/include/boost/geometry/algorithms/overlaps.hpp b/include/boost/geometry/algorithms/overlaps.hpp index 0ddef684c7..2f854b4fdd 100644 --- a/include/boost/geometry/algorithms/overlaps.hpp +++ b/include/boost/geometry/algorithms/overlaps.hpp @@ -179,7 +179,9 @@ struct overlaps \brief \brief_check2{overlap} \ingroup overlaps \return \return_check2{overlap} - */ + +\qbk{[include reference/algorithms/overlaps.qbk]} +*/ template inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2) { diff --git a/include/boost/geometry/geometries/point_xy.hpp b/include/boost/geometry/geometries/point_xy.hpp index 90a83cf5f5..652930666f 100644 --- a/include/boost/geometry/geometries/point_xy.hpp +++ b/include/boost/geometry/geometries/point_xy.hpp @@ -36,6 +36,9 @@ namespace model { namespace d2 [heading Model of] [link geometry.reference.concepts.concept_point Point Concept] } + +\qbk{[include reference/geometries/point_assign_warning.qbk]} + */ template class point_xy : public model::point From 30ae1548b9da084b91862079cf8940bf50fb9a60 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Thu, 23 Feb 2012 18:42:40 +0000 Subject: [PATCH 039/135] Boost.Geometry doc-update empty-sub-table for pdf-generation 1.49 [SVN r77100] --- doc/quickref.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/quickref.xml b/doc/quickref.xml index 906ffd005a..153fb4893d 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -112,8 +112,6 @@ 1-dimensional (adapted) - - 2-dimensional (adapted) From 547e49d38860acc2c8e08bf1f2bcfc967281b4c9 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Mon, 28 May 2012 13:04:24 +0000 Subject: [PATCH 040/135] [geometry] merge since today's r78712 [SVN r78717] --- doc/doxy/doxygen_input/groups/groups.hpp | 1 + doc/make_qbk.py | 2 +- doc/quickref.xml | 1 + doc/reference.qbk | 4 ++++ doc/release_notes.qbk | 2 ++ .../boost/geometry/algorithms/detail/partition.hpp | 12 ++++++------ include/boost/geometry/geometry.hpp | 1 + 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/doc/doxy/doxygen_input/groups/groups.hpp b/doc/doxy/doxygen_input/groups/groups.hpp index d141f6e12d..a6f1d88564 100644 --- a/doc/doxy/doxygen_input/groups/groups.hpp +++ b/doc/doxy/doxygen_input/groups/groups.hpp @@ -58,6 +58,7 @@ \defgroup strategies strategies: strategies \defgroup svg x Extension svg: Stream SVG (Scalable Vector Graphics) \defgroup sym_difference sym_difference: sym_difference of two geometries +\defgroup touches touches: detect if a geometry self-touches or if two geometries touch \defgroup traits traits: adapt geometries \defgroup transform transform: apply transformations on geometries \defgroup union union: calculate new geometry containing geometries A or B diff --git a/doc/make_qbk.py b/doc/make_qbk.py index 0fc3b97ab9..74aa52995c 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -73,7 +73,7 @@ def cs_to_quickbook(section): , "envelope", "equals", "expand", "for_each", "intersection", "intersects" , "length", "num_geometries", "num_interior_rings", "num_points" , "overlaps", "perimeter", "reverse", "simplify", "sym_difference" - , "transform", "union", "unique", "within"] + , "touches", "transform", "union", "unique", "within"] access_functions = ["get", "set", "exterior_ring", "interior_rings" , "num_points", "num_interior_rings", "num_geometries"] diff --git a/doc/quickref.xml b/doc/quickref.xml index 153fb4893d..2a70b4612f 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -322,6 +322,7 @@ equals intersects overlaps + touches within diff --git a/doc/reference.qbk b/doc/reference.qbk index d665e087cd..a9a2192b94 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -143,6 +143,10 @@ [include generated/sym_difference.qbk] [/endsect] +[section:touches touches] +[include generated/touches.qbk] +[endsect] + [section:transform transform] [include generated/transform.qbk] [endsect] diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index fb8226c0c8..6d31b9378b 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -19,6 +19,7 @@ [*Breaking changes] [*Bugfixes] + * the return type of comparable projected point strategy for integer points was wrong (integer), fixed * several robustness issues in intersection of segments and polygons, fixed * invalid intersection output is filtered out @@ -33,6 +34,7 @@ * [@https://svn.boost.org/trac/boost/ticket/6696 6696] invalid intersection output, was (by chance) already fixed in Trunk before reported [*Additional functionality] + * added algorithm "touches" (OGC SF compliant) for *polygon/*polygon [*Documentation] diff --git a/include/boost/geometry/algorithms/detail/partition.hpp b/include/boost/geometry/algorithms/detail/partition.hpp index be98fb4e93..45ff52ccb1 100644 --- a/include/boost/geometry/algorithms/detail/partition.hpp +++ b/include/boost/geometry/algorithms/detail/partition.hpp @@ -158,7 +158,7 @@ class partition_one_collection { if (boost::size(input) > 0) { - if (boost::size(input) > min_elements && level < 100) + if (std::size_t(boost::size(input)) > min_elements && level < 100) { sub_divide::apply(box, collection, input, level + 1, min_elements, policy, box_policy); @@ -235,8 +235,8 @@ class partition_two_collections { if (boost::size(input1) > 0 && boost::size(input2) > 0) { - if (boost::size(input1) > min_elements - && boost::size(input2) > min_elements + if (std::size_t(boost::size(input1)) > min_elements + && std::size_t(boost::size(input2)) > min_elements && level < 100) { sub_divide::apply(box, collection1, input1, collection2, @@ -339,7 +339,7 @@ public : VisitBoxPolicy box_visitor = visit_no_policy() ) { - if (boost::size(collection) > min_elements) + if (std::size_t(boost::size(collection)) > min_elements) { index_vector_type index_vector; Box total; @@ -381,8 +381,8 @@ public : VisitBoxPolicy box_visitor = visit_no_policy() ) { - if (boost::size(collection1) > min_elements - && boost::size(collection2) > min_elements) + if (std::size_t(boost::size(collection1)) > min_elements + && std::size_t(boost::size(collection2)) > min_elements) { index_vector_type index_vector1, index_vector2; Box total; diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp index 22d08e2a45..b696b652cf 100644 --- a/include/boost/geometry/geometry.hpp +++ b/include/boost/geometry/geometry.hpp @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include From d55936194dc8b952ccffc740c6b13359349371e8 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Mon, 28 May 2012 16:44:06 +0000 Subject: [PATCH 041/135] [geometry] merge since todays r78718 [SVN r78724] --- test/algorithms/difference.cpp | 2 +- test/algorithms/overlay/get_turns.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/algorithms/difference.cpp b/test/algorithms/difference.cpp index 1d48fc7b85..e72af3c24b 100644 --- a/test/algorithms/difference.cpp +++ b/test/algorithms/difference.cpp @@ -7,7 +7,7 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#define TEST_ISOVIST +// #define TEST_ISOVIST //#define BOOST_GEOMETRY_CHECK_WITH_POSTGIS diff --git a/test/algorithms/overlay/get_turns.cpp b/test/algorithms/overlay/get_turns.cpp index 07c401c3b9..cfeb4ca07b 100644 --- a/test/algorithms/overlay/get_turns.cpp +++ b/test/algorithms/overlay/get_turns.cpp @@ -304,9 +304,10 @@ void test_all() ggl_list_20110306_javier[0], ggl_list_20110306_javier[1]); #ifdef _MSC_VER // gcc returns 14 for float - test_get_turns::apply("ggl_list_20110716_enrico", - 13, - ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1]); + // test_get_turns::apply("ggl_list_20110716_enrico", + // 13, + // ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1]); + #endif // pies From ab7ea123f8a96df7d57aef6a80c1b7f398910e7c Mon Sep 17 00:00:00 2001 From: John Maddock Date: Thu, 7 Jun 2012 16:47:33 +0000 Subject: [PATCH 042/135] Update Jamfiles and build scripts for PDF generation. Set local_function image DPI's for better PDF builds. [SVN r78849] --- doc/Jamfile.v2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index c9e77c4e02..6b938b8a54 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -41,3 +41,5 @@ boostbook geometry pdf:img.src.path=$(images_location)/ ; +install pdf-install : geometry : . geometry.pdf PDF ; + From acf672695fba0a5b2243879104236bd83e28c75b Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Thu, 7 Jun 2012 18:43:44 +0000 Subject: [PATCH 043/135] [geometry] merged revision 78724 thru 7880 w.r.t. bugfixes [SVN r78852] --- doc/html/index.html | 12 ++++++------ .../algorithms/detail/overlay/get_turns.hpp | 13 ++++++++++--- .../geometry/algorithms/detail/overlay/overlay.hpp | 2 +- .../geometry/algorithms/detail/point_on_border.hpp | 9 ++++++--- test/algorithms/disjoint.cpp | 9 +++++++++ 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/doc/html/index.html b/doc/html/index.html index 7ed18f667c..47e629047e 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -34,7 +34,7 @@
    -

    +

    Distributed under 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)

    @@ -89,24 +89,24 @@ Alfredo Correa (adaption of Boost.Array)
  • - Adam Wulkiewicz (spatial indexes) [1] + Adam Wulkiewicz (spatial indexes) [1]
  • - Federico Fernández (spatial indexes) [2] + Federico Fernández (spatial indexes) [2]


  • -

    [1] +

    [1] Currently an extension

    -

    [2] +

    [2] Currently an extension

    - +

    Last revised: February 12, 2012 at 17:59:04 GMT

    Last revised: May 28, 2012 at 16:44:23 GMT


    diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 5740a8b7ba..26629043cb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -495,7 +495,7 @@ struct get_turns_cs int source_id1, Range const& range, int source_id2, Box const& box, Turns& turns, - InterruptPolicy& , + InterruptPolicy& interrupt_policy, int multi_index = -1, int ring_index = -1) { if (boost::size(range) <= 1) @@ -557,7 +557,7 @@ struct get_turns_cs get_turns_with_box(seg_id, source_id2, *prev, *it, *next, bp[0], bp[1], bp[2], bp[3], - turns); + turns, interrupt_policy); // Future performance enhancement: // return if told by the interrupt policy } @@ -596,7 +596,8 @@ struct get_turns_cs box_point_type const& bp2, box_point_type const& bp3, // Output - Turns& turns) + Turns& turns, + InterruptPolicy& interrupt_policy) { // Depending on code some relations can be left out @@ -622,6 +623,12 @@ struct get_turns_cs ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3); TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1, ti, std::back_inserter(turns)); + + if (InterruptPolicy::enabled) + { + interrupt_policy.apply(turns); + } + } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index ab5b6d123d..41665e0af1 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -233,7 +233,7 @@ std::cout << "traverse" << std::endl; std::cout << "map_turns: " << timer.elapsed() << std::endl; #endif - typedef ring_properties::type> properties; + typedef ring_properties::type> properties; std::map selected; select_rings(geometry1, geometry2, map, selected, ! turn_points.empty()); diff --git a/include/boost/geometry/algorithms/detail/point_on_border.hpp b/include/boost/geometry/algorithms/detail/point_on_border.hpp index 33177924aa..b7e15ba3f9 100644 --- a/include/boost/geometry/algorithms/detail/point_on_border.hpp +++ b/include/boost/geometry/algorithms/detail/point_on_border.hpp @@ -25,6 +25,7 @@ #include #include +#include #include @@ -50,7 +51,8 @@ struct get_point template struct midpoint_helper { - static inline bool apply(Point& p, Point const& p1, Point const& p2) + template + static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2) { typename coordinate_type::type const two = 2; set(p, @@ -63,7 +65,8 @@ struct midpoint_helper template struct midpoint_helper { - static inline bool apply(Point& , Point const& , Point const& ) + template + static inline bool apply(Point& , InputPoint const& , InputPoint const& ) { return true; } @@ -102,7 +105,7 @@ struct point_on_range if (n > 0) { - point = *boost::begin(range); + geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point); return true; } return false; diff --git a/test/algorithms/disjoint.cpp b/test/algorithms/disjoint.cpp index 83738e24f6..7cf3c683cc 100644 --- a/test/algorithms/disjoint.cpp +++ b/test/algorithms/disjoint.cpp @@ -119,6 +119,15 @@ void test_all() test_disjoint("ls/ls co-e", "linestring(0 0,1 1)", "linestring(1 1,0 0)", false); + // Problem described by Volker/Albert 2012-06-01 + test_disjoint("volker_albert_1", + "POLYGON((1992 3240,1992 1440,3792 1800,3792 3240,1992 3240))", + "BOX(1941 2066, 2055 2166)", false); + + test_disjoint("volker_albert_2", + "POLYGON((1941 2066,2055 2066,2055 2166,1941 2166))", + "BOX(1941 2066, 2055 2166)", false); + // Degenerate linestrings { // Submitted by Zachary on the Boost.Geometry Mailing List, on 2012-01-29 From 443b01bc07b0fb329aee803ea1bef6a8f14e449b Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 11 Jun 2012 07:23:17 +0000 Subject: [PATCH 044/135] Merge documentation build fix from trunk. [SVN r78888] --- doc/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 6b938b8a54..ea2b2b2b74 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -42,4 +42,4 @@ boostbook geometry ; install pdf-install : geometry : . geometry.pdf PDF ; - +explicit pdf-install ; From a0572c75e7a38c9710009a28b25b10269f728256 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Mon, 9 Jul 2012 21:06:05 +0000 Subject: [PATCH 045/135] [geometry] merged into release for 1.51 (breaking change w.r.t. custom point traits) [SVN r79395] --- doc/geometry.qbk | 1 + example/c05_custom_point_pointer_example.cpp | 28 +-- example/c07_custom_ring_pointer_example.cpp | 81 ++++----- include/boost/geometry/core/access.hpp | 161 +++++++++++++----- .../geometry/core/coordinate_dimension.hpp | 6 +- .../boost/geometry/core/coordinate_system.hpp | 15 +- .../boost/geometry/core/coordinate_type.hpp | 20 ++- include/boost/geometry/core/point_type.hpp | 4 +- include/boost/geometry/core/tag.hpp | 5 +- .../spherical/distance_cross_track.hpp | 47 ++++- include/boost/geometry/util/bare_type.hpp | 38 +++++ test/strategies/cross_track.cpp | 37 ++++ test/test_common/test_point.hpp | 3 + test/test_common/with_pointer.hpp | 33 ++-- 14 files changed, 340 insertions(+), 139 deletions(-) create mode 100644 include/boost/geometry/util/bare_type.hpp diff --git a/doc/geometry.qbk b/doc/geometry.qbk index 8297e3de7c..8059fe03af 100644 --- a/doc/geometry.qbk +++ b/doc/geometry.qbk @@ -110,6 +110,7 @@ Boost.Geometry contains contributions by: * Alfredo Correa (adaption of Boost.Array) * Adam Wulkiewicz (spatial indexes) [footnote Currently an extension] * Federico Fern\u00E1ndez (spatial indexes) [footnote Currently an extension] +* Karsten Ahnert (patch for cross-track distance) [include imports.qbk] diff --git a/example/c05_custom_point_pointer_example.cpp b/example/c05_custom_point_pointer_example.cpp index 96bc22e497..d8059fe04d 100644 --- a/example/c05_custom_point_pointer_example.cpp +++ b/example/c05_custom_point_pointer_example.cpp @@ -35,42 +35,42 @@ struct my_point namespace boost { namespace geometry { namespace traits { -template<> struct tag +template<> struct tag { typedef point_tag type; }; -template<> struct coordinate_type +template<> struct coordinate_type { typedef double type; }; -template<> struct coordinate_system +template<> struct coordinate_system { typedef cs::cartesian type; }; -template<> struct dimension : boost::mpl::int_<2> {}; +template<> struct dimension : boost::mpl::int_<2> {}; template<> -struct access +struct access { - static double get(my_point const* p) + static double get(my_point const& p) { - return p->x; + return p.x; } - static void set(my_point* p, double const& value) + static void set(my_point& p, double const& value) { - p->x = value; + p.x = value; } }; template<> -struct access +struct access { - static double get(my_point const* p) + static double get(my_point const& p) { - return p->y; + return p.y; } - static void set(my_point* p, double const& value) + static void set(my_point& p, double const& value) { - p->y = value; + p.y = value; } }; diff --git a/example/c07_custom_ring_pointer_example.cpp b/example/c07_custom_ring_pointer_example.cpp index 812dff21aa..9126e04bcb 100644 --- a/example/c07_custom_ring_pointer_example.cpp +++ b/example/c07_custom_ring_pointer_example.cpp @@ -14,7 +14,9 @@ #include -#include +#include +#include +#include #include BOOST_GEOMETRY_REGISTER_RING_TEMPLATED(std::vector) @@ -32,42 +34,42 @@ struct my_point namespace boost { namespace geometry { namespace traits { -template<> struct tag +template<> struct tag { typedef point_tag type; }; -template<> struct coordinate_type +template<> struct coordinate_type { typedef double type; }; -template<> struct coordinate_system +template<> struct coordinate_system { typedef cs::cartesian type; }; -template<> struct dimension : boost::mpl::int_<2> {}; +template<> struct dimension : boost::mpl::int_<2> {}; template<> -struct access +struct access { - static double get(my_point const* p) + static double get(my_point const& p) { - return p->x; + return p.x; } - static void set(my_point* p, double const& value) + static void set(my_point& p, double const& value) { - p->x = value; + p.x = value; } }; template<> -struct access +struct access { - static double get(my_point const* p) + static double get(my_point const& p) { - return p->y; + return p.y; } - static void set(my_point* p, double const& value) + static void set(my_point& p, double const& value) { - p->y = value; + p.y = value; } }; @@ -101,30 +103,33 @@ int main() //std::vector unioned; //boost::geometry::union(a, b, unioned); - /* This once worked, using pointers, but has to be fixed or deprecated - typedef boost::geometry::model::ring > ring_2d; - std::vector unioned; - std::vector intersected; + // BEGIN TODO + // This compiles (and once worked) using pointers, but has to be fixed or deprecated + // The problem is now the cart_intersect/side where a temporary point is generated + //typedef boost::geometry::model::ring > ring_2d; + //std::vector unioned; + //std::vector intersected; + + //boost::geometry::intersection(a, b, intersected); + //boost::geometry::union_(a, b, unioned); + + //double ai = 0, au = 0; + //BOOST_FOREACH(ring_2d const& ring, intersected) + //{ + // ai += boost::geometry::area(ring); + //} + //BOOST_FOREACH(ring_2d const& ring, unioned) + //{ + // au += boost::geometry::area(ring); + //} + + //std::cout << "a: " << aa << std::endl; + //std::cout << "b: " << ab << std::endl; + //std::cout << "a & b: " << ai << std::endl; + //std::cout << "a | b: " << au << std::endl; + //std::cout << "a + b - (a & b): " << (aa + ab - ai) << std::endl; + // END TODO - boost::geometry::intersection(a, b, intersected); - boost::geometry::union_(a, b, unioned); - - double ai = 0, au = 0; - BOOST_FOREACH(ring_2d const& ring, intersected) - { - ai += boost::geometry::area(ring); - } - BOOST_FOREACH(ring_2d const& ring, unioned) - { - au += boost::geometry::area(ring); - } - - std::cout << "a: " << aa << std::endl; - std::cout << "b: " << ab << std::endl; - std::cout << "a & b: " << ai << std::endl; - std::cout << "a | b: " << au << std::endl; - std::cout << "a + b - (a & b): " << (aa + ab - ai) << std::endl; - */ // free BOOST_FOREACH(my_point* p, a) diff --git a/include/boost/geometry/core/access.hpp b/include/boost/geometry/core/access.hpp index a463b8cdc3..cdc8ff9cff 100644 --- a/include/boost/geometry/core/access.hpp +++ b/include/boost/geometry/core/access.hpp @@ -18,12 +18,13 @@ #include #include -#include #include +#include #include #include #include +#include namespace boost { namespace geometry @@ -79,6 +80,52 @@ struct indexed_access {}; } // namespace traits +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +< + typename Geometry, + typename CoordinateType, + std::size_t Index, + std::size_t Dimension +> +struct indexed_access_non_pointer +{ + static inline CoordinateType get(Geometry const& geometry) + { + return traits::indexed_access::get(geometry); + } + static inline void set(Geometry& b, CoordinateType const& value) + { + traits::indexed_access::set(b, value); + } +}; + +template +< + typename Geometry, + typename CoordinateType, + std::size_t Index, + std::size_t Dimension +> +struct indexed_access_pointer +{ + static inline CoordinateType get(Geometry const* geometry) + { + return traits::indexed_access::type, Index, Dimension>::get(*geometry); + } + static inline void set(Geometry* geometry, CoordinateType const& value) + { + traits::indexed_access::type, Index, Dimension>::set(*geometry, value); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + #ifndef DOXYGEN_NO_DISPATCH namespace core_dispatch @@ -89,7 +136,9 @@ template typename Tag, typename Geometry, typename - CoordinateType, std::size_t Dimension + CoordinateType, + std::size_t Dimension, + typename IsPointer > struct access { @@ -103,7 +152,8 @@ template typename Geometry, typename CoordinateType, std::size_t Index, - std::size_t Dimension + std::size_t Dimension, + typename IsPointer > struct indexed_access { @@ -112,7 +162,7 @@ struct indexed_access }; template -struct access +struct access { static inline CoordinateType get(Point const& point) { @@ -124,6 +174,20 @@ struct access } }; +template +struct access +{ + static inline CoordinateType get(Point const* point) + { + return traits::access::type, Dimension>::get(*point); + } + static inline void set(Point* p, CoordinateType const& value) + { + traits::access::type, Dimension>::set(*p, value); + } +}; + + template < typename Box, @@ -131,17 +195,21 @@ template std::size_t Index, std::size_t Dimension > -struct indexed_access -{ - static inline CoordinateType get(Box const& box) - { - return traits::indexed_access::get(box); - } - static inline void set(Box& b, CoordinateType const& value) - { - traits::indexed_access::set(b, value); - } -}; +struct indexed_access + : detail::indexed_access_non_pointer +{}; + +template +< + typename Box, + typename CoordinateType, + std::size_t Index, + std::size_t Dimension +> +struct indexed_access + : detail::indexed_access_pointer +{}; + template < @@ -150,17 +218,21 @@ template std::size_t Index, std::size_t Dimension > -struct indexed_access -{ - static inline CoordinateType get(Segment const& segment) - { - return traits::indexed_access::get(segment); - } - static inline void set(Segment& segment, CoordinateType const& value) - { - traits::indexed_access::set(segment, value); - } -}; +struct indexed_access + : detail::indexed_access_non_pointer +{}; + + +template +< + typename Segment, + typename CoordinateType, + std::size_t Index, + std::size_t Dimension +> +struct indexed_access + : detail::indexed_access_pointer +{}; } // namespace core_dispatch #endif // DOXYGEN_NO_DISPATCH @@ -199,14 +271,13 @@ inline typename coordinate_type::type get(Geometry const& geometry { boost::ignore_unused_variable_warning(dummy); - typedef typename boost::remove_const::type ncg_type; - typedef core_dispatch::access < typename tag::type, - ncg_type, - typename coordinate_type::type, - Dimension + typename geometry::util::bare_type::type, + typename coordinate_type::type, + Dimension, + typename boost::is_pointer::type > coord_access_type; return coord_access_type::get(geometry); @@ -234,14 +305,13 @@ inline void set(Geometry& geometry { boost::ignore_unused_variable_warning(dummy); - typedef typename boost::remove_const::type ncg_type; - typedef core_dispatch::access < typename tag::type, - ncg_type, - typename coordinate_type::type, - Dimension + typename geometry::util::bare_type::type, + typename coordinate_type::type, + Dimension, + typename boost::is_pointer::type > coord_access_type; coord_access_type::set(geometry, value); @@ -269,15 +339,14 @@ inline typename coordinate_type::type get(Geometry const& geometry { boost::ignore_unused_variable_warning(dummy); - typedef typename boost::remove_const::type ncg_type; - typedef core_dispatch::indexed_access < typename tag::type, - ncg_type, - typename coordinate_type::type, + typename geometry::util::bare_type::type, + typename coordinate_type::type, Index, - Dimension + Dimension, + typename boost::is_pointer::type > coord_access_type; return coord_access_type::get(geometry); @@ -306,14 +375,14 @@ inline void set(Geometry& geometry { boost::ignore_unused_variable_warning(dummy); - typedef typename boost::remove_const::type ncg_type; - typedef core_dispatch::indexed_access < - typename tag::type, ncg_type, - typename coordinate_type::type, + typename tag::type, + typename geometry::util::bare_type::type, + typename coordinate_type::type, Index, - Dimension + Dimension, + typename boost::is_pointer::type > coord_access_type; coord_access_type::set(geometry, value); diff --git a/include/boost/geometry/core/coordinate_dimension.hpp b/include/boost/geometry/core/coordinate_dimension.hpp index 84c11e2a55..2f3c914601 100644 --- a/include/boost/geometry/core/coordinate_dimension.hpp +++ b/include/boost/geometry/core/coordinate_dimension.hpp @@ -20,9 +20,9 @@ #include #include #include -#include #include +#include namespace boost { namespace geometry { @@ -58,7 +58,7 @@ template struct dimension : dimension::type> {}; template -struct dimension : traits::dimension

    {}; +struct dimension : traits::dimension::type> {}; } // namespace core_dispatch #endif @@ -75,7 +75,7 @@ struct dimension : core_dispatch::dimension < typename tag::type, - typename boost::remove_const::type + typename geometry::util::bare_type::type > {}; diff --git a/include/boost/geometry/core/coordinate_system.hpp b/include/boost/geometry/core/coordinate_system.hpp index c23b8af15c..01e5ad1dd7 100644 --- a/include/boost/geometry/core/coordinate_system.hpp +++ b/include/boost/geometry/core/coordinate_system.hpp @@ -16,8 +16,9 @@ #include -#include + #include +#include namespace boost { namespace geometry @@ -61,10 +62,13 @@ namespace core_dispatch }; - template - struct coordinate_system + template + struct coordinate_system { - typedef typename traits::coordinate_system

    ::type type; + typedef typename traits::coordinate_system + < + typename geometry::util::bare_type::type + >::type type; }; @@ -82,11 +86,10 @@ namespace core_dispatch template struct coordinate_system { - typedef typename boost::remove_const::type ncg; typedef typename core_dispatch::coordinate_system < typename tag::type, - ncg + typename geometry::util::bare_type::type >::type type; }; diff --git a/include/boost/geometry/core/coordinate_type.hpp b/include/boost/geometry/core/coordinate_type.hpp index 0f901d3f19..d17f66ab73 100644 --- a/include/boost/geometry/core/coordinate_type.hpp +++ b/include/boost/geometry/core/coordinate_type.hpp @@ -16,9 +16,10 @@ #include -#include +#include #include +#include #include @@ -63,12 +64,17 @@ struct coordinate_type template struct coordinate_type { - typedef typename traits::coordinate_type::type type; + typedef typename traits::coordinate_type + < + typename geometry::util::bare_type::type + >::type type; }; + } // namespace core_dispatch #endif // DOXYGEN_NO_DISPATCH + /*! \brief \brief_meta{type, coordinate type (int\, float\, double\, etc), \meta_point_type} \tparam Geometry \tparam_geometry @@ -79,11 +85,11 @@ struct coordinate_type template struct coordinate_type { - typedef typename core_dispatch::coordinate_type - < - typename tag::type, - typename boost::remove_const::type - >::type type; + typedef typename core_dispatch::coordinate_type + < + typename tag::type, + typename geometry::util::bare_type::type + >::type type; }; template diff --git a/include/boost/geometry/core/point_type.hpp b/include/boost/geometry/core/point_type.hpp index f49a43c56a..e148c84a57 100644 --- a/include/boost/geometry/core/point_type.hpp +++ b/include/boost/geometry/core/point_type.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace boost { namespace geometry { @@ -115,11 +116,10 @@ struct point_type template struct point_type { - typedef typename boost::remove_const::type ncg; typedef typename core_dispatch::point_type < typename tag::type, - ncg + typename boost::geometry::util::bare_type::type >::type type; }; diff --git a/include/boost/geometry/core/tag.hpp b/include/boost/geometry/core/tag.hpp index 5a99c97071..4c790fdc9e 100644 --- a/include/boost/geometry/core/tag.hpp +++ b/include/boost/geometry/core/tag.hpp @@ -16,9 +16,9 @@ #include -#include #include +#include namespace boost { namespace geometry @@ -47,6 +47,7 @@ struct tag } // namespace traits + /*! \brief \brief_meta{type, tag, \meta_geometry_type} \details With Boost.Geometry, tags are the driving force of the tag dispatching @@ -61,7 +62,7 @@ struct tag { typedef typename traits::tag < - typename boost::remove_const::type + typename geometry::util::bare_type::type >::type type; }; diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp index ba589223ec..7b353020eb 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -101,23 +101,56 @@ public : { // http://williams.best.vwh.net/avform.htm#XTE return_type d1 = m_strategy.apply(sp1, p); + return_type d3 = m_strategy.apply(sp1, sp2); + + if (geometry::math::equals(d3, 0.0)) + { + // "Degenerate" segment, return either d1 or d2 + return d1; + } - // Actually, calculation of d2 not necessary if we know that the projected point is on the great circle... return_type d2 = m_strategy.apply(sp2, p); return_type crs_AD = course(sp1, p); return_type crs_AB = course(sp1, sp2); - return_type XTD = m_radius * geometry::math::abs(asin(sin(d1 / m_radius) * sin(crs_AD - crs_AB))); + return_type crs_BA = crs_AB - geometry::math::pi(); + return_type crs_BD = course(sp2, p); + return_type d_crs1 = crs_AD - crs_AB; + return_type d_crs2 = crs_BD - crs_BA; + + // d1, d2, d3 are in principle not needed, only the sign matters + return_type projection1 = cos( d_crs1 ) * d1 / d3; + return_type projection2 = cos( d_crs2 ) * d2 / d3; #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK -std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl; -std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl; -std::cout << "XTD: " << XTD << " d1: " << d1 << " d2: " << d2 << std::endl; + std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl; + std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl; + std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " " << crs_BD * geometry::math::r2d << std::endl; + std::cout << "Projection AD-AB " << projection1 << " : " << d_crs1 * geometry::math::r2d << std::endl; + std::cout << "Projection BD-BA " << projection2 << " : " << d_crs2 * geometry::math::r2d << std::endl; #endif + if(projection1 > 0.0 && projection2 > 0.0) + { + return_type XTD = m_radius * geometry::math::abs( asin( sin( d1 / m_radius ) * sin( d_crs1 ) )); + + #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK + std::cout << "Projection ON the segment" << std::endl; + std::cout << "XTD: " << XTD << " d1: " << d1 << " d2: " << d2 << std::endl; +#endif + + // Return shortest distance, projected point on segment sp1-sp2 + return return_type(XTD); + } + else + { +#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK + std::cout << "Projection OUTSIDE the segment" << std::endl; +#endif - // Return shortest distance, either to projected point on segment sp1-sp2, or to sp1, or to sp2 - return return_type((std::min)((std::min)(d1, d2), XTD)); + // Return shortest distance, project either on point sp1 or sp2 + return return_type( (std::min)( d1 , d2 ) ); + } } inline return_type radius() const { return m_radius; } diff --git a/include/boost/geometry/util/bare_type.hpp b/include/boost/geometry/util/bare_type.hpp new file mode 100644 index 0000000000..1b49de6436 --- /dev/null +++ b/include/boost/geometry/util/bare_type.hpp @@ -0,0 +1,38 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012 Bruno Lalande, Paris, France. +// Copyright (c) 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) + +#ifndef BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP +#define BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP + +#include + + +namespace boost { namespace geometry +{ + +namespace util +{ + +template +struct bare_type +{ + typedef typename boost::remove_const + < + typename boost::remove_pointer::type + >::type type; +}; + + +} // namespace util + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP diff --git a/test/strategies/cross_track.cpp b/test/strategies/cross_track.cpp index 2165549d46..38840dc725 100644 --- a/test/strategies/cross_track.cpp +++ b/test/strategies/cross_track.cpp @@ -15,6 +15,7 @@ #include +#include #include #include @@ -84,6 +85,40 @@ void test_distance( } +template +void test_case_boost_geometry_list_20120625() +{ + // This function tests the bug submitted by Karsten Ahnert + // on Boost.Geometry list at 2012-06-25, and wherefore he + // submitted a patch a few days later. + + Point p1, p2; + bg::model::segment s1, s2; + + bg::read_wkt("POINT(1 1)", p1); + bg::read_wkt("POINT(5 1)", p2); + bg::read_wkt("LINESTRING(0 2,2 2)", s1); + bg::read_wkt("LINESTRING(2 2,4 2)", s2); + + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, s1), 0.0174586, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, s2), 0.0246783, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, s1), 0.0551745, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, s2), 0.0246783, 0.0001); + + // Check degenerated segments + bg::model::segment s3; + bg::read_wkt("LINESTRING(2 2,2 2)", s3); + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, s3), 0.0246783, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, s3), 0.0551745, 0.0001); + + // Point/Point distance should be identical: + Point p3; + bg::read_wkt("POINT(2 2)", p3); + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, p3), 0.0246783, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, p3), 0.0551745, 0.0001); +} + + template void test_all() { @@ -95,6 +130,8 @@ void test_all() typename bg::coordinate_type::type const p_to_ab = 86.798321 * 1000.0; test_distance(2, 48, 4, 52, 2, 41, average_earth_radius, p_to_ab, 0.1); test_distance(2, 48, 2, 41, 4, 52, average_earth_radius, p_to_ab, 0.1); + + test_case_boost_geometry_list_20120625(); } diff --git a/test/test_common/test_point.hpp b/test/test_common/test_point.hpp index 359819e943..5a19d6c3cb 100644 --- a/test/test_common/test_point.hpp +++ b/test/test_common/test_point.hpp @@ -18,6 +18,9 @@ #include #include +// NOTE: since Boost 1.51 the Point type may always be a pointer. +// Therefore the traits class don't need to add a pointer. +// This obsoletes this whole test-point-type namespace test { diff --git a/test/test_common/with_pointer.hpp b/test/test_common/with_pointer.hpp index ff8967f7ec..22edbdef54 100644 --- a/test/test_common/with_pointer.hpp +++ b/test/test_common/with_pointer.hpp @@ -19,6 +19,11 @@ #include #include +// NOTE: since Boost 1.51 the Point type may always be a pointer. +// Therefore the traits class don't need to add a pointer. +// This obsoletes this whole test-point-type + + namespace test { @@ -34,44 +39,44 @@ struct test_point_xy namespace boost { namespace geometry { namespace traits { -template<> struct tag +template<> struct tag { typedef point_tag type; }; -template<> struct coordinate_type +template<> struct coordinate_type { typedef double type; }; -template<> struct coordinate_system +template<> struct coordinate_system { typedef cs::cartesian type; }; -template<> struct dimension : boost::mpl::int_<2> {}; +template<> struct dimension : boost::mpl::int_<2> {}; template<> -struct access +struct access { - static double get(test::test_point_xy const* p) + static double get(test::test_point_xy const& p) { - return p->x; + return p.x; } - static void set(test::test_point_xy* p, double const& value) + static void set(test::test_point_xy& p, double const& value) { - p->x = value; + p.x = value; } }; template<> -struct access +struct access { - static double get(test::test_point_xy const* p) + static double get(test::test_point_xy const& p) { - return p->y; + return p.y; } - static void set(test::test_point_xy* p, double const& value) + static void set(test::test_point_xy& p, double const& value) { - p->y = value; + p.y = value; } }; From d316c1bf681e20190a9e597b8d94db414f199bcc Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 15 Jul 2012 15:02:16 +0000 Subject: [PATCH 046/135] [geometry] merged into release (two fixes, doc change) since r79395 [SVN r79534] --- doc/Jamfile.v2 | 4 +- doc/release_notes.qbk | 24 ++- .../doxygen_xml2qbk/doxygen_xml_parser.hpp | 54 +++++- .../strategies/cartesian/cart_intersect.hpp | 168 +++++++++--------- 4 files changed, 157 insertions(+), 93 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index ea2b2b2b74..1deb3fd94d 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -41,5 +41,5 @@ boostbook geometry pdf:img.src.path=$(images_location)/ ; -install pdf-install : geometry : . geometry.pdf PDF ; -explicit pdf-install ; +install pdfinstall : geometry/pdf : . geometry.pdf PDF ; +explicit pdfinstall ; diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 6d31b9378b..445c03862a 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -12,12 +12,29 @@ [section:release_notes Release Notes] + [/=================] -[heading Boost 1.50] +[heading Boost 1.51] [/=================] [*Breaking changes] +* points accessed through a pointer (e.g. in a linestring) should now be specialized without the pointer. In previous versions a type `my_point` used like `linestring` had to be specalized like: `template<> struct tag`. Now the library itself removes the pointer before calling the traits class, so now it should be like: `template<> struct tag` + +[*Bugfixes] + +* intersection was sometimes wrong for integer points, fixed +* documentation, order of parameters in simplify was wrong, fixed + +[*Solved tickets] + +* [@https://svn.boost.org/trac/boost/ticket/7030 7030] spherical distance, fixed (by patch of Karsten Ahnert) + + +[/=================] +[heading Boost 1.50] +[/=================] + [*Bugfixes] * the return type of comparable projected point strategy for integer points was wrong (integer), fixed @@ -37,11 +54,6 @@ * added algorithm "touches" (OGC SF compliant) for *polygon/*polygon -[*Documentation] - -[*Internal changes] - - [/=================] [heading Boost 1.49] [/=================] diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp index 070f202a19..aa8b902192 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp @@ -228,6 +228,46 @@ static void parse_parameter_list(rapidxml::xml_node<>* node, Parameters& paramet } } +static void copy_string_property(std::string const& source, std::string& target) +{ + if (target.empty()) + { + target = source; + } +} + + +template +static void copy_parameter_properties(parameter const& source, Parameters& target) +{ + BOOST_FOREACH(parameter& t, target) + { + if (source.name == t.name) + { + t.skip = source.skip; + copy_string_property(source.brief_description, t.brief_description); + copy_string_property(source.type, t.type); + copy_string_property(source.default_value, t.default_value); + copy_string_property(source.fulltype, t.fulltype); + + return; + } + } + // If not found, write a warning + std::cerr << "Parameter not found: " << source.name << std::endl; +} + + +template +static void copy_parameters_properties(Parameters const& source, Parameters& target) +{ + BOOST_FOREACH(parameter const& s, source) + { + copy_parameter_properties(s, target); + } +} + + template static void parse_element(rapidxml::xml_node<>* node, configuration const& config, std::string const& parent, Element& el) @@ -290,13 +330,25 @@ static void parse_element(rapidxml::xml_node<>* node, configuration const& confi std::string kind = get_attribute(node, "kind"); if (kind == "param") { - parse_parameter_list(node->first_node(), el.parameters); + // Parse parameters and their descriptions. + // NOTE: they are listed here, but the order might not be the order in the function call + std::vector parameters; + parse_parameter_list(node->first_node(), parameters); + copy_parameters_properties(parameters, el.parameters); } else if (kind == "templateparam") { parse_parameter_list(node->first_node(), el.template_parameters); } } + else if (full == ".param") + { + // Parse one parameter, and add it to el.parameters + parameter p; + parse_parameter(node->first_node(), p); + el.parameters.push_back(p); + } + parse_element(node->first_node(), config, full, el); parse_element(node->next_sibling(), config, parent, el); diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index ed0f500877..ea92cf37b0 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -172,28 +172,28 @@ struct relate_cartesian_segments >::type promoted_type; // r: ratio 0-1 where intersection divides A/B - // (only calculated for non-collinear segments) - promoted_type r; - if (! collinear) - { - // Calculate determinants - Cramers rule - coordinate_type const wx = get<0, 0>(a) - get<0, 0>(b); - coordinate_type const wy = get<0, 1>(a) - get<0, 1>(b); - coordinate_type const d = geometry::detail::determinant(dx_a, dy_a, dx_b, dy_b); - coordinate_type const da = geometry::detail::determinant(dx_b, dy_b, wx, wy); - - coordinate_type const zero = coordinate_type(); - if (math::equals(d, zero)) - { - // This is still a collinear case (because of FP imprecision this can occur here) - // sides.debug(); - sides.set<0>(0,0); - sides.set<1>(0,0); - collinear = true; - } - else - { - r = da / d; + // (only calculated for non-collinear segments) + promoted_type r; + if (! collinear) + { + // Calculate determinants - Cramers rule + coordinate_type const wx = get<0, 0>(a) - get<0, 0>(b); + coordinate_type const wy = get<0, 1>(a) - get<0, 1>(b); + coordinate_type const d = geometry::detail::determinant(dx_a, dy_a, dx_b, dy_b); + coordinate_type const da = geometry::detail::determinant(dx_b, dy_b, wx, wy); + + coordinate_type const zero = coordinate_type(); + if (math::equals(d, zero)) + { + // This is still a collinear case (because of FP imprecision this can occur here) + // sides.debug(); + sides.set<0>(0,0); + sides.set<1>(0,0); + collinear = true; + } + else + { + r = promoted_type(da) / promoted_type(d); if (! robustness_verify_r(a, b, r)) { @@ -207,8 +207,8 @@ struct relate_cartesian_segments return Policy::disjoint(); } - } - } + } + } if(collinear) { @@ -218,7 +218,7 @@ struct relate_cartesian_segments } else { - // Y direction contains larger segments (maybe dx is zero) + // Y direction contains larger segments (maybe dx is zero) return relate_collinear<1>(a, b); } } @@ -231,23 +231,23 @@ struct relate_cartesian_segments private : - // Ratio should lie between 0 and 1 - // Also these three conditions might be of FP imprecision, the segments were actually (nearly) collinear + // Ratio should lie between 0 and 1 + // Also these three conditions might be of FP imprecision, the segments were actually (nearly) collinear template static inline bool robustness_verify_r( segment_type1 const& a, segment_type2 const& b, T& r) { - T const zero = 0; - T const one = 1; + T const zero = 0; + T const one = 1; if (r < zero || r > one) { - if (verify_disjoint<0>(a, b) || verify_disjoint<1>(a, b)) - { - // Can still be disjoint (even if not one is left or right from another) + if (verify_disjoint<0>(a, b) || verify_disjoint<1>(a, b)) + { + // Can still be disjoint (even if not one is left or right from another) // This is e.g. in case #snake4 of buffer test. - return false; - } + return false; + } //std::cout << "ROBUSTNESS: correction of r " << r << std::endl; // sides.debug(); @@ -273,7 +273,7 @@ private : } else if (r < zero) { - r = zero; + r = zero; } } return true; @@ -284,16 +284,16 @@ private : side_info& sides, bool& collinear) { - if ((sides.zero<0>() && ! sides.zero<1>()) || (sides.zero<1>() && ! sides.zero<0>())) - { - // If one of the segments is collinear, the other must be as well. - // So handle it as collinear. - // (In float/double epsilon margins it can easily occur that one or two of them are -1/1) - // sides.debug(); + if ((sides.zero<0>() && ! sides.zero<1>()) || (sides.zero<1>() && ! sides.zero<0>())) + { + // If one of the segments is collinear, the other must be as well. + // So handle it as collinear. + // (In float/double epsilon margins it can easily occur that one or two of them are -1/1) + // sides.debug(); sides.set<0>(0,0); sides.set<1>(0,0); collinear = true; - } + } } static inline void robustness_verify_meeting( @@ -389,11 +389,11 @@ private : { if (sides.one_of_all_zero()) { - if (verify_disjoint<0>(a, b) || verify_disjoint<1>(a, b)) - { - return true; + if (verify_disjoint<0>(a, b) || verify_disjoint<1>(a, b)) + { + return true; } - } + } return false; } @@ -412,11 +412,11 @@ private : T const db = geometry::detail::determinant(dx_a, dy_a, wx, wy); - R const zero = 0; - R const one = 1; + R const zero = 0; + R const one = 1; if (math::equals(r, zero) || math::equals(r, one)) { - R rb = db / d; + R rb = db / d; if (rb <= 0 || rb >= 1 || math::equals(rb, 0) || math::equals(rb, 1)) { if (sides.one_zero<0>() && ! sides.one_zero<1>()) // or vice versa @@ -432,16 +432,16 @@ private : } } - template + template static inline bool verify_disjoint(segment_type1 const& a, - segment_type2 const& b) - { - coordinate_type a_1, a_2, b_1, b_2; - bool a_swapped = false, b_swapped = false; - detail::segment_arrange(a, a_1, a_2, a_swapped); - detail::segment_arrange(b, b_1, b_2, b_swapped); - return math::smaller(a_2, b_1) || math::larger(a_1, b_2); - } + segment_type2 const& b) + { + coordinate_type a_1, a_2, b_1, b_2; + bool a_swapped = false, b_swapped = false; + detail::segment_arrange(a, a_1, a_2, a_swapped); + detail::segment_arrange(b, b_1, b_2, b_swapped); + return math::smaller(a_2, b_1) || math::larger(a_1, b_2); + } template static inline typename point_type::type select(int index, Segment const& segment) @@ -476,10 +476,10 @@ private : template static inline bool analyse_equal(segment_type1 const& a, segment_type2 const& b) { - coordinate_type const a_1 = geometry::get<0, Dimension>(a); - coordinate_type const a_2 = geometry::get<1, Dimension>(a); - coordinate_type const b_1 = geometry::get<0, Dimension>(b); - coordinate_type const b_2 = geometry::get<1, Dimension>(b); + coordinate_type const a_1 = geometry::get<0, Dimension>(a); + coordinate_type const a_2 = geometry::get<1, Dimension>(a); + coordinate_type const b_1 = geometry::get<0, Dimension>(b); + coordinate_type const b_2 = geometry::get<1, Dimension>(b); return math::equals(a_1, b_1) || math::equals(a_2, b_1) || math::equals(a_1, b_2) @@ -487,21 +487,21 @@ private : ; } - template + template static inline return_type relate_collinear(segment_type1 const& a, - segment_type2 const& b) - { - coordinate_type a_1, a_2, b_1, b_2; - bool a_swapped = false, b_swapped = false; - detail::segment_arrange(a, a_1, a_2, a_swapped); - detail::segment_arrange(b, b_1, b_2, b_swapped); - if (math::smaller(a_2, b_1) || math::larger(a_1, b_2)) - //if (a_2 < b_1 || a_1 > b_2) - { - return Policy::disjoint(); - } + segment_type2 const& b) + { + coordinate_type a_1, a_2, b_1, b_2; + bool a_swapped = false, b_swapped = false; + detail::segment_arrange(a, a_1, a_2, a_swapped); + detail::segment_arrange(b, b_1, b_2, b_swapped); + if (math::smaller(a_2, b_1) || math::larger(a_1, b_2)) + //if (a_2 < b_1 || a_1 > b_2) + { + return Policy::disjoint(); + } return relate_collinear(a, b, a_1, a_2, b_1, b_2, a_swapped, b_swapped); - } + } /// Relate segments known collinear static inline return_type relate_collinear(segment_type1 const& a @@ -535,22 +535,22 @@ private : bool const both_swapped = a_swapped && b_swapped; // Check if segments are equal or opposite equal... - bool const swapped_a1_eq_b1 = math::equals(a_1, b_1); - bool const swapped_a2_eq_b2 = math::equals(a_2, b_2); + bool const swapped_a1_eq_b1 = math::equals(a_1, b_1); + bool const swapped_a2_eq_b2 = math::equals(a_2, b_2); if (swapped_a1_eq_b1 && swapped_a2_eq_b2) { return Policy::segment_equal(a, opposite); } - bool const swapped_a2_eq_b1 = math::equals(a_2, b_1); - bool const swapped_a1_eq_b2 = math::equals(a_1, b_2); + bool const swapped_a2_eq_b1 = math::equals(a_2, b_1); + bool const swapped_a1_eq_b2 = math::equals(a_1, b_2); - bool const a1_eq_b1 = both_swapped ? swapped_a2_eq_b2 : a_swapped ? swapped_a2_eq_b1 : b_swapped ? swapped_a1_eq_b2 : swapped_a1_eq_b1; - bool const a2_eq_b2 = both_swapped ? swapped_a1_eq_b1 : a_swapped ? swapped_a1_eq_b2 : b_swapped ? swapped_a2_eq_b1 : swapped_a2_eq_b2; + bool const a1_eq_b1 = both_swapped ? swapped_a2_eq_b2 : a_swapped ? swapped_a2_eq_b1 : b_swapped ? swapped_a1_eq_b2 : swapped_a1_eq_b1; + bool const a2_eq_b2 = both_swapped ? swapped_a1_eq_b1 : a_swapped ? swapped_a1_eq_b2 : b_swapped ? swapped_a2_eq_b1 : swapped_a2_eq_b2; - bool const a1_eq_b2 = both_swapped ? swapped_a2_eq_b1 : a_swapped ? swapped_a2_eq_b2 : b_swapped ? swapped_a1_eq_b1 : swapped_a1_eq_b2; - bool const a2_eq_b1 = both_swapped ? swapped_a1_eq_b2 : a_swapped ? swapped_a1_eq_b1 : b_swapped ? swapped_a2_eq_b2 : swapped_a2_eq_b1; + bool const a1_eq_b2 = both_swapped ? swapped_a2_eq_b1 : a_swapped ? swapped_a2_eq_b2 : b_swapped ? swapped_a1_eq_b1 : swapped_a1_eq_b2; + bool const a2_eq_b1 = both_swapped ? swapped_a1_eq_b2 : a_swapped ? swapped_a1_eq_b1 : b_swapped ? swapped_a2_eq_b2 : swapped_a2_eq_b1; @@ -722,7 +722,7 @@ private : ; } // Nothing should goes through. If any we have made an error - // std::cout << "Robustness issue, non-logical behaviour" << std::endl; + // std::cout << "Robustness issue, non-logical behaviour" << std::endl; return Policy::error("Robustness issue, non-logical behaviour"); } }; From 8ffd54aeeecd2b32d980fd94ddb3c487886fab03 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Fri, 7 Sep 2012 08:43:19 +0000 Subject: [PATCH 047/135] Merge accumulated changes from Trunk for Boost.Math - see documentation for a full lost of changes. [SVN r80432] --- doc/doxy/doxygen_output/html/doxygen.css | 191 ++++++++++++++++++++++- doc/html/index.html | 23 +-- 2 files changed, 198 insertions(+), 16 deletions(-) diff --git a/doc/doxy/doxygen_output/html/doxygen.css b/doc/doxy/doxygen_output/html/doxygen.css index 658686fe4e..74445fe1fe 100644 --- a/doc/doxy/doxygen_output/html/doxygen.css +++ b/doc/doxy/doxygen_output/html/doxygen.css @@ -11,6 +11,12 @@ h1 { font-size: 150%; } +.title { + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + h2 { font-size: 120%; } @@ -158,6 +164,7 @@ div.ah { border-radius: 0.5em; -webkit-border-radius: .5em; -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; -webkit-box-shadow: 2px 2px 3px #999; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); @@ -167,7 +174,6 @@ div.ah { div.groupHeader { margin-left: 16px; margin-top: 12px; - margin-bottom: 6px; font-weight: bold; } @@ -185,7 +191,7 @@ body { div.contents { margin-top: 10px; margin-left: 10px; - margin-right: 10px; + margin-right: 5px; } td.indexkey { @@ -361,6 +367,10 @@ table.memberdecls { white-space: nowrap; } +.memItemRight { + width: 100%; +} + .memTemplParams { color: #4665A2; white-space: nowrap; @@ -376,7 +386,7 @@ table.memberdecls { font-size: 80%; color: #4665A2; font-weight: normal; - margin-left: 3px; + margin-left: 9px; } .memnav { @@ -388,9 +398,14 @@ table.memberdecls { padding: 2px; } +.mempage { + width: 100%; +} + .memitem { padding: 0; margin-bottom: 10px; + margin-right: 5px; } .memname { @@ -407,6 +422,10 @@ table.memberdecls { color: #253555; font-weight: bold; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 8px; + border-top-left-radius: 8px; /* firefox specific markup */ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 8px; @@ -428,6 +447,10 @@ table.memberdecls { padding: 2px 5px; background-color: #FBFCFD; border-top-width: 0; + /* opera specific markup */ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ -moz-border-radius-bottomleft: 8px; -moz-border-radius-bottomright: 8px; @@ -456,6 +479,28 @@ table.memberdecls { font-style: normal; } +.params, .retval, .exception, .tparams { + border-spacing: 6px 2px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + + + + /* @end */ /* @group Directory (tree) */ @@ -606,14 +651,14 @@ table.doxtable th { list-style-type:none; float:left; padding-left:10px; - padding-right: 15px; + padding-right:15px; background-image:url('bc_s.png'); background-repeat:no-repeat; background-position:right; color:#364D7C; } -.navpath a +.navpath li.navelem a { height:32px; display:block; @@ -621,11 +666,25 @@ table.doxtable th { outline: none; } -.navpath a:hover +.navpath li.navelem a:hover { color:#6884BD; } +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + div.summary { float: right; @@ -640,6 +699,19 @@ div.summary a white-space: nowrap; } +div.ingroups +{ + font-size: 8pt; + padding-left: 5px; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + div.header { background-image:url('nav_h.png'); @@ -654,3 +726,110 @@ div.headertitle padding: 5px 5px 5px 10px; } +dl +{ + padding: 0 0 0 10px; +} + +dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug +{ + border-left:4px solid; + padding: 0 0 0 6px; +} + +dl.note +{ + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + border-color: #00D000; +} + +dl.deprecated +{ + border-color: #505050; +} + +dl.todo +{ + border-color: #00C0E0; +} + +dl.test +{ + border-color: #3030E0; +} + +dl.bug +{ + border-color: #C08050; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + diff --git a/doc/html/index.html b/doc/html/index.html index 47e629047e..b5ad714c8e 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -3,7 +3,7 @@ Chapter 1. Geometry - + @@ -34,7 +34,7 @@

    -

    +

    Distributed under 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)

    @@ -74,9 +74,9 @@
    Acknowledgments
    -

    - - Contributions +

    + + Contributions

    Boost.Geometry contains contributions by: @@ -89,24 +89,27 @@ Alfredo Correa (adaption of Boost.Array)

  • - Adam Wulkiewicz (spatial indexes) [1] + Adam Wulkiewicz (spatial indexes) [1]
  • - Federico Fernández (spatial indexes) [2] + Federico Fernández (spatial indexes) [2] +
  • +
  • + Karsten Ahnert (patch for cross-track distance)


  • -

    [1] +

    [1] Currently an extension

    -

    [2] +

    [2] Currently an extension

    - +

    Last revised: May 28, 2012 at 16:44:23 GMT

    Last revised: August 21, 2012 at 16:43:26 GMT


    From 5ce1a36676b3c67d1746dad2de877d8d22e1c1a9 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 16 Dec 2012 15:14:35 +0000 Subject: [PATCH 048/135] [geometry] merged to release branch [SVN r82022] --- doc/generated/buffer_status.qbk | 13 + doc/generated/centroid_status.qbk | 13 + doc/generated/for_each_point_status.qbk | 13 + doc/generated/for_each_segment_status.qbk | 13 + doc/generated/length_status.qbk | 13 + doc/generated/num_geometries_status.qbk | 13 + doc/generated/num_interior_rings_status.qbk | 13 + doc/generated/num_points_status.qbk | 13 + doc/generated/perimeter_status.qbk | 13 + doc/generated/reverse_status.qbk | 13 + doc/generated/simplify_status.qbk | 13 + doc/generated/transform_status.qbk | 13 + doc/generated/unique_status.qbk | 13 + doc/release_notes.qbk | 22 ++ .../tools/support_status/support_status.cpp | 74 ++++- .../x04_wxwidgets_world_mapper.cpp | 6 +- include/boost/geometry/algorithms/area.hpp | 140 +++++---- include/boost/geometry/algorithms/buffer.hpp | 27 +- .../boost/geometry/algorithms/centroid.hpp | 105 ++----- .../boost/geometry/algorithms/convex_hull.hpp | 50 +--- include/boost/geometry/algorithms/correct.hpp | 4 +- .../algorithms/detail/calculate_null.hpp | 2 +- .../algorithms/detail/calculate_sum.hpp | 12 +- .../geometry/algorithms/detail/disjoint.hpp | 14 + .../algorithms/detail/get_left_turns.hpp | 22 +- .../algorithms/detail/occupation_info.hpp | 2 +- .../algorithms/detail/overlay/add_rings.hpp | 35 ++- .../detail/overlay/convert_ring.hpp | 21 +- .../detail/overlay/handle_tangencies.hpp | 33 ++- .../detail/overlay/intersection_insert.hpp | 278 ++++++++---------- .../algorithms/detail/overlay/overlay.hpp | 6 +- .../algorithms/detail/overlay/traverse.hpp | 16 +- .../boost/geometry/algorithms/difference.hpp | 14 +- .../boost/geometry/algorithms/disjoint.hpp | 103 +++---- .../boost/geometry/algorithms/distance.hpp | 5 +- .../boost/geometry/algorithms/for_each.hpp | 223 +++++--------- .../geometry/algorithms/intersection.hpp | 143 ++++----- include/boost/geometry/algorithms/length.hpp | 49 ++- .../geometry/algorithms/num_geometries.hpp | 36 +-- .../algorithms/num_interior_rings.hpp | 10 +- .../boost/geometry/algorithms/num_points.hpp | 61 ++-- .../boost/geometry/algorithms/perimeter.hpp | 61 ++-- include/boost/geometry/algorithms/reverse.hpp | 35 +-- .../boost/geometry/algorithms/simplify.hpp | 124 +++----- .../geometry/algorithms/sym_difference.hpp | 27 +- .../boost/geometry/algorithms/transform.hpp | 68 ++--- include/boost/geometry/algorithms/union.hpp | 129 +++----- include/boost/geometry/algorithms/unique.hpp | 38 +-- include/boost/geometry/geometries/variant.hpp | 34 +++ .../boost/geometry/multi/algorithms/area.hpp | 29 +- .../geometry/multi/algorithms/centroid.hpp | 66 +---- .../multi/algorithms/detail/multi_sum.hpp | 8 +- .../geometry/multi/algorithms/disjoint.hpp | 41 +++ .../geometry/multi/algorithms/for_each.hpp | 60 +--- .../multi/algorithms/intersection.hpp | 237 +++++++-------- .../geometry/multi/algorithms/length.hpp | 34 ++- .../multi/algorithms/num_geometries.hpp | 2 +- .../multi/algorithms/num_interior_rings.hpp | 2 +- .../geometry/multi/algorithms/num_points.hpp | 12 +- .../geometry/multi/algorithms/perimeter.hpp | 29 +- .../geometry/multi/algorithms/reverse.hpp | 10 +- .../geometry/multi/algorithms/simplify.hpp | 45 +-- .../geometry/multi/algorithms/transform.hpp | 22 +- .../geometry/multi/algorithms/unique.hpp | 33 +-- include/boost/geometry/multi/multi.hpp | 1 + .../strategies/cartesian/cart_intersect.hpp | 26 +- .../cartesian/distance_pythagoras.hpp | 4 +- .../boost/geometry/strategies/covered_by.hpp | 2 +- include/boost/geometry/strategies/within.hpp | 2 +- test/algorithms/area.cpp | 26 ++ test/algorithms/comparable_distance.cpp | 8 +- test/algorithms/difference.cpp | 142 +++++---- test/algorithms/disjoint.cpp | 16 + test/algorithms/intersects.cpp | 43 ++- test/algorithms/overlay/overlay_cases.hpp | 7 + test/algorithms/overlay/traverse.cpp | 13 +- test/algorithms/test_difference.hpp | 31 +- test/algorithms/test_for_each.hpp | 60 ++++ test/algorithms/test_intersects.hpp | 6 + test/core/point_type.cpp | 10 +- test/geometry_test_common.hpp | 3 + test/multi/algorithms/Jamfile.v2 | 1 + test/multi/algorithms/multi_difference.cpp | 37 ++- test/multi/algorithms/multi_disjoint.cpp | 34 +++ test/multi/algorithms/multi_intersection.cpp | 7 + test/multi/algorithms/multi_intersects.cpp | 51 ++++ test/multi/algorithms/multi_union.cpp | 7 + .../overlay/multi_overlay_cases.hpp | 15 + .../algorithms/overlay/multi_traverse.cpp | 2 +- 89 files changed, 1774 insertions(+), 1608 deletions(-) create mode 100644 doc/generated/buffer_status.qbk create mode 100644 doc/generated/centroid_status.qbk create mode 100644 doc/generated/for_each_point_status.qbk create mode 100644 doc/generated/for_each_segment_status.qbk create mode 100644 doc/generated/length_status.qbk create mode 100644 doc/generated/num_geometries_status.qbk create mode 100644 doc/generated/num_interior_rings_status.qbk create mode 100644 doc/generated/num_points_status.qbk create mode 100644 doc/generated/perimeter_status.qbk create mode 100644 doc/generated/reverse_status.qbk create mode 100644 doc/generated/simplify_status.qbk create mode 100644 doc/generated/transform_status.qbk create mode 100644 doc/generated/unique_status.qbk create mode 100644 include/boost/geometry/geometries/variant.hpp create mode 100644 include/boost/geometry/multi/algorithms/disjoint.hpp create mode 100644 test/multi/algorithms/multi_intersects.cpp diff --git a/doc/generated/buffer_status.qbk b/doc/generated/buffer_status.qbk new file mode 100644 index 0000000000..6caf4c90c3 --- /dev/null +++ b/doc/generated/buffer_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[ ][Point][Segment][Box][Linestring][Ring][Polygon][MultiPoint][MultiLinestring][MultiPolygon]] +[[Point][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Segment][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Linestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Ring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Polygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPoint][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiLinestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPolygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +] diff --git a/doc/generated/centroid_status.qbk b/doc/generated/centroid_status.qbk new file mode 100644 index 0000000000..10e064127a --- /dev/null +++ b/doc/generated/centroid_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/nyi.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/for_each_point_status.qbk b/doc/generated/for_each_point_status.qbk new file mode 100644 index 0000000000..b5383e0d10 --- /dev/null +++ b/doc/generated/for_each_point_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/for_each_segment_status.qbk b/doc/generated/for_each_segment_status.qbk new file mode 100644 index 0000000000..b5383e0d10 --- /dev/null +++ b/doc/generated/for_each_segment_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/length_status.qbk b/doc/generated/length_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/length_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/num_geometries_status.qbk b/doc/generated/num_geometries_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/num_geometries_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/num_interior_rings_status.qbk b/doc/generated/num_interior_rings_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/num_interior_rings_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/num_points_status.qbk b/doc/generated/num_points_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/num_points_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/perimeter_status.qbk b/doc/generated/perimeter_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/perimeter_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/reverse_status.qbk b/doc/generated/reverse_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/reverse_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/simplify_status.qbk b/doc/generated/simplify_status.qbk new file mode 100644 index 0000000000..b5383e0d10 --- /dev/null +++ b/doc/generated/simplify_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/transform_status.qbk b/doc/generated/transform_status.qbk new file mode 100644 index 0000000000..d7d9e977ee --- /dev/null +++ b/doc/generated/transform_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[ ][Point][Segment][Box][Linestring][Ring][Polygon][MultiPoint][MultiLinestring][MultiPolygon]] +[[Point][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +] diff --git a/doc/generated/unique_status.qbk b/doc/generated/unique_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/unique_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 445c03862a..1bb40e2bc5 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -13,6 +13,28 @@ [section:release_notes Release Notes] +[/=================] +[heading Boost 1.53] +[/=================] + +[*Bugfixes] + +* avoid generating output polygons with interior rings below minimum size (e.g. one or two points) +* `geometry::disjoint` for degenerate segments (patched by Karsten Ahnert) +* problem in `geometry::difference` for missing handling tangency, reported by H2 +* fixed `geometry::for_each` for use with Lambda's +* fixed `geometry::comparable_distance` point-linestring (and -range, -polygon) + +[*Additional functionality] + +* combinations for `geometry::disjoint`: point/ring, point/polygon, point/multi_polygon +* combinations for `geometry::intersects`: point/ring, point/polygon, point/multi_polygon + +[*Internal changes] + +* updates in specializations/not_implemented for various algorithms (as in an earlier version, these changes are still going on; they take care for simplified structs, better error reporting, and automatized documentation) +* fixes in unit tests + [/=================] [heading Boost 1.51] [/=================] diff --git a/doc/src/docutils/tools/support_status/support_status.cpp b/doc/src/docutils/tools/support_status/support_status.cpp index b1cc806e62..d3c788db32 100644 --- a/doc/src/docutils/tools/support_status/support_status.cpp +++ b/doc/src/docutils/tools/support_status/support_status.cpp @@ -22,19 +22,49 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include "text_outputter.hpp" @@ -76,13 +106,31 @@ typedef boost::mpl::vector< {}; DECLARE_BINARY_ALGORITHM(append) -DECLARE_UNARY_ALGORITHM (area) -DECLARE_UNARY_ALGORITHM (clear) +DECLARE_UNARY_ALGORITHM(area) +DECLARE_BINARY_ALGORITHM(buffer) +DECLARE_UNARY_ALGORITHM(centroid) +DECLARE_UNARY_ALGORITHM(clear) DECLARE_BINARY_ALGORITHM(convert) -DECLARE_UNARY_ALGORITHM (convex_hull) -DECLARE_UNARY_ALGORITHM (correct) +DECLARE_UNARY_ALGORITHM(convex_hull) +DECLARE_UNARY_ALGORITHM(correct) DECLARE_BINARY_ALGORITHM(covered_by) +DECLARE_BINARY_ALGORITHM(disjoint) DECLARE_BINARY_ALGORITHM(distance) +DECLARE_UNARY_ALGORITHM(envelope) +DECLARE_BINARY_ALGORITHM(equals) +DECLARE_BINARY_ALGORITHM(expand) +DECLARE_UNARY_ALGORITHM(for_each_point) +DECLARE_UNARY_ALGORITHM(for_each_segment) +DECLARE_UNARY_ALGORITHM(length) +DECLARE_UNARY_ALGORITHM(num_geometries) +DECLARE_UNARY_ALGORITHM(num_interior_rings) +DECLARE_UNARY_ALGORITHM(num_points) +DECLARE_BINARY_ALGORITHM(overlaps) +DECLARE_UNARY_ALGORITHM(perimeter) +DECLARE_UNARY_ALGORITHM(reverse) +DECLARE_UNARY_ALGORITHM(simplify) +DECLARE_BINARY_ALGORITHM(transform) +DECLARE_UNARY_ALGORITHM(unique) DECLARE_BINARY_ALGORITHM(within) @@ -194,12 +242,30 @@ void support_status() { test_binary_algorithm >, OutputFactory>("append"); test_unary_algorithm("area"); + test_binary_algorithm("buffer"); + test_unary_algorithm("centroid"); test_unary_algorithm("clear"); test_binary_algorithm("convert"); test_unary_algorithm("convex_hull"); test_unary_algorithm("correct"); test_binary_algorithm("covered_by"); + test_binary_algorithm("disjoint"); test_binary_algorithm("distance"); + test_unary_algorithm("envelope"); + test_binary_algorithm("equals"); + test_binary_algorithm("expand"); + test_unary_algorithm("for_each_point"); + test_unary_algorithm("for_each_segment"); + test_unary_algorithm("length"); + test_unary_algorithm("num_geometries"); + test_unary_algorithm("num_interior_rings"); + test_unary_algorithm("num_points"); + test_binary_algorithm("overlaps"); + test_unary_algorithm("perimeter"); + test_unary_algorithm("reverse"); + test_unary_algorithm("simplify"); + test_binary_algorithm("transform"); + test_unary_algorithm("unique"); test_binary_algorithm("within"); } diff --git a/example/with_external_libs/x04_wxwidgets_world_mapper.cpp b/example/with_external_libs/x04_wxwidgets_world_mapper.cpp index f507f4cb44..1a8bde389e 100644 --- a/example/with_external_libs/x04_wxwidgets_world_mapper.cpp +++ b/example/with_external_libs/x04_wxwidgets_world_mapper.cpp @@ -357,15 +357,15 @@ void HelloWorldCanvas::DrawCountry(wxDC& dc, country_type const& country) BOOST_FOREACH(bg::model::polygon const& poly, country) { - // Use only outer, holes are (for the moment) ignored. This would need + // Use only exterior ring, holes are (for the moment) ignored. This would need // a holey-polygon compatible wx object - std::size_t n = boost::size(poly.outer()); + std::size_t n = boost::size(bg::exterior_ring(poly)); boost::scoped_array points(new wxPoint[n]); wxPointPointerPair pair = std::make_pair(points.get(), points.get() + n); - bg::transform(poly.outer(), pair, *m_map_transformer); + bg::transform(bg::exterior_ring(poly), pair, *m_map_transformer); dc.DrawPolygon(n, points.get()); } diff --git a/include/boost/geometry/algorithms/area.hpp b/include/boost/geometry/algorithms/area.hpp index 8193200ab9..514134e0fd 100644 --- a/include/boost/geometry/algorithms/area.hpp +++ b/include/boost/geometry/algorithms/area.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -26,6 +28,7 @@ #include #include +#include #include #include @@ -49,41 +52,33 @@ namespace boost { namespace geometry namespace detail { namespace area { -template struct box_area { - typedef typename coordinate_type::type return_type; - - static inline return_type apply(Box const& box, Strategy const&) + template + static inline typename coordinate_type::type + apply(Box const& box, Strategy const&) { // Currently only works for 2D Cartesian boxes assert_dimension(); - return_type const dx = get(box) - - get(box); - return_type const dy = get(box) - - get(box); - - return dx * dy; + return (get(box) - get(box)) + * (get(box) - get(box)); } }; template < - typename Ring, iterate_direction Direction, - closure_selector Closure, - typename Strategy + closure_selector Closure > struct ring_area { - BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy) ); - - typedef typename Strategy::return_type type; - - static inline type apply(Ring const& ring, Strategy const& strategy) + template + static inline typename Strategy::return_type + apply(Ring const& ring, Strategy const& strategy) { + BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy) ); assert_dimension(); // Ignore warning (because using static method sometimes) on strategy @@ -95,7 +90,7 @@ struct ring_area if (int(boost::size(ring)) < core_detail::closure::minimum_ring_size::value) { - return type(); + return typename Strategy::return_type(); } typedef typename reversible_view::type rview_type; @@ -136,71 +131,75 @@ namespace dispatch template < typename Geometry, - typename Strategy = typename strategy::area::services::default_strategy - < - typename cs_tag - < - typename point_type::type - >::type, - typename point_type::type - >::type, typename Tag = typename tag::type > -struct area - : detail::calculate_null - < - typename Strategy::return_type, - Geometry, - Strategy - > {}; +struct area : detail::calculate_null +{ + template + static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy) + { + return calculate_null::apply(geometry, strategy); + } +}; -template -< - typename Geometry, - typename Strategy -> -struct area - : detail::area::box_area +template +struct area, void> +{ + template + struct visitor: boost::static_visitor + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy): m_strategy(strategy) {} + + template + typename Strategy::return_type operator()(Geometry const& geometry) const + { + return dispatch::area::apply(geometry, m_strategy); + } + }; + + template + static inline typename Strategy::return_type + apply(Variant const& variant_geometry, Strategy const& strategy) + { + return boost::apply_visitor(visitor(strategy), variant_geometry); + } +}; + + +template +struct area : detail::area::box_area {}; -template -< - typename Ring, - typename Strategy -> -struct area +template +struct area : detail::area::ring_area < - Ring, order_as_direction::value>::value, - geometry::closure::value, - Strategy + geometry::closure::value > {}; -template -< - typename Polygon, - typename Strategy -> -struct area - : detail::calculate_polygon_sum - < +template +struct area : detail::calculate_polygon_sum +{ + template + static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy) + { + return calculate_polygon_sum::apply< typename Strategy::return_type, - Polygon, - Strategy, detail::area::ring_area < - typename ring_type::type, order_as_direction::value>::value, - geometry::closure::value, - Strategy + geometry::closure::value > - > -{}; + >(polygon, strategy); + } +}; } // namespace dispatch @@ -243,10 +242,7 @@ inline typename default_area_result::type area(Geometry const& geometr // detail::throw_on_empty_input(geometry); - return dispatch::area - < - Geometry - >::apply(geometry, strategy_type()); + return dispatch::area::apply(geometry, strategy_type()); } /*! @@ -281,11 +277,7 @@ inline typename Strategy::return_type area( // detail::throw_on_empty_input(geometry); - return dispatch::area - < - Geometry, - Strategy - >::apply(geometry, strategy); + return dispatch::area::apply(geometry, strategy); } diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index e22e36addc..2edce0a093 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -20,6 +20,7 @@ #include +#include #include #include #include @@ -75,15 +76,23 @@ inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out) namespace dispatch { -template -struct buffer {}; +template +< + typename Input, + typename Output, + typename TagIn = typename tag::type, + typename TagOut = typename tag::type +> +struct buffer: not_implemented +{}; -template -struct buffer +template +struct buffer { - static inline void apply(BoxIn const& box_in, T const& distance, - T const& , BoxIn& box_out) + template + static inline void apply(BoxIn const& box_in, Distance const& distance, + Distance const& , BoxIn& box_out) { detail::buffer::buffer_box(box_in, distance, box_out); } @@ -122,10 +131,7 @@ inline void buffer(Input const& geometry_in, Output& geometry_out, dispatch::buffer < - typename tag::type, - typename tag::type, Input, - Distance, Output >::apply(geometry_in, distance, chord_length, geometry_out); } @@ -152,10 +158,7 @@ Output return_buffer(Input const& geometry, T const& distance, T const& chord_le dispatch::buffer < - typename tag::type, - typename tag::type, Input, - T, Output >::apply(geometry, distance, chord_length, geometry_out); diff --git a/include/boost/geometry/algorithms/centroid.hpp b/include/boost/geometry/algorithms/centroid.hpp index 69ad9fe829..9be51f4093 100644 --- a/include/boost/geometry/algorithms/centroid.hpp +++ b/include/boost/geometry/algorithms/centroid.hpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -77,9 +78,9 @@ class centroid_exception : public geometry::exception namespace detail { namespace centroid { -template struct centroid_point { + template static inline void apply(Point const& point, PointCentroid& centroid, Strategy const&) { @@ -127,9 +128,9 @@ struct centroid_box_calculator }; -template struct centroid_box { + template static inline void apply(Box const& box, Point& centroid, Strategy const&) { @@ -173,9 +174,10 @@ inline bool range_ok(Range const& range, Point& centroid) /*! \brief Calculate the centroid of a ring. */ -template +template struct centroid_range_state { + template static inline void apply(Ring const& ring, Strategy const& strategy, typename Strategy::state_type& state) { @@ -196,21 +198,17 @@ struct centroid_range_state } }; -template +template struct centroid_range { + template static inline void apply(Range const& range, Point& centroid, Strategy const& strategy) { if (range_ok(range, centroid)) { typename Strategy::state_type state; - centroid_range_state - < - Range, - Closure, - Strategy - >::apply(range, strategy, state); + centroid_range_state::apply(range, strategy, state); strategy.result(state, centroid); } } @@ -222,20 +220,14 @@ struct centroid_range \note Because outer ring is clockwise, inners are counter clockwise, triangle approach is OK and works for polygons with rings. */ -template struct centroid_polygon_state { - typedef typename ring_type::type ring_type; - + template static inline void apply(Polygon const& poly, Strategy const& strategy, typename Strategy::state_type& state) { - typedef centroid_range_state - < - ring_type, - geometry::closure::value, - Strategy - > per_ring; + typedef typename ring_type::type ring_type; + typedef centroid_range_state::value> per_ring; per_ring::apply(exterior_ring(poly), strategy, state); @@ -248,20 +240,16 @@ struct centroid_polygon_state } }; -template struct centroid_polygon { + template static inline void apply(Polygon const& poly, Point& centroid, Strategy const& strategy) { if (range_ok(exterior_ring(poly), centroid)) { typename Strategy::state_type state; - centroid_polygon_state - < - Polygon, - Strategy - >::apply(poly, strategy, state); + centroid_polygon_state::apply(poly, strategy, state); strategy.result(state, centroid); } } @@ -278,58 +266,35 @@ namespace dispatch template < - typename Tag, typename Geometry, - typename Point, - typename Strategy + typename Tag = typename tag::type > -struct centroid {}; +struct centroid: not_implemented +{}; -template -< - typename Geometry, - typename Point, - typename Strategy -> -struct centroid - : detail::centroid::centroid_point +template +struct centroid + : detail::centroid::centroid_point {}; -template -< - typename Box, - typename Point, - typename Strategy -> -struct centroid - : detail::centroid::centroid_box +template +struct centroid + : detail::centroid::centroid_box {}; -template -struct centroid - : detail::centroid::centroid_range - < - Ring, - Point, - geometry::closure::value, - Strategy - > +template +struct centroid + : detail::centroid::centroid_range::value> {}; -template -struct centroid - : detail::centroid::centroid_range - < - Linestring, - Point, - closed, - Strategy - > +template +struct centroid + : detail::centroid::centroid_range {}; -template -struct centroid - : detail::centroid::centroid_polygon +template +struct centroid + : detail::centroid::centroid_polygon {}; } // namespace dispatch @@ -365,13 +330,7 @@ inline void centroid(Geometry const& geometry, Point& c, // Call dispatch apply method. That one returns true if centroid // should be taken from state. - dispatch::centroid - < - typename tag::type, - Geometry, - Point, - Strategy - >::apply(geometry, c, strategy); + dispatch::centroid::apply(geometry, c, strategy); } diff --git a/include/boost/geometry/algorithms/convex_hull.hpp b/include/boost/geometry/algorithms/convex_hull.hpp index 56b87c8c15..d31efe9e44 100644 --- a/include/boost/geometry/algorithms/convex_hull.hpp +++ b/include/boost/geometry/algorithms/convex_hull.hpp @@ -40,18 +40,13 @@ namespace boost { namespace geometry namespace detail { namespace convex_hull { -template -< - typename Geometry, - order_selector Order, - typename Strategy -> +template struct hull_insert { // Member template function (to avoid inconvenient declaration // of output-iterator-type, from hull_to_geometry) - template + template static inline OutputIterator apply(Geometry const& geometry, OutputIterator out, Strategy const& strategy) { @@ -63,22 +58,15 @@ struct hull_insert } }; -template -< - typename Geometry, - typename Strategy -> struct hull_to_geometry { - template + template static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy) { hull_insert < - Geometry, - geometry::point_order::value, - Strategy + geometry::point_order::value >::apply(geometry, std::back_inserter( // Handle linestring, ring and polygon the same: @@ -113,21 +101,16 @@ namespace dispatch template < typename Geometry, - typename Strategy = typename detail::convex_hull::default_strategy::type, typename Tag = typename tag::type > struct convex_hull - : detail::convex_hull::hull_to_geometry + : detail::convex_hull::hull_to_geometry {}; -template -< - typename Box, - typename Strategy -> -struct convex_hull +template +struct convex_hull { - template + template static inline void apply(Box const& box, OutputGeometry& out, Strategy const& ) { @@ -149,13 +132,9 @@ struct convex_hull -template -< - order_selector Order, - typename Geometry, typename Strategy -> +template struct convex_hull_insert - : detail::convex_hull::hull_insert + : detail::convex_hull::hull_insert {}; @@ -181,11 +160,7 @@ inline void convex_hull(Geometry const& geometry, return; } - dispatch::convex_hull - < - Geometry, - Strategy - >::apply(geometry, out, strategy); + dispatch::convex_hull::apply(geometry, out, strategy); } @@ -232,8 +207,7 @@ inline OutputIterator convex_hull_insert(Geometry const& geometry, return dispatch::convex_hull_insert < - geometry::point_order::value, - Geometry, Strategy + geometry::point_order::value >::apply(geometry, out, strategy); } diff --git a/include/boost/geometry/algorithms/correct.hpp b/include/boost/geometry/algorithms/correct.hpp index 583e395f8e..39249e7de1 100644 --- a/include/boost/geometry/algorithms/correct.hpp +++ b/include/boost/geometry/algorithms/correct.hpp @@ -119,10 +119,8 @@ struct correct_ring typedef detail::area::ring_area < - Ring, order_as_direction::value>::value, - geometry::closure::value, - strategy_type + geometry::closure::value > ring_area_type; diff --git a/include/boost/geometry/algorithms/detail/calculate_null.hpp b/include/boost/geometry/algorithms/detail/calculate_null.hpp index 4b48d62fc2..3ebca83506 100644 --- a/include/boost/geometry/algorithms/detail/calculate_null.hpp +++ b/include/boost/geometry/algorithms/detail/calculate_null.hpp @@ -21,9 +21,9 @@ namespace boost { namespace geometry namespace detail { -template struct calculate_null { + template static inline ReturnType apply(Geometry const& , Strategy const&) { return ReturnType(); diff --git a/include/boost/geometry/algorithms/detail/calculate_sum.hpp b/include/boost/geometry/algorithms/detail/calculate_sum.hpp index 2ad349080b..dd0399bb17 100644 --- a/include/boost/geometry/algorithms/detail/calculate_sum.hpp +++ b/include/boost/geometry/algorithms/detail/calculate_sum.hpp @@ -26,16 +26,9 @@ namespace detail { -template -< - typename ReturnType, - typename Polygon, - typename Strategy, - typename Policy -> class calculate_polygon_sum { - template + template static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy) { ReturnType sum = ReturnType(); @@ -47,10 +40,11 @@ class calculate_polygon_sum } public : + template static inline ReturnType apply(Polygon const& poly, Strategy const& strategy) { return Policy::apply(exterior_ring(poly), strategy) - + sum_interior_rings(interior_rings(poly), strategy) + + sum_interior_rings(interior_rings(poly), strategy) ; } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint.hpp b/include/boost/geometry/algorithms/detail/disjoint.hpp index 2ced5b1ce3..e944e5169a 100644 --- a/include/boost/geometry/algorithms/detail/disjoint.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint.hpp @@ -26,6 +26,7 @@ #include #include +#include #include @@ -165,6 +166,19 @@ struct box_box }; +template +< + typename Geometry1, typename Geometry2 +> +struct reverse_covered_by +{ + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + { + return ! geometry::covered_by(geometry1, geometry2); + } +}; + + /*! \brief Internal utility function to detect of boxes are disjoint diff --git a/include/boost/geometry/algorithms/detail/get_left_turns.hpp b/include/boost/geometry/algorithms/detail/get_left_turns.hpp index 62f0f7f0f4..d23f1e4c27 100644 --- a/include/boost/geometry/algorithms/detail/get_left_turns.hpp +++ b/include/boost/geometry/algorithms/detail/get_left_turns.hpp @@ -120,10 +120,10 @@ inline bool include_left_turn_of_all( bool result = false; std::pair pair = ordered_pair(outgoing_seg_id, incoming_seg_id); - auto it = turn_segment_indices.find(pair); + typename boost::range_iterator::type it = turn_segment_indices.find(pair); if (it != turn_segment_indices.end()) { - for (auto sit = it->second.begin(); sit != it->second.end(); ++sit) + for (std::set::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit) { if (process_include(outgoing_seg_id, incoming_seg_id, *sit, turns[*sit], keep_indices, priority)) { @@ -148,14 +148,17 @@ inline bool prefer_by_other(Turns const& turns, std::set& indices) { std::map map; - for (auto sit = indices.begin(); sit != indices.end(); ++sit) + for (std::set::const_iterator sit = indices.begin(); + sit != indices.end(); + ++sit) { map[turns[*sit].operations[0].seg_id]++; map[turns[*sit].operations[1].seg_id]++; } std::set segment_occuring_once; - for (auto mit = map.begin(); mit != map.end(); ++mit) + for (std::map::const_iterator mit = map.begin(); + mit != map.end();++mit) { if (mit->second == 1) { @@ -176,13 +179,14 @@ inline bool prefer_by_other(Turns const& turns, segment_identifier back = *soo_it; std::pair pair = ordered_pair(front, back); - auto it = turn_segment_indices.find(pair); + + typename boost::range_iterator::type it = turn_segment_indices.find(pair); if (it != turn_segment_indices.end()) { // debug_turns_by_indices("Found", it->second); // Check which is the union/continue segment_identifier good; - for (auto sit = it->second.begin(); sit != it->second.end(); ++sit) + for (std::set::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit) { if (turns[*sit].operations[0].operation == detail::overlay::operation_union) { @@ -200,7 +204,7 @@ inline bool prefer_by_other(Turns const& turns, // Find in indexes-to-keep this segment with the union. Discard the other one std::set ok_indices; - for (auto sit = indices.begin(); sit != indices.end(); ++sit) + for (std::set::const_iterator sit = indices.begin(); sit != indices.end(); ++sit) { if (corresponds<0>(turns[*sit], good) || corresponds<1>(turns[*sit], good)) { @@ -223,7 +227,7 @@ inline void prefer_by_priority(Turns const& turns, std::set& indices) { // Find max prio int min_prio = 1024, max_prio = 0; - for (auto sit = indices.begin(); sit != indices.end(); ++sit) + for (std::set::const_iterator sit = indices.begin(); sit != indices.end(); ++sit) { if (turns[*sit].priority > max_prio) { @@ -242,7 +246,7 @@ inline void prefer_by_priority(Turns const& turns, std::set& indices) // Only keep indices with high prio std::set ok_indices; - for (auto sit = indices.begin(); sit != indices.end(); ++sit) + for (std::set::const_iterator sit = indices.begin(); sit != indices.end(); ++sit) { if (turns[*sit].priority >= max_prio) { diff --git a/include/boost/geometry/algorithms/detail/occupation_info.hpp b/include/boost/geometry/algorithms/detail/occupation_info.hpp index e147ba12d8..6d15f2dd63 100644 --- a/include/boost/geometry/algorithms/detail/occupation_info.hpp +++ b/include/boost/geometry/algorithms/detail/occupation_info.hpp @@ -10,7 +10,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP #if ! defined(NDEBUG) - #define BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION +// #define BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION #endif #include diff --git a/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp index 74595fedd0..5ff0b57d6e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp @@ -75,15 +75,15 @@ inline OutputIterator add_rings(SelectionMap const& map, OutputIterator out) { typedef typename SelectionMap::const_iterator iterator; - typedef typename SelectionMap::mapped_type property_type; - typedef typename property_type::area_type area_type; - - area_type const zero = 0; - std::size_t const min_num_points = core_detail::closure::minimum_ring_size - < - geometry::closure - < - typename boost::range_value + typedef typename SelectionMap::mapped_type property_type; + typedef typename property_type::area_type area_type; + + area_type const zero = 0; + std::size_t const min_num_points = core_detail::closure::minimum_ring_size + < + geometry::closure + < + typename boost::range_value < RingCollection const >::type @@ -117,15 +117,14 @@ inline OutputIterator add_rings(SelectionMap const& map, } } - // Only add rings if they satisfy minimal requirements. - // This cannot be done earlier (during traversal), not - // everything is figured out yet (sum of positive/negative rings) - // TODO: individual rings can still contain less than 3 points. - if (geometry::num_points(result) >= min_num_points - && math::larger(geometry::area(result), zero)) - { - *out++ = result; - } + // Only add rings if they satisfy minimal requirements. + // This cannot be done earlier (during traversal), not + // everything is figured out yet (sum of positive/negative rings) + if (geometry::num_points(result) >= min_num_points + && math::larger(geometry::area(result), zero)) + { + *out++ = result; + } } } return out; diff --git a/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp index 05bd721e7f..51955b515d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp @@ -77,12 +77,23 @@ struct convert_ring } else { - interior_rings(destination).resize( - interior_rings(destination).size() + 1); - geometry::convert(source, interior_rings(destination).back()); - if (reverse) + // Avoid adding interior rings which are invalid + // because of its number of points: + std::size_t const min_num_points + = core_detail::closure::minimum_ring_size + < + geometry::closure::value + >::value; + + if (geometry::num_points(source) >= min_num_points) { - boost::reverse(interior_rings(destination).back()); + interior_rings(destination).resize( + interior_rings(destination).size() + 1); + geometry::convert(source, interior_rings(destination).back()); + if (reverse) + { + boost::reverse(interior_rings(destination).back()); + } } } } diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp index 1e878ca525..84ec16f238 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp @@ -252,6 +252,32 @@ private : : order == 1; } + inline bool consider_ix_ix(Indexed const& left, Indexed const& right + , std::string const& // header + ) const + { + // Take first intersection, then blocked. + if (left.subject.operation == operation_intersection + && right.subject.operation == operation_blocked) + { + return true; + } + else if (left.subject.operation == operation_blocked + && right.subject.operation == operation_intersection) + { + return false; + } + + // Default case, should not occur + +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + std::cout << "ix/ix unhandled" << std::endl; +#endif + //debug_consider(0, left, right, header, false, "-> return", ret); + + return left.index < right.index; + } + inline bool consider_iu_iu(Indexed const& left, Indexed const& right, std::string const& header) const @@ -446,6 +472,11 @@ public : { return consider_iu_iu(left, right, "iu/iu"); } + else if (m_turn_points[left.index].combination(operation_intersection, operation_blocked) + && m_turn_points[right.index].combination(operation_intersection, operation_blocked)) + { + return consider_ix_ix(left, right, "ix/ix"); + } else if (m_turn_points[left.index].both(operation_intersection) && m_turn_points[right.index].both(operation_intersection)) { @@ -493,7 +524,7 @@ public : << "/" << operation_char(m_turn_points[right.index].operations[0].operation) << operation_char(m_turn_points[right.index].operations[1].operation) << " " << " Take " << left.index << " < " << right.index - << std::cout; + << std::endl; #endif return default_order; diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 8bca790d74..f0307eaf83 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -41,14 +41,14 @@ namespace boost { namespace geometry namespace detail { namespace intersection { -template -< - typename Segment1, typename Segment2, - typename OutputIterator, typename PointOut, - typename Strategy -> +template struct intersection_segment_segment_point { + template + < + typename Segment1, typename Segment2, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(Segment1 const& segment1, Segment2 const& segment2, OutputIterator out, Strategy const& ) @@ -77,14 +77,14 @@ struct intersection_segment_segment_point } }; -template -< - typename Linestring1, typename Linestring2, - typename OutputIterator, typename PointOut, - typename Strategy -> +template struct intersection_linestring_linestring_point { + template + < + typename Linestring1, typename Linestring2, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(Linestring1 const& linestring1, Linestring2 const& linestring2, OutputIterator out, Strategy const& ) @@ -112,22 +112,12 @@ struct intersection_linestring_linestring_point */ template < - typename LineString, typename Areal, bool ReverseAreal, - typename OutputIterator, typename LineStringOut, - overlay_type OverlayType, - typename Strategy + typename LineStringOut, + overlay_type OverlayType > struct intersection_of_linestring_with_areal { - typedef detail::overlay::follow - < - LineStringOut, - LineString, - Areal, - OverlayType - > follower; - #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) template static inline void debug_follow(Turn const& turn, Operation op, @@ -145,6 +135,11 @@ struct intersection_of_linestring_with_areal } #endif + template + < + typename LineString, typename Areal, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(LineString const& linestring, Areal const& areal, OutputIterator out, Strategy const& ) @@ -154,6 +149,14 @@ struct intersection_of_linestring_with_areal return out; } + typedef detail::overlay::follow + < + LineStringOut, + LineString, + Areal, + OverlayType + > follower; + typedef typename point_type::type point_type; typedef detail::overlay::traversal_turn_info turn_info; @@ -220,18 +223,22 @@ namespace dispatch template < - // tag dispatching: - typename TagIn1, typename TagIn2, typename TagOut, - // orientation - // metafunction finetuning helpers: - bool Areal1, bool Areal2, bool ArealOut, // real types typename Geometry1, typename Geometry2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, overlay_type OverlayType, - typename Strategy + // orientation + bool Reverse1 = detail::overlay::do_reverse::value>::value, + bool Reverse2 = detail::overlay::do_reverse::value>::value, + bool ReverseOut = detail::overlay::do_reverse::value>::value, + // tag dispatching: + typename TagIn1 = typename geometry::tag::type, + typename TagIn2 = typename geometry::tag::type, + typename TagOut = typename geometry::tag::type, + // metafunction finetuning helpers: + bool Areal1 = geometry::is_areal::value, + bool Areal2 = geometry::is_areal::value, + bool ArealOut = geometry::is_areal::value > struct intersection_insert { @@ -245,122 +252,103 @@ struct intersection_insert template < - typename TagIn1, typename TagIn2, typename TagOut, typename Geometry1, typename Geometry2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut, + typename TagIn1, typename TagIn2, typename TagOut > struct intersection_insert < - TagIn1, TagIn2, TagOut, - true, true, true, Geometry1, Geometry2, - Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + TagIn1, TagIn2, TagOut, + true, true, true > : detail::overlay::overlay - + {}; // Any areal type with box: template < - typename TagIn, typename TagOut, typename Geometry, typename Box, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut, + typename TagIn, typename TagOut > struct intersection_insert < - TagIn, box_tag, TagOut, - true, true, true, Geometry, Box, - Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + TagIn, box_tag, TagOut, + true, true, true > : detail::overlay::overlay - + {}; template < typename Segment1, typename Segment2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert < - segment_tag, segment_tag, point_tag, - false, false, false, Segment1, Segment2, + GeometryOut, + OverlayType, Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, - OverlayType, Strategy - > : detail::intersection::intersection_segment_segment_point - < - Segment1, Segment2, - OutputIterator, GeometryOut, - Strategy - > + segment_tag, segment_tag, point_tag, + false, false, false + > : detail::intersection::intersection_segment_segment_point {}; template < typename Linestring1, typename Linestring2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert < - linestring_tag, linestring_tag, point_tag, - false, false, false, Linestring1, Linestring2, + GeometryOut, + OverlayType, Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, - OverlayType, Strategy - > : detail::intersection::intersection_linestring_linestring_point - < - Linestring1, Linestring2, - OutputIterator, GeometryOut, - Strategy - > + linestring_tag, linestring_tag, point_tag, + false, false, false + > : detail::intersection::intersection_linestring_linestring_point {}; template < typename Linestring, typename Box, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert < - linestring_tag, box_tag, linestring_tag, - false, true, false, Linestring, Box, - Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + linestring_tag, box_tag, linestring_tag, + false, true, false > { + template static inline OutputIterator apply(Linestring const& linestring, Box const& box, OutputIterator out, Strategy const& ) { @@ -375,27 +363,23 @@ struct intersection_insert template < typename Linestring, typename Polygon, - bool ReverseLinestring, bool ReversePolygon, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool ReverseLinestring, bool ReversePolygon, bool ReverseOut > struct intersection_insert < - linestring_tag, polygon_tag, linestring_tag, - false, true, false, Linestring, Polygon, - ReverseLinestring, ReversePolygon, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + ReverseLinestring, ReversePolygon, ReverseOut, + linestring_tag, polygon_tag, linestring_tag, + false, true, false > : detail::intersection::intersection_of_linestring_with_areal < - Linestring, Polygon, ReversePolygon, - OutputIterator, GeometryOut, - OverlayType, - Strategy + GeometryOut, + OverlayType > {}; @@ -403,49 +387,44 @@ struct intersection_insert template < typename Linestring, typename Ring, - bool ReverseLinestring, bool ReverseRing, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool ReverseLinestring, bool ReverseRing, bool ReverseOut > struct intersection_insert < - linestring_tag, ring_tag, linestring_tag, - false, true, false, Linestring, Ring, - ReverseLinestring, ReverseRing, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + ReverseLinestring, ReverseRing, ReverseOut, + linestring_tag, ring_tag, linestring_tag, + false, true, false > : detail::intersection::intersection_of_linestring_with_areal < - Linestring, Ring, ReverseRing, - OutputIterator, GeometryOut, - OverlayType, - Strategy + GeometryOut, + OverlayType > {}; template < typename Segment, typename Box, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert < - segment_tag, box_tag, linestring_tag, - false, true, false, Segment, Box, - Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + segment_tag, box_tag, linestring_tag, + false, true, false > { + template static inline OutputIterator apply(Segment const& segment, Box const& box, OutputIterator out, Strategy const& ) { @@ -460,25 +439,24 @@ struct intersection_insert template < - typename Tag1, typename Tag2, - bool Areal1, bool Areal2, typename Geometry1, typename Geometry2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename PointOut, + typename PointOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag1, typename Tag2, + bool Areal1, bool Areal2 > struct intersection_insert < - Tag1, Tag2, point_tag, - Areal1, Areal2, false, Geometry1, Geometry2, - Reverse1, Reverse2, ReverseOut, - OutputIterator, PointOut, + PointOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + Tag1, Tag2, point_tag, + Areal1, Areal2, false > { + template static inline OutputIterator apply(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out, Strategy const& ) { @@ -504,29 +482,22 @@ struct intersection_insert template < - typename GeometryTag1, typename GeometryTag2, typename GeometryTag3, - bool Areal1, bool Areal2, bool ArealOut, - typename Geometry1, typename Geometry2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename Geometry1, typename Geometry2, typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert_reversed { + template static inline OutputIterator apply(Geometry1 const& g1, Geometry2 const& g2, OutputIterator out, Strategy const& strategy) { return intersection_insert < - GeometryTag2, GeometryTag1, GeometryTag3, - Areal2, Areal1, ArealOut, - Geometry2, Geometry1, - Reverse2, Reverse1, ReverseOut, - OutputIterator, GeometryOut, + Geometry2, Geometry1, GeometryOut, OverlayType, - Strategy + Reverse2, Reverse1, ReverseOut >::apply(g2, g1, out, strategy); } }; @@ -561,35 +532,20 @@ inline OutputIterator insert(Geometry1 const& geometry1, geometry::reverse_dispatch::type::value, geometry::dispatch::intersection_insert_reversed < - typename geometry::tag::type, - typename geometry::tag::type, - typename geometry::tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, Geometry1, Geometry2, + GeometryOut, + OverlayType, overlay::do_reverse::value>::value, overlay::do_reverse::value, ReverseSecond>::value, - overlay::do_reverse::value>::value, - OutputIterator, GeometryOut, - OverlayType, - Strategy + overlay::do_reverse::value>::value >, geometry::dispatch::intersection_insert < - typename geometry::tag::type, - typename geometry::tag::type, - typename geometry::tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, Geometry1, Geometry2, - geometry::detail::overlay::do_reverse::value>::value, - geometry::detail::overlay::do_reverse::value, ReverseSecond>::value, - geometry::detail::overlay::do_reverse::value>::value, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + geometry::detail::overlay::do_reverse::value>::value, + geometry::detail::overlay::do_reverse::value, ReverseSecond>::value > >::type::apply(geometry1, geometry2, out, strategy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index 41665e0af1..8b89d39c5b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -134,12 +134,12 @@ template < typename Geometry1, typename Geometry2, bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, - overlay_type Direction, - typename Strategy + typename GeometryOut, + overlay_type Direction > struct overlay { + template static inline OutputIterator apply( Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out, diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index 12daafa0cf..02dd01d6c2 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #include #include @@ -233,6 +235,7 @@ public : detail::overlay::operation_type operation, Turns& turns, Rings& rings) { + typedef typename boost::range_value::type ring_type; typedef typename boost::range_iterator::type turn_iterator; typedef typename boost::range_value::type turn_type; typedef typename boost::range_iterator @@ -240,6 +243,12 @@ public : typename turn_type::container_type >::type turn_operation_iterator_type; + std::size_t const min_num_points + = core_detail::closure::minimum_ring_size + < + geometry::closure::value + >::value; + std::size_t size_at_start = boost::size(rings); typename Backtrack::state_type state; @@ -267,7 +276,7 @@ public : { set_visited_for_continue(*it, *iit); - typename boost::range_value::type current_output; + ring_type current_output; detail::overlay::append_no_duplicates(current_output, it->point, true); @@ -376,7 +385,10 @@ public : { iit->visited.set_finished(); detail::overlay::debug_traverse(*current, *iit, "->Finished"); - rings.push_back(current_output); + if (geometry::num_points(current_output) >= min_num_points) + { + rings.push_back(current_output); + } } } } diff --git a/include/boost/geometry/algorithms/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index 480dd928de..2f32b344c4 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -56,19 +56,11 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, return geometry::dispatch::intersection_insert < - typename geometry::tag::type, - typename geometry::tag::type, - typename geometry::tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, Geometry1, Geometry2, - geometry::detail::overlay::do_reverse::value>::value, - geometry::detail::overlay::do_reverse::value, true>::value, - geometry::detail::overlay::do_reverse::value>::value, - OutputIterator, GeometryOut, + GeometryOut, overlay_difference, - Strategy + geometry::detail::overlay::do_reverse::value>::value, + geometry::detail::overlay::do_reverse::value, true>::value >::apply(geometry1, geometry2, out, strategy); } diff --git a/include/boost/geometry/algorithms/disjoint.hpp b/include/boost/geometry/algorithms/disjoint.hpp index f986cc24af..b2de6e01d7 100644 --- a/include/boost/geometry/algorithms/disjoint.hpp +++ b/include/boost/geometry/algorithms/disjoint.hpp @@ -184,68 +184,82 @@ namespace dispatch template < - typename GeometryTag1, typename GeometryTag2, typename Geometry1, typename Geometry2, - std::size_t DimensionCount + std::size_t DimensionCount = dimension::type::value, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type, + bool Reverse = reverse_dispatch::type::value > struct disjoint : detail::disjoint::general_areal {}; -template -struct disjoint +// If reversal is needed, perform it +template +< + typename Geometry1, typename Geometry2, + std::size_t DimensionCount, + typename Tag1, typename Tag2 +> +struct disjoint + : disjoint +{ + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + { + return disjoint + < + Geometry2, Geometry1, + DimensionCount, + Tag2, Tag1 + >::apply(g2, g1); + } +}; + + +template +struct disjoint : detail::disjoint::point_point {}; -template -struct disjoint +template +struct disjoint : detail::disjoint::box_box {}; -template -struct disjoint +template +struct disjoint : detail::disjoint::point_box {}; -template -struct disjoint +template +struct disjoint + : detail::disjoint::reverse_covered_by +{}; + +template +struct disjoint + : detail::disjoint::reverse_covered_by +{}; + +template +struct disjoint : detail::disjoint::disjoint_linear {}; -template -struct disjoint +template +struct disjoint : detail::disjoint::disjoint_segment {}; -template -struct disjoint +template +struct disjoint : detail::disjoint::disjoint_linear {}; -template -< - typename GeometryTag1, typename GeometryTag2, - typename Geometry1, typename Geometry2, - std::size_t DimensionCount -> -struct disjoint_reversed -{ - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) - { - return disjoint - < - GeometryTag2, GeometryTag1, - Geometry2, Geometry1, - DimensionCount - >::apply(g2, g1); - } -}; - - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -272,26 +286,7 @@ inline bool disjoint(Geometry1 const& geometry1, Geometry2 const >(); - return boost::mpl::if_c - < - reverse_dispatch::type::value, - dispatch::disjoint_reversed - < - typename tag::type, - typename tag::type, - Geometry1, - Geometry2, - dimension::type::value - >, - dispatch::disjoint - < - typename tag::type, - typename tag::type, - Geometry1, - Geometry2, - dimension::type::value - > - >::type::apply(geometry1, geometry2); + return dispatch::disjoint::apply(geometry1, geometry2); } diff --git a/include/boost/geometry/algorithms/distance.hpp b/include/boost/geometry/algorithms/distance.hpp index 11c2bc929b..c5a65ba150 100644 --- a/include/boost/geometry/algorithms/distance.hpp +++ b/include/boost/geometry/algorithms/distance.hpp @@ -369,7 +369,10 @@ struct distance < segment_tag, Point, - typename point_type::type + typename point_type::type, + typename cs_tag::type, + typename cs_tag::type>::type, + Strategy >::type ps_strategy_type; return detail::distance::point_to_range diff --git a/include/boost/geometry/algorithms/for_each.hpp b/include/boost/geometry/algorithms/for_each.hpp index 671f26a70d..06a400cf63 100644 --- a/include/boost/geometry/algorithms/for_each.hpp +++ b/include/boost/geometry/algorithms/for_each.hpp @@ -18,8 +18,10 @@ #include #include +#include #include +#include #include #include #include @@ -39,53 +41,55 @@ namespace detail { namespace for_each { -template struct fe_point_per_point { - static inline Functor apply( - typename add_const_if_c::type& point, Functor f) + template + static inline void apply(Point& point, Functor& f) { f(point); - return f; } }; -template struct fe_point_per_segment { - static inline Functor apply( - typename add_const_if_c::type& , Functor f) + template + static inline void apply(Point& , Functor& f) { // TODO: if non-const, we should extract the points from the segment // and call the functor on those two points - return f; } }; -template struct fe_range_per_point { - static inline Functor apply( - typename add_const_if_c::type& range, - Functor f) + template + static inline void apply(Range& range, Functor& f) { - return (std::for_each(boost::begin(range), boost::end(range), f)); + // The previous implementation called the std library: + // return (std::for_each(boost::begin(range), boost::end(range), f)); + // But that is not accepted for capturing lambda's. + // It needs to do it like that to return the state of Functor f (f is passed by value in std::for_each). + + // So we now loop manually. + + for (typename boost::range_iterator::type it = boost::begin(range); it != boost::end(range); ++it) + { + f(*it); + } } }; -template struct fe_range_per_segment { - static inline Functor apply( - typename add_const_if_c::type& range, - Functor f) + template + static inline void apply(Range& range, Functor& f) { typedef typename add_const_if_c < - IsConst, + is_const::value, typename point_type::type >::type point_type; @@ -97,65 +101,41 @@ struct fe_range_per_segment f(s); previous = it++; } - - return f; } }; -template struct fe_polygon_per_point { - typedef typename add_const_if_c::type poly_type; - - static inline Functor apply(poly_type& poly, Functor f) + template + static inline void apply(Polygon& poly, Functor& f) { - typedef fe_range_per_point - < - typename ring_type::type, - Functor, - IsConst - > per_ring; - - f = per_ring::apply(exterior_ring(poly), f); + fe_range_per_point::apply(exterior_ring(poly), f); - typename interior_return_type::type rings + typename interior_return_type::type rings = interior_rings(poly); for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) { - f = per_ring::apply(*it, f); + fe_range_per_point::apply(*it, f); } - - return f; } }; -template struct fe_polygon_per_segment { - typedef typename add_const_if_c::type poly_type; - - static inline Functor apply(poly_type& poly, Functor f) + template + static inline void apply(Polygon& poly, Functor& f) { - typedef fe_range_per_segment - < - typename ring_type::type, - Functor, - IsConst - > per_ring; - - f = per_ring::apply(exterior_ring(poly), f); + fe_range_per_segment::apply(exterior_ring(poly), f); - typename interior_return_type::type rings + typename interior_return_type::type rings = interior_rings(poly); for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) { - f = per_ring::apply(*it, f); + fe_range_per_segment::apply(*it, f); } - - return f; } }; @@ -171,68 +151,66 @@ namespace dispatch template < - typename Tag, typename Geometry, - typename Functor, - bool IsConst + typename Tag = typename tag_cast::type, multi_tag>::type > -struct for_each_point {}; +struct for_each_point: not_implemented +{}; -template -struct for_each_point - : detail::for_each::fe_point_per_point +template +struct for_each_point + : detail::for_each::fe_point_per_point {}; -template -struct for_each_point - : detail::for_each::fe_range_per_point +template +struct for_each_point + : detail::for_each::fe_range_per_point {}; -template -struct for_each_point - : detail::for_each::fe_range_per_point +template +struct for_each_point + : detail::for_each::fe_range_per_point {}; -template -struct for_each_point - : detail::for_each::fe_polygon_per_point +template +struct for_each_point + : detail::for_each::fe_polygon_per_point {}; template < - typename Tag, typename Geometry, - typename Functor, - bool IsConst + typename Tag = typename tag_cast::type, multi_tag>::type > -struct for_each_segment {}; +struct for_each_segment: not_implemented +{}; -template -struct for_each_segment - : detail::for_each::fe_point_per_segment +template +struct for_each_segment + : detail::for_each::fe_point_per_segment {}; -template -struct for_each_segment - : detail::for_each::fe_range_per_segment +template +struct for_each_segment + : detail::for_each::fe_range_per_segment {}; -template -struct for_each_segment - : detail::for_each::fe_range_per_segment +template +struct for_each_segment + : detail::for_each::fe_range_per_segment {}; -template -struct for_each_segment - : detail::for_each::fe_polygon_per_segment +template +struct for_each_segment + : detail::for_each::fe_polygon_per_segment {}; @@ -240,35 +218,6 @@ struct for_each_segment #endif // DOXYGEN_NO_DISPATCH -/*! -\brief \brf_for_each{point} -\details \det_for_each{point} -\ingroup for_each -\param geometry \param_geometry -\param f \par_for_each_f{const point} -\tparam Geometry \tparam_geometry -\tparam Functor \tparam_functor - -\qbk{distinguish,const version} -\qbk{[include reference/algorithms/for_each_point.qbk]} -\qbk{[heading Example]} -\qbk{[for_each_point_const] [for_each_point_const_output]} -*/ -template -inline Functor for_each_point(Geometry const& geometry, Functor f) -{ - concept::check(); - - return dispatch::for_each_point - < - typename tag_cast::type, multi_tag>::type, - Geometry, - Functor, - true - >::apply(geometry, f); -} - - /*! \brief \brf_for_each{point} \details \det_for_each{point} @@ -281,19 +230,15 @@ inline Functor for_each_point(Geometry const& geometry, Functor f) \qbk{[include reference/algorithms/for_each_point.qbk]} \qbk{[heading Example]} \qbk{[for_each_point] [for_each_point_output]} +\qbk{[for_each_point_const] [for_each_point_const_output]} */ template inline Functor for_each_point(Geometry& geometry, Functor f) { concept::check(); - return dispatch::for_each_point - < - typename tag_cast::type, multi_tag>::type, - Geometry, - Functor, - false - >::apply(geometry, f); + dispatch::for_each_point::apply(geometry, f); + return f; } @@ -302,53 +247,21 @@ inline Functor for_each_point(Geometry& geometry, Functor f) \details \det_for_each{segment} \ingroup for_each \param geometry \param_geometry -\param f \par_for_each_f{const segment} +\param f \par_for_each_f{segment} \tparam Geometry \tparam_geometry \tparam Functor \tparam_functor -\qbk{distinguish,const version} \qbk{[include reference/algorithms/for_each_segment.qbk]} \qbk{[heading Example]} \qbk{[for_each_segment_const] [for_each_segment_const_output]} */ template -inline Functor for_each_segment(Geometry const& geometry, Functor f) -{ - concept::check(); - - return dispatch::for_each_segment - < - typename tag_cast::type, multi_tag>::type, - Geometry, - Functor, - true - >::apply(geometry, f); -} - - -/*! -\brief \brf_for_each{segment} -\details \det_for_each{segment} -\ingroup for_each -\param geometry \param_geometry -\param f \par_for_each_f{segment} -\tparam Geometry \tparam_geometry -\tparam Functor \tparam_functor - -\qbk{[include reference/algorithms/for_each_segment.qbk]} -*/ -template inline Functor for_each_segment(Geometry& geometry, Functor f) { concept::check(); - return dispatch::for_each_segment - < - typename tag_cast::type, multi_tag>::type, - Geometry, - Functor, - false - >::apply(geometry, f); + dispatch::for_each_segment::apply(geometry, f); + return f; } diff --git a/include/boost/geometry/algorithms/intersection.hpp b/include/boost/geometry/algorithms/intersection.hpp index 8d3dd68b3a..3125752db8 100644 --- a/include/boost/geometry/algorithms/intersection.hpp +++ b/include/boost/geometry/algorithms/intersection.hpp @@ -22,15 +22,14 @@ namespace boost { namespace geometry namespace detail { namespace intersection { -template -< - typename Box1, typename Box2, - typename BoxOut, - typename Strategy, - std::size_t Dimension, std::size_t DimensionCount -> +template struct intersection_box_box { + template + < + typename Box1, typename Box2, typename BoxOut, + typename Strategy + > static inline bool apply(Box1 const& box1, Box2 const& box2, BoxOut& box_out, Strategy const& strategy) @@ -50,23 +49,19 @@ struct intersection_box_box set(box_out, min1 < min2 ? min2 : min1); set(box_out, max1 > max2 ? max2 : max1); - return intersection_box_box - < - Box1, Box2, BoxOut, Strategy, - Dimension + 1, DimensionCount - >::apply(box1, box2, box_out, strategy); + return intersection_box_box + ::apply(box1, box2, box_out, strategy); } }; -template -< - typename Box1, typename Box2, - typename BoxOut, - typename Strategy, - std::size_t DimensionCount -> -struct intersection_box_box +template +struct intersection_box_box { + template + < + typename Box1, typename Box2, typename BoxOut, + typename Strategy + > static inline bool apply(Box1 const&, Box2 const&, BoxOut&, Strategy const&) { return true; @@ -86,15 +81,14 @@ namespace dispatch // By default, all is forwarded to the intersection_insert-dispatcher template < - typename Tag1, typename Tag2, typename TagOut, typename Geometry1, typename Geometry2, - typename GeometryOut, - typename Strategy + typename Tag1 = typename geometry::tag::type, + typename Tag2 = typename geometry::tag::type, + bool Reverse = reverse_dispatch::type::value > struct intersection { - typedef std::back_insert_iterator output_iterator; - + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, GeometryOut& geometry_out, @@ -104,17 +98,8 @@ struct intersection intersection_insert < - Tag1, Tag2, typename geometry::tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, - Geometry1, Geometry2, - detail::overlay::do_reverse::value, false>::value, - detail::overlay::do_reverse::value, false>::value, - detail::overlay::do_reverse::value>::value, - output_iterator, OneOut, - overlay_intersection, - Strategy + Geometry1, Geometry2, OneOut, + overlay_intersection >::apply(geometry1, geometry2, std::back_inserter(geometry_out), strategy); return true; @@ -123,50 +108,50 @@ struct intersection }; +// If reversal is needed, perform it template < - typename Box1, typename Box2, - typename BoxOut, - typename Strategy + typename Geometry1, typename Geometry2, + typename Tag1, typename Tag2 > struct intersection - < - box_tag, box_tag, box_tag, - Box1, Box2, BoxOut, - Strategy - > : public detail::intersection::intersection_box_box - < - Box1, Box2, BoxOut, - Strategy, - 0, geometry::dimension::value - > -{}; - - -template < - typename Tag1, typename Tag2, typename TagOut, - typename Geometry1, typename Geometry2, - typename GeometryOut, - typename Strategy + Geometry1, Geometry2, + Tag1, Tag2, + true > -struct intersection_reversed + : intersection { - static inline bool apply(Geometry1 const& geometry1, - Geometry2 const& geometry2, - GeometryOut& geometry_out, - Strategy const& strategy) + template + static inline bool apply( + Geometry1 const& g1, + Geometry2 const& g2, + GeometryOut& out, + Strategy const& strategy) { - return intersection - < - Tag2, Tag1, TagOut, - Geometry2, Geometry1, - GeometryOut, Strategy - >::apply(geometry2, geometry1, geometry_out, strategy); + return intersection< + Geometry2, Geometry1, + Tag2, Tag1, + false + >::apply(g2, g1, out, strategy); } }; +template +< + typename Box1, typename Box2, bool Reverse +> +struct intersection + < + Box1, Box2, + box_tag, box_tag, + Reverse + > : public detail::intersection::intersection_box_box + < + 0, geometry::dimension::value + > +{}; } // namespace dispatch @@ -210,24 +195,10 @@ inline bool intersection(Geometry1 const& geometry1, > strategy; - return boost::mpl::if_c - < - geometry::reverse_dispatch::type::value, - dispatch::intersection_reversed - < - typename geometry::tag::type, - typename geometry::tag::type, - typename geometry::tag::type, - Geometry1, Geometry2, GeometryOut, strategy - >, - dispatch::intersection - < - typename geometry::tag::type, - typename geometry::tag::type, - typename geometry::tag::type, - Geometry1, Geometry2, GeometryOut, strategy - > - >::type::apply(geometry1, geometry2, geometry_out, strategy()); + return dispatch::intersection< + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, geometry_out, strategy()); } diff --git a/include/boost/geometry/algorithms/length.hpp b/include/boost/geometry/algorithms/length.hpp index de53a39e8f..b537186a3e 100644 --- a/include/boost/geometry/algorithms/length.hpp +++ b/include/boost/geometry/algorithms/length.hpp @@ -43,9 +43,10 @@ namespace detail { namespace length { -template +template struct segment_length { + template static inline typename default_length_result::type apply( Segment const& segment, Strategy const& strategy) { @@ -63,11 +64,12 @@ struct segment_length \note for_each could be used here, now that point_type is changed by boost range iterator */ -template +template struct range_length { typedef typename default_length_result::type return_type; + template static inline return_type apply( Range const& range, Strategy const& strategy) { @@ -106,28 +108,31 @@ namespace dispatch { -template +template ::type> struct length : detail::calculate_null - < - typename default_length_result::type, - Geometry, - Strategy - > -{}; +{ + typedef typename default_length_result::type return_type; + + template + static inline return_type apply(Geometry const& geometry, Strategy const& strategy) + { + return calculate_null::apply(geometry, strategy); + } +}; -template -struct length - : detail::length::range_length +template +struct length + : detail::length::range_length {}; // RING: length is currently 0; it might be argued that it is the "perimeter" -template -struct length - : detail::length::segment_length +template +struct length + : detail::length::segment_length {}; @@ -159,12 +164,7 @@ inline typename default_length_result::type length( point_tag, typename point_type::type >::type strategy_type; - return dispatch::length - < - typename tag::type, - Geometry, - strategy_type - >::apply(geometry, strategy_type()); + return dispatch::length::apply(geometry, strategy_type()); } @@ -190,12 +190,7 @@ inline typename default_length_result::type length( // detail::throw_on_empty_input(geometry); - return dispatch::length - < - typename tag::type, - Geometry, - Strategy - >::apply(geometry, strategy); + return dispatch::length::apply(geometry, strategy); } diff --git a/include/boost/geometry/algorithms/num_geometries.hpp b/include/boost/geometry/algorithms/num_geometries.hpp index 20f35e90d2..58afe4b979 100644 --- a/include/boost/geometry/algorithms/num_geometries.hpp +++ b/include/boost/geometry/algorithms/num_geometries.hpp @@ -17,7 +17,7 @@ #include -#include +#include #include #include @@ -35,19 +35,22 @@ namespace dispatch { -template -struct num_geometries -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; +template +< + typename Geometry, + typename Tag = typename tag_cast + < + typename tag::type, + single_tag, + multi_tag + >::type +> +struct num_geometries: not_implemented +{}; template -struct num_geometries +struct num_geometries { static inline std::size_t apply(Geometry const&) { @@ -76,16 +79,7 @@ inline std::size_t num_geometries(Geometry const& geometry) { concept::check(); - return dispatch::num_geometries - < - typename tag_cast - < - typename tag::type, - single_tag, - multi_tag - >::type, - Geometry - >::apply(geometry); + return dispatch::num_geometries::apply(geometry); } diff --git a/include/boost/geometry/algorithms/num_interior_rings.hpp b/include/boost/geometry/algorithms/num_interior_rings.hpp index 2149f46576..e815f5981d 100644 --- a/include/boost/geometry/algorithms/num_interior_rings.hpp +++ b/include/boost/geometry/algorithms/num_interior_rings.hpp @@ -32,7 +32,7 @@ namespace dispatch { -template +template ::type> struct num_interior_rings { static inline std::size_t apply(Geometry const& ) @@ -44,7 +44,7 @@ struct num_interior_rings template -struct num_interior_rings +struct num_interior_rings { static inline std::size_t apply(Polygon const& polygon) { @@ -74,11 +74,7 @@ struct num_interior_rings template inline std::size_t num_interior_rings(Geometry const& geometry) { - return dispatch::num_interior_rings - < - typename tag::type, - Geometry - >::apply(geometry); + return dispatch::num_interior_rings::apply(geometry); } diff --git a/include/boost/geometry/algorithms/num_points.hpp b/include/boost/geometry/algorithms/num_points.hpp index c480068f43..e5a7aef6d4 100644 --- a/include/boost/geometry/algorithms/num_points.hpp +++ b/include/boost/geometry/algorithms/num_points.hpp @@ -16,7 +16,6 @@ #include -#include #include #include @@ -27,6 +26,7 @@ #include #include +#include #include @@ -38,9 +38,9 @@ namespace detail { namespace num_points { -template struct range_count { + template static inline std::size_t apply(Range const& range, bool add_for_open) { std::size_t n = boost::size(range); @@ -60,30 +60,31 @@ struct range_count } }; -template +template struct other_count { + template static inline std::size_t apply(Geometry const&, bool) { return D; } }; -template -struct polygon_count +struct polygon_count: private range_count { + template static inline std::size_t apply(Polygon const& poly, bool add_for_open) { typedef typename geometry::ring_type::type ring_type; - std::size_t n = range_count::apply( + std::size_t n = range_count::apply( exterior_ring(poly), add_for_open); typename interior_return_type::type rings = interior_rings(poly); for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) { - n += range_count::apply(*it, add_for_open); + n += range_count::apply(*it, add_for_open); } return n; @@ -98,44 +99,42 @@ struct polygon_count namespace dispatch { -template -struct num_points -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; +template +< + typename Geometry, + typename Tag = typename tag_cast::type, multi_tag>::type +> +struct num_points: not_implemented +{}; template -struct num_points - : detail::num_points::other_count +struct num_points + : detail::num_points::other_count<1> {}; template -struct num_points - : detail::num_points::other_count +struct num_points + : detail::num_points::other_count<4> {}; template -struct num_points - : detail::num_points::other_count +struct num_points + : detail::num_points::other_count<2> {}; template -struct num_points - : detail::num_points::range_count +struct num_points + : detail::num_points::range_count {}; template -struct num_points - : detail::num_points::range_count +struct num_points + : detail::num_points::range_count {}; template -struct num_points - : detail::num_points::polygon_count +struct num_points + : detail::num_points::polygon_count {}; } // namespace dispatch @@ -158,11 +157,7 @@ inline std::size_t num_points(Geometry const& geometry, bool add_for_open = fals { concept::check(); - return dispatch::num_points - < - typename tag_cast::type, multi_tag>::type, - Geometry - >::apply(geometry, add_for_open); + return dispatch::num_points::apply(geometry, add_for_open); } }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/perimeter.hpp b/include/boost/geometry/algorithms/perimeter.hpp index adeb0b05b0..b70517e3e5 100644 --- a/include/boost/geometry/algorithms/perimeter.hpp +++ b/include/boost/geometry/algorithms/perimeter.hpp @@ -33,40 +33,43 @@ namespace dispatch { // Default perimeter is 0.0, specializations implement calculated values -template +template ::type> struct perimeter : detail::calculate_null - < - typename default_length_result::type, - Geometry, - Strategy - > -{}; +{ + typedef typename default_length_result::type return_type; + + template + static inline return_type apply(Geometry const& geometry, Strategy const& strategy) + { + return calculate_null::apply(geometry, strategy); + } +}; -template -struct perimeter +template +struct perimeter : detail::length::range_length < Geometry, - Strategy, closure::value > {}; -template -struct perimeter - : detail::calculate_polygon_sum - < - typename default_length_result::type, - Polygon, - Strategy, - detail::length::range_length +template +struct perimeter : detail::calculate_polygon_sum +{ + typedef typename default_length_result::type return_type; + typedef detail::length::range_length < typename ring_type::type, - Strategy, closure::value - > - > -{}; + > policy; + + template + static inline return_type apply(Polygon const& polygon, Strategy const& strategy) + { + return calculate_polygon_sum::apply(polygon, strategy); + } +}; // box,n-sphere: to be implemented @@ -100,12 +103,7 @@ inline typename default_length_result::type perimeter( // detail::throw_on_empty_input(geometry); - return dispatch::perimeter - < - typename tag::type, - Geometry, - strategy_type - >::apply(geometry, strategy_type()); + return dispatch::perimeter::apply(geometry, strategy_type()); } /*! @@ -130,12 +128,7 @@ inline typename default_length_result::type perimeter( // detail::throw_on_empty_input(geometry); - return dispatch::perimeter - < - typename tag::type, - Geometry, - Strategy - >::apply(geometry, strategy); + return dispatch::perimeter::apply(geometry, strategy); } }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/reverse.hpp b/include/boost/geometry/algorithms/reverse.hpp index bf0ef2d9a9..1e1168a5ae 100644 --- a/include/boost/geometry/algorithms/reverse.hpp +++ b/include/boost/geometry/algorithms/reverse.hpp @@ -32,9 +32,9 @@ namespace detail { namespace reverse { -template struct range_reverse { + template static inline void apply(Range& range) { std::reverse(boost::begin(range), boost::end(range)); @@ -42,21 +42,20 @@ struct range_reverse }; -template -struct polygon_reverse +struct polygon_reverse: private range_reverse { + template static inline void apply(Polygon& polygon) { typedef typename geometry::ring_type::type ring_type; - typedef range_reverse per_range; - per_range::apply(exterior_ring(polygon)); + range_reverse::apply(exterior_ring(polygon)); typename interior_return_type::type rings = interior_rings(polygon); for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) { - per_range::apply(*it); + range_reverse::apply(*it); } } }; @@ -71,11 +70,7 @@ namespace dispatch { -template -< - typename Tag, - typename Geometry -> +template ::type> struct reverse { static inline void apply(Geometry&) @@ -84,20 +79,20 @@ struct reverse template -struct reverse - : detail::reverse::range_reverse +struct reverse + : detail::reverse::range_reverse {}; template -struct reverse - : detail::reverse::range_reverse +struct reverse + : detail::reverse::range_reverse {}; template -struct reverse - : detail::reverse::polygon_reverse +struct reverse + : detail::reverse::polygon_reverse {}; @@ -121,11 +116,7 @@ inline void reverse(Geometry& geometry) { concept::check(); - dispatch::reverse - < - typename tag::type, - Geometry - >::apply(geometry); + dispatch::reverse::apply(geometry); } }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/simplify.hpp b/include/boost/geometry/algorithms/simplify.hpp index 225321d303..7e3aca4016 100644 --- a/include/boost/geometry/algorithms/simplify.hpp +++ b/include/boost/geometry/algorithms/simplify.hpp @@ -33,6 +33,7 @@ #include #include +#include #include @@ -43,12 +44,11 @@ namespace boost { namespace geometry namespace detail { namespace simplify { -template struct simplify_range_insert { - template + template static inline void apply(Range const& range, OutputIterator out, - Distance const& max_distance, Strategy const& strategy) + Distance const& max_distance, Strategy const& strategy) { if (boost::size(range) <= 2 || max_distance < 0) { @@ -62,12 +62,11 @@ struct simplify_range_insert }; -template struct simplify_copy { - template + template static inline void apply(Range const& range, Range& out, - Distance const& , Strategy const& ) + Distance const& , Strategy const& ) { std::copy ( @@ -77,10 +76,10 @@ struct simplify_copy }; -template +template struct simplify_range { - template + template static inline void apply(Range const& range, Range& out, Distance const& max_distance, Strategy const& strategy) { @@ -101,14 +100,11 @@ struct simplify_range if (boost::size(range) <= int(Minimum) || max_distance < 0.0) { - simplify_copy::apply - ( - range, out, max_distance, strategy - ); + simplify_copy::apply(range, out, max_distance, strategy); } else { - simplify_range_insert::apply + simplify_range_insert::apply ( range, std::back_inserter(out), max_distance, strategy ); @@ -116,10 +112,9 @@ struct simplify_range } }; -template struct simplify_polygon { - template + template static inline void apply(Polygon const& poly_in, Polygon& poly_out, Distance const& max_distance, Strategy const& strategy) { @@ -133,9 +128,9 @@ struct simplify_polygon // Note that if there are inner rings, and distance is too large, // they might intersect with the outer ring in the output, // while it didn't in the input. - simplify_range::apply(exterior_ring(poly_in), - exterior_ring(poly_out), - max_distance, strategy); + simplify_range::apply(exterior_ring(poly_in), + exterior_ring(poly_out), + max_distance, strategy); traits::resize < @@ -154,8 +149,7 @@ struct simplify_polygon it_in != boost::end(rings_in); ++it_in, ++it_out) { - simplify_range::apply(*it_in, - *it_out, max_distance, strategy); + simplify_range::apply(*it_in, *it_out, max_distance, strategy); } } }; @@ -169,15 +163,18 @@ struct simplify_polygon namespace dispatch { -template -struct simplify -{ -}; +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct simplify: not_implemented +{}; -template -struct simplify +template +struct simplify { - template + template static inline void apply(Point const& point, Point& out, Distance const& , Strategy const& ) { @@ -186,22 +183,15 @@ struct simplify }; -template -struct simplify - : detail::simplify::simplify_range - < - Linestring, - Strategy, - 2 - > +template +struct simplify + : detail::simplify::simplify_range<2> {}; -template -struct simplify +template +struct simplify : detail::simplify::simplify_range < - Ring, - Strategy, core_detail::closure::minimum_ring_size < geometry::closure::value @@ -209,38 +199,29 @@ struct simplify > {}; -template -struct simplify +template +struct simplify : detail::simplify::simplify_polygon - < - Polygon, - Strategy - > {}; -template -struct simplify_insert -{ -}; +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct simplify_insert: not_implemented +{}; -template -struct simplify_insert +template +struct simplify_insert : detail::simplify::simplify_range_insert - < - Linestring, - Strategy - > {}; -template -struct simplify_insert +template +struct simplify_insert : detail::simplify::simplify_range_insert - < - Ring, - Strategy - > {}; @@ -275,12 +256,7 @@ inline void simplify(Geometry const& geometry, Geometry& out, geometry::clear(out); - dispatch::simplify - < - typename tag::type, - Geometry, - Strategy - >::apply(geometry, out, max_distance, strategy); + dispatch::simplify::apply(geometry, out, max_distance, strategy); } @@ -348,12 +324,7 @@ inline void simplify_insert(Geometry const& geometry, OutputIterator out, concept::check(); BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy) ); - dispatch::simplify_insert - < - typename tag::type, - Geometry, - Strategy - >::apply(geometry, out, max_distance, strategy); + dispatch::simplify_insert::apply(geometry, out, max_distance, strategy); } /*! @@ -387,12 +358,7 @@ inline void simplify_insert(Geometry const& geometry, OutputIterator out, point_type, ds_strategy_type > strategy_type; - dispatch::simplify_insert - < - typename tag::type, - Geometry, - strategy_type - >::apply(geometry, out, max_distance, strategy_type()); + dispatch::simplify_insert::apply(geometry, out, max_distance, strategy_type()); } }} // namespace detail::simplify diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index 6394576de4..28affc43c0 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -59,35 +59,20 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, out = geometry::dispatch::intersection_insert < - typename geometry::tag::type, - typename geometry::tag::type, - typename geometry::tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, Geometry1, Geometry2, - geometry::detail::overlay::do_reverse::value>::value, - geometry::detail::overlay::do_reverse::value, true>::value, - geometry::detail::overlay::do_reverse::value>::value, - OutputIterator, GeometryOut, + GeometryOut, overlay_difference, - Strategy + geometry::detail::overlay::do_reverse::value>::value, + geometry::detail::overlay::do_reverse::value, true>::value >::apply(geometry1, geometry2, out, strategy); out = geometry::dispatch::intersection_insert < - typename geometry::tag::type, - typename geometry::tag::type, - typename geometry::tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, Geometry2, Geometry1, + GeometryOut, + overlay_difference, geometry::detail::overlay::do_reverse::value>::value, geometry::detail::overlay::do_reverse::value, true>::value, - geometry::detail::overlay::do_reverse::value>::value, - OutputIterator, GeometryOut, - overlay_difference, - Strategy + geometry::detail::overlay::do_reverse::value>::value >::apply(geometry2, geometry1, out, strategy); return out; } diff --git a/include/boost/geometry/algorithms/transform.hpp b/include/boost/geometry/algorithms/transform.hpp index 22b45dc77e..52d195fe89 100644 --- a/include/boost/geometry/algorithms/transform.hpp +++ b/include/boost/geometry/algorithms/transform.hpp @@ -41,9 +41,9 @@ namespace boost { namespace geometry namespace detail { namespace transform { -template struct transform_point { + template static inline bool apply(Point1 const& p1, Point2& p2, Strategy const& strategy) { @@ -52,9 +52,9 @@ struct transform_point }; -template struct transform_box { + template static inline bool apply(Box1 const& b1, Box2& b2, Strategy const& strategy) { @@ -91,9 +91,9 @@ struct transform_box } }; -template struct transform_box_or_segment { + template static inline bool apply(Geometry1 const& source, Geometry2& target, Strategy const& strategy) { @@ -133,12 +133,7 @@ inline bool transform_range_out(Range const& range, it != boost::end(range); ++it) { - if (! transform_point - < - typename point_type::type, - PointOut, - Strategy - >::apply(*it, point_out, strategy)) + if (! transform_point::apply(*it, point_out, strategy)) { return false; } @@ -148,9 +143,9 @@ inline bool transform_range_out(Range const& range, } -template struct transform_polygon { + template static inline bool apply(Polygon1 const& poly1, Polygon2& poly2, Strategy const& strategy) { @@ -211,9 +206,9 @@ struct select_strategy >::type type; }; -template struct transform_range { + template static inline bool apply(Range1 const& range1, Range2& range2, Strategy const& strategy) { @@ -236,50 +231,50 @@ namespace dispatch template < - typename Tag1, typename Tag2, typename Geometry1, typename Geometry2, - typename Strategy + typename Tag1 = typename tag_cast::type, multi_tag>::type, + typename Tag2 = typename tag_cast::type, multi_tag>::type > struct transform {}; -template -struct transform - : detail::transform::transform_point +template +struct transform + : detail::transform::transform_point { }; -template +template struct transform < - linestring_tag, linestring_tag, - Linestring1, Linestring2, Strategy + Linestring1, Linestring2, + linestring_tag, linestring_tag > - : detail::transform::transform_range + : detail::transform::transform_range { }; -template -struct transform - : detail::transform::transform_range +template +struct transform + : detail::transform::transform_range { }; -template -struct transform - : detail::transform::transform_polygon +template +struct transform + : detail::transform::transform_polygon { }; -template -struct transform - : detail::transform::transform_box +template +struct transform + : detail::transform::transform_box { }; -template -struct transform - : detail::transform::transform_box_or_segment +template +struct transform + : detail::transform::transform_box_or_segment { }; @@ -310,14 +305,7 @@ inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2, concept::check(); concept::check(); - typedef dispatch::transform - < - typename tag_cast::type, multi_tag>::type, - typename tag_cast::type, multi_tag>::type, - Geometry1, - Geometry2, - Strategy - > transform_type; + typedef dispatch::transform transform_type; return transform_type::apply(geometry1, geometry2, strategy); } diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index 28d8e5dc0b..479f556a19 100644 --- a/include/boost/geometry/algorithms/union.hpp +++ b/include/boost/geometry/algorithms/union.hpp @@ -10,14 +10,13 @@ #define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP -#include - #include #include #include #include #include +#include #include @@ -30,78 +29,70 @@ namespace dispatch template < - // tag dispatching: - typename TagIn1, typename TagIn2, typename TagOut, - // metafunction finetuning helpers: - bool Areal1, bool Areal2, bool ArealOut, - // real types - typename Geometry1, typename Geometry2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, - typename GeometryOut, - typename Strategy + typename Geometry1, typename Geometry2, typename GeometryOut, + typename TagIn1 = typename tag::type, + typename TagIn2 = typename tag::type, + typename TagOut = typename tag::type, + bool Areal1 = geometry::is_areal::value, + bool Areal2 = geometry::is_areal::value, + bool ArealOut = geometry::is_areal::value, + bool Reverse1 = detail::overlay::do_reverse::value>::value, + bool Reverse2 = detail::overlay::do_reverse::value>::value, + bool ReverseOut = detail::overlay::do_reverse::value>::value, + bool Reverse = geometry::reverse_dispatch::type::value > -struct union_insert -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES - , (types) - ); -}; +struct union_insert: not_implemented +{}; + +// If reversal is needed, perform it first template < + typename Geometry1, typename Geometry2, typename GeometryOut, typename TagIn1, typename TagIn2, typename TagOut, - typename Geometry1, typename Geometry2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, - typename GeometryOut, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct union_insert < + Geometry1, Geometry2, GeometryOut, TagIn1, TagIn2, TagOut, true, true, true, - Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, - Strategy - > : detail::overlay::overlay - -{}; - - - -template -< - typename GeometryTag1, typename GeometryTag2, typename GeometryTag3, - bool Areal1, bool Areal2, bool ArealOut, - typename Geometry1, typename Geometry2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, - typename Strategy -> -struct union_insert_reversed + true + >: union_insert { + template static inline OutputIterator apply(Geometry1 const& g1, Geometry2 const& g2, OutputIterator out, Strategy const& strategy) { return union_insert < - GeometryTag2, GeometryTag1, GeometryTag3, - Areal2, Areal1, ArealOut, - Geometry2, Geometry1, - Reverse2, Reverse1, ReverseOut, - OutputIterator, GeometryOut, - Strategy + Geometry2, Geometry1, GeometryOut >::apply(g2, g1, out, strategy); } }; +template +< + typename Geometry1, typename Geometry2, typename GeometryOut, + typename TagIn1, typename TagIn2, typename TagOut, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct union_insert + < + Geometry1, Geometry2, GeometryOut, + TagIn1, TagIn2, TagOut, + true, true, true, + Reverse1, Reverse2, ReverseOut, + false + > : detail::overlay::overlay + +{}; + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -121,40 +112,10 @@ inline OutputIterator insert(Geometry1 const& geometry1, OutputIterator out, Strategy const& strategy) { - return boost::mpl::if_c - < - geometry::reverse_dispatch::type::value, - dispatch::union_insert_reversed - < - typename tag::type, - typename tag::type, - typename tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, - Geometry1, Geometry2, - overlay::do_reverse::value>::value, - overlay::do_reverse::value>::value, - overlay::do_reverse::value>::value, - OutputIterator, GeometryOut, - Strategy - >, - dispatch::union_insert - < - typename tag::type, - typename tag::type, - typename tag::type, - geometry::is_areal::value, - geometry::is_areal::value, - geometry::is_areal::value, - Geometry1, Geometry2, - overlay::do_reverse::value>::value, - overlay::do_reverse::value>::value, - overlay::do_reverse::value>::value, - OutputIterator, GeometryOut, - Strategy - > - >::type::apply(geometry1, geometry2, out, strategy); + return dispatch::union_insert + < + Geometry1, Geometry2, GeometryOut + >::apply(geometry1, geometry2, out, strategy); } /*! diff --git a/include/boost/geometry/algorithms/unique.hpp b/include/boost/geometry/algorithms/unique.hpp index 3bbf479f9b..e11dc13c49 100644 --- a/include/boost/geometry/algorithms/unique.hpp +++ b/include/boost/geometry/algorithms/unique.hpp @@ -34,9 +34,9 @@ namespace detail { namespace unique { -template struct range_unique { + template static inline void apply(Range& range, ComparePolicy const& policy) { typename boost::range_iterator::type it @@ -52,21 +52,20 @@ struct range_unique }; -template struct polygon_unique { + template static inline void apply(Polygon& polygon, ComparePolicy const& policy) { typedef typename geometry::ring_type::type ring_type; - typedef range_unique per_range; - per_range::apply(exterior_ring(polygon), policy); + range_unique::apply(exterior_ring(polygon), policy); typename interior_return_type::type rings = interior_rings(polygon); for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) { - per_range::apply(*it, policy); + range_unique::apply(*it, policy); } } }; @@ -85,32 +84,32 @@ namespace dispatch template < - typename Tag, typename Geometry, - typename ComparePolicy + typename Tag = typename tag::type > struct unique { + template static inline void apply(Geometry&, ComparePolicy const& ) {} }; -template -struct unique - : detail::unique::range_unique +template +struct unique + : detail::unique::range_unique {}; -template -struct unique - : detail::unique::range_unique +template +struct unique + : detail::unique::range_unique {}; -template -struct unique - : detail::unique::polygon_unique +template +struct unique + : detail::unique::polygon_unique {}; @@ -139,12 +138,7 @@ inline void unique(Geometry& geometry) > policy; - dispatch::unique - < - typename tag::type, - Geometry, - policy - >::apply(geometry, policy()); + dispatch::unique::apply(geometry, policy()); } }} // namespace boost::geometry diff --git a/include/boost/geometry/geometries/variant.hpp b/include/boost/geometry/geometries/variant.hpp new file mode 100644 index 0000000000..9db11d5a82 --- /dev/null +++ b/include/boost/geometry/geometries/variant.hpp @@ -0,0 +1,34 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_GEOMETRIES_VARIANT_GEOMETRY_HPP +#define BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP + + +#include + + +namespace boost { namespace geometry { + + +template +struct point_type > + : point_type +{}; + + +} // namespace geometry +} // namespace boost + + +#endif // BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP diff --git a/include/boost/geometry/multi/algorithms/area.hpp b/include/boost/geometry/multi/algorithms/area.hpp index 6695686358..7d0206109d 100644 --- a/include/boost/geometry/multi/algorithms/area.hpp +++ b/include/boost/geometry/multi/algorithms/area.hpp @@ -30,21 +30,20 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -struct area - : detail::multi_sum - < - typename Strategy::return_type, - MultiGeometry, - Strategy, - area - < - typename boost::range_value::type, - Strategy, - polygon_tag - > - > -{}; +template +struct area : detail::multi_sum +{ + template + static inline typename Strategy::return_type + apply(MultiGeometry const& multi, Strategy const& strategy) + { + return multi_sum::apply + < + typename Strategy::return_type, + area::type> + >(multi, strategy); + } +}; } // namespace dispatch diff --git a/include/boost/geometry/multi/algorithms/centroid.hpp b/include/boost/geometry/multi/algorithms/centroid.hpp index 855ed22fda..e990f4effd 100644 --- a/include/boost/geometry/multi/algorithms/centroid.hpp +++ b/include/boost/geometry/multi/algorithms/centroid.hpp @@ -35,13 +35,9 @@ namespace detail { namespace centroid \brief Building block of a multi-point, to be used as Policy in the more generec centroid_multi */ -template -< - typename Point, - typename Strategy -> struct centroid_multi_point_state { + template static inline void apply(Point const& point, Strategy const& strategy, typename Strategy::state_type& state) { @@ -59,15 +55,10 @@ struct centroid_multi_point_state detail::centroid::centroid_multi */ -template -< - typename Multi, - typename Point, - typename Strategy, - typename Policy -> +template struct centroid_multi { + template static inline void apply(Multi const& multi, Point& centroid, Strategy const& strategy) { @@ -104,65 +95,28 @@ struct centroid_multi namespace dispatch { -template -< - typename MultiLinestring, - typename Point, - typename Strategy -> -struct centroid +template +struct centroid : detail::centroid::centroid_multi < - MultiLinestring, - Point, - Strategy, - detail::centroid::centroid_range_state - < - typename boost::range_value::type, - closed, - Strategy - > + detail::centroid::centroid_range_state > {}; -template -< - typename MultiPolygon, - typename Point, - typename Strategy -> -struct centroid +template +struct centroid : detail::centroid::centroid_multi < - MultiPolygon, - Point, - Strategy, detail::centroid::centroid_polygon_state - < - typename boost::range_value::type, - Strategy - > > {}; -template -< - typename MultiPoint, - typename Point, - typename Strategy -> -struct centroid +template +struct centroid : detail::centroid::centroid_multi < - MultiPoint, - Point, - Strategy, detail::centroid::centroid_multi_point_state - < - typename boost::range_value::type, - Strategy - > > {}; diff --git a/include/boost/geometry/multi/algorithms/detail/multi_sum.hpp b/include/boost/geometry/multi/algorithms/detail/multi_sum.hpp index a47685ceb1..704c3e6a96 100644 --- a/include/boost/geometry/multi/algorithms/detail/multi_sum.hpp +++ b/include/boost/geometry/multi/algorithms/detail/multi_sum.hpp @@ -23,15 +23,9 @@ namespace boost { namespace geometry namespace detail { -template -< - typename ReturnType, - typename MultiGeometry, - typename Strategy, - typename Policy -> struct multi_sum { + template static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy) { ReturnType sum = ReturnType(); diff --git a/include/boost/geometry/multi/algorithms/disjoint.hpp b/include/boost/geometry/multi/algorithms/disjoint.hpp new file mode 100644 index 0000000000..7d1bed794e --- /dev/null +++ b/include/boost/geometry/multi/algorithms/disjoint.hpp @@ -0,0 +1,41 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012 Bruno Lalande, Paris, France. +// Copyright (c) 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) + +#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP +#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct disjoint + : detail::disjoint::reverse_covered_by +{}; + +} // namespace dispatch + + +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP diff --git a/include/boost/geometry/multi/algorithms/for_each.hpp b/include/boost/geometry/multi/algorithms/for_each.hpp index 1be38e0a7e..adf12dbba5 100644 --- a/include/boost/geometry/multi/algorithms/for_each.hpp +++ b/include/boost/geometry/multi/algorithms/for_each.hpp @@ -36,24 +36,16 @@ namespace detail { namespace for_each // Implementation of multi, for both point and segment, // just calling the single version. -template -< - typename MultiGeometry, - typename Functor, - bool IsConst, - typename Policy -> +template struct for_each_multi { - static inline Functor apply( - typename add_const_if_c::type& multi, - Functor f) + template + static inline void apply(MultiGeometry& multi, Functor& f) { for(BOOST_AUTO_TPL(it, boost::begin(multi)); it != boost::end(multi); ++it) { - f = Policy::apply(*it, f); + Policy::apply(*it, f); } - return f; } }; @@ -66,55 +58,35 @@ struct for_each_multi namespace dispatch { -template -< - typename MultiGeometry, - typename Functor, - bool IsConst -> -struct for_each_point +template +struct for_each_point : detail::for_each::for_each_multi < - MultiGeometry, - Functor, - IsConst, // Specify the dispatch of the single-version as policy for_each_point < - typename single_tag_of + typename add_const_if_c < - typename tag::type - >::type, - typename boost::range_value::type, - Functor, - IsConst + is_const::value, + typename boost::range_value::type + >::type > > {}; -template -< - typename MultiGeometry, - typename Functor, - bool IsConst -> -struct for_each_segment +template +struct for_each_segment : detail::for_each::for_each_multi < - MultiGeometry, - Functor, - IsConst, // Specify the dispatch of the single-version as policy for_each_segment < - typename single_tag_of + typename add_const_if_c < - typename tag::type - >::type, - typename boost::range_value::type, - Functor, - IsConst + is_const::value, + typename boost::range_value::type + >::type > > {}; diff --git a/include/boost/geometry/multi/algorithms/intersection.hpp b/include/boost/geometry/multi/algorithms/intersection.hpp index 31e74a79ba..0027a4e153 100644 --- a/include/boost/geometry/multi/algorithms/intersection.hpp +++ b/include/boost/geometry/multi/algorithms/intersection.hpp @@ -36,14 +36,14 @@ namespace detail { namespace intersection { -template -< - typename MultiLinestring1, typename MultiLinestring2, - typename OutputIterator, typename PointOut, - typename Strategy -> +template struct intersection_multi_linestring_multi_linestring_point { + template + < + typename MultiLinestring1, typename MultiLinestring2, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(MultiLinestring1 const& ml1, MultiLinestring2 const& ml2, OutputIterator out, Strategy const& strategy) @@ -64,12 +64,8 @@ struct intersection_multi_linestring_multi_linestring_point it2 != boost::end(ml2); ++it2) { - out = intersection_linestring_linestring_point - < - typename boost::range_value::type, - typename boost::range_value::type, - OutputIterator, PointOut, Strategy - >::apply(*it1, *it2, out, strategy); + out = intersection_linestring_linestring_point + ::apply(*it1, *it2, out, strategy); } } @@ -78,14 +74,14 @@ struct intersection_multi_linestring_multi_linestring_point }; -template -< - typename Linestring, typename MultiLinestring, - typename OutputIterator, typename PointOut, - typename Strategy -> +template struct intersection_linestring_multi_linestring_point { + template + < + typename Linestring, typename MultiLinestring, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(Linestring const& linestring, MultiLinestring const& ml, OutputIterator out, Strategy const& strategy) @@ -97,12 +93,8 @@ struct intersection_linestring_multi_linestring_point it != boost::end(ml); ++it) { - out = intersection_linestring_linestring_point - < - Linestring, - typename boost::range_value::type, - OutputIterator, PointOut, Strategy - >::apply(linestring, *it, out, strategy); + out = intersection_linestring_linestring_point + ::apply(linestring, *it, out, strategy); } return out; @@ -114,14 +106,17 @@ struct intersection_linestring_multi_linestring_point // is second (above) or first (below) argument, it is not trivial to merge them. template < - typename MultiLinestring, typename Areal, bool ReverseAreal, - typename OutputIterator, typename LineStringOut, - overlay_type OverlayType, - typename Strategy + typename LineStringOut, + overlay_type OverlayType > struct intersection_of_multi_linestring_with_areal { + template + < + typename MultiLinestring, typename Areal, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(MultiLinestring const& ml, Areal const& areal, OutputIterator out, Strategy const& strategy) @@ -135,9 +130,7 @@ struct intersection_of_multi_linestring_with_areal { out = intersection_of_linestring_with_areal < - typename boost::range_value::type, - Areal, ReverseAreal, - OutputIterator, LineStringOut, OverlayType, Strategy + ReverseAreal, LineStringOut, OverlayType >::apply(*it, areal, out, strategy); } @@ -149,38 +142,38 @@ struct intersection_of_multi_linestring_with_areal // This one calls the one above with reversed arguments template < - typename Areal, typename MultiLinestring, bool ReverseAreal, - typename OutputIterator, typename LineStringOut, - overlay_type OverlayType, - typename Strategy + typename LineStringOut, + overlay_type OverlayType > struct intersection_of_areal_with_multi_linestring { + template + < + typename Areal, typename MultiLinestring, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(Areal const& areal, MultiLinestring const& ml, OutputIterator out, Strategy const& strategy) { return intersection_of_multi_linestring_with_areal < - MultiLinestring, Areal, ReverseAreal, - OutputIterator, LineStringOut, - OverlayType, - Strategy + ReverseAreal, LineStringOut, OverlayType >::apply(ml, areal, out, strategy); } }; -template -< - typename MultiLinestring, typename Box, - typename OutputIterator, typename LinestringOut, - typename Strategy -> +template struct clip_multi_linestring { + template + < + typename MultiLinestring, typename Box, + typename OutputIterator, typename Strategy + > static inline OutputIterator apply(MultiLinestring const& multi_linestring, Box const& box, OutputIterator out, Strategy const& ) { @@ -211,25 +204,21 @@ namespace dispatch template < typename MultiLinestring1, typename MultiLinestring2, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert < - multi_linestring_tag, multi_linestring_tag, point_tag, - false, false, false, MultiLinestring1, MultiLinestring2, - Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + multi_linestring_tag, multi_linestring_tag, point_tag, + false, false, false > : detail::intersection::intersection_multi_linestring_multi_linestring_point < - MultiLinestring1, MultiLinestring2, - OutputIterator, GeometryOut, - Strategy + GeometryOut > {}; @@ -237,25 +226,21 @@ struct intersection_insert template < typename Linestring, typename MultiLinestring, - typename OutputIterator, typename GeometryOut, - bool Reverse1, bool Reverse2, bool ReverseOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert < - linestring_tag, multi_linestring_tag, point_tag, - false, false, false, Linestring, MultiLinestring, - Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + linestring_tag, multi_linestring_tag, point_tag, + false, false, false > : detail::intersection::intersection_linestring_multi_linestring_point < - Linestring, MultiLinestring, - OutputIterator, GeometryOut, - Strategy + GeometryOut > {}; @@ -263,25 +248,21 @@ struct intersection_insert template < typename MultiLinestring, typename Box, - bool Reverse1, bool Reverse2, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool Reverse1, bool Reverse2, bool ReverseOut > struct intersection_insert < - multi_linestring_tag, box_tag, linestring_tag, - false, true, false, MultiLinestring, Box, - Reverse1, Reverse2, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + Reverse1, Reverse2, ReverseOut, + multi_linestring_tag, box_tag, linestring_tag, + false, true, false > : detail::intersection::clip_multi_linestring < - MultiLinestring, Box, - OutputIterator, GeometryOut, - Strategy + GeometryOut > {}; @@ -289,27 +270,23 @@ struct intersection_insert template < typename Linestring, typename MultiPolygon, - bool ReverseLinestring, bool ReverseMultiPolygon, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool ReverseLinestring, bool ReverseMultiPolygon, bool ReverseOut > struct intersection_insert < - linestring_tag, multi_polygon_tag, linestring_tag, - false, true, false, Linestring, MultiPolygon, - ReverseLinestring, ReverseMultiPolygon, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + ReverseLinestring, ReverseMultiPolygon, ReverseOut, + linestring_tag, multi_polygon_tag, linestring_tag, + false, true, false > : detail::intersection::intersection_of_linestring_with_areal < - Linestring, MultiPolygon, ReverseMultiPolygon, - OutputIterator, GeometryOut, - OverlayType, - Strategy + GeometryOut, + OverlayType > {}; @@ -319,27 +296,23 @@ struct intersection_insert template < typename Polygon, typename MultiLinestring, - bool ReversePolygon, bool ReverseMultiLinestring, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool ReversePolygon, bool ReverseMultiLinestring, bool ReverseOut > struct intersection_insert < - polygon_tag, multi_linestring_tag, linestring_tag, - true, false, false, Polygon, MultiLinestring, - ReversePolygon, ReverseMultiLinestring, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + ReversePolygon, ReverseMultiLinestring, ReverseOut, + polygon_tag, multi_linestring_tag, linestring_tag, + true, false, false > : detail::intersection::intersection_of_areal_with_multi_linestring < - Polygon, MultiLinestring, ReversePolygon, - OutputIterator, GeometryOut, - OverlayType, - Strategy + GeometryOut, + OverlayType > {}; @@ -347,54 +320,46 @@ struct intersection_insert template < typename MultiLinestring, typename Ring, - bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut > struct intersection_insert < - multi_linestring_tag, ring_tag, linestring_tag, - false, true, false, MultiLinestring, Ring, - ReverseMultiLinestring, ReverseRing, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + ReverseMultiLinestring, ReverseRing, ReverseOut, + multi_linestring_tag, ring_tag, linestring_tag, + false, true, false > : detail::intersection::intersection_of_multi_linestring_with_areal < - MultiLinestring, Ring, ReverseRing, - OutputIterator, GeometryOut, - OverlayType, - Strategy + GeometryOut, + OverlayType > {}; template < typename MultiLinestring, typename Polygon, - bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut > struct intersection_insert < - multi_linestring_tag, polygon_tag, linestring_tag, - false, true, false, MultiLinestring, Polygon, - ReverseMultiLinestring, ReverseRing, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + ReverseMultiLinestring, ReverseRing, ReverseOut, + multi_linestring_tag, polygon_tag, linestring_tag, + false, true, false > : detail::intersection::intersection_of_multi_linestring_with_areal < - MultiLinestring, Polygon, ReverseRing, - OutputIterator, GeometryOut, - OverlayType, - Strategy + GeometryOut, + OverlayType > {}; @@ -403,27 +368,23 @@ struct intersection_insert template < typename MultiLinestring, typename MultiPolygon, - bool ReverseMultiLinestring, bool ReverseMultiPolygon, bool ReverseOut, - typename OutputIterator, typename GeometryOut, + typename GeometryOut, overlay_type OverlayType, - typename Strategy + bool ReverseMultiLinestring, bool ReverseMultiPolygon, bool ReverseOut > struct intersection_insert < - multi_linestring_tag, multi_polygon_tag, linestring_tag, - false, true, false, MultiLinestring, MultiPolygon, - ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut, - OutputIterator, GeometryOut, + GeometryOut, OverlayType, - Strategy + ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut, + multi_linestring_tag, multi_polygon_tag, linestring_tag, + false, true, false > : detail::intersection::intersection_of_multi_linestring_with_areal < - MultiLinestring, MultiPolygon, ReverseMultiPolygon, - OutputIterator, GeometryOut, - OverlayType, - Strategy + GeometryOut, + OverlayType > {}; diff --git a/include/boost/geometry/multi/algorithms/length.hpp b/include/boost/geometry/multi/algorithms/length.hpp index 51ff9ef3c2..ef5fb3c978 100644 --- a/include/boost/geometry/multi/algorithms/length.hpp +++ b/include/boost/geometry/multi/algorithms/length.hpp @@ -30,21 +30,25 @@ namespace boost { namespace geometry namespace dispatch { -template -struct length - : detail::multi_sum - < - typename default_length_result::type, - MultiLinestring, - Strategy, - detail::length::range_length - < - typename boost::range_value::type, - Strategy, - closed // no need to close it explicitly - > - > -{}; +template +struct length : detail::multi_sum +{ + template + static inline typename default_length_result::type + apply(MultiLinestring const& multi, Strategy const& strategy) + { + return multi_sum::apply + < + typename default_length_result::type, + detail::length::range_length + < + typename boost::range_value::type, + closed // no need to close it explicitly + > + >(multi, strategy); + + } +}; } // namespace dispatch diff --git a/include/boost/geometry/multi/algorithms/num_geometries.hpp b/include/boost/geometry/multi/algorithms/num_geometries.hpp index 213339a18c..cc59655bee 100644 --- a/include/boost/geometry/multi/algorithms/num_geometries.hpp +++ b/include/boost/geometry/multi/algorithms/num_geometries.hpp @@ -32,7 +32,7 @@ namespace dispatch { template -struct num_geometries +struct num_geometries { static inline std::size_t apply(MultiGeometry const& multi_geometry) { diff --git a/include/boost/geometry/multi/algorithms/num_interior_rings.hpp b/include/boost/geometry/multi/algorithms/num_interior_rings.hpp index 87b0bdea91..8390fe77ae 100644 --- a/include/boost/geometry/multi/algorithms/num_interior_rings.hpp +++ b/include/boost/geometry/multi/algorithms/num_interior_rings.hpp @@ -34,7 +34,7 @@ namespace dispatch template -struct num_interior_rings +struct num_interior_rings { static inline std::size_t apply(MultiPolygon const& multi_polygon) { diff --git a/include/boost/geometry/multi/algorithms/num_points.hpp b/include/boost/geometry/multi/algorithms/num_points.hpp index 5ea53854eb..1cc82b2f0c 100644 --- a/include/boost/geometry/multi/algorithms/num_points.hpp +++ b/include/boost/geometry/multi/algorithms/num_points.hpp @@ -30,9 +30,9 @@ namespace detail { namespace num_points { -template struct multi_count { + template static inline size_t apply(MultiGeometry const& geometry, bool add_for_open) { typedef typename boost::range_value::type geometry_type; @@ -46,11 +46,7 @@ struct multi_count it != boost::end(geometry); ++it) { - n += dispatch::num_points - < - typename tag::type, - geometry_type - >::apply(*it, add_for_open); + n += dispatch::num_points::apply(*it, add_for_open); } return n; } @@ -67,8 +63,8 @@ namespace dispatch template -struct num_points - : detail::num_points::multi_count {}; +struct num_points + : detail::num_points::multi_count {}; } // namespace dispatch diff --git a/include/boost/geometry/multi/algorithms/perimeter.hpp b/include/boost/geometry/multi/algorithms/perimeter.hpp index 147f6fcc30..6a13f90e35 100644 --- a/include/boost/geometry/multi/algorithms/perimeter.hpp +++ b/include/boost/geometry/multi/algorithms/perimeter.hpp @@ -30,21 +30,20 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -struct perimeter - : detail::multi_sum - < - typename default_length_result::type, - MultiPolygon, - Strategy, - perimeter - < - polygon_tag, - typename boost::range_value::type, - Strategy - > - > -{}; +template +struct perimeter : detail::multi_sum +{ + template + static inline typename default_length_result::type + apply(MultiPolygon const& multi, Strategy const& strategy) + { + return multi_sum::apply + < + typename default_length_result::type, + perimeter::type> + >(multi, strategy); + } +}; } // namespace dispatch #endif diff --git a/include/boost/geometry/multi/algorithms/reverse.hpp b/include/boost/geometry/multi/algorithms/reverse.hpp index f8a9442ac0..910f1e3d10 100644 --- a/include/boost/geometry/multi/algorithms/reverse.hpp +++ b/include/boost/geometry/multi/algorithms/reverse.hpp @@ -34,27 +34,21 @@ namespace dispatch template -struct reverse +struct reverse : detail::multi_modify < Geometry, detail::reverse::range_reverse - < - typename boost::range_value::type - > > {}; template -struct reverse +struct reverse : detail::multi_modify < Geometry, detail::reverse::polygon_reverse - < - typename boost::range_value::type - > > {}; diff --git a/include/boost/geometry/multi/algorithms/simplify.hpp b/include/boost/geometry/multi/algorithms/simplify.hpp index dc3c7b5937..1706c69f48 100644 --- a/include/boost/geometry/multi/algorithms/simplify.hpp +++ b/include/boost/geometry/multi/algorithms/simplify.hpp @@ -31,9 +31,10 @@ namespace boost { namespace geometry namespace detail { namespace simplify { -template +template struct simplify_multi { + template static inline void apply(MultiGeometry const& multi, MultiGeometry& out, double max_distance, Strategy const& strategy) { @@ -63,47 +64,21 @@ struct simplify_multi namespace dispatch { -template -struct simplify +template +struct simplify : detail::simplify::simplify_copy - < - MultiPoint, - Strategy - > - {}; -template -struct simplify - : detail::simplify::simplify_multi - < - MultiLinestring, - Strategy, - detail::simplify::simplify_range - < - typename boost::range_value::type, - Strategy, - 2 - > - > - +template +struct simplify + : detail::simplify::simplify_multi > {}; -template -struct simplify - : detail::simplify::simplify_multi - < - MultiPolygon, - Strategy, - detail::simplify::simplify_polygon - < - typename boost::range_value::type, - Strategy - > - > - +template +struct simplify + : detail::simplify::simplify_multi {}; diff --git a/include/boost/geometry/multi/algorithms/transform.hpp b/include/boost/geometry/multi/algorithms/transform.hpp index 09926778f9..110e96958f 100644 --- a/include/boost/geometry/multi/algorithms/transform.hpp +++ b/include/boost/geometry/multi/algorithms/transform.hpp @@ -31,10 +31,10 @@ namespace detail { namespace transform /*! \brief Is able to transform any multi-geometry, calling the single-version as policy */ -template +template struct transform_multi { - template + template static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy) { traits::resize::apply(multi2, boost::size(multi1)); @@ -65,30 +65,18 @@ struct transform_multi namespace dispatch { -template +template struct transform < - multi_tag, multi_tag, Multi1, Multi2, - Strategy + multi_tag, multi_tag > : detail::transform::transform_multi < - Multi1, - Multi2, transform < - typename single_tag_of - < - typename tag::type - >::type, - typename single_tag_of - < - typename tag::type - >::type, typename boost::range_value::type, - typename boost::range_value::type, - Strategy + typename boost::range_value::type > > {}; diff --git a/include/boost/geometry/multi/algorithms/unique.hpp b/include/boost/geometry/multi/algorithms/unique.hpp index 5067e71f3f..bda2234a60 100644 --- a/include/boost/geometry/multi/algorithms/unique.hpp +++ b/include/boost/geometry/multi/algorithms/unique.hpp @@ -30,9 +30,10 @@ namespace detail { namespace unique { -template +template struct multi_unique { + template static inline void apply(MultiGeometry& multi, ComparePolicy const& compare) { for (typename boost::range_iterator::type @@ -62,33 +63,15 @@ namespace dispatch // possible for multi-points as well, removing points at the same location. -template -struct unique - : detail::unique::multi_unique - < - MultiLineString, - ComparePolicy, - detail::unique::range_unique - < - typename boost::range_value::type, - ComparePolicy - > - > +template +struct unique + : detail::unique::multi_unique {}; -template -struct unique - : detail::unique::multi_unique - < - MultiPolygon, - ComparePolicy, - detail::unique::polygon_unique - < - typename boost::range_value::type, - ComparePolicy - > - > +template +struct unique + : detail::unique::multi_unique {}; diff --git a/include/boost/geometry/multi/multi.hpp b/include/boost/geometry/multi/multi.hpp index db33a9dd03..df10392cb8 100644 --- a/include/boost/geometry/multi/multi.hpp +++ b/include/boost/geometry/multi/multi.hpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index ea92cf37b0..564010f0a7 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -120,6 +120,22 @@ struct relate_cartesian_segments typedef side::side_by_triangle side; side_info sides; + coordinate_type const zero = 0; + bool const a_is_point = math::equals(dx_a, zero) && math::equals(dy_a, zero); + bool const b_is_point = math::equals(dx_b, zero) && math::equals(dy_b, zero); + + if(a_is_point && b_is_point) + { + if(math::equals(get<1,0>(a), get<1,0>(b)) && math::equals(get<1,1>(a), get<1,1>(b))) + { + Policy::degenerate(a, true); + } + else + { + return Policy::disjoint(); + } + } + bool collinear_use_first = math::abs(dx_a) + math::abs(dx_b) >= math::abs(dy_a) + math::abs(dy_b); sides.set<0> @@ -143,7 +159,7 @@ struct relate_cartesian_segments bool collinear = sides.collinear(); - robustness_verify_collinear(a, b, sides, collinear); + robustness_verify_collinear(a, b, a_is_point, b_is_point, sides, collinear); robustness_verify_meeting(a, b, sides, collinear, collinear_use_first); if (sides.same<0>() || sides.same<1>()) @@ -156,12 +172,11 @@ struct relate_cartesian_segments } // Degenerate cases: segments of single point, lying on other segment, non disjoint - coordinate_type const zero = 0; - if (math::equals(dx_a, zero) && math::equals(dy_a, zero)) + if (a_is_point) { return Policy::degenerate(a, true); } - if (math::equals(dx_b, zero) && math::equals(dy_b, zero)) + if (b_is_point) { return Policy::degenerate(b, false); } @@ -281,10 +296,11 @@ private : static inline void robustness_verify_collinear( segment_type1 const& a, segment_type2 const& b, + bool a_is_point, bool b_is_point, side_info& sides, bool& collinear) { - if ((sides.zero<0>() && ! sides.zero<1>()) || (sides.zero<1>() && ! sides.zero<0>())) + if ((sides.zero<0>() && ! b_is_point && ! sides.zero<1>()) || (sides.zero<1>() && ! a_is_point && ! sides.zero<0>())) { // If one of the segments is collinear, the other must be as well. // So handle it as collinear. diff --git a/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp b/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp index 51d2722663..c62cf749ee 100644 --- a/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp @@ -42,8 +42,8 @@ struct compute_pythagoras { static inline T apply(Point1 const& p1, Point2 const& p2) { - T const c1 = boost::numeric_cast(get(p2)); - T const c2 = boost::numeric_cast(get(p1)); + T const c1 = boost::numeric_cast(get(p1)); + T const c2 = boost::numeric_cast(get(p2)); T const d = c1 - c2; return d * d + compute_pythagoras::apply(p1, p2); } diff --git a/include/boost/geometry/strategies/covered_by.hpp b/include/boost/geometry/strategies/covered_by.hpp index a878b26c86..a5aae7703b 100644 --- a/include/boost/geometry/strategies/covered_by.hpp +++ b/include/boost/geometry/strategies/covered_by.hpp @@ -53,7 +53,7 @@ struct default_strategy { BOOST_MPL_ASSERT_MSG ( - false, NOT_IMPLEMENTED_FOR_THIS_TYPES + false, NOT_IMPLEMENTED_FOR_THESE_TYPES , (types) ); }; diff --git a/include/boost/geometry/strategies/within.hpp b/include/boost/geometry/strategies/within.hpp index 0852a22d2d..d625bc40e6 100644 --- a/include/boost/geometry/strategies/within.hpp +++ b/include/boost/geometry/strategies/within.hpp @@ -52,7 +52,7 @@ struct default_strategy { BOOST_MPL_ASSERT_MSG ( - false, NOT_IMPLEMENTED_FOR_THIS_TYPES + false, NOT_IMPLEMENTED_FOR_THESE_TYPES , (types) ); }; diff --git a/test/algorithms/area.cpp b/test/algorithms/area.cpp index 1b2dc49f50..1d05439f63 100644 --- a/test/algorithms/area.cpp +++ b/test/algorithms/area.cpp @@ -25,6 +25,8 @@ #include //#define GEOMETRY_TEST_DEBUG +#include + template void test_polygon() { @@ -222,6 +224,28 @@ void test_large_integers() BOOST_CHECK_CLOSE(int_area, double_area, 0.0001); } +void test_variant() +{ + typedef bg::model::point double_point_type; + typedef bg::model::polygon polygon_type; + typedef bg::model::box box_type; + + polygon_type poly; + std::string const polygon_li = "POLYGON((18 5,18 1,15 1,15 5,12 5,12 8,15 8,18 8,18 5))"; + bg::read_wkt(polygon_li, poly); + + box_type box; + std::string const box_li = "BOX(0 0,2 2)"; + bg::read_wkt(box_li, box); + + boost::variant v; + + v = poly; + BOOST_CHECK_CLOSE(bg::area(v), bg::area(poly), 0.0001); + v = box; + BOOST_CHECK_CLOSE(bg::area(v), bg::area(box), 0.0001); +} + int test_main(int, char* []) { test_all >(); @@ -242,6 +266,8 @@ int test_main(int, char* []) test_large_integers(); + test_variant(); + // test_empty_input >(); return 0; diff --git a/test/algorithms/comparable_distance.cpp b/test/algorithms/comparable_distance.cpp index 1f5266fdde..294321c4f8 100644 --- a/test/algorithms/comparable_distance.cpp +++ b/test/algorithms/comparable_distance.cpp @@ -102,11 +102,11 @@ void test_distance_linestring() P p = bg::make

    (2, 1); typename bg::coordinate_type

    ::type d = bg::comparable_distance(p, points); - BOOST_CHECK_CLOSE(d, 0.70710678, 0.001); + BOOST_CHECK_CLOSE(d, 0.5, 0.001); p = bg::make

    (5, 5); d = bg::comparable_distance(p, points); - BOOST_CHECK_CLOSE(d, 2.828427, 0.001); + BOOST_CHECK_CLOSE(d, 8.0, 0.001); bg::model::linestring

    line; @@ -117,11 +117,11 @@ void test_distance_linestring() p = bg::make

    (5, 5); d = bg::comparable_distance(p, line); - BOOST_CHECK_CLOSE(d, 2.828427, 0.001); + BOOST_CHECK_CLOSE(d, 8.0, 0.001); // Reverse case d = bg::comparable_distance(line, p); - BOOST_CHECK_CLOSE(d, 2.828427, 0.001); + BOOST_CHECK_CLOSE(d, 8.0, 0.001); } template diff --git a/test/algorithms/difference.cpp b/test/algorithms/difference.cpp index e72af3c24b..62269a93d6 100644 --- a/test/algorithms/difference.cpp +++ b/test/algorithms/difference.cpp @@ -9,6 +9,8 @@ // #define TEST_ISOVIST +//#define HAVE_TTMATH + //#define BOOST_GEOMETRY_CHECK_WITH_POSTGIS //#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER @@ -111,8 +113,8 @@ void test_all() test_one("simplex_normal", simplex_normal[0], simplex_normal[1], - 3, 3, 2.52636706856656, - 3, 3, 3.52636706856656); + 3, 12, 2.52636706856656, + 3, 12, 3.52636706856656); test_one("simplex_with_empty", simplex_normal[0], polygon_empty, @@ -126,24 +128,24 @@ void test_all() test_one("two_bends", two_bends[0], two_bends[1], - 1, 7, 8.0, - 1, 7, 8.0); + 1, 5, 8.0, + 1, 5, 8.0); test_one("star_comb_15", star_comb_15[0], star_comb_15[1], - 30, 150, 227.658275102812, - 30, 150, 480.485775259312); + 30, 160, 227.658275102812, + 30, 198, 480.485775259312); test_one("new_hole", new_hole[0], new_hole[1], - 1, 10, 7.0, - 1, 10, 14.0); + 1, 9, 7.0, + 1, 13, 14.0); test_one("crossed", crossed[0], crossed[1], - 1, 0, 19.5, - 1, 0, 2.5); + 1, 18, 19.5, + 1, 7, 2.5); test_one("disjoint", disjoint[0], disjoint[1], @@ -152,35 +154,35 @@ void test_all() test_one("distance_zero", distance_zero[0], distance_zero[1], - 2, 0, 8.7048386, + 2, -1, 8.7048386, if_typed(1, 2), // The too small one is discarded for floating point - 0, 0.0098387); + -1, 0.0098387); test_one("equal_holes_disjoint", equal_holes_disjoint[0], equal_holes_disjoint[1], - 1, 0, 9.0, - 1, 0, 9.0); + 1, 5, 9.0, + 1, 5, 9.0); test_one("only_hole_intersections1", only_hole_intersections[0], only_hole_intersections[1], - 2, 0, 1.9090909, - 4, 0, 10.9090909); + 2, 10, 1.9090909, + 4, 16, 10.9090909); test_one("only_hole_intersection2", only_hole_intersections[0], only_hole_intersections[2], - 3, 0, 30.9090909, - 4, 0, 10.9090909); + 3, 20, 30.9090909, + 4, 16, 10.9090909); test_one("first_within_second", first_within_second[1], first_within_second[0], - 1, 1, 24, + 1, 10, 24, 0, 0, 0); test_one("fitting", fitting[0], fitting[1], - 1, 0, 21.0, - 1, 0, 4.0); + 1, 9, 21.0, + 1, 4, 4.0); test_one("identical", identical[0], identical[1], @@ -189,63 +191,63 @@ void test_all() test_one("intersect_exterior_and_interiors_winded", intersect_exterior_and_interiors_winded[0], intersect_exterior_and_interiors_winded[1], - 4, 0, 11.533333, - 5, 0, 29.783333); + 4, 20, 11.533333, + 5, 26, 29.783333); test_one("intersect_holes_intersect_and_disjoint", intersect_holes_intersect_and_disjoint[0], intersect_holes_intersect_and_disjoint[1], - 2, 0, 15.75, - 3, 0, 6.75); + 2, 16, 15.75, + 3, 17, 6.75); test_one("intersect_holes_intersect_and_touch", intersect_holes_intersect_and_touch[0], intersect_holes_intersect_and_touch[1], - 3, 0, 16.25, - 3, 0, 6.25); + 3, 21, 16.25, + 3, 17, 6.25); test_one("intersect_holes_new_ring", intersect_holes_new_ring[0], intersect_holes_new_ring[1], - 3, 0, 9.8961, - 4, 0, 121.8961, 0.01); + 3, 15, 9.8961, + 4, 25, 121.8961, 0.01); test_one("first_within_hole_of_second", first_within_hole_of_second[0], first_within_hole_of_second[1], - 1, -1, 1, - 1, -1, 16); + 1, 5, 1, + 1, 10, 16); test_one("intersect_holes_disjoint", intersect_holes_disjoint[0], intersect_holes_disjoint[1], - 2, 15, 16.0, - 2, 15, 6.0); + 2, 14, 16.0, + 2, 10, 6.0); test_one("intersect_holes_intersect", intersect_holes_intersect[0], intersect_holes_intersect[1], - 2, 14, 15.75, - 2, 14, 5.75); + 2, 16, 15.75, + 2, 12, 5.75); test_one( "case4", case_4[0], case_4[1], - 6, 22, 2.77878787878788, - 4, 27, 4.77878787878788); + 6, 28, 2.77878787878788, + 4, 22, 4.77878787878788); test_one( "case5", case_5[0], case_5[1], - 8, 22, 2.43452380952381, - 7, 27, 3.18452380952381); + 8, 36, 2.43452380952381, + 7, 33, 3.18452380952381); test_one("winded", winded[0], winded[1], - 3, 1, 61, - 1, 0, 13); + 3, 37, 61, + 1, 15, 13); test_one("within_holes_disjoint", within_holes_disjoint[0], within_holes_disjoint[1], - 2, 1, 25, - 1, 0, 1); + 2, 15, 25, + 1, 5, 1); test_one("side_side", side_side[0], side_side[1], - 1, 0, 1, - 1, 0, 1); + 1, 5, 1, + 1, 5, 1); /*** TODO: self-tangencies for difference test_one("wrapped_a", @@ -274,32 +276,35 @@ void test_all() test_one("ggl_list_20110306_javier", ggl_list_20110306_javier[0], ggl_list_20110306_javier[1], - 1, 0, 71495.3331, - 2, 0, 8960.49049); + 1, -1, 71495.3331, + 2, -1, 8960.49049); #endif test_one("ggl_list_20110307_javier", ggl_list_20110307_javier[0], ggl_list_20110307_javier[1], - 1, 0, 16815.6, - 1, 0, 3200.4, + 1, 13, 16815.6, + 1, 4, 3200.4, 0.01); if (! boost::is_same::value) { test_one("ggl_list_20110716_enrico", ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1], - 3, 0, 35723.8506317139, - 1, 0, 58456.4964294434 + 3, -1, 35723.8506317139, + 1, -1, 58456.4964294434 ); } test_one("ggl_list_20110820_christophe", ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1], - 1, 0, 2.8570121719168924, - 1, 0, 64.498061986388564); - - - + 1, -1, 2.8570121719168924, + 1, -1, 64.498061986388564); + + test_one("ggl_list_20120717_volker", + ggl_list_20120717_volker[0], ggl_list_20120717_volker[1], + 1, 11, 3370866.2295081965, + 1, 5, 384.2295081964694, 0.01); + #ifdef _MSC_VER // 2011-07-02 // Interesting FP-precision case. @@ -310,9 +315,9 @@ void test_all() // Because we cannot predict this, we only test for MSVC test_one("ggl_list_20110627_phillip", ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1], - if_typed_tt(1, 0), 0, + if_typed_tt(1, 0), -1, if_typed_tt(0.0000000000001105367, 0.0), - 1, 0, 3577.40960816756, + 1, -1, 3577.40960816756, 0.01 ); #endif @@ -325,17 +330,17 @@ void test_all() test_one( "ring_star_ring", example_ring, example_star, - 5, 22, 1.6701714, 5, 27, 1.1901714); + 5, 27, 1.6701714, 5, 22, 1.1901714); static std::string const clip = "POLYGON((2.5 0.5,5.5 2.5))"; test_one("star_box", clip, example_star, - 4, 11, 2.833333, 4, 11, 0.833333); + 4, 20, 2.833333, 4, 16, 0.833333); test_one("box_star", example_star, clip, - 4, 11, 0.833333, 4, 11, 2.833333); + 4, 16, 0.833333, 4, 20, 2.833333); } // Counter clockwise @@ -464,6 +469,19 @@ void test_difference_parcel_precision() } *****/ + +template +void test_specific() +{ + typedef bg::model::polygon polygon; + + test_one("ggl_list_20120717_volker", + ggl_list_20120717_volker[0], ggl_list_20120717_volker[1], + 1, 11, 3370866.2295081965, + 1, 5, 384, 0.01); +} + + int test_main(int, char* []) { //test_difference_parcel_precision(); @@ -471,6 +489,8 @@ int test_main(int, char* []) test_all >(); + test_specific, false, false>(); + #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) test_all >(); diff --git a/test/algorithms/disjoint.cpp b/test/algorithms/disjoint.cpp index 7cf3c683cc..8620350058 100644 --- a/test/algorithms/disjoint.cpp +++ b/test/algorithms/disjoint.cpp @@ -105,6 +105,16 @@ void test_all() test_disjoint("within_simplex_rr1", within_simplex[0], within_simplex[1], false); test_disjoint("within_simplex_rr2", within_simplex[1], within_simplex[0], false); + test_disjoint("point_ring1", "POINT(0 0)", "POLYGON((0 0,3 3,6 0,0 0))", false); + test_disjoint("point_ring2", "POINT(3 1)", "POLYGON((0 0,3 3,6 0,0 0))", false); + test_disjoint("point_ring3", "POINT(0 3)", "POLYGON((0 0,3 3,6 0,0 0))", true); + test_disjoint("point_polygon1", "POINT(0 0)", "POLYGON((0 0,3 3,6 0,0 0))", false); + test_disjoint("point_polygon2", "POINT(3 1)", "POLYGON((0 0,3 3,6 0,0 0))", false); + test_disjoint("point_polygon3", "POINT(0 3)", "POLYGON((0 0,3 3,6 0,0 0))", true); + + test_disjoint("point_ring2", "POLYGON((0 0,3 3,6 0,0 0))", "POINT(0 0)", false); + test_disjoint("point_polygon2", "POLYGON((0 0,3 3,6 0,0 0))", "POINT(0 0)", false); + // Linear typedef bg::model::linestring

    ls; typedef bg::model::segment

    segment; @@ -113,6 +123,12 @@ void test_all() test_disjoint("s/s 1", "linestring(0 0,1 1)", "linestring(1 0,0 1)", false); test_disjoint("s/s 2", "linestring(0 0,1 1)", "linestring(1 0,2 1)", true); + // Test degenerate segments (patched by Karsten Ahnert on 2012-07-25) + test_disjoint("s/s 3", "linestring(0 0,0 0)", "linestring(1 0,0 1)", true); + test_disjoint("s/s 4", "linestring(0 0,0 0)", "linestring(0 0,0 0)", false); + test_disjoint("s/s 5", "linestring(0 0,0 0)", "linestring(1 0,1 0)", true); + test_disjoint("s/s 6", "linestring(0 0,0 0)", "linestring(0 1,0 1)", true); + // Collinear opposite test_disjoint("ls/ls co", "linestring(0 0,2 2)", "linestring(1 1,0 0)", false); // Collinear opposite and equal diff --git a/test/algorithms/intersects.cpp b/test/algorithms/intersects.cpp index ab8a36ae9a..feafb04379 100644 --- a/test/algorithms/intersects.cpp +++ b/test/algorithms/intersects.cpp @@ -17,13 +17,28 @@ template void test_all() { - // intersect <=> ! disjoint + typedef bg::model::polygon

    polygon; + typedef bg::model::ring

    ring; + + // intersect <=> ! disjoint (in most cases) // so most tests are done in disjoint test. - // We only test compilation of one case. + // We only test compilation of a few cases. test_geometry >("POINT(1 1)", "BOX(0 0,2 2)", true); + test_geometry >( + "POLYGON((1992 3240,1992 1440,3792 1800,3792 3240,1992 3240))", + "BOX(1941 2066, 2055 2166)", true); + + test_geometry >( + "POLYGON((1992 3240,1992 1440,3792 1800,3792 3240,1992 3240))", + "BOX(1941 2066, 2055 2166)", true); + + test_geometry >( + "POLYGON((1941 2066,2055 2066,2055 2166,1941 2166))", + "BOX(1941 2066, 2055 2166)", true); + + // self-intersecting is not tested in disjoint, so that is done here. - typedef bg::model::polygon

    polygon; // Just a normal polygon test_self_intersects("POLYGON((0 0,0 4,1.5 2.5,2.5 1.5,4 0,0 0))", false); @@ -111,6 +126,28 @@ void test_all() "POLYGON((0 0,3 3,3 3,4 1,0 0))", false); test_self_intersects >( "POLYGON((0 0,3 3,3 3,4 1))", false); + + test_geometry >( + "POINT(0 0)", + "BOX(0 0,4 4)", + true); + test_geometry >( + "POINT(0 0)", + "POLYGON((0 0,3 3,3 3,4 1))", + true); + test_geometry >( + "POINT(0 0)", + "POLYGON((0 0,3 3,3 3,4 1))", + true); + + test_geometry, P>( + "POLYGON((0 0,3 3,3 3,4 1))", + "POINT(0 0)", + true); + test_geometry, P>( + "POLYGON((0 0,3 3,3 3,4 1))", + "POINT(0 0)", + true); } diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index a4326b07ba..848ae8601a 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -567,6 +567,13 @@ static std::string ggl_list_20120229_volker[3] = "POLYGON((1716 1554,2076 2250,2436 2352,2796 1248,3156 2484,3516 2688,3156 2483,2796 1247,2436 2351,2076 2249, 1716 1554))", }; +static std::string ggl_list_20120717_volker[2] = + { + "POLYGON((1031 1056,3232 1056,3232 2856,1031 2856))", + "POLYGON((1032 1458,1032 1212,2136 2328,3234 2220,3234 2412,2136 2646))" + }; + + static std::string buffer_rt_a[2] = { "POLYGON((1 7,1 8,1.0012 8.04907,1.00482 8.09802,1.01082 8.14673,1.01921 8.19509,1.02997 8.24298,1.04306 8.29028,1.05846 8.33689,1.07612 8.38268,1.09601 8.42756,1.11808 8.4714,1.14227 8.5141,1.16853 8.55557,1.19679 8.5957,1.22699 8.63439,1.25905 8.67156,1.29289 8.70711,1.32844 8.74095,1.36561 8.77301,1.4043 8.80321,1.44443 8.83147,1.4859 8.85773,1.5286 8.88192,1.57244 8.90399,1.61732 8.92388,1.66311 8.94154,1.70972 8.95694,1.75702 8.97003,1.80491 8.98079,1.85327 8.98918,1.90198 8.99518,1.95093 8.9988,2 9,3 9,3.04907 8.9988,3.09802 8.99518,3.14673 8.98918,3.19509 8.98079,3.24298 8.97003,3.29028 8.95694,3.33689 8.94154,3.38268 8.92388,3.42756 8.90399,3.4714 8.88192,3.5141 8.85773,3.55557 8.83147,3.5957 8.80321,3.63439 8.77301,3.67156 8.74095,3.70711 8.70711,3.74095 8.67156,3.77301 8.63439,3.80321 8.5957,3.83147 8.55557,3.85773 8.5141,3.88192 8.4714,3.90399 8.42756,3.92388 8.38268,3.94154 8.33689,3.95694 8.29028,3.97003 8.24298,3.98079 8.19509,3.98918 8.14673,3.99518 8.09802,3.9988 8.04907,4 8,4 7,3.9988 6.95093,3.99518 6.90198,3.98918 6.85327,3.98079 6.80491,3.97003 6.75702,3.95694 6.70972,3.94154 6.66311,3.92388 6.61732,3.90399 6.57244,3.88192 6.5286,3.85773 6.4859,3.83147 6.44443,3.80321 6.4043,3.77301 6.36561,3.74095 6.32844,3.70711 6.29289,3.67156 6.25905,3.63439 6.22699,3.5957 6.19679,3.55557 6.16853,3.5141 6.14227,3.4714 6.11808,3.42756 6.09601,3.38268 6.07612,3.33689 6.05846,3.29028 6.04306,3.24298 6.02997,3.19509 6.01921,3.14673 6.01082,3.09802 6.00482,3.04907 6.0012,3 6,2 6,1.95093 6.0012,1.90198 6.00482,1.85327 6.01082,1.80491 6.01921,1.75702 6.02997,1.70972 6.04306,1.66311 6.05846,1.61732 6.07612,1.57244 6.09601,1.5286 6.11808,1.4859 6.14227,1.44443 6.16853,1.4043 6.19679,1.36561 6.22699,1.32844 6.25905,1.29289 6.29289,1.25905 6.32844,1.22699 6.36561,1.19679 6.4043,1.16853 6.44443,1.14227 6.4859,1.11808 6.5286,1.09601 6.57244,1.07612 6.61732,1.05846 6.66311,1.04306 6.70972,1.02997 6.75702,1.01921 6.80491,1.01082 6.85327,1.00482 6.90198,1.0012 6.95093,1 7))", diff --git a/test/algorithms/overlay/traverse.cpp b/test/algorithms/overlay/traverse.cpp index cebd8b0009..6d588c6527 100644 --- a/test/algorithms/overlay/traverse.cpp +++ b/test/algorithms/overlay/traverse.cpp @@ -7,9 +7,10 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE +// #define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE // #define BOOST_GEOMETRY_OVERLAY_NO_THROW // #define TEST_WITH_SVG +// #define HAVE_TTMATH #include #include @@ -633,8 +634,7 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false) 2, 16, case_53[0], case_53[2]); if (test_self_tangencies) { - // The st_st version might generate one ring with area zero, which is OK - test_traverse::apply("54_st_st", 3, 20, case_54[0], case_54[2]); + test_traverse::apply("54_st_st", 2, 20, case_54[0], case_54[2]); test_traverse::apply("54_st_iet", 2, 20, case_54[0], case_54[3]); test_traverse::apply("54_iet_st", 2, 20, case_54[1], case_54[2]); } @@ -786,6 +786,7 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false) // the chance is 50% that the segments are not sorted correctly and the wrong // decision is taken. // Solved now (by sorting on sides in those cases) + if (! is_float_on_non_msvc) { test_traverse::apply("dz_1", 3, 16.887537949472005, dz_1[0], dz_1[1]); @@ -884,8 +885,10 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false) #if defined(_MSC_VER) double const expected = if_typed_tt(3.63794e-17, 0.0); + int expected_count = if_typed_tt(1, 0); #else double const expected = if_typed(2.77555756156289135106e-17, 0.0); + int expected_count = if_typed(1, 0); #endif // Calculate intersection/union of two triangles. Robustness case. @@ -893,7 +896,7 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false) // (which is even not accomplished by SQL Server/PostGIS) std::string const caseid = "ggl_list_20110820_christophe"; test_traverse::apply(caseid, - 1, expected, + expected_count, expected, ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1]); test_traverse::apply(caseid, 1, 67.3550722317627, @@ -905,7 +908,7 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false) buffer_rt_f[0], buffer_rt_f[1]); test_traverse::apply("buffer_rt_f", 1, 0.0002943725152286, - buffer_rt_f[0], buffer_rt_f[1]); + buffer_rt_f[0], buffer_rt_f[1], 0.01); test_traverse::apply("buffer_rt_g", 1, 16.571, diff --git a/test/algorithms/test_difference.hpp b/test/algorithms/test_difference.hpp index fab6fe3d27..1ea583fb80 100644 --- a/test/algorithms/test_difference.hpp +++ b/test/algorithms/test_difference.hpp @@ -38,7 +38,10 @@ #if defined(TEST_WITH_SVG) +# define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER +# define BOOST_GEOMETRY_DEBUG_IDENTIFIER # include +# include #endif @@ -79,7 +82,7 @@ void difference_output(std::string const& caseid, G1 const& g1, G2 const& g2, Ou template void test_difference(std::string const& caseid, G1 const& g1, G2 const& g2, - std::size_t expected_count, std::size_t expected_point_count, + std::size_t expected_count, int expected_point_count, double expected_area, double percentage = 0.0001, bool sym = false) @@ -103,7 +106,7 @@ void test_difference(std::string const& caseid, G1 const& g1, G2 const& g2, it != clip.end(); ++it) { - if (expected_point_count > 0) + if (expected_point_count >= 0) { n += bg::num_points(*it); } @@ -135,15 +138,15 @@ void test_difference(std::string const& caseid, G1 const& g1, G2 const& g2, #if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST) - /*if (expected_point_count > 0) + if (expected_point_count >= 0) { - BOOST_CHECK_MESSAGE(n == expected_point_count, + BOOST_CHECK_MESSAGE(n == std::size_t(expected_point_count), "difference: " << caseid << " #points expected: " << expected_point_count << " detected: " << n << " type: " << string_from_type::name() ); - }*/ + } if (expected_count > 0) { @@ -171,11 +174,11 @@ template void test_one(std::string const& caseid, std::string const& wkt1, std::string const& wkt2, std::size_t expected_count1, - std::size_t expected_point_count1, + int expected_point_count1, double expected_area1, std::size_t expected_count2, - std::size_t expected_point_count2, + int expected_point_count2, double expected_area2, double percentage = 0.0001) @@ -256,7 +259,7 @@ template void test_one_lp(std::string const& caseid, std::string const& wkt1, std::string const& wkt2, std::size_t expected_count, - std::size_t expected_point_count, + int expected_point_count, double expected_length) { G1 g1; @@ -272,25 +275,29 @@ void test_one_lp(std::string const& caseid, typename bg::default_length_result::type length = 0; std::size_t n = 0; + std::size_t piece_count = 0; for (typename std::vector::iterator it = pieces.begin(); it != pieces.end(); ++it) { - if (expected_point_count > 0) + if (expected_point_count >= 0) { n += bg::num_points(*it); } - + piece_count++; length += bg::length(*it); } - BOOST_CHECK_MESSAGE(pieces.size() == expected_count, + BOOST_CHECK_MESSAGE(piece_count == expected_count, "difference: " << caseid << " #outputs expected: " << expected_count << " detected: " << pieces.size() ); - BOOST_CHECK_EQUAL(n, expected_point_count); + if (expected_point_count >= 0) + { + BOOST_CHECK_EQUAL(n, std::size_t(expected_point_count)); + } BOOST_CHECK_CLOSE(length, expected_length, 0.001); diff --git a/test/algorithms/test_for_each.hpp b/test/algorithms/test_for_each.hpp index 40c7d1f455..b93b72de3e 100644 --- a/test/algorithms/test_for_each.hpp +++ b/test/algorithms/test_for_each.hpp @@ -11,6 +11,7 @@ #include +#include #include #include @@ -87,9 +88,29 @@ void test_per_point_const(Geometry const& geometry, int expected) { typedef typename bg::point_type::type point_type; + // Class (functor) sum_x_functor functor; functor = bg::for_each_point(geometry, functor); BOOST_CHECK_EQUAL(functor.sum, expected); + + + // Lambda +#if !defined(BOOST_NO_CXX11_LAMBDAS) + + typename bg::coordinate_type::type sum_x = 0; + + bg::for_each_point + ( + geometry, + [&sum_x](point_type const& p) + { + sum_x += bg::get<0>(p); + } + + ); + + BOOST_CHECK_EQUAL(sum_x, expected); +#endif } template @@ -97,6 +118,10 @@ void test_per_point_non_const(Geometry& geometry, std::string const& expected1, std::string const& expected2) { +#if !defined(BOOST_NO_CXX11_LAMBDAS) + Geometry copy = geometry; +#endif + typedef typename bg::point_type::type point_type; // function @@ -119,6 +144,41 @@ void test_per_point_non_const(Geometry& geometry, "for_each_point: " << " expected " << expected2 << " got " << bg::wkt(geometry)); + +#if !defined(BOOST_NO_CXX11_LAMBDAS) + // Lambda, both functions above together. Without / with capturing + + geometry = copy; + bg::for_each_point + ( + geometry, + [](point_type& p) + { + bg::set<0>(p, bg::get<0>(p) + 100); + } + + ); + + typename bg::coordinate_type::type scale = 100; + bg::for_each_point + ( + geometry, + [&](point_type& p) + { + bg::set<1>(p, bg::get<1>(p) * scale); + } + + ); + + std::ostringstream out3; + out3 << bg::wkt(geometry); + + BOOST_CHECK_MESSAGE(out3.str() == expected2, + "for_each_point (lambda): " + << " expected " << expected2 + << " got " << bg::wkt(geometry)); +#endif + } diff --git a/test/algorithms/test_intersects.hpp b/test/algorithms/test_intersects.hpp index 4f9922a762..dac1b1eaef 100644 --- a/test/algorithms/test_intersects.hpp +++ b/test/algorithms/test_intersects.hpp @@ -32,12 +32,18 @@ void test_geometry(std::string const& wkt1, bg::read_wkt(wkt2, geometry2); bool detected = bg::intersects(geometry1, geometry2); + bool detected2 = bg::intersects(geometry2, geometry1); BOOST_CHECK_MESSAGE(detected == expected, "intersects: " << wkt1 << " with " << wkt2 << " -> Expected: " << expected << " detected: " << detected); + BOOST_CHECK_MESSAGE(detected2 == expected, + "intersects: " << wkt1 + << " with " << wkt2 + << " -> Expected: " << expected + << " detected: " << detected2); } diff --git a/test/core/point_type.cpp b/test/core/point_type.cpp index a1154295e0..3178bcb91f 100644 --- a/test/core/point_type.cpp +++ b/test/core/point_type.cpp @@ -14,12 +14,15 @@ #include #include +#include #include #include #include +#include + #include #include @@ -64,9 +67,12 @@ int test_main(int, char* []) test_geometry(); test_geometry, - boost::tuple >(); + boost::tuple >(); test_geometry, - boost::tuple >(); + boost::tuple >(); + + test_geometry > >, + boost::tuple >(); test_all >(); test_all >(); diff --git a/test/geometry_test_common.hpp b/test/geometry_test_common.hpp index 4777a0ab7e..689408c775 100644 --- a/test/geometry_test_common.hpp +++ b/test/geometry_test_common.hpp @@ -89,6 +89,9 @@ template <> struct string_from_type template <> struct string_from_type { static std::string name() { return "e"; } }; +template <> struct string_from_type +{ static std::string name() { return "i"; } }; + #if defined(HAVE_TTMATH) template <> struct string_from_type { static std::string name() { return "t"; } }; diff --git a/test/multi/algorithms/Jamfile.v2 b/test/multi/algorithms/Jamfile.v2 index 813d6aafa0..624193c219 100644 --- a/test/multi/algorithms/Jamfile.v2 +++ b/test/multi/algorithms/Jamfile.v2 @@ -23,6 +23,7 @@ test-suite boost-geometry-multi-algorithms [ run multi_equals.cpp ] [ run multi_for_each.cpp ] [ run multi_intersection.cpp ] + [ run multi_intersects.cpp ] [ run multi_length.cpp ] [ run multi_num_geometries.cpp ] [ run multi_num_interior_rings.cpp ] diff --git a/test/multi/algorithms/multi_difference.cpp b/test/multi/algorithms/multi_difference.cpp index e5e47bc5c0..893d3009b5 100644 --- a/test/multi/algorithms/multi_difference.cpp +++ b/test/multi/algorithms/multi_difference.cpp @@ -10,7 +10,8 @@ #include #include -// #define BOOST_GEOMETRY_DEBUG_ASSEMBLE +//#define HAVE_TTMATH +//#define BOOST_GEOMETRY_DEBUG_ASSEMBLE //#define BOOST_GEOMETRY_CHECK_WITH_SQLSERVER //#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER @@ -38,7 +39,7 @@ void test_areal() { test_one("simplex_multi", case_multi_simplex[0], case_multi_simplex[1], - 5, 12, 5.58, 4, 12, 2.58); + 5, 21, 5.58, 4, 17, 2.58); test_one("case_multi_no_ip", case_multi_no_ip[0], case_multi_no_ip[1], @@ -49,13 +50,13 @@ void test_areal() test_one("simplex_multi_mp_p", case_multi_simplex[0], case_single_simplex, - 5, 22, 5.58, 4, 17, 2.58); + 5, 21, 5.58, 4, 17, 2.58); test_one("simplex_multi_r_mp", case_single_simplex, case_multi_simplex[0], - 4, 17, 2.58, 5, 22, 5.58); + 4, 17, 2.58, 5, 21, 5.58); test_one("simplex_multi_mp_r", case_multi_simplex[0], case_single_simplex, - 5, 22, 5.58, 4, 17, 2.58); + 5, 21, 5.58, 4, 17, 2.58); // Constructed cases for multi/touch/equal/etc test_one("case_61_multi", @@ -69,7 +70,7 @@ void test_areal() 0, 0, 0, 1, 5, 1); test_one("case_64_multi", case_64_multi[0], case_64_multi[1], - 1, 1, 1, 1, 1, 1); + 1, 5, 1, 1, 5, 1); test_one("case_65_multi", case_65_multi[0], case_65_multi[1], 0, 0, 0, 2, 10, 3); @@ -84,22 +85,22 @@ void test_areal() test_one("case_78_multi", case_78_multi[0], case_78_multi[1], - 1, 1, 1.0, 1, 1, 1.0); + 1, 5, 1.0, 1, 5, 1.0); // Ticket on GGL list 2011/10/25 // to mix polygon/multipolygon in call to difference test_one("ggl_list_20111025_vd_pp", ggl_list_20111025_vd[0], ggl_list_20111025_vd[1], - 1, -999, 8.0, 1, -999, 12.5); + 1, 4, 8.0, 1, 4, 12.5); test_one("ggl_list_20111025_vd_pm", ggl_list_20111025_vd[0], ggl_list_20111025_vd[3], - 1, -999, 8.0, 1, -999, 12.5); + 1, 4, 8.0, 1, 4, 12.5); test_one("ggl_list_20111025_vd_mp", ggl_list_20111025_vd[2], ggl_list_20111025_vd[1], - 1, -999, 8.0, 1, -999, 12.5); + 1, 4, 8.0, 1, 4, 12.5); test_one("ggl_list_20111025_vd_mm", ggl_list_20111025_vd[2], ggl_list_20111025_vd[3], - 1, -999, 8.0, 1, -999, 12.5); + 1, 4, 8.0, 1, 4, 12.5); // Second case // This can be tested with this SQL for SQL-Server @@ -120,7 +121,19 @@ void test_areal() test_one("ggl_list_20111025_vd_2", ggl_list_20111025_vd_2[0], ggl_list_20111025_vd_2[1], - 1, -999, 10.0, 2, -999, 6.0); + 1, 7, 10.0, 2, 10, 6.0); + + test_one("ggl_list_20120915_h2_a", + ggl_list_20120915_h2[0], ggl_list_20120915_h2[1], + 2, 13, 17.0, 0, 0, 0.0); + test_one("ggl_list_20120915_h2_b", + ggl_list_20120915_h2[0], ggl_list_20120915_h2[2], + 2, 13, 17.0, 0, 0, 0.0); + + test_one("ggl_list_20120221_volker", + ggl_list_20120221_volker[0], ggl_list_20120221_volker[1], + 2, 12, 7962.66, 1, 18, 2775258.93, + 0.001); /* TODO: fix diff --git a/test/multi/algorithms/multi_disjoint.cpp b/test/multi/algorithms/multi_disjoint.cpp index a1b88ce213..9d374f7c72 100644 --- a/test/multi/algorithms/multi_disjoint.cpp +++ b/test/multi/algorithms/multi_disjoint.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,39 @@ void test_all() "MULTIPOLYGON(((2 12,2 18,8 18,8 12,2 12)),((22 2,28 2,28 8,22 8,22 2)))", "MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2)),((20 0,20 10,30 10,30 0,20 0)))", false); + + + test_disjoint("point_mp1", + "POINT(0 0)", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + false); + + test_disjoint("point_mp2", + "POINT(5 5)", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + false); + + test_disjoint("point_mp1", + "POINT(11 11)", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + true); + + std::string polygon_inside_hole("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0), (2 2,8 2,8 8,2 8,2 2)),((4 4,4 6,6 6,6 4,4 4)))"); + test_disjoint("point_mp_pih1", + "POINT(5 5)", + polygon_inside_hole, + false); + + test_disjoint("point_mp_pih2", + "POINT(3 3)", + polygon_inside_hole, + true); + + test_disjoint("point_mp1rev", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + "POINT(0 0)", + false); + } int test_main(int, char* []) diff --git a/test/multi/algorithms/multi_intersection.cpp b/test/multi/algorithms/multi_intersection.cpp index d479f5d115..fc94811f87 100644 --- a/test/multi/algorithms/multi_intersection.cpp +++ b/test/multi/algorithms/multi_intersection.cpp @@ -100,6 +100,13 @@ void test_areal() test_one("case_recursive_boxes_4", case_recursive_boxes_4[0], case_recursive_boxes_4[1], 13, 157, 67.0); // Area from SQL Server + + test_one("ggl_list_20120915_h2_a", + ggl_list_20120915_h2[0], ggl_list_20120915_h2[1], + 2, 10, 6.0); // Area from SQL Server + test_one("ggl_list_20120915_h2_b", + ggl_list_20120915_h2[0], ggl_list_20120915_h2[2], + 2, 10, 6.0); // Area from SQL Server } template diff --git a/test/multi/algorithms/multi_intersects.cpp b/test/multi/algorithms/multi_intersects.cpp new file mode 100644 index 0000000000..d07b8b6cf1 --- /dev/null +++ b/test/multi/algorithms/multi_intersects.cpp @@ -0,0 +1,51 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2012 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) + +#include +#include + + +#include + +#include + +#include + +#include +#include +#include + +template +void test_all() +{ + typedef bg::model::polygon

    polygon; + typedef bg::model::multi_polygon mp; + + test_geometry("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + true); + + test_geometry("POINT(0 0)", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + true); + +} + +int test_main(int, char* []) +{ + //test_all >(); + test_all >(); + +#ifdef HAVE_TTMATH + test_all >(); +#endif + + return 0; +} + diff --git a/test/multi/algorithms/multi_union.cpp b/test/multi/algorithms/multi_union.cpp index ffa694291a..5cbe1e7a70 100644 --- a/test/multi/algorithms/multi_union.cpp +++ b/test/multi/algorithms/multi_union.cpp @@ -106,6 +106,13 @@ void test_areal() test_one("case_recursive_boxes_3", case_recursive_boxes_3[0], case_recursive_boxes_3[1], 17, 0, 159, 56.5); // Area from SQL Server + + test_one("ggl_list_20120915_h2_a", + ggl_list_20120915_h2[0], ggl_list_20120915_h2[1], + 1, 0, 12, 23.0); // Area from SQL Server + test_one("ggl_list_20120915_h2_b", + ggl_list_20120915_h2[0], ggl_list_20120915_h2[2], + 1, 0, 12, 23.0); // Area from SQL Server } template diff --git a/test/multi/algorithms/overlay/multi_overlay_cases.hpp b/test/multi/algorithms/overlay/multi_overlay_cases.hpp index 536aa09531..0ddd3a0a7b 100644 --- a/test/multi/algorithms/overlay/multi_overlay_cases.hpp +++ b/test/multi/algorithms/overlay/multi_overlay_cases.hpp @@ -426,6 +426,21 @@ static std::string ggl_list_20111025_vd_2[2] = "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((4 0,4 2,6 2,6 0,4 0)))" }; +// Mail of h2 indicating that reversed order (in second polygon) has ix/ix problems +static std::string ggl_list_20120915_h2[3] = + { + "MULTIPOLYGON(((-2 5, -1 5, 0 5, 2 5, 2 -2, 1 -2, 1 -1, 0 -1,0 0, -1 0, -2 0, -2 5)))", + "MULTIPOLYGON(((0 0, 1 0, 1 -1, 0 -1, 0 0)), ((-1 5, 0 5, 0 0, -1 0, -1 5)))", + "MULTIPOLYGON(((-1 5, 0 5, 0 0, -1 0, -1 5)), ((0 0, 1 0, 1 -1, 0 -1, 0 0)))" + }; + +// Mail of volker, about another problem, but this specific example is causing two-point inner rings polygons which should be discarded +// (condition of num_points in detail/overlay/convert_ring.hpp) +static std::string ggl_list_20120221_volker[2] = + { + "MULTIPOLYGON(((1032 2130,1032 1764,2052 2712,1032 2130)),((3234 2580,2558 2690,3234 2532,3234 2580)),((2558 2690,2136 2790,2052 2712,2136 2760,2558 2690)))", + "MULTIPOLYGON(((3232 2532.469945355191,2136 2790,1032 1764,1032 1458,1032 1212,2136 2328,3232 2220.196721311475,3232 1056,1031 1056,1031 2856,3232 2856,3232 2532.469945355191),(3232 2412.426229508197,2136 2646,3232 2412.426229508197)))" + }; #endif // BOOST_GEOMETRY_TEST_MULTI_OVERLAY_CASES_HPP diff --git a/test/multi/algorithms/overlay/multi_traverse.cpp b/test/multi/algorithms/overlay/multi_traverse.cpp index f731f73cbc..faacd36157 100644 --- a/test/multi/algorithms/overlay/multi_traverse.cpp +++ b/test/multi/algorithms/overlay/multi_traverse.cpp @@ -386,7 +386,7 @@ void test_geometries() test_traverse_union::apply ( - "case_recursive_boxes_3", 8, 49.5, + "case_recursive_boxes_3", 7, 49.5, case_recursive_boxes_3[0], case_recursive_boxes_3[1] ); From 106876b29d04b03d943e447ba35b1797863a1383 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 16 Dec 2012 16:08:33 +0000 Subject: [PATCH 049/135] [geometry] merged revisions r78001:r78851 which were not yet merged earlier [SVN r82023] --- doc/generated/disjoint_status.qbk | 13 ++ doc/generated/envelope_status.qbk | 13 ++ doc/generated/equals_status.qbk | 17 +- doc/generated/expand_status.qbk | 13 ++ doc/generated/overlaps_status.qbk | 13 ++ .../boost/geometry/algorithms/envelope.hpp | 136 ++++----------- include/boost/geometry/algorithms/equals.hpp | 159 +++++++----------- include/boost/geometry/algorithms/expand.hpp | 107 +++++------- .../boost/geometry/algorithms/overlaps.hpp | 44 ++--- .../geometry/multi/algorithms/envelope.hpp | 34 ++-- .../geometry/multi/algorithms/equals.hpp | 26 ++- 11 files changed, 229 insertions(+), 346 deletions(-) create mode 100644 doc/generated/disjoint_status.qbk create mode 100644 doc/generated/envelope_status.qbk create mode 100644 doc/generated/expand_status.qbk create mode 100644 doc/generated/overlaps_status.qbk diff --git a/doc/generated/disjoint_status.qbk b/doc/generated/disjoint_status.qbk new file mode 100644 index 0000000000..d7d9e977ee --- /dev/null +++ b/doc/generated/disjoint_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[ ][Point][Segment][Box][Linestring][Ring][Polygon][MultiPoint][MultiLinestring][MultiPolygon]] +[[Point][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/ok.png] ]] +] diff --git a/doc/generated/envelope_status.qbk b/doc/generated/envelope_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/envelope_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/generated/equals_status.qbk b/doc/generated/equals_status.qbk index 6dc8bc0b20..573c78f4b7 100644 --- a/doc/generated/equals_status.qbk +++ b/doc/generated/equals_status.qbk @@ -1,10 +1,13 @@ [heading Supported geometries] [table -[[ ][Point][Box][Linestring][Ring][Polygon][MultiPolygon]] -[[Point][[$img/ok.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]]] -[[Box][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]][[$img/nyi.png]]] -[[Linestring][[$img/nyi.png]][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]]] -[[Ring][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]][[$img/nyi.png]]] -[[Polygon][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]][[$img/ok.png]]] -[[MultiPolygon][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]]] +[[ ][Point][Segment][Box][Linestring][Ring][Polygon][MultiPoint][MultiLinestring][MultiPolygon]] +[[Point][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Segment][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Linestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Ring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Polygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ]] +[[MultiPoint][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiLinestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPolygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ]] ] diff --git a/doc/generated/expand_status.qbk b/doc/generated/expand_status.qbk new file mode 100644 index 0000000000..37635e1611 --- /dev/null +++ b/doc/generated/expand_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[ ][Point][Segment][Box][Linestring][Ring][Polygon][MultiPoint][MultiLinestring][MultiPolygon]] +[[Point][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Segment][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Linestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Ring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Polygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPoint][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiLinestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPolygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +] diff --git a/doc/generated/overlaps_status.qbk b/doc/generated/overlaps_status.qbk new file mode 100644 index 0000000000..6caf4c90c3 --- /dev/null +++ b/doc/generated/overlaps_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[ ][Point][Segment][Box][Linestring][Ring][Polygon][MultiPoint][MultiLinestring][MultiPolygon]] +[[Point][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Segment][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Box][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/ok.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Linestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Ring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[Polygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPoint][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiLinestring][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +[[MultiPolygon][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ][ [$img/nyi.png] ]] +] diff --git a/include/boost/geometry/algorithms/envelope.hpp b/include/boost/geometry/algorithms/envelope.hpp index da34f6a783..ee88fe888a 100644 --- a/include/boost/geometry/algorithms/envelope.hpp +++ b/include/boost/geometry/algorithms/envelope.hpp @@ -14,13 +14,13 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP #define BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP -#include #include #include #include #include +#include #include #include #include @@ -35,9 +35,9 @@ namespace detail { namespace envelope /// Calculate envelope of an 2D or 3D segment -template struct envelope_expand_one { + template static inline void apply(Geometry const& geometry, Box& mbr) { assign_inverse(mbr); @@ -63,10 +63,10 @@ inline void envelope_range_additional(Range const& range, Box& mbr) /// Generic range dispatching struct -template struct envelope_range { /// Calculate envelope of range using a strategy + template static inline void apply(Range const& range, Box& mbr) { assign_inverse(mbr); @@ -82,122 +82,54 @@ namespace dispatch { -// Note, the strategy is for future use (less/greater -> compare spherical -// using other methods), defaults are OK for now. -// However, they are already in the template methods - template < - typename Tag1, typename Tag2, - typename Geometry, typename Box, - typename StrategyLess, typename StrategyGreater + typename Geometry, + typename Tag = typename tag::type > -struct envelope -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; +struct envelope: not_implemented +{}; -template -< - typename Point, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - < - point_tag, box_tag, - Point, Box, - StrategyLess, StrategyGreater - > - : detail::envelope::envelope_expand_one +template +struct envelope + : detail::envelope::envelope_expand_one {}; -template -< - typename BoxIn, typename BoxOut, - typename StrategyLess, typename StrategyGreater -> -struct envelope - < - box_tag, box_tag, - BoxIn, BoxOut, - StrategyLess, StrategyGreater - > - : detail::envelope::envelope_expand_one +template +struct envelope + : detail::envelope::envelope_expand_one {}; -template -< - typename Segment, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - < - segment_tag, box_tag, - Segment, Box, - StrategyLess, StrategyGreater - > - : detail::envelope::envelope_expand_one +template +struct envelope + : detail::envelope::envelope_expand_one {}; -template -< - typename Linestring, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - < - linestring_tag, box_tag, - Linestring, Box, - StrategyLess, StrategyGreater - > - : detail::envelope::envelope_range +template +struct envelope + : detail::envelope::envelope_range {}; -template -< - typename Ring, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - < - ring_tag, box_tag, - Ring, Box, - StrategyLess, StrategyGreater - > - : detail::envelope::envelope_range +template +struct envelope + : detail::envelope::envelope_range {}; -template -< - typename Polygon, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - < - polygon_tag, box_tag, - Polygon, Box, - StrategyLess, StrategyGreater - > +template +struct envelope + : detail::envelope::envelope_range { + template static inline void apply(Polygon const& poly, Box& mbr) { // For polygon, inspecting outer ring is sufficient - - detail::envelope::envelope_range - < - typename ring_type::type, - Box - >::apply(exterior_ring(poly), mbr); + detail::envelope::envelope_range::apply(exterior_ring(poly), mbr); } }; @@ -228,12 +160,7 @@ inline void envelope(Geometry const& geometry, Box& mbr) concept::check(); concept::check(); - dispatch::envelope - < - typename tag::type, typename tag::type, - Geometry, Box, - void, void - >::apply(geometry, mbr); + dispatch::envelope::apply(geometry, mbr); } @@ -259,12 +186,7 @@ inline Box return_envelope(Geometry const& geometry) concept::check(); Box mbr; - dispatch::envelope - < - typename tag::type, typename tag::type, - Geometry, Box, - void, void - >::apply(geometry, mbr); + dispatch::envelope::apply(geometry, mbr); return mbr; } diff --git a/include/boost/geometry/algorithms/equals.hpp b/include/boost/geometry/algorithms/equals.hpp index 6b094f76d0..d9502bb3fd 100644 --- a/include/boost/geometry/algorithms/equals.hpp +++ b/include/boost/geometry/algorithms/equals.hpp @@ -18,8 +18,6 @@ #include #include -#include -#include #include #include @@ -30,6 +28,7 @@ #include #include +#include // For trivial checks #include @@ -51,13 +50,12 @@ namespace detail { namespace equals template < - typename Box1, - typename Box2, std::size_t Dimension, std::size_t DimensionCount > struct box_box { + template static inline bool apply(Box1 const& box1, Box2 const& box2) { if (!geometry::math::equals(get(box1), get(box2)) @@ -65,13 +63,14 @@ struct box_box { return false; } - return box_box::apply(box1, box2); + return box_box::apply(box1, box2); } }; -template -struct box_box +template +struct box_box { + template static inline bool apply(Box1 const& , Box2 const& ) { return true; @@ -103,9 +102,10 @@ struct length_check }; -template +template struct equals_by_collection { + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { if (! TrivialCheck::apply(geometry1, geometry2)) @@ -152,17 +152,42 @@ namespace dispatch template < - typename Tag1, typename Tag2, typename Geometry1, typename Geometry2, - std::size_t DimensionCount + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type, + std::size_t DimensionCount = dimension::type::value, + bool Reverse = reverse_dispatch::type::value > -struct equals +struct equals: not_implemented {}; -template -struct equals +// If reversal is needed, perform it +template +< + typename Geometry1, typename Geometry2, + typename Tag1, typename Tag2, + std::size_t DimensionCount +> +struct equals + : equals +{ + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + { + return equals + < + Geometry2, Geometry1, + Tag2, Tag1, + DimensionCount, + false + >::apply(g2, g1); + } +}; + + +template +struct equals : geometry::detail::not_ < P1, @@ -172,93 +197,48 @@ struct equals {}; -template -struct equals - : detail::equals::box_box +template +struct equals + : detail::equals::box_box<0, DimensionCount> {}; -template -struct equals - : detail::equals::equals_by_collection - < - Ring1, Ring2, - detail::equals::area_check - > +template +struct equals + : detail::equals::equals_by_collection {}; -template -struct equals - : detail::equals::equals_by_collection - < - Polygon1, Polygon2, - detail::equals::area_check - > +template +struct equals + : detail::equals::equals_by_collection {}; -template -struct equals - : detail::equals::equals_by_collection - < - LineString1, LineString2, - detail::equals::length_check - > +template +struct equals + : detail::equals::equals_by_collection {}; -template -struct equals - : detail::equals::equals_by_collection - < - Polygon, Ring, - detail::equals::area_check - > +template +struct equals + : detail::equals::equals_by_collection {}; -template -struct equals - : detail::equals::equals_by_collection - < - Ring, Box, - detail::equals::area_check - > +template +struct equals + : detail::equals::equals_by_collection {}; -template -struct equals - : detail::equals::equals_by_collection - < - Polygon, Box, - detail::equals::area_check - > +template +struct equals + : detail::equals::equals_by_collection {}; -template -< - typename Tag1, typename Tag2, - typename Geometry1, - typename Geometry2, - std::size_t DimensionCount -> -struct equals_reversed -{ - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) - { - return equals - < - Tag2, Tag1, - Geometry2, Geometry1, - DimensionCount - >::apply(g2, g1); - } -}; - - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -289,26 +269,7 @@ inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2) Geometry2 const >(); - return boost::mpl::if_c - < - reverse_dispatch::type::value, - dispatch::equals_reversed - < - typename tag::type, - typename tag::type, - Geometry1, - Geometry2, - dimension::type::value - >, - dispatch::equals - < - typename tag::type, - typename tag::type, - Geometry1, - Geometry2, - dimension::type::value - > - >::type::apply(geometry1, geometry2); + return dispatch::equals::apply(geometry1, geometry2); } diff --git a/include/boost/geometry/algorithms/expand.hpp b/include/boost/geometry/algorithms/expand.hpp index da7442b593..2e1531bf02 100644 --- a/include/boost/geometry/algorithms/expand.hpp +++ b/include/boost/geometry/algorithms/expand.hpp @@ -19,6 +19,7 @@ #include +#include #include #include @@ -38,26 +39,26 @@ namespace detail { namespace expand template < - typename Box, typename Point, typename StrategyLess, typename StrategyGreater, std::size_t Dimension, std::size_t DimensionCount > struct point_loop { - typedef typename strategy::compare::detail::select_strategy - < - StrategyLess, 1, Point, Dimension - >::type less_type; + template + static inline void apply(Box& box, Point const& source) + { + typedef typename strategy::compare::detail::select_strategy + < + StrategyLess, 1, Point, Dimension + >::type less_type; - typedef typename strategy::compare::detail::select_strategy - < - StrategyGreater, -1, Point, Dimension - >::type greater_type; + typedef typename strategy::compare::detail::select_strategy + < + StrategyGreater, -1, Point, Dimension + >::type greater_type; - typedef typename select_coordinate_type::type coordinate_type; + typedef typename select_coordinate_type::type coordinate_type; - static inline void apply(Box& box, Point const& source) - { less_type less; greater_type greater; @@ -75,7 +76,6 @@ struct point_loop point_loop < - Box, Point, StrategyLess, StrategyGreater, Dimension + 1, DimensionCount >::apply(box, source); @@ -85,49 +85,47 @@ struct point_loop template < - typename Box, typename Point, typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount > struct point_loop < - Box, Point, StrategyLess, StrategyGreater, DimensionCount, DimensionCount > { + template static inline void apply(Box&, Point const&) {} }; template < - typename Box, typename Geometry, typename StrategyLess, typename StrategyGreater, std::size_t Index, std::size_t Dimension, std::size_t DimensionCount > struct indexed_loop { - typedef typename strategy::compare::detail::select_strategy - < - StrategyLess, 1, Box, Dimension - >::type less_type; - - typedef typename strategy::compare::detail::select_strategy - < - StrategyGreater, -1, Box, Dimension - >::type greater_type; + template + static inline void apply(Box& box, Geometry const& source) + { + typedef typename strategy::compare::detail::select_strategy + < + StrategyLess, 1, Box, Dimension + >::type less_type; - typedef typename select_coordinate_type + typedef typename strategy::compare::detail::select_strategy < - Box, - Geometry - >::type coordinate_type; + StrategyGreater, -1, Box, Dimension + >::type greater_type; + typedef typename select_coordinate_type + < + Box, + Geometry + >::type coordinate_type; - static inline void apply(Box& box, Geometry const& source) - { less_type less; greater_type greater; @@ -145,7 +143,6 @@ struct indexed_loop indexed_loop < - Box, Geometry, StrategyLess, StrategyGreater, Index, Dimension + 1, DimensionCount >::apply(box, source); @@ -155,17 +152,16 @@ struct indexed_loop template < - typename Box, typename Geometry, typename StrategyLess, typename StrategyGreater, std::size_t Index, std::size_t DimensionCount > struct indexed_loop < - Box, Geometry, StrategyLess, StrategyGreater, Index, DimensionCount, DimensionCount > { + template static inline void apply(Box&, Geometry const&) {} }; @@ -174,23 +170,21 @@ struct indexed_loop // Changes a box such that the other box is also contained by the box template < - typename Box, typename Geometry, typename StrategyLess, typename StrategyGreater > struct expand_indexed { + template static inline void apply(Box& box, Geometry const& geometry) { indexed_loop < - Box, Geometry, StrategyLess, StrategyGreater, 0, 0, dimension::type::value >::apply(box, geometry); indexed_loop < - Box, Geometry, StrategyLess, StrategyGreater, 1, 0, dimension::type::value >::apply(box, geometry); @@ -206,11 +200,13 @@ namespace dispatch template < - typename Tag, - typename BoxOut, typename Geometry, - typename StrategyLess, typename StrategyGreater + typename GeometryOut, typename Geometry, + typename StrategyLess = strategy::compare::default_strategy, + typename StrategyGreater = strategy::compare::default_strategy, + typename TagOut = typename tag::type, + typename Tag = typename tag::type > -struct expand +struct expand: not_implemented {}; @@ -220,10 +216,9 @@ template typename BoxOut, typename Point, typename StrategyLess, typename StrategyGreater > -struct expand +struct expand : detail::expand::point_loop < - BoxOut, Point, StrategyLess, StrategyGreater, 0, dimension::type::value > @@ -236,9 +231,8 @@ template typename BoxOut, typename BoxIn, typename StrategyLess, typename StrategyGreater > -struct expand - : detail::expand::expand_indexed - +struct expand + : detail::expand::expand_indexed {}; template @@ -246,9 +240,8 @@ template typename Box, typename Segment, typename StrategyLess, typename StrategyGreater > -struct expand - : detail::expand::expand_indexed - +struct expand + : detail::expand::expand_indexed {}; @@ -279,13 +272,7 @@ inline void expand(Box& box, Geometry const& geometry, { concept::check_concepts_and_equal_dimensions(); - dispatch::expand - < - typename tag::type, - Box, - Geometry, - StrategyLess, StrategyGreater - >::apply(box, geometry); + dispatch::expand::apply(box, geometry); } ***/ @@ -305,13 +292,7 @@ inline void expand(Box& box, Geometry const& geometry) { concept::check_concepts_and_equal_dimensions(); - dispatch::expand - < - typename tag::type, - Box, Geometry, - strategy::compare::default_strategy, - strategy::compare::default_strategy - >::apply(box, geometry); + dispatch::expand::apply(box, geometry); } }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/overlaps.hpp b/include/boost/geometry/algorithms/overlaps.hpp index 2f854b4fdd..d417a4b1f5 100644 --- a/include/boost/geometry/algorithms/overlaps.hpp +++ b/include/boost/geometry/algorithms/overlaps.hpp @@ -17,10 +17,10 @@ #include -#include - #include +#include + #include namespace boost { namespace geometry @@ -32,13 +32,12 @@ namespace detail { namespace overlaps template < - typename Box1, - typename Box2, std::size_t Dimension, std::size_t DimensionCount > struct box_box_loop { + template static inline void apply(Box1 const& b1, Box2 const& b2, bool& overlaps, bool& one_in_two, bool& two_in_one) { @@ -84,8 +83,6 @@ struct box_box_loop box_box_loop < - Box1, - Box2, Dimension + 1, DimensionCount >::apply(b1, b2, overlaps, one_in_two, two_in_one); @@ -94,24 +91,19 @@ struct box_box_loop template < - typename Box1, - typename Box2, std::size_t DimensionCount > -struct box_box_loop +struct box_box_loop { + template static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&) { } }; -template -< - typename Box1, - typename Box2 -> struct box_box { + template static inline bool apply(Box1 const& b1, Box2 const& b2) { bool overlaps = true; @@ -119,8 +111,6 @@ struct box_box bool within2 = true; box_box_loop < - Box1, - Box2, 0, dimension::type::value >::apply(b1, b2, overlaps, within1, within2); @@ -148,24 +138,18 @@ namespace dispatch template < - typename Tag1, - typename Tag2, typename Geometry1, - typename Geometry2 + typename Geometry2, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type > -struct overlaps -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; +struct overlaps: not_implemented +{}; template -struct overlaps - : detail::overlaps::box_box +struct overlaps + : detail::overlaps::box_box {}; @@ -190,8 +174,6 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2) return dispatch::overlaps < - typename tag::type, - typename tag::type, Geometry1, Geometry2 >::apply(geometry1, geometry2); diff --git a/include/boost/geometry/multi/algorithms/envelope.hpp b/include/boost/geometry/multi/algorithms/envelope.hpp index 1876b5f91e..026fc71e62 100644 --- a/include/boost/geometry/multi/algorithms/envelope.hpp +++ b/include/boost/geometry/multi/algorithms/envelope.hpp @@ -34,9 +34,9 @@ namespace detail { namespace envelope { -template struct envelope_multi_linestring { + template static inline void apply(MultiLinestring const& mp, Box& mbr) { assign_inverse(mbr); @@ -52,9 +52,9 @@ struct envelope_multi_linestring // version for multi_polygon: outer ring's of all polygons -template struct envelope_multi_polygon { + template static inline void apply(MultiPolygon const& mp, Box& mbr) { assign_inverse(mbr); @@ -78,32 +78,20 @@ struct envelope_multi_polygon namespace dispatch { -template -< - typename Multi, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - : detail::envelope::envelope_range +template +struct envelope + : detail::envelope::envelope_range {}; -template -< - typename Multi, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - : detail::envelope::envelope_multi_linestring +template +struct envelope + : detail::envelope::envelope_multi_linestring {}; -template -< - typename Multi, typename Box, - typename StrategyLess, typename StrategyGreater -> -struct envelope - : detail::envelope::envelope_multi_polygon +template +struct envelope + : detail::envelope::envelope_multi_polygon {}; diff --git a/include/boost/geometry/multi/algorithms/equals.hpp b/include/boost/geometry/multi/algorithms/equals.hpp index a307ebae8b..8c47672d95 100644 --- a/include/boost/geometry/multi/algorithms/equals.hpp +++ b/include/boost/geometry/multi/algorithms/equals.hpp @@ -29,33 +29,27 @@ namespace dispatch { -template +template struct equals < - multi_polygon_tag, multi_polygon_tag, MultiPolygon1, MultiPolygon2, - 2 + multi_polygon_tag, multi_polygon_tag, + 2, + Reverse > - : detail::equals::equals_by_collection - < - MultiPolygon1, MultiPolygon2, - detail::equals::area_check - > + : detail::equals::equals_by_collection {}; -template +template struct equals < - polygon_tag, multi_polygon_tag, Polygon, MultiPolygon, - 2 + polygon_tag, multi_polygon_tag, + 2, + Reverse > - : detail::equals::equals_by_collection - < - Polygon, MultiPolygon, - detail::equals::area_check - > + : detail::equals::equals_by_collection {}; From 485923d149432fbdd1647f98e05fc5221588a04e Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 12 May 2013 10:58:26 +0000 Subject: [PATCH 050/135] [geometry] merge of Boost.Geometry into release branch [SVN r84242] --- doc/concept/polygon.qbk | 4 +- doc/doxy/Doxyfile | 5 +- .../doxygen_input/sourcecode/doxygen_4.cpp | 4 +- doc/doxy/doxygen_output/html/doxygen.css | 591 +++- doc/doxy/doxygen_output/html/doxygen.png | Bin 3942 -> 3779 bytes doc/doxy/doxygen_output/html/tabs.css | 1 + doc/generated/wkt_status.qbk | 13 + doc/geometry.qbk | 14 +- doc/html/img/index/rtree/disjoint.png | Bin 0 -> 2223 bytes doc/html/img/index/rtree/intersects.png | Bin 0 -> 2228 bytes doc/html/img/index/rtree/intersects_mpoly.png | Bin 0 -> 2687 bytes doc/html/img/index/rtree/intersects_poly.png | Bin 0 -> 2654 bytes doc/html/img/index/rtree/intersects_ring.png | Bin 0 -> 2641 bytes doc/html/img/index/rtree/knn.png | Bin 0 -> 2774 bytes doc/html/img/index/rtree/linear.png | Bin 0 -> 2204 bytes doc/html/img/index/rtree/overlaps.png | Bin 0 -> 2209 bytes doc/html/img/index/rtree/path.png | Bin 0 -> 2840 bytes doc/html/img/index/rtree/quadratic.png | Bin 0 -> 2096 bytes doc/html/img/index/rtree/rstar.png | Bin 0 -> 2079 bytes doc/html/img/index/rtree/within.png | Bin 0 -> 2208 bytes doc/html/index.html | 25 +- doc/index/Doxyfile | 332 +++ doc/index/Jamfile.v2 | 32 + doc/index/imports.qbk | 17 + doc/index/index.qbk | 38 + doc/index/introduction.qbk | 19 + doc/index/make_qbk.py | 39 + doc/index/rtree.qbk | 21 + doc/index/rtree/creation.qbk | 231 ++ doc/index/rtree/examples.qbk | 41 + doc/index/rtree/exception_safety.qbk | 57 + doc/index/rtree/experimental.qbk | 110 + doc/index/rtree/introduction.qbk | 68 + doc/index/rtree/query.qbk | 219 ++ doc/index/rtree/quickstart.qbk | 59 + doc/index/rtree/reference.qbk | 40 + doc/index/src/examples/Jamfile.v2 | 19 + doc/index/src/examples/rtree/Jamfile.v2 | 25 + doc/index/src/examples/rtree/interprocess.cpp | 112 + .../examples/rtree/polygons_shared_ptr.cpp | 88 + .../src/examples/rtree/polygons_vector.cpp | 96 + doc/index/src/examples/rtree/quick_start.cpp | 87 + doc/index/src/examples/rtree/value_index.cpp | 97 + .../src/examples/rtree/value_shared_ptr.cpp | 91 + doc/index/src/examples/rtree/variants_map.cpp | 143 + doc/make_qbk.py | 7 +- doc/quickref.xml | 124 + doc/readme.txt | 7 +- doc/reference.qbk | 29 + doc/reference/core/max_corner.qbk | 4 +- doc/reference/core/min_corner.qbk | 4 +- doc/release_notes.qbk | 28 +- .../tools/doxygen_xml2qbk/configuration.hpp | 8 +- .../contrib/rapidxml-1.13/license.txt | 52 + .../contrib/rapidxml-1.13/manual.html | 406 +++ .../contrib/rapidxml-1.13/rapidxml.hpp | 2596 +++++++++++++++++ .../rapidxml-1.13/rapidxml_iterators.hpp | 174 ++ .../contrib/rapidxml-1.13/rapidxml_print.hpp | 421 +++ .../contrib/rapidxml-1.13/rapidxml_utils.hpp | 122 + .../doxygen_xml2qbk/doxygen_elements.hpp | 30 +- .../tools/doxygen_xml2qbk/doxygen_xml2qbk.cpp | 101 +- .../doxygen_xml2qbk/doxygen_xml_parser.hpp | 224 +- .../tools/doxygen_xml2qbk/file_to_string.hpp | 3 +- .../doxygen_xml2qbk/parameter_predicates.hpp | 3 +- .../doxygen_xml2qbk/quickbook_output.hpp | 808 ++++- .../tools/doxygen_xml2qbk/rapidxml_util.hpp | 3 +- .../tools/support_status/support_status.cpp | 4 + .../algorithms/create_svg_overlay.hpp | 2 +- .../examples/algorithms/create_svg_two.hpp | 2 +- example/05_a_overlay_polygon_example.cpp | 2 +- ...5_b_overlay_linestring_polygon_example.cpp | 2 +- example/06_b_transformation_example.cpp | 2 +- example/07_a_graph_route_example.cpp | 14 +- example/07_b_graph_route_example.cpp | 13 +- include/boost/geometry/algorithms/append.hpp | 87 +- include/boost/geometry/algorithms/area.hpp | 70 +- include/boost/geometry/algorithms/assign.hpp | 4 +- include/boost/geometry/algorithms/clear.hpp | 49 +- include/boost/geometry/algorithms/convert.hpp | 60 +- include/boost/geometry/algorithms/correct.hpp | 11 +- .../algorithms/detail/assign_box_corners.hpp | 10 + .../algorithms/detail/occupation_info.hpp | 190 +- .../overlay/calculate_distance_policy.hpp | 14 +- .../overlay/enrich_intersection_points.hpp | 30 +- .../detail/overlay/get_turn_info.hpp | 142 +- .../algorithms/detail/overlay/get_turns.hpp | 21 +- .../algorithms/detail/overlay/overlay.hpp | 11 + .../algorithms/detail/overlay/traverse.hpp | 7 +- .../detail/sections/sectionalize.hpp | 24 + .../boost/geometry/algorithms/disjoint.hpp | 14 +- .../boost/geometry/algorithms/distance.hpp | 2 + include/boost/geometry/algorithms/equals.hpp | 120 +- .../boost/geometry/algorithms/for_each.hpp | 18 +- include/boost/geometry/algorithms/length.hpp | 88 +- .../boost/geometry/algorithms/num_points.hpp | 56 +- include/boost/geometry/algorithms/within.hpp | 4 + include/boost/geometry/core/access.hpp | 27 +- .../geometry/core/coordinate_dimension.hpp | 2 +- .../boost/geometry/core/coordinate_system.hpp | 8 +- .../boost/geometry/core/coordinate_type.hpp | 14 +- include/boost/geometry/core/tag.hpp | 2 +- .../geometry/geometries/concepts/check.hpp | 70 +- include/boost/geometry/geometries/point.hpp | 10 + include/boost/geometry/geometry.hpp | 1 + include/boost/geometry/io/svg/svg_mapper.hpp | 347 +++ include/boost/geometry/io/svg/write_svg.hpp | 272 ++ .../boost/geometry/io/svg/write_svg_multi.hpp | 78 + include/boost/geometry/io/wkt/read.hpp | 11 + include/boost/geometry/io/wkt/write.hpp | 87 +- .../iterators/ever_circling_iterator.hpp | 2 +- .../geometry/multi/algorithms/append.hpp | 1 + .../boost/geometry/multi/algorithms/area.hpp | 2 + .../geometry/multi/algorithms/centroid.hpp | 2 + .../boost/geometry/multi/algorithms/clear.hpp | 1 + .../geometry/multi/algorithms/convert.hpp | 1 + .../geometry/multi/algorithms/correct.hpp | 1 + .../geometry/multi/algorithms/covered_by.hpp | 1 + .../algorithms/detail/for_each_range.hpp | 1 + .../detail/overlay/copy_segment_point.hpp | 1 + .../detail/overlay/copy_segments.hpp | 1 + .../algorithms/detail/overlay/get_ring.hpp | 2 + .../algorithms/detail/overlay/get_turns.hpp | 2 + .../detail/overlay/select_rings.hpp | 3 + .../detail/overlay/self_turn_points.hpp | 1 + .../algorithms/detail/point_on_border.hpp | 1 + .../detail/sections/range_by_section.hpp | 1 + .../detail/sections/sectionalize.hpp | 2 + .../geometry/multi/algorithms/disjoint.hpp | 3 + .../geometry/multi/algorithms/distance.hpp | 1 + .../geometry/multi/algorithms/envelope.hpp | 2 + .../geometry/multi/algorithms/equals.hpp | 1 + .../geometry/multi/algorithms/for_each.hpp | 2 +- .../multi/algorithms/intersection.hpp | 3 + .../geometry/multi/algorithms/length.hpp | 1 + .../multi/algorithms/num_geometries.hpp | 2 + .../multi/algorithms/num_interior_rings.hpp | 1 + .../geometry/multi/algorithms/num_points.hpp | 1 + .../geometry/multi/algorithms/perimeter.hpp | 1 + .../geometry/multi/algorithms/reverse.hpp | 2 +- .../geometry/multi/algorithms/simplify.hpp | 2 +- .../geometry/multi/algorithms/transform.hpp | 1 + .../geometry/multi/algorithms/unique.hpp | 1 + .../geometry/multi/algorithms/within.hpp | 1 + .../multi/geometries/concepts/check.hpp | 12 +- include/boost/geometry/multi/io/dsv/write.hpp | 3 + include/boost/geometry/multi/io/wkt/read.hpp | 1 + include/boost/geometry/multi/io/wkt/write.hpp | 7 +- .../geometry/policies/relate/direction.hpp | 4 +- .../policies/relate/intersection_points.hpp | 8 +- .../boost/geometry/policies/relate/tupled.hpp | 4 +- .../agnostic/simplify_douglas_peucker.hpp | 8 +- .../strategies/cartesian/cart_intersect.hpp | 8 +- .../cartesian/distance_projected_point.hpp | 1 + .../boost/geometry/strategies/side_info.hpp | 10 +- .../spherical/distance_haversine.hpp | 8 +- .../strategies/strategy_transform.hpp | 44 +- .../strategies/transform/map_transformer.hpp | 10 +- .../transform/matrix_transformers.hpp | 4 +- include/boost/geometry/util/math.hpp | 41 +- include/boost/geometry/util/rational.hpp | 24 +- .../boost/geometry/views/closeable_view.hpp | 9 + .../boost/geometry/views/identity_view.hpp | 8 + test/Jamfile.v2 | 1 - test/algorithms/append.cpp | 33 +- test/algorithms/detail/partition.cpp | 2 +- .../detail/sections/sectionalize.cpp | 2 +- test/algorithms/difference.cpp | 13 + test/algorithms/disjoint.cpp | 19 + test/algorithms/intersection.cpp | 9 + test/algorithms/overlay/assemble.cpp | 2 +- test/algorithms/overlay/ccw_traverse.cpp | 2 +- test/algorithms/overlay/dissolver.cpp | 4 +- .../overlay/enrich_intersection_points.cpp | 2 +- test/algorithms/overlay/get_turn_info.cpp | 2 +- test/algorithms/overlay/get_turns.cpp | 2 +- test/algorithms/overlay/overlay_cases.hpp | 46 + test/algorithms/overlay/overlay_common.hpp | 2 +- test/algorithms/overlay/relative_order.cpp | 2 +- .../overlay/robustness/test_overlay_p_q.hpp | 2 +- .../overlay/self_intersection_points.cpp | 2 +- test/algorithms/overlay/split_rings.cpp | 2 +- test/algorithms/overlay/traverse.cpp | 35 +- test/algorithms/overlay/traverse_gmp.cpp | 2 +- test/algorithms/test_convert.hpp | 17 +- test/algorithms/test_difference.hpp | 2 +- test/algorithms/test_equals.hpp | 35 +- test/algorithms/test_intersection.hpp | 2 +- test/algorithms/test_length.hpp | 5 +- test/algorithms/test_union.hpp | 2 +- test/algorithms/union.cpp | 36 +- test/algorithms/within.cpp | 7 + test/geometries/Jamfile.v2 | 2 +- test/io/wkt/wkt.cpp | 16 +- test/multi/algorithms/multi_clear.cpp | 69 + test/multi/algorithms/multi_num_points.cpp | 16 +- .../convex_hull/random_multi_points.cpp | 2 +- .../buffer/recursive_polygons_buffer.cpp | 2 +- .../recursive_polygons_linear_areal.cpp | 2 +- 198 files changed, 9801 insertions(+), 759 deletions(-) create mode 100644 doc/generated/wkt_status.qbk create mode 100644 doc/html/img/index/rtree/disjoint.png create mode 100644 doc/html/img/index/rtree/intersects.png create mode 100644 doc/html/img/index/rtree/intersects_mpoly.png create mode 100644 doc/html/img/index/rtree/intersects_poly.png create mode 100644 doc/html/img/index/rtree/intersects_ring.png create mode 100644 doc/html/img/index/rtree/knn.png create mode 100644 doc/html/img/index/rtree/linear.png create mode 100644 doc/html/img/index/rtree/overlaps.png create mode 100644 doc/html/img/index/rtree/path.png create mode 100644 doc/html/img/index/rtree/quadratic.png create mode 100644 doc/html/img/index/rtree/rstar.png create mode 100644 doc/html/img/index/rtree/within.png create mode 100644 doc/index/Doxyfile create mode 100644 doc/index/Jamfile.v2 create mode 100644 doc/index/imports.qbk create mode 100644 doc/index/index.qbk create mode 100644 doc/index/introduction.qbk create mode 100755 doc/index/make_qbk.py create mode 100644 doc/index/rtree.qbk create mode 100644 doc/index/rtree/creation.qbk create mode 100644 doc/index/rtree/examples.qbk create mode 100644 doc/index/rtree/exception_safety.qbk create mode 100644 doc/index/rtree/experimental.qbk create mode 100644 doc/index/rtree/introduction.qbk create mode 100644 doc/index/rtree/query.qbk create mode 100644 doc/index/rtree/quickstart.qbk create mode 100644 doc/index/rtree/reference.qbk create mode 100644 doc/index/src/examples/Jamfile.v2 create mode 100644 doc/index/src/examples/rtree/Jamfile.v2 create mode 100644 doc/index/src/examples/rtree/interprocess.cpp create mode 100644 doc/index/src/examples/rtree/polygons_shared_ptr.cpp create mode 100644 doc/index/src/examples/rtree/polygons_vector.cpp create mode 100644 doc/index/src/examples/rtree/quick_start.cpp create mode 100644 doc/index/src/examples/rtree/value_index.cpp create mode 100644 doc/index/src/examples/rtree/value_shared_ptr.cpp create mode 100644 doc/index/src/examples/rtree/variants_map.cpp create mode 100644 doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/license.txt create mode 100644 doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/manual.html create mode 100644 doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml.hpp create mode 100644 doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_iterators.hpp create mode 100644 doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_print.hpp create mode 100644 doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_utils.hpp create mode 100644 include/boost/geometry/io/svg/svg_mapper.hpp create mode 100644 include/boost/geometry/io/svg/write_svg.hpp create mode 100644 include/boost/geometry/io/svg/write_svg_multi.hpp create mode 100644 test/multi/algorithms/multi_clear.cpp diff --git a/doc/concept/polygon.qbk b/doc/concept/polygon.qbk index 14f040ce8c..a2de9fd6a2 100644 --- a/doc/concept/polygon.qbk +++ b/doc/concept/polygon.qbk @@ -44,8 +44,8 @@ above). but holes are allowed in __boost_geometry__ polygons). * If the polygons underlying `ring_type` is defined as clockwise, the exterior ring must have the clockwise orientation, and any interior ring must be - counter clockwise. If the `ring_type` is defined counter clockwise, it is - vice versa. + reversed w.r.t. the defined orientation (so: counter clockwise for clockwise exterior rings). + If the `ring_type` is defined counter clockwise, it is vice versa. * If the polygons underlying `ring_type` is defined as closed, all rings must be closed: the first point must be spatially equal to the last point. * The interior is a connected point set. diff --git a/doc/doxy/Doxyfile b/doc/doxy/Doxyfile index 50a390a581..e75f5a84c2 100644 --- a/doc/doxy/Doxyfile +++ b/doc/doxy/Doxyfile @@ -39,7 +39,6 @@ TAB_SIZE = 8 # \return* for various return cases ALIASES = qbk{1}="\xmlonly \1 \endxmlonly" \ qbk{2}="\xmlonly \2 \endxmlonly" \ - qbk_skip="\xmlonly \endxmlonly" \ brief_calc{1}="Calculates the \1 of a geometry" \ brief_calc2{1}="Calculate the \1 of two geometries" \ brief_calc2{2}="Calculate the \1 \2 two geometries" \ @@ -56,7 +55,7 @@ ALIASES = qbk{1}="\xmlonly \1 \endxmlonly" \ tparam_box_or_segment="Any type fulfilling a Box Concept or a Segment Concept" \ tparam_calculation="numeric type for calculation (e.g. high precision); if [*void] then it is extracted automatically from the coordinate type and (if necessary) promoted to floating point" \ tparam_container="container type, for example std::vector, std::deque" \ - tparam_dimension_required="Dimension, this template parameter is required. Should contain \[0 .. n-1\] for an n-dimensional geometry" \ + tparam_dimension_required="Dimension, this template parameter is required. Should contain \\[0 .. n-1\\] for an n-dimensional geometry" \ tparam_first_point="first point type" \ tparam_functor="Function or class with operator()" \ tparam_output_collection="output collection, either a multi-geometry, or a std::vector / std::deque etc" \ @@ -159,7 +158,6 @@ GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = NO -SHOW_DIRECTORIES = NO FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages @@ -254,7 +252,6 @@ HTML_FILE_EXTENSION = .html HTML_HEADER = doxygen_input/ggl_doxygen_header.html HTML_FOOTER = doxygen_input/ggl_doxygen_footer.html HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Generated documentation, by Doxygen" diff --git a/doc/doxy/doxygen_input/sourcecode/doxygen_4.cpp b/doc/doxy/doxygen_input/sourcecode/doxygen_4.cpp index 203d10f5fc..b6fdecb73d 100644 --- a/doc/doxy/doxygen_input/sourcecode/doxygen_4.cpp +++ b/doc/doxy/doxygen_input/sourcecode/doxygen_4.cpp @@ -18,9 +18,9 @@ OBSOLETE #include #include -#include +#include -#include +#include static const int wkt_countries_count = 1; diff --git a/doc/doxy/doxygen_output/html/doxygen.css b/doc/doxy/doxygen_output/html/doxygen.css index 74445fe1fe..4f78a1bf00 100644 --- a/doc/doxy/doxygen_output/html/doxygen.css +++ b/doc/doxy/doxygen_output/html/doxygen.css @@ -1,13 +1,12 @@ -/* The standard CSS for doxygen */ +/* The standard CSS for doxygen 1.8.3.1-20130324 */ body, table, div, p, dl { - font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; - font-size: 12px; + font: 400 14px/19px Roboto,sans-serif; } /* @group Heading Levels */ -h1 { +h1.groupheader { font-size: 150%; } @@ -17,14 +16,34 @@ h1 { margin: 10px 2px; } -h2 { - font-size: 120%; +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; } -h3 { +h3.groupheader { font-size: 100%; } +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + dt { font-weight: bold; } @@ -72,8 +91,6 @@ div.qindex, div.navtab{ background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; - margin: 2px; - padding: 2px; } div.qindex, div.navpath { @@ -123,12 +140,12 @@ a.el { a.elRef { } -a.code { - color: #4665A2; +a.code, a.code:visited { + color: #4665A2; } -a.codeRef { - color: #4665A2; +a.codeRef, a.codeRef:visited { + color: #4665A2; } /* @end */ @@ -137,20 +154,72 @@ dl.el { margin-left: -1cm; } -.fragment { +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 4px; + margin: 4px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { font-family: monospace, fixed; - font-size: 105%; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; } -pre.fragment { - border: 1px solid #C4CFE5; - background-color: #FBFCFD; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; } div.ah { @@ -183,15 +252,15 @@ div.groupText { } body { - background: white; + background-color: white; color: black; margin: 0; } div.contents { margin-top: 10px; - margin-left: 10px; - margin-right: 5px; + margin-left: 12px; + margin-right: 8px; } td.indexkey { @@ -200,6 +269,8 @@ td.indexkey { border: 1px solid #C4CFE5; margin: 2px 0px 2px 0; padding: 2px 10px; + white-space: nowrap; + vertical-align: top; } td.indexvalue { @@ -292,6 +363,13 @@ span.vhdllogic { color: #ff0000 } +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + /* @end */ /* @@ -345,6 +423,24 @@ table.memberdecls { padding: 0px; } +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { @@ -359,8 +455,11 @@ table.memberdecls { color: #555; } -.memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #C4CFE5; +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; } .memItemLeft, .memTemplItemLeft { @@ -374,6 +473,7 @@ table.memberdecls { .memTemplParams { color: #4665A2; white-space: nowrap; + font-size: 80%; } /* @end */ @@ -406,15 +506,29 @@ table.memberdecls { padding: 0; margin-bottom: 10px; margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; } .memname { - white-space: nowrap; font-weight: bold; margin-left: 6px; } -.memproto { +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { border-top: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; @@ -422,45 +536,55 @@ table.memberdecls { color: #253555; font-weight: bold; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; /* opera specific markup */ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 8px; - border-top-left-radius: 8px; + border-top-right-radius: 4px; + border-top-left-radius: 4px; /* firefox specific markup */ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 8px; - -moz-border-radius-topleft: 8px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; /* webkit specific markup */ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 8px; - -webkit-border-top-left-radius: 8px; - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; } -.memdoc { +.memdoc, dl.reflist dd { border-bottom: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; - padding: 2px 5px; + padding: 6px 10px 2px 10px; background-color: #FBFCFD; border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; /* opera specific markup */ - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ - -moz-border-radius-bottomleft: 8px; - -moz-border-radius-bottomright: 8px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); /* webkit specific markup */ - -webkit-border-bottom-left-radius: 8px; - -webkit-border-bottom-right-radius: 8px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; } .paramkey { @@ -478,9 +602,13 @@ table.memberdecls { .paramname em { font-style: normal; } +.paramname code { + line-height: 14px; +} .params, .retval, .exception, .tparams { - border-spacing: 6px 2px; + margin-left: 0px; + padding-left: 0px; } .params .paramname, .retval .paramname { @@ -498,105 +626,116 @@ table.memberdecls { vertical-align: top; } +table.mlabels { + border-spacing: 0px; +} +td.mlabels-left { + width: 100%; + padding: 0px; +} +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} -/* @end */ - -/* @group Directory (tree) */ - -/* for the tree view */ +span.mlabels { + margin-left: 8px; +} -.ftvtree { - font-family: sans-serif; - margin: 0px; +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; } -/* these are for tree view when used as main index */ -.directory { - font-size: 9pt; - font-weight: bold; - margin: 5px; -} -.directory h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} +/* @end */ -/* -The following two styles can be used to replace the root node title -with an image of your choice. Simply uncomment the next two styles, -specify the name of your image and be sure to set 'height' to the -proper pixel height of your image. -*/ +/* these are for tree view when not used as main index */ -/* -.directory h3.swap { - height: 61px; - background-repeat: no-repeat; - background-image: url("yourimage.gif"); -} -.directory h3.swap span { - display: none; +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; } -*/ -.directory > h3 { - margin-top: 0; +.directory table { + border-collapse:collapse; } -.directory p { - margin: 0px; - white-space: nowrap; +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; } -.directory div { - display: none; - margin: 0px; +.directory td.entry { + white-space: nowrap; + padding-right: 6px; } -.directory img { - vertical-align: -30%; +.directory td.entry a { + outline:none; } -/* these are for tree view when not used as main index */ - -.directory-alt { - font-size: 100%; - font-weight: bold; +.directory td.entry a img { + border: none; } -.directory-alt h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); } -.directory-alt > h3 { - margin-top: 0; +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; } -.directory-alt p { - margin: 0px; - white-space: nowrap; +.directory img { + vertical-align: -30%; } -.directory-alt div { - display: none; - margin: 0px; +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; } -.directory-alt img { - vertical-align: -30%; +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; } -/* @end */ - div.dynheader { margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } address { @@ -606,6 +745,8 @@ address { table.doxtable { border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; } table.doxtable td, table.doxtable th { @@ -619,9 +760,72 @@ table.doxtable th { font-size: 110%; padding-bottom: 4px; padding-top: 5px; - text-align:left; } +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + .tabsearch { top: 0px; left: 10px; @@ -637,6 +841,7 @@ table.doxtable th { font-size: 11px; background-image:url('tab_b.png'); background-repeat:repeat-x; + background-position: 0 -5px; height:30px; line-height:30px; color:#8AA0CC; @@ -664,6 +869,10 @@ table.doxtable th { display:block; text-decoration: none; outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; } .navpath li.navelem a:hover @@ -702,7 +911,6 @@ div.summary a div.ingroups { font-size: 8pt; - padding-left: 5px; width: 50%; text-align: left; } @@ -731,47 +939,74 @@ dl padding: 0 0 0 10px; } -dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section { - border-left:4px solid; - padding: 0 0 0 6px; + margin-left: 0px; + padding-left: 0px; } dl.note { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #D0C000; } dl.warning, dl.attention { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #FF0000; } dl.pre, dl.post, dl.invariant { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #00D000; } dl.deprecated { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #505050; } dl.todo { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #00C0E0; } dl.test { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #3030E0; } dl.bug { + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; border-color: #C08050; } +dl.section dd { + margin-bottom: 6px; +} + + #projectlogo { text-align: center; @@ -833,3 +1068,117 @@ dl.bug font-weight: bold; } +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/doc/doxy/doxygen_output/html/doxygen.png b/doc/doxy/doxygen_output/html/doxygen.png index 635ed52fce7057ac24df92ec7664088a881fa5d0..3ff17d807fd8aa003bed8bb2a69e8f0909592fd1 100644 GIT binary patch literal 3779 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 literal 3942 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 A+yDRo diff --git a/doc/doxy/doxygen_output/html/tabs.css b/doc/doxy/doxygen_output/html/tabs.css index 21920562a8..9cf578f23a 100644 --- a/doc/doxy/doxygen_output/html/tabs.css +++ b/doc/doxy/doxygen_output/html/tabs.css @@ -3,6 +3,7 @@ width: 100%; z-index: 101; font-size: 13px; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; } .tabs2 { diff --git a/doc/generated/wkt_status.qbk b/doc/generated/wkt_status.qbk new file mode 100644 index 0000000000..e4d8d3023b --- /dev/null +++ b/doc/generated/wkt_status.qbk @@ -0,0 +1,13 @@ +[heading Supported geometries] +[table +[[Geometry][Status]] +[[Point][ [$img/ok.png] ]] +[[Segment][ [$img/ok.png] ]] +[[Box][ [$img/ok.png] ]] +[[Linestring][ [$img/ok.png] ]] +[[Ring][ [$img/ok.png] ]] +[[Polygon][ [$img/ok.png] ]] +[[MultiPoint][ [$img/ok.png] ]] +[[MultiLinestring][ [$img/ok.png] ]] +[[MultiPolygon][ [$img/ok.png] ]] +] diff --git a/doc/geometry.qbk b/doc/geometry.qbk index 8059fe03af..d0c40eb16e 100644 --- a/doc/geometry.qbk +++ b/doc/geometry.qbk @@ -12,8 +12,8 @@ [library Geometry [quickbook 1.5] - [authors [Gehrels, Barend], [Lalande, Bruno], [Loskot, Mateusz]] - [copyright 2009-2012 Barend Gehrels, Bruno Lalande, Mateusz Loskot] + [authors [Gehrels, Barend], [Lalande, Bruno], [Loskot, Mateusz], [Wulkiewicz, Adam]] + [copyright 2009-2013 Barend Gehrels, Bruno Lalande, Mateusz Loskot, Adam Wulkiewicz] [purpose Documentation of Boost.Geometry library] [license Distributed under the Boost Software License, Version 1.0. @@ -35,7 +35,8 @@ [def __geo__ Geographic] [def __rev__ Reversed polygon (coordinates not according their orientiation)] [def __empty__ Empty (e.g. polygon without points)] -[def __box__ Rectangle] +[def __box__ Box] +[def __rectangle__ Rectangle] [def __segment__ Segment] [def __point__ Point] [def __linestring__ Linestring] @@ -108,8 +109,7 @@ Boost.Geometry contains contributions by: * Akira Takahashi (adaption of Boost.Fusion) * Alfredo Correa (adaption of Boost.Array) -* Adam Wulkiewicz (spatial indexes) [footnote Currently an extension] -* Federico Fern\u00E1ndez (spatial indexes) [footnote Currently an extension] +* Federico Fern\u00E1ndez (preliminary version of R-tree spatial index) * Karsten Ahnert (patch for cross-track distance) [include imports.qbk] @@ -120,6 +120,10 @@ Boost.Geometry contains contributions by: [include design_rationale.qbk] [include compiling.qbk] +[section Spatial indexes] +[include index/index.qbk] +[endsect] + [section Indexes] [include matrix.qbk] [section Alphabetical Index] diff --git a/doc/html/img/index/rtree/disjoint.png b/doc/html/img/index/rtree/disjoint.png new file mode 100644 index 0000000000000000000000000000000000000000..131a915865d2e57778ca9c8c7223640cbd0cb2b3 GIT binary patch literal 2223 zcmYLLc|6oz7yk{J8OuC`H~U&DDO>X}L?-(-lY|VfqQXp=#$<~uA;y$K5n~3484+2M zE&GHXdqYCDvS&$_DXMvf=UqPcbM86!`_Db+d(Zven_!2wfC)$o00029vNW~l`tDtW zg1NKI>kS;&fiK%wm;#*LkyFoj$VK=GmY5p=ASkwLAb>)ZTBU4g5-$oM%eXtyVnK%zD@O;)p3>f`h zxe?p2T4^s3F!t>FP((N9=T_Z4uX0KS=a3cPwFj5$K-8$tODYHCb9L%aUAEP;sKzx8f zz>?}%2HL_;FxH+WZVJ`GI5@$lm5)(luj!M`f}>btEbQd(!|Ai|7jlRVD*H&+cGF2t z#M;rbnp80I;kB)2@Co)sdn!h;zAy{(My-g_1`5xVn|i@Glp3 zHRssT^lmph+s53W+wh@gJbOhVw;i09I&nZQhy+%Yj>1NfEj7Z@n$(?4w^tC|W{LPO z=uiiz(Wwhgmw1||Pf(fQPfvz}pJt|m9nVUzKhAqu0E>amw38CK2?(;`YKZ}&SZGt< z=VnmZGf}tHBUeb^%mhcki1M9RSjSXM3y2U$8o7`R2foPu%N(z(KM|q9>Hc+r^)g$9 zWS+LPeJ*tA`M}w@D*dX?n0}`LBDg#|Yd@c8yFLsF2l@e1UXk74KdBx+>fJiq8Btk( zW^^RNU z9-I7XNn^3jFLMm&3r+8vn)%0iJIgzV)4h&1cSaopYi06QjXbVvUY%112ns4e+fOR};k9kFUb0BkMrVD3BbI)qwckqc~ z6+a_^Ab6)8rubsHHXUqhs^a$KgOb_q$(nz7_LVwj!j7$JLJQQBR_Rk!%Q zd?3eU=g$b=SnU0jzO{La_-C6-Xv^l;0^W_-+L8q^-+~(9LHLyL!{sb}z1Xyiu155- z^Sl%6WVfCK^`H~{Udz~&Pe)0{mnqXdX189*sFujj^orlx_JeHqo99t&($fki4j9PO zGRNm=&_1oUQ!zn$hp72d#%bt^V;#DN&8b?b!j|NW+P<6K<38ATZ!fkXZO;Qw<=}Ky ziHP^HVHgVnj zy}&th*Xyp4#|37E>Z)=R-(9B6V=~xojD5UXFuM#E6&w#@VBT8xUHYaYM4(Kz_!9)F zds+g-l5xNF!WxuGkitNUqqlNiLNiXMn!j1maeT+CNh&!VJR^AcE5Pw#E38EariPL> z-8ABO!l=scF1BG98EQPge3_PNY_gY#ZQ+xqT-L^=^*MOJ@;3Bzj@Hb-M)w~GBWMqMwBVHaXJ4S5Qrs^GY{anN5GWNE zMUt4bcSVcL@3$Z;cc%f&2~cVXZy4E5Uv{mtujSGV^C&N!wI<-B3RiZ-KO9a6xNkTj5uz77Q4~A_NfK>e@wd(M;Om zYqTQU*w4S^o(EB|fhAF&7~a`2fdWX|JwZg0of!!s69x#>kLZk0p$|*&{NTKIML$0q zFr?i0bi+Z6jJd74Xt$oIba1sk9V9x}Wtc(*dqQVvBr7?zSj}yJ9E~@gOwTDw8Ypw`fn!88211G literal 0 HcmV?d00001 diff --git a/doc/html/img/index/rtree/intersects.png b/doc/html/img/index/rtree/intersects.png new file mode 100644 index 0000000000000000000000000000000000000000..066a1dd80b711b4f58f9e085f7308cb575e83c9f GIT binary patch literal 2228 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 literal 0 HcmV?d00001 diff --git a/doc/html/img/index/rtree/intersects_poly.png b/doc/html/img/index/rtree/intersects_poly.png new file mode 100644 index 0000000000000000000000000000000000000000..d87607857b8c95c8768bdc5bf5a20bed2afa7e93 GIT binary patch literal 2654 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 EKdj%%EdT%j literal 0 HcmV?d00001 diff --git a/doc/html/img/index/rtree/intersects_ring.png b/doc/html/img/index/rtree/intersects_ring.png new file mode 100644 index 0000000000000000000000000000000000000000..6af2c96a39a63357072cddd2cede05dbebfecb6e GIT binary patch literal 2641 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 literal 0 HcmV?d00001 diff --git a/doc/html/img/index/rtree/knn.png b/doc/html/img/index/rtree/knn.png new file mode 100644 index 0000000000000000000000000000000000000000..f142919d8cf5d7b3e403ed1fa5abe7eea909e436 GIT binary patch literal 2774 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 Sx(;{kr{Hh|vMaYGru-M>njE13 literal 0 HcmV?d00001 diff --git a/doc/html/img/index/rtree/path.png b/doc/html/img/index/rtree/path.png new file mode 100644 index 0000000000000000000000000000000000000000..fa393abff3d261fabfc20cbaaf5920050be4759a GIT binary patch literal 2840 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 I#+|$I4{Ep0=>Px# literal 0 HcmV?d00001 diff --git a/doc/html/img/index/rtree/rstar.png b/doc/html/img/index/rtree/rstar.png new file mode 100644 index 0000000000000000000000000000000000000000..45308b361820341eb2e19789c0054e291af2810b GIT binary patch literal 2079 zcmYjS3pCVQ7ayN7lgDU8XuNaj;aT6`V{qq_N0R)zC=x1Vm{Ayph(x0ar96u}{Y|2b z@kp)6bNW1PqR6co3NsgD%tT&!G&du@QR}Ytt+V#o=j?U%+UxB7+rORp8|a2oz$n0A zFqHct7jLQV+mtN`>8{nfOq43bSr0cC*v956VKMTh7J1Ske=-cFsJbaKFdC#OH6ml( zJzbGp#T_b0WAXv&EvZR|cYk)tH6au6g0}_fSvqcpxoEkZzp!hrA9lz$z*IMWnTsgIo5la{C!mNw`J9>6xY60Km5I7nTYQT_*5doUm zy^sSOOnXSOH0ViDZ;r+&nL&eObx^i$4j8?Y&b@GFzfV6>c(~(B#W;lx?J44nN@Fqe za*~PVH_Ys#U5nL*dd0Ok#kM( z$vAML564lvtHYYRXn)H_vhaHD{`q|$p6qx-Bpqtx`0TDtyv`r@iE6T7$Ydb&F{uPt zsSKjDdD{(tyagT=-y=3W2&m};u@>Lu4qz8nj)90 z!?|pji!2)D2*BP+4?luuAPAJmW++8mHJfa>RWdZ4@mJzd)gv$``!9I@s?h`8b_alogG4}lY6-&3}g-shN_S@Gs48D z@3xAAcMAbB{```c!%RK#mb80;fJpJYCch{hEN*}iG>brBO|D?|wJ7eY*z-I)8G70eHcU@d`eZey$ z`KeusUn&ZyWmF3qV=$CUCtNR!QE!c=cN}?fyx%}k3hb6Pc{Z@;#Ywh`mp%EDa#uRL6~!Gnl{pYh z3&$qHXFd(Q@nrliM0d#8e@y0Agse4_lxMja6S&XWp6%LS)`|&b4N!UPap90@u%i^> ze88c+2ct~n^*CBV{LX^Rb}3z`QV!H` zYx^LTTnNEaG!`Q^n#3u5o43ci9&qAWcNAu#Z+Nq^s=#N~@YQ?XyTsQ+(MM{SZRPCC zW*%{>*3sroHg)k~CVFOolxWJ9bxK3wXEev9P4&wrXOx)6(0bP%e_Xa@Hwu2Wt%)rn z(VQsXSlx-+j$~5T=aTn9!ZBW@%biDJrkxRP)L#6OL`$0uV($?E!IF@sI@M+KKP3G& zC+8nPVNU8YLyM41{fF-|bYQvVqc{FHfHBFhs=Ch&gfmi|~**8hTYvB_O=R zPyoOvL_k{(3f)@c>3m=k^oecB;h~pk;d6Lmc#0>S1fokO>!c>$-z!=5X@So>FCo zd}SzWp+ey#Uwf|8S$Rlr?=(+|d?BaP9+kVSw@-je&u5ohx{W(pz%J1m*N&ri6My`q z;zl8vR-)yB2GFyF)u{>PSEtmmC{hBrq$7*FsdE4O3&#)Pe&%G0u uq6AFK_o0ni_g}>oqMaIfk*E6L+rA+ay84AaRx$dUbK2b%bb0J_hVnn4x!;BW literal 0 HcmV?d00001 diff --git a/doc/html/img/index/rtree/within.png b/doc/html/img/index/rtree/within.png new file mode 100644 index 0000000000000000000000000000000000000000..44ab19e48dac0ec7431b9d30ffd12c63189303c7 GIT binary patch literal 2208 zcmX|Dc{tSDA0EsdW0{65F|wAWy7n(KmdQ?*nS|~|NcJf^S)xnUL}Zu7kY!Y|WFBkA za>+6`M!qIX7#^V_B+JeE8+D)GbDq!nJm>x6ob$Y&&-EmZ!U8!%&2c82Q#_*l zoE#XFD>N1)PO!5NH45K&yXr5+D z>~+}8V0wLK{rkTzr(Q@bUQ*6H(Ys2-`I_|JQZ za7t0{z{UM;yJ>s!mj#rZyDEalBe$gyb)OJ>7X5j}9$LwEA0~y0^?{VKg&E(TprBsZ zt7aDg$R9rDD$i@XXyv|6q}>U4ZE$gK$}m3BcEb3y5%G4}lLFXumfFBj%R8J2q*Z>0 zmIy+KuoeZzr$eE!w;kvt`?JD}z`t4%I$9fX!9p zFw8L=RjU8>K7n=k|8JoWK;A)&IRFFn)gk6GW0BO~9Zf!;U0W;=FgzUeDPsm2a%w0| zAaeYYiZsB;DXaPpG_`769r>_cul=LyPD{QE-3{eR$H&t?mn)+x4I)p*?RUozVV8u5 zCaG{%O|!sJHKUv_+Uy=7g-`2W{qQ{lz9QHy0o|$z5!F7Y(Ax(lZi_Lko8!GSXIMnd;V;ot7l$-acE95y4ZcUH#p4gzeE} z-;*S+SWxinnD$}BVYc+SKRD2`2~S@0@m5Y8oK%zT*W;Si!gc42D{JrX4DuIinZJ0Q z*0zdT^q#9Jo(s?jSt?xwL?au~b{|!yrgW495;Wv_#y&)f;weu9A9$7Jy`8EUY6uN> zNdj3^@gaV4)_f+a(age=A~(~NKdFhQ$XgUK=eXIDd zB2}GXAJ{9q#Nt|b`uuo^Fuh2|j0F>eXKm;j*=XjKQ#XZ%>E-7>1(r*{ znV{(@AfO`Uzo2NjO!2>WXeXmD>0A0asp9J2&zmkdoyhaf^M06J#g6fuSGy%P4J!b9 zioq2t43$~aNr0&061St%cO>4%xds+OyL3x)pvKvqD!iv*#vFE{AW%#{Y7P7xWWH#s z;t^i>Lg|@vCk2}_m0ahvPb0Jn;8#ATIyot>KN57%j^wRgvNd&cQbly>4$3HDyCQwD zwQ5-=SNVteL-ONlSGkM!{zCINwW1zBU}z!gOl2TasGoFMbJcq{m)YlnQkmXwUU1uM zA-v$6#9uN{Mbw>G6Ru7dF7L%m(jI`ZuB5>9pnKryj5(XRc+{S?biz&l&0u(SyZ3=T z;~=D8@>CCy>mP>WlDn<>JV@ABUKQuJBr}xqu&s%-FeaFG=(ncc#BOK>vh6le&1eZ~ zjcoziQC_aPlDwpU)aI1GkyiO`Rq2J!jRPoAvp!d|+rNh0Sq< zVB6zhxt#@;oL?$>P48myh;a0*zWa3awT>3zh38k{x+uB}UVAVIF8xv^9t%si>0RUT zX3!osGrbQ~&lPBpI>h}pg~6O5TH6;{UY7c)m_f%tk-)-HscrLNW{4;ZgA1F(H2-#7 zeO5aKzX3A5>9%nZu1)ytU^&A=5#k~OEiE!in;(DMB6AWfiR$`DnvEGexE$TrPWww? z%lUF5dkC@API3Mjn5J>B{mRWH7mzpZxrSgtXd$>@@pxLrWhh@9DZy73aJHh>P&S_>^7hjiNs$Jk|UBIxwa$gNl;t25@o7#68KX0T5f;+ z=FHW~o~3KS*Lf=)CT4_+46Ovn;dz!i25W}V`_WNVSV2%w_}1l=SVg_-xQ6>UoxyqD z{K>)gPgaqW%$_Bu90%?TW59f}0l~-C5hn5Gq=n zP-Y^A}exX5x3n`98`Kyiu4`%Uo`a%WCDc?Bu7 zg-_Cw>z~#^WNvo2^;41ZWP|T7sl^Ip1N7exxAZc98HKe_Kp$W$3ZHm}7~6`X;&yNK zW5W;+uK#&gFMXn7I`LvKH|uriw`^N|T@r?A$Db(QUuij!9F13Bl!F>!u6^48`$W_4 zwy+wA;a>Owwa!3&V=TYnC8(d8bQ>i|pi^z$$5Xd;B^GORWlblYR(r>mTf4XJ-2Po4 bBL0YNVrQ%>i;sEl_@iKMf;X-)bdCETL3RTx literal 0 HcmV?d00001 diff --git a/doc/html/index.html b/doc/html/index.html index b5ad714c8e..e73e9fd8b0 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -31,8 +31,10 @@

    Mateusz Loskot

    -
    +

    +Adam Wulkiewicz +

    +

    Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -47,6 +49,8 @@

    Quick Start
    Design Rationale
    Compilation
    +
    Spatial indexes
    +
    R-tree
    Indexes
    Reference matrix
    @@ -66,6 +70,7 @@
    Exceptions
    Iterators
    Models
    +
    Spatial indexes
    Strategies
    Views
    @@ -89,27 +94,15 @@

    Alfredo Correa (adaption of Boost.Array)
  • - Adam Wulkiewicz (spatial indexes) [1] -
  • -
  • - Federico Fernández (spatial indexes) [2] + Federico Fernández (preliminary version of R-tree spatial index)
  • Karsten Ahnert (patch for cross-track distance)
  • -
    -

    -

    [1] - Currently an extension -

    -

    [2] - Currently an extension -

    -
    - +

    Last revised: August 21, 2012 at 16:43:26 GMT

    Last revised: May 12, 2013 at 10:55:03 GMT


    diff --git a/doc/index/Doxyfile b/doc/index/Doxyfile new file mode 100644 index 0000000000..597de34d0f --- /dev/null +++ b/doc/index/Doxyfile @@ -0,0 +1,332 @@ +# Doxyfile 1.8.1.2 +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "Boost.Geometry.Index" +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +BUILTIN_STL_SUPPORT = YES +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +LOOKUP_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../../../../boost/geometry/index/ \ + ../../../../boost/geometry/index/adaptors +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html_by_doxygen +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = YES +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = "BOOST_RV_REF(T)=T &&" \ + "BOOST_COPY_ASSIGN_REF(T)=T const &" +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/doc/index/Jamfile.v2 b/doc/index/Jamfile.v2 new file mode 100644 index 0000000000..e6f507006e --- /dev/null +++ b/doc/index/Jamfile.v2 @@ -0,0 +1,32 @@ +# Boost.Geometry Index +# +# Copyright (c) 2011-2012 Adam Wulkiewicz. +# +# 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) + +project geometry_index/doc ; + +import boostbook ; +import quickbook ; + +boostbook geometry_index-doc + : + index.qbk + : + Jamfile.v2 + generated/rtree.qbk + + html + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + chunk.section.depth=2 + chunk.first.sections=1 + toc.section.depth=3 + toc.max.depth=2 + generate.section.toc.level=2 + boost.root=http://www.boost.org/doc/libs/release + + enable_index + $(here) + ; diff --git a/doc/index/imports.qbk b/doc/index/imports.qbk new file mode 100644 index 0000000000..5d81a76398 --- /dev/null +++ b/doc/index/imports.qbk @@ -0,0 +1,17 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[import src/examples/rtree/quick_start.cpp] +[import src/examples/rtree/polygons_vector.cpp] +[import src/examples/rtree/polygons_shared_ptr.cpp] +[import src/examples/rtree/variants_map.cpp] +[import src/examples/rtree/value_shared_ptr.cpp] +[import src/examples/rtree/value_index.cpp] +[import src/examples/rtree/interprocess.cpp] diff --git a/doc/index/index.qbk b/doc/index/index.qbk new file mode 100644 index 0000000000..5766162af4 --- /dev/null +++ b/doc/index/index.qbk @@ -0,0 +1,38 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[/library Geometry Index + [quickbook 1.5] + [authors [Wulkiewicz, Adam]] + [copyright 2011-2013 Adam Wulkiewicz] + [purpose Documentation of Boost.Geometry Index library] + [license + Distributed under 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]) + ] + [id geometry] + [category geometry] +/] + +[def __boost_geometry_index__ Boost.Geometry.Index] + +[def __rtree__ R-tree] + +[def __value__ Value] +[def __parameters__ Parameters] +[def __allocator__ Allocator] +[def __indexable__ Indexable] + +[include imports.qbk] + +[/include introduction.qbk/] + +[include rtree.qbk] diff --git a/doc/index/introduction.qbk b/doc/index/introduction.qbk new file mode 100644 index 0000000000..0c7e0b7a84 --- /dev/null +++ b/doc/index/introduction.qbk @@ -0,0 +1,19 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section Introduction] + +The __boost_geometry_index__ is intetended to gather containers (spatial indexes) which may be used to accelerate spatial searching. +It is a part of the __boost_geometry__ library. In general, spatial indexes stores geometric objects' representations and +allows searching for objects occupying some space or close to some point in space. + +Currently, only one spatial index is implemented - __rtree__. + +[endsect] diff --git a/doc/index/make_qbk.py b/doc/index/make_qbk.py new file mode 100755 index 0000000000..9185f3f107 --- /dev/null +++ b/doc/index/make_qbk.py @@ -0,0 +1,39 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# =========================================================================== +# Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +# +# 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)9 +# ============================================================================ + +import os, sys + +cmd = "doxygen_xml2qbk" +cmd = cmd + " --xml xml/%s.xml" +cmd = cmd + " --start_include boost/" +cmd = cmd + " --output_style alt" +cmd = cmd + " > generated/%s.qbk" + +os.system("doxygen Doxyfile") +os.system(cmd % ("classboost_1_1geometry_1_1index_1_1rtree", "rtree")) +os.system(cmd % ("group__rtree__functions", "rtree_functions")) + +os.system(cmd % ("structboost_1_1geometry_1_1index_1_1linear", "rtree_linear")) +os.system(cmd % ("structboost_1_1geometry_1_1index_1_1quadratic", "rtree_quadratic")) +os.system(cmd % ("structboost_1_1geometry_1_1index_1_1rstar", "rtree_rstar")) +os.system(cmd % ("classboost_1_1geometry_1_1index_1_1dynamic__linear", "rtree_dynamic_linear")) +os.system(cmd % ("classboost_1_1geometry_1_1index_1_1dynamic__quadratic", "rtree_dynamic_quadratic")) +os.system(cmd % ("classboost_1_1geometry_1_1index_1_1dynamic__rstar", "rtree_dynamic_rstar")) + +os.system(cmd % ("structboost_1_1geometry_1_1index_1_1indexable", "indexable")) +os.system(cmd % ("structboost_1_1geometry_1_1index_1_1equal__to", "equal_to")) + +os.system(cmd % ("group__predicates", "predicates")) +#os.system(cmd % ("group__nearest__relations", "nearest_relations")) +os.system(cmd % ("group__adaptors", "adaptors")) +os.system(cmd % ("group__inserters", "inserters")) + +#os.system("b2") diff --git a/doc/index/rtree.qbk b/doc/index/rtree.qbk new file mode 100644 index 0000000000..46063c8f57 --- /dev/null +++ b/doc/index/rtree.qbk @@ -0,0 +1,21 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section R-tree] + +[include rtree/introduction.qbk] +[include rtree/quickstart.qbk] +[include rtree/creation.qbk] +[include rtree/query.qbk] +[include rtree/examples.qbk] +[include rtree/experimental.qbk] +[/include rtree/reference.qbk] + +[endsect] diff --git a/doc/index/rtree/creation.qbk b/doc/index/rtree/creation.qbk new file mode 100644 index 0000000000..04aa9734b8 --- /dev/null +++ b/doc/index/rtree/creation.qbk @@ -0,0 +1,231 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section Creation and modification] + +[section Template parameters] + +__rtree__ has 5 parameters: + + rtree, + EqualTo = index::equal_to, + Allocator = std::allocator > + +* `__value__` - type of object which will be stored in the container, +* `Parameters` - parameters type, inserting/splitting algorithm, +* `IndexableGetter` - function object translating `__value__` to `__indexable__` (`__point__` or `__box__`) which __rtree__ can handle, +* `EqualTo` - function object comparing `__value__`s, +* `Allocator` - `Value`s allocator, all allocators needed by the container are created from it. + +[endsect] + +[section Values and Indexables] + +__rtree__ may store `__value__`s of any type as long as passed function objects know how to interpret those `__value__`s, that is +extract an `__indexable__` that the __rtree__ can handle and compare `__value__`s. + +By default function objects `index::indexable` and `index::equal_to` are defined for some typically used `__value__` +types which may be stored without defining any additional classes. By default the rtree may store pure `__indexable__`s, pairs +and tuples. In the case of those two collection types, the `__indexable__` must be the first stored type. + +* `__indexable__ = __point__ | __box__` +* `__value__ = Indexable | std::pair<__indexable__, T> | tuple<__indexable__, ...>` + +By default `boost::tuple<...>` is supported on all compilers. If the compiler supports C++11 tuples and variadic templates +then `std::tuple<...>` may be used "out of the box" as well. + +Examples of default `__value__` types: + + geometry::model::point<...> + geometry::model::point_xy<...> + geometry::model::box<...> + std::pair, unsigned> + boost::tuple, int, float> + +The predefined `index::indexable` returns const reference to the `__indexable__` stored in the `__value__`. + +[important The translation is done quite frequently inside the continer - each time the rtree needs it. ] + +The predefined `index::equal_to`: + +* for `__point__` and `__box__` - compares `__value__`s with geometry::equals(). +* for `std::pair<...>` - compares both components of the `__value__`. The first value stored in the pair is compared before the second one. + If the value stored in the pair is a Geometry, `geometry::equals()` is used. For other types it uses `operator==()`. +* for `tuple<...>` - compares all components of the `__value__`. If the component is a `Geometry`, `geometry::equals()` + function is used. For other types it uses `operator==()`. + +[endsect] + +[section Balancing algorithms] + +[heading Compile-time] + +`__value__`s may be inserted to the __rtree__ in many various ways. Final internal structure +of the __rtree__ depends on algorithms used in the insertion process and parameters. The most important is +nodes' balancing algorithm. Currently, three well-known types of R-trees may be created. + +Linear - classic __rtree__ using balancing algorithm of linear complexity + + index::rtree< __value__, index::linear<16> > rt; + +Quadratic - classic __rtree__ using balancing algorithm of quadratic complexity + + index::rtree< __value__, index::quadratic<16> > rt; + +R*-tree - balancing algorithm minimizing nodes' overlap with forced reinsertions + + index::rtree< __value__, index::rstar<16> > rt; + +[heading Run-time] + +Balancing algorithm parameters may be passed to the __rtree__ in run-time. +To use run-time versions of the __rtree__ one may pass parameters which +names start with `dynamic_`. + + // linear + index::rtree<__value__, index::dynamic_linear> rt(index::dynamic_linear(16)); + + // quadratic + index::rtree<__value__, index::dynamic_quadratic> rt(index::dynamic_quadratic(16)); + + // rstar + index::rtree<__value__, index::dynamic_rstar> rt(index::dynamic_rstar(16)); + +The obvious drawback is a slightly slower __rtree__. + +[heading Non-default parameters] + +Non-default R-tree parameters are described in the reference. + +[endsect] + +[section Copying, moving and swapping] + +The __rtree__ is copyable and movable container. Move semantics is implemented using Boost.Move library +so it's possible to move the container on a compilers without rvalue references support. + + // default constructor + index::rtree< __value__, index::rstar<8> > rt1; + + // copy constructor + index::rtree< __value__, index::rstar<8> > rt2(r1); + + // copy assignment + rt2 = r1; + + // move constructor + index::rtree< __value__, index::rstar<8> > rt3(boost::move(rt1)); + + // move assignment + rt3 = boost::move(rt2); + + // swap + rt3.swap(rt2); + +[endsect] + +[section Inserting and removing Values] + +The following code creates an __rtree__ using quadratic balancing algorithm. + + using namespace boost::geometry; + typedef std::pair __value__; + index::rtree< __value__, index::quadratic<16> > rt; + +To insert or remove a `__value__' by method call one may use the following +code. + + __value__ v = std::make_pair(__box__(...), 0); + + rt.insert(v); + + rt.remove(v); + +To insert or remove a `__value__' by function call one may use the following +code. + + __value__ v = std::make_pair(__box__(...), 0); + + index::insert(rt, v); + + index::remove(rt, v); + +Typically you will perform those operations in a loop in order to e.g. insert +some number of `__value__`s corresponding to geometrical objects (e.g. `Polygons`) +stored in another container. + +[heading Additional interface] + +The __rtree__ allows creation, inserting and removing of Values from a range. The range may be passed as +[first, last) Iterators pair or as a Range. + + namespace bgi = boost::geometry::index; + typedef std::pair __value__; + typedef bgi::rtree< __value__, bgi::linear<32> > RTree; + + std::vector<__value__> values; + /* vector filling code, here */ + + // create R-tree with default constructor and insert values with insert(Value const&) + RTree rt1; + BOOST_FOREACH(__value__ const& v, values) + rt1.insert(v); + + // create R-tree with default constructor and insert values with insert(Iter, Iter) + RTree rt2; + rt2.insert(values.begin(), values.end()); + + // create R-tree with default constructor and insert values with insert(Range) + RTree rt3; + rt3.insert(values); + + // create R-tree with constructor taking Iterators + RTree rt4(values.begin(), values.end()); + + // create R-tree with constructor taking Range + RTree rt5(values); + + // remove values with remove(Value const&) + BOOST_FOREACH(__value__ const& v, values) + rt1.remove(v); + + // remove values with remove(Iter, Iter) + rt2.remove(values.begin(), values.end()); + + // remove values with remove(Range) + rt3.remove(values); + +[heading Insert iterator] + +There are functions like `std::copy()`, or __rtree__'s queries that copy values to an output iterator. +In order to insert values to a container in this kind of function insert iterators may be used. +Geometry.Index provide its own `bgi::insert_iterator` which is generated by +`bgi::inserter()` function. + + namespace bgi = boost::geometry::index; + typedef std::pair __value__; + typedef bgi::rtree< __value__, bgi::linear<32> > RTree; + + std::vector<__value__> values; + /* vector filling code, here */ + + // create R-tree and insert values from the vector + RTree rt1; + std::copy(values.begin(), values.end(), bgi::inserter(rt1)); + + // create R-tree and insert values returned by a query + RTree rt2; + rt1.spatial_query(Box(/*...*/), bgi::inserter(rt2)); + +[endsect] + +[endsect] [/ Creation and modification /] diff --git a/doc/index/rtree/examples.qbk b/doc/index/rtree/examples.qbk new file mode 100644 index 0000000000..8b57bde7ee --- /dev/null +++ b/doc/index/rtree/examples.qbk @@ -0,0 +1,41 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2013 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section:rtree_examples Examples] + +[section Quick start] +[rtree_quickstart] +[endsect] + +[section Index of polygons stored in vector] +[rtree_polygons_vector] +[endsect] + +[section Index of shared pointers to polygons] +[rtree_polygons_shared_ptr] +[endsect] + +[section Index of iterators of a map storing variant geometries] +[rtree_variants_map] +[endsect] + +[section Specializing index::indexable function object - storing shared pointers in the rtree] +[rtree_value_shared_ptr] +[endsect] + +[section Using IndexableGetter function object - storing indexes of external container's elements] +[rtree_value_index] +[endsect] + +[section Index stored in shared memory using Boost.Interprocess] +[rtree_interprocess] +[endsect] + +[endsect] diff --git a/doc/index/rtree/exception_safety.qbk b/doc/index/rtree/exception_safety.qbk new file mode 100644 index 0000000000..8f1dbb6afc --- /dev/null +++ b/doc/index/rtree/exception_safety.qbk @@ -0,0 +1,57 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section Exception safety] + +In order to be exception-safe the __rtree__ requires: + +* exception-safe copy constructor and copy assignment of the `__value__`. +* exception-safe copy constructor and copy assignment of the `CoordinateType` used in the `Indexable`. +* nonthrowing copy constructor of the `Translator`. +* nonthrowing destructors of above types. + +[table +[[Operation] [exception-safety]] +[[`rtree()`] [ /nothrow/ ]] +[[`rtree(Iterator, Iterator)`] [ *strong* ]] +[[`~rtree()`] [ /nothrow/ ]] +[[][]] +[[`rtree(rtree const&)`] [ *strong* ]] +[[`operator=(rtree const&)`] [ *strong* ]] +[[][]] +[[`rtree(rtree &&)`] [ /nothrow/ ]] +[[`operator=(rtree &&)`] [ /nothrow/ or *strong* +[footnote /nothrow/ - if allocators are equal, *strong* - otherwise]]] +[[`swap(rtree &)`] [ /nothrow/ ]] +[[][]] +[[`insert(__value__)`] [ not safe +[footnote If this operation throws, the R-tree may be left in an inconsistent state, elements must not be inserted or removed, methods may return invalid data.]]] +[[`insert(Iterator, Iterator)`][ not safe ]] +[[`insert(Range)`] [ not safe ]] +[[`remove(__value__)`] [ not safe ]] +[[`remove(Iterator, Iterator)`][ not safe ]] +[[`remove(Range)`] [ not safe ]] +[[`clear()`] [ /nothrow/ ]] +[[][]] +[[`spatial_query(...)`] [ *strong* ]] +[[`nearest_query(...)`] [ *strong* ]] +[[`count(ValueOrIndexable)`] [ /nothrow/ ]] +[[][]] +[[`size()`] [ /nothrow/ ]] +[[`empty()`] [ /nothrow/ ]] +[[`box()`] [ /nothrow/ or *strong* +[footnote /nothrow/ - if `CoordinateType` has nonthrowing copy constructor, *strong* - otherwise]]] +[[][]] +[[`get_allocator()`] [ /nothrow/ ]] +[[`parameters()`] [ /nothrow/ ]] +[[`translator()`] [ /nothrow/ ]] +] + +[endsect] [/Exception safety/] diff --git a/doc/index/rtree/experimental.qbk b/doc/index/rtree/experimental.qbk new file mode 100644 index 0000000000..71aae4f288 --- /dev/null +++ b/doc/index/rtree/experimental.qbk @@ -0,0 +1,110 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2013 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section Experimental features] + +This section describes experimental features which are implemented but unavailable by default. +Be aware that they may not be released in the future or functionalities may be released but +behind different interface. + +To enable them one must define `BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL` in compiler's command line or before +including spatial index. + +[heading Nearest query distance calculation] + +It is possible to define how distance to the non-point `__value__` should be calculated. To do this one may pass +a relation object instead of a Point to the nearest predicate, as follows: + + /* caluclate distance to the Indexables' nearest points */ + rtree.query(index::nearest(index::to_nearest(pt), k), std::back_inserter(returned_values)); // same as default + + /* caluclate distance to the Indexables' centroid */ + rtree.query(index::nearest(index::to_centroid(pt), k), std::back_inserter(returned_values)); + + /* caluclate distance to the Indexables' furthest points */ + rtree.query(index::nearest(index::to_furthest(pt), k), std::back_inserter(returned_values)); + +[heading Path query] + +Path query returns `k` first `__value__`s intersecting a path defined by a `Linestring`. The result of a query returning first 5 +values intersecting a path is presented below. Path's flow is denoted by blue arrows, returned values are orange. + +[$img/index/rtree/path.png] + +To perform this query one may pass a `path()` predicate taking a `Linestring` and maximum number of `__value__`s which +should be returned: + + rtree.query(index::path(linestring, k), std::back_inserter(returned_values)); + +[warning Only one distance predicate may be used in a query. This means that there can be only one `nearest()` or `path()` predicate passed. Passing more of them will result in compile-time error.] + +[heading Incremental queries] + +Sometimes there is a need to stop querying at some desired moment because for example the decision that query should find another value +is made after analysis of previously returned values. There can also be desirable to pause querying and resume it later. + +Currently, those kind of incremental queries are implemented as input (single pass) const iterators, relatively +big fat-iterators storing stack used in the tree-traversing process. Because the type of predicates passed +to the query varies, the type of the iterator varies as well. + +Therefore to use query iterators one must pass them to some function template, then types will be deduced +automatically. If iterators objects must be stored one may use Boost.Typeof library to retrieve a type from +an expression or use C++11 `auto` or `decltype`. + + /* function call */ + std::copy(rtree.qbegin(index::intersects(box)), rtree.qend(index::intersects(box)), std::back_inserter(returned_values)); + + /* Boost.Typeof */ + typedef BOOST_TYPEOF(rtree.qbegin(index::nearest(pt, 5))) const_query_iterator; + const_query_iterator first = rtree.qbegin(index::nearest(pt, 5)); + const_query_iterator last = rtree.qend(index::nearest(pt, 5)); + // ... + for ( ; first != last ; ++first ) + *first; // do domething with Value + + /* C++11 */ + auto first = rtree.qbegin(index::nearest(pt, 5)); + auto last = rtree.qend(index::nearest(pt, 5)); + // ... + for ( ; first != last ; ++first ) + *first; // do domething with Value + +`qend()` method is overloaded to return a different, lighter type of iterator which may be compared +with query iterator to check if the querying was finished. But since it has different type than the one returned by +`qbegin(Pred)` it can't be used with STL-like functions like `std::copy()` which expect that `first` and `last` +iterators have the same type. + + /* function call */ + template + void my_copy(First first, Last last, Out out) + { + for ( ; first != last ; ++out, ++first ) + *out = *first; + } + // ... + my_copy(rtree.qbegin(index::intersects(box)), rtree.qend(), std::back_inserter(returned_values)); + + /* Boost.Typeof */ + typedef BOOST_TYPEOF(rtree.qbegin(index::nearest(pt, 5))) const_query_iterator; + typedef BOOST_TYPEOF(rtree.qend()) end_iterator; + const_query_iterator first = rtree.qbegin(index::nearest(pt, 5)); + end_iterator last = rtree.qend(); + // ... + for ( ; first != last ; ++first ) + *first; // do domething with Value + + /* C++11 */ + auto first = rtree.qbegin(index::nearest(pt, 5)); + auto last = rtree.qend(); + // ... + for ( ; first != last ; ++first ) + *first; // do domething with Value + +[endsect] [/ Experimental features /] diff --git a/doc/index/rtree/introduction.qbk b/doc/index/rtree/introduction.qbk new file mode 100644 index 0000000000..9d25d47a99 --- /dev/null +++ b/doc/index/rtree/introduction.qbk @@ -0,0 +1,68 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section Introduction] + +__rtree__ is a tree data structure used for spatial searching. It was proposed by +Antonin Guttman in 1984 [footnote Guttman, A. (1984). /R-Trees: A Dynamic Index Structure for Spatial Searching/] +as an expansion of B-tree for multi-dimensional data. It may be used to store points or volumetric data in order to +perform a spatial query later. This query may return objects that are inside some area or are close to some point in space +[footnote Cheung, K.; Fu, A. (1998). /Enhanced Nearest Neighbour Search on the R-tree/]. + +The __rtree__ structure is presented on the image below. Each __rtree__'s node store a box descring the space occupied by +its children nodes. At the bottom of the structure, there are leaf-nodes which contains values +(geometric objects representations). + +[$img/index/rtree/rstar.png] + +The __rtree__ is a self-balanced data structure. The key part of balancing algorithm is node splitting algorithm +[footnote Greene, D. (1989). /An implementation and performance analysis of spatial data access methods/] +[footnote Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). /The R*-tree: an efficient and robust access method for points and rectangles/]. +Each algorithm produces different splits so the internal structure of a tree may be different for each one of them. +In general more complex algorithms analyses elements better and produces less overlapping nodes. In the searching process less nodes must be traversed +in order to find desired obejcts. On the other hand more complex analysis takes more time. In general faster inserting will result in slower searching +and vice versa. The performance of the R-tree depends on balancing algorithm, parameters and data inserted into the container. +Example structures of trees created by use of three different algorithms and operations time are presented below. Data used in benchmark was random, +non-overlapping boxes. + +[table +[[] [linear algorithm] [quadratic algorithm] [R*-tree]] +[[*Example structure*] [[$img/index/rtree/linear.png]] [[$img/index/rtree/quadratic.png]] [[$img/index/rtree/rstar.png]]] +[[*1M Values inserts*] [1.65s] [2.51s] [4.96s]] +[[*100k spatial queries*] [0.87s] [0.25s] [0.09s]] +[[*100k knn queries*] [3.25s] [1.41s] [0.51s]] +] + +[heading Implementation details] + +Key features of this implementation of the __rtree__ are: + +* capable to store arbitrary __value__ type, +* three different creation algorithms - linear, quadratic or rstar, +* parameters (including maximal and minimal number of elements) may be passed as compile- or run-time parameters, +* advanced queries - e.g. search for 5 nearest values to some point and intersecting some region but not within the other one, +* C++11 conformant: move semantics, stateful allocators, +* capable to store __value__ type with no default constructor. + +[heading Dependencies] + +R-tree depends on *Boost.Move*, *Boost.Container*, *Boost.Tuple*, *Boost.Utility*, *Boost.MPL*. + +[heading Contributors] + +The spatial index was originally started by Federico J. Fernandez during the Google Summer of Code 2008 program, mentored by Hartmut Kaiser. + +[heading Spatial thanks] + +I'd like to thank Barend Gehrels, Bruno Lalande, Mateusz Łoskot, Lucanus J. Simonson for their support and ideas. + +[endsect] + + diff --git a/doc/index/rtree/query.qbk b/doc/index/rtree/query.qbk new file mode 100644 index 0000000000..328dc64377 --- /dev/null +++ b/doc/index/rtree/query.qbk @@ -0,0 +1,219 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2013 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section Queries] + +Queries returns `__value__`s which meets some predicates. Currently supported are three types of predicates: + +* spatial predicates - spatial conditions that must be met by stored Value and some Geometry, +* distance predicates - distance conditions that must be met by stored Value and some Geometry, +* user-defined unary predicate - function, function object or lambda expression checking user-defined condition. + +For example queries may be used to retrieve Values: + +* intersecting some area but not within other area, +* are nearest to some point, +* overlapping a box and has user-defined property. + +[section Performing a query] + +There are three ways to perform a query presented below. All of them returns `__value__`s intersecting some +region defined as a `__box__`. + +Method call + + std::vector<__value__> returned_values; + __box__ box_region(...); + rt.query(bgi::intersects(box_region), std::back_inserter(returned_values)); + +Function call + + std::vector<__value__> returned_values; + __box__ box_region(...); + index::query(rt, bgi::intersects(box_region), std::back_inserter(returned_values)); + +Use of pipe operator generating a range + + __box__ box_region(...); + BOOST_FOREACH(__value__ & v, rt | index::adaptors::queried(bgi::intersects(box_region))) + ; // do something with v + +[endsect] + +[section Spatial predicates] + +Queries using spatial predicates returns `__value__`s which are related somehow to some Geometry - box, polygon, etc. +Names of spatial predicates correspond to names of __boost_geometry__ algorithms. Examples of some +basic queries may be found in tables below. The query region and result `Value`s are orange. + +[table +[[intersects(Box)] [covered_by(Box)] [disjoint(Box)] [overlaps(Box)] [within(Box)]] +[[[$img/index/rtree/intersects.png]] [[$img/index/rtree/within.png]] [[$img/index/rtree/disjoint.png]] [[$img/index/rtree/overlaps.png]] [[$img/index/rtree/within.png]]] +] + +[table +[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)]] +[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]]] +] + +To use a spatial predicate one may use one of the functions defined in `boost::geometry::index` namespace. + + rt.query(index::intersects(box), std::back_inserter(result)); + rt.query(index::covered_by(box), std::back_inserter(result)); + rt.query(index::disjont(box), std::back_inserter(result)); + rt.query(index::overlaps(box), std::back_inserter(result)); + rt.query(index::within(box), std::back_inserter(result)); + +All spatial predicates may be negated, e.g.: + + rt.query(!index::intersects(box), std::back_inserter(result)); + // the same as + rt.query(index::disjoint(box), std::back_inserter(result)); + +[endsect] + +[section Distance predicates] + +[heading Nearest neighbours queries] + +Nearest neighbours queries returns `__value__`s which are closest to some point in space. +Additionally it is possible to define how the distance to the `Value` should be calculated. +The example of knn query is presented below. 5 `__value__`s nearest to some point are orange. + +[$img/index/rtree/knn.png] + +[heading k nearest neighbours] + +There are three ways of performing knn queries. Following queries returns +`k` `__value__`s closest to some point in space. For `__box__`es +`__indexable__`s the distance to the nearest point is calculated by default. + +Method call + + std::vector<__value__> returned_values; + __point__ pt(...); + rt.query(index::nearest(pt, k), std::back_inserter(returned_values)); + +Function call + + std::vector<__value__> returned_values; + __point__ pt(...); + index::query(rt, index::nearest(pt, k), std::back_inserter(returned_values)); + +Use of `operator |` + + __point__ pt(...); + BOOST_FOREACH(__value__ & v, rt | index::adaptors::queried(index::nearest(pt, k))) + ; // do something with v + +[endsect] + +[section User-defined unary predicate] + +The user may pass a `UnaryPredicate` - function, function object or lambda expression taking const reference to Value and returning bool. +This object may be passed to the query in order to check if `__value__` should be returned by the query. To do it one +may use `index::satisfies()` function like on the example below: + + bool is_red(__value__ const& v) + { + return v.is_red(); + } + + struct is_red_o + { + template + bool operator()(__value__ const& v) + { + return v.is_red(); + } + } + + // ... + + rt.query(index::intersects(box) && index::satisfies(is_red), + std::back_inserter(result)); + + rt.query(index::intersects(box) && index::satisfies(is_red_o()), + std::back_inserter(result)); + + #ifndef BOOST_NO_CXX11_LAMBDAS + rt.query(index::intersects(box) && index::satisfies([](__value__ const& v) { return v.is_red(); }), + std::back_inserter(result)); + #endif + +`satisfies()` may be negated, e.g.: + + bool is_red(__value__ const& v) { return v.is_red(); } + bool is_not_red(__value__ const& v) { return !v.is_red(); } + + // ... + + rt.query(index::intersects(box) && index::satisfies(is_red), + std::back_inserter(result)); + // the same as + rt.query(index::intersects(box) && !index::satisfies(is_not_red), + std::back_inserter(result)); + +[endsect] + +[section Passing a set of predicates] + +It's possible to use some number of predicates in one query by connecting them with `operator&&` e.g. `Pred1 && Pred2 && Pred3 && ...`. + +These predicates are connected by logical AND. Passing all predicates together not only makes possible +to construct advanced queries but is also faster than separate calls because the tree is traversed only once. +Traversing is continued and `Value`s are returned only if all predicates are met. Predicates are checked +left-to-right so placing most restictive predicates first should accelerate the search. + + rt.query(index::intersects(box1) && !index::within(box2), + std::back_inserter(result)); + + rt.query(index::intersects(box1) && !index::within(box2) && index::overlaps(box3), + std::back_inserter(result)); + +Of course it's possible to connect different types of predicates together. + + index::query(rt, index::nearest(pt, k) && index::within(b), std::back_inserter(returned_values)); + + BOOST_FOREACH(Value & v, rt | index::adaptors::queried(index::nearest(pt, k) && index::covered_by(b))) + ; // do something with v + +[endsect] + +[section Inserting query results into the other R-tree] + +There are several ways of inserting Values returned by a query to the other R-tree container. +The most basic way is creating a temporary container for Values and insert them later. + + namespace bgi = boost::geometry::index; + typedef std::pair __value__; + typedef bgi::rtree< __value__, bgi::linear<32, 8> > RTree; + + RTree rt1; + /* some inserting into the tree */ + + std::vector result; + rt1.query(bgi::intersects(Box(/*...*/)), std::back_inserter(result)); + RTree rt2(result.begin(), result.end()); + +However there are better ways. One of these methods is mentioned in the "Creation and modification" section. +The insert iterator may be passed directly into the query. + + RTree rt3; + rt1.query(bgi::intersects(Box(/*...*/))), bgi::inserter(rt3)); + +If you like Boost.Range you'll appreciate the third option. You may pass the result Range directly into the +constructor. + + RTree rt4(rt1 | bgi::adaptors::queried(bgi::intersects(Box(/*...*/))))); + +[endsect] + +[endsect] [/ Queries /] diff --git a/doc/index/rtree/quickstart.qbk b/doc/index/rtree/quickstart.qbk new file mode 100644 index 0000000000..92c50c4fcb --- /dev/null +++ b/doc/index/rtree/quickstart.qbk @@ -0,0 +1,59 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2012 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section:rtree_quickstart Quick Start] + +This Quick Start section shows simple way to creating a typical R-tree and perform +spatial query. + +The code below assumes that following files are included and namespaces used. + +[rtree_quickstart_include] + +Typically you'll store e.g. `std::pair` in the __rtree__. `MyGeometryId` +will be some indentifier of a complex `Geometry` stored in other container, e.g. index type +of a `Polygon` stored in the vector or an iterator of list of `Ring`s. To keep it simple to +define `Value` we will use predefined __box__ and unsigned int. + +[rtree_quickstart_valuetype] + +R-tree may be created using various algorithm and parameters. You should choose the algorithm you'll +find the best for your purpose. In this example we will use quadratic algorithm. Parameters are +passed as template parameters. Maximum number of elements in nodes is set to 16. + +[rtree_quickstart_create] + +Typically `Value`s will be generated in a loop from e.g. `Polygon`s stored in some other container. +In this case `Box` objects will probably be created with `geometry::envelope()` function. +But to keep it simple lets just generate some boxes manually and insert them into the R-tree by +using `insert()` method. + +[rtree_quickstart_insert] + +There are various types of spatial queries that may be performed, they can be even combined together +in one call. For simplicity, we use the default one. The following query return values intersecting +a box. The sequence of `Values` in the result is not specified. + +[rtree_quickstart_spatial_query] + +Other type of query is k-nearest neighbor search. It returns some number of values nearest to some point +in space. The default knn query may be performed as follows. The sequence of `Values` in the result is not specified. + +[rtree_quickstart_nearest_query] + +At the end we'll print results. + +[rtree_quickstart_output] + +[h3 More] +More information about the R-tree implementation, other algorithms and queries may be found in +other parts of this documentation. + +[endsect] diff --git a/doc/index/rtree/reference.qbk b/doc/index/rtree/reference.qbk new file mode 100644 index 0000000000..c53b01fbdf --- /dev/null +++ b/doc/index/rtree/reference.qbk @@ -0,0 +1,40 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2013 Adam Wulkiewicz. + + 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) +=============================================================================/] + +[section:reference Reference] + +[include ../generated/rtree.qbk] +[include ../generated/rtree_functions.qbk] + +[section:parameters R-tree parameters (boost::geometry::index::)] + +[include ../generated/rtree_linear.qbk] +[include ../generated/rtree_quadratic.qbk] +[include ../generated/rtree_rstar.qbk] +[include ../generated/rtree_dynamic_linear.qbk] +[include ../generated/rtree_dynamic_quadratic.qbk] +[include ../generated/rtree_dynamic_rstar.qbk] + +[endsect] + +[/section:function_objects Function objects (boost::geometry::index::)/] + +[include ../generated/indexable.qbk] +[include ../generated/equal_to.qbk] + +[/endsect/] + +[include ../generated/predicates.qbk] +[include ../generated/nearest_relations.qbk] +[include ../generated/adaptors.qbk] + +[include ../generated/inserters.qbk] + +[endsect] diff --git a/doc/index/src/examples/Jamfile.v2 b/doc/index/src/examples/Jamfile.v2 new file mode 100644 index 0000000000..e221ca86bd --- /dev/null +++ b/doc/index/src/examples/Jamfile.v2 @@ -0,0 +1,19 @@ +# Boost.Geometry Index +# +# Copyright (c) 2011-2012 Adam Wulkiewicz, Lodz, Poland. +# +# 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) + +import testing ; + +project boost-geometry-index-doc-src-examples + : + requirements + ../../.. + #../../../boost/geometry/extensions/contrib/ttmath + msvc:on + ; + +build-project rtree ; diff --git a/doc/index/src/examples/rtree/Jamfile.v2 b/doc/index/src/examples/rtree/Jamfile.v2 new file mode 100644 index 0000000000..79778b9abf --- /dev/null +++ b/doc/index/src/examples/rtree/Jamfile.v2 @@ -0,0 +1,25 @@ +# Boost.Geometry Index +# +# Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +# +# 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) + +exe quick_start : quick_start.cpp ; +exe polygons_vector : polygons_vector.cpp ; +exe polygons_shared_ptr : polygons_shared_ptr.cpp ; +exe variants_map : variants_map.cpp ; +exe value_shared_ptr : value_shared_ptr.cpp ; +exe value_index : value_index.cpp ; + +exe interprocess : interprocess.cpp /boost/thread//boost_thread + : + acc:-lrt + acc-pa_risc:-lrt + gcc-mingw:"-lole32 -loleaut32 -lpsapi -ladvapi32" + hpux,gcc:"-Wl,+as,mpas" + : + multi + : # requirements + ; diff --git a/doc/index/src/examples/rtree/interprocess.cpp b/doc/index/src/examples/rtree/interprocess.cpp new file mode 100644 index 0000000000..61d3f0b505 --- /dev/null +++ b/doc/index/src/examples/rtree/interprocess.cpp @@ -0,0 +1,112 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// +// 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) + +//[rtree_interprocess + +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include //std::system + +//For parent process argc == 1, for child process argc > 1 +int main(int argc, char *argv[]) +{ + using namespace boost::interprocess; + namespace bg = boost::geometry; + namespace bgm = bg::model; + namespace bgi = bg::index; + + typedef bgm::point P; + typedef bgm::box

    B; + + typedef bgi::linear<32, 8> Par; + typedef bgi::indexable I; + typedef bgi::equal_to E; + typedef allocator Alloc; + typedef bgi::rtree Rtree; + + //Parent process + if ( argc == 1 ) + { + struct shm_remove + { + shm_remove() { shared_memory_object::remove("MySharedMemory"); } + ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } + } remover; + + managed_shared_memory segment(create_only, "MySharedMemory", 65536); + + std::cout << "Parent: Constructing container\n"; + + Rtree * tree = segment.construct("Rtree")(Par(), I(), E(), Alloc(segment.get_segment_manager())); + + std::cout << "Parent: Filling container with 100 boxes\n"; + + for ( float i = 0 ; i < 100 ; i += 1 ) + tree->insert(B(P(i, i), P(i+0.5f, i+0.5f))); + + std::cout << "Parent: Tree content\n"; + Rtree::bounds_type bb = tree->bounds(); + std::cout << "[(" << bg::get<0>(bb.min_corner()) << ", " << bg::get<1>(bb.min_corner()) + << ")(" << bg::get<0>(bb.max_corner()) << ", " << bg::get<1>(bb.max_corner()) << ")]\n"; + + std::cout << "Parent: Running child process\n"; + + std::string s(argv[0]); s += " child "; + if ( 0 != std::system(s.c_str()) ) + return 1; + + if ( segment.find("Rtree").first ) + return 1; + + std::cout << "Parent: Container was properly destroyed by the child process\n"; + } + //Child process + else + { + managed_shared_memory segment(open_only, "MySharedMemory"); + + std::cout << "Child: Searching of the container in shared memory\n"; + + Rtree * tree = segment.find("Rtree").first; + + std::cout << "Child: Querying for objects intersecting box = [(45, 45)(55, 55)]\n"; + + std::vector result; + unsigned k = tree->query(bgi::intersects(B(P(45, 45), P(55, 55))), std::back_inserter(result)); + + std::cout << "Child: Found objects:\n"; + std::cout << k << "\n"; + BOOST_FOREACH(B const& b, result) + { + std::cout << "[(" << bg::get<0>(b.min_corner()) << ", " << bg::get<1>(b.min_corner()) + << ")(" << bg::get<0>(b.max_corner()) << ", " << bg::get<1>(b.max_corner()) << ")]\n"; + } + std::cout << "\n"; + + std::cout << "Child: Destroying container\n"; + + segment.destroy("Rtree"); + } + + return 0; +}; + +//] diff --git a/doc/index/src/examples/rtree/polygons_shared_ptr.cpp b/doc/index/src/examples/rtree/polygons_shared_ptr.cpp new file mode 100644 index 0000000000..c65ba53762 --- /dev/null +++ b/doc/index/src/examples/rtree/polygons_shared_ptr.cpp @@ -0,0 +1,88 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// +// 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) + +//[rtree_polygons_shared_ptr + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace bg = boost::geometry; +namespace bgi = boost::geometry::index; + +int main(void) +{ + typedef bg::model::point point; + typedef bg::model::box box; + typedef bg::model::polygon polygon; // ccw, open polygon + typedef boost::shared_ptr shp; + typedef std::pair value; + + // create the rtree using default constructor + bgi::rtree< value, bgi::linear<16, 4> > rtree; + + std::cout << "filling index with polygons shared pointers:" << std::endl; + + // create some polygons and fill the spatial index + for ( unsigned i = 0 ; i < 10 ; ++i ) + { + // create a polygon + shp p(new polygon()); + for ( float a = 0 ; a < 6.28316f ; a += 1.04720f ) + { + float x = i + int(10*::cos(a))*0.1f; + float y = i + int(10*::sin(a))*0.1f; + p->outer().push_back(point(x, y)); + } + + // display new polygon + std::cout << bg::wkt(*p) << std::endl; + + // calculate polygon bounding box + box b = bg::return_envelope(*p); + // insert new value + rtree.insert(std::make_pair(b, p)); + } + + // find values intersecting some area defined by a box + box query_box(point(0, 0), point(5, 5)); + std::vector result_s; + rtree.query(bgi::intersects(query_box), std::back_inserter(result_s)); + + // find 5 nearest values to a point + std::vector result_n; + rtree.query(bgi::nearest(point(0, 0), 5), std::back_inserter(result_n)); + + // display results + std::cout << "spatial query box:" << std::endl; + std::cout << bg::wkt(query_box) << std::endl; + std::cout << "spatial query result:" << std::endl; + BOOST_FOREACH(value const& v, result_s) + std::cout << bg::wkt(*v.second) << std::endl; + + std::cout << "knn query point:" << std::endl; + std::cout << bg::wkt(point(0, 0)) << std::endl; + std::cout << "knn query result:" << std::endl; + BOOST_FOREACH(value const& v, result_n) + std::cout << bg::wkt(*v.second) << std::endl; + + return 0; +} + +//] diff --git a/doc/index/src/examples/rtree/polygons_vector.cpp b/doc/index/src/examples/rtree/polygons_vector.cpp new file mode 100644 index 0000000000..a8984a732f --- /dev/null +++ b/doc/index/src/examples/rtree/polygons_vector.cpp @@ -0,0 +1,96 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// +// 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) + +//[rtree_polygons_vector + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace bg = boost::geometry; +namespace bgi = boost::geometry::index; + +int main(void) +{ + typedef bg::model::point point; + typedef bg::model::box box; + typedef bg::model::polygon polygon; // ccw, open polygon + typedef std::pair value; + + // polygons + std::vector polygons; + + // create some polygons + for ( unsigned i = 0 ; i < 10 ; ++i ) + { + // create a polygon + polygon p; + for ( float a = 0 ; a < 6.28316f ; a += 1.04720f ) + { + float x = i + int(10*::cos(a))*0.1f; + float y = i + int(10*::sin(a))*0.1f; + p.outer().push_back(point(x, y)); + } + + // add polygon + polygons.push_back(p); + } + + // display polygons + std::cout << "generated polygons:" << std::endl; + BOOST_FOREACH(polygon const& p, polygons) + std::cout << bg::wkt(p) << std::endl; + + // create the rtree using default constructor + bgi::rtree< value, bgi::rstar<16, 4> > rtree; + + // fill the spatial index + for ( unsigned i = 0 ; i < polygons.size() ; ++i ) + { + // calculate polygon bounding box + box b = bg::return_envelope(polygons[i]); + // insert new value + rtree.insert(std::make_pair(b, i)); + } + + // find values intersecting some area defined by a box + box query_box(point(0, 0), point(5, 5)); + std::vector result_s; + rtree.query(bgi::intersects(query_box), std::back_inserter(result_s)); + + // find 5 nearest values to a point + std::vector result_n; + rtree.query(bgi::nearest(point(0, 0), 5), std::back_inserter(result_n)); + + // display results + std::cout << "spatial query box:" << std::endl; + std::cout << bg::wkt(query_box) << std::endl; + std::cout << "spatial query result:" << std::endl; + BOOST_FOREACH(value const& v, result_s) + std::cout << bg::wkt(polygons[v.second]) << std::endl; + + std::cout << "knn query point:" << std::endl; + std::cout << bg::wkt(point(0, 0)) << std::endl; + std::cout << "knn query result:" << std::endl; + BOOST_FOREACH(value const& v, result_n) + std::cout << bg::wkt(polygons[v.second]) << std::endl; + + return 0; +} + +//] diff --git a/doc/index/src/examples/rtree/quick_start.cpp b/doc/index/src/examples/rtree/quick_start.cpp new file mode 100644 index 0000000000..80c8831227 --- /dev/null +++ b/doc/index/src/examples/rtree/quick_start.cpp @@ -0,0 +1,87 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// +// 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) + +//[rtree_quickstart + +//[rtree_quickstart_include + +#include +#include +#include + +#include + +// to store queries results +#include + +// just for output +#include +#include + +namespace bg = boost::geometry; +namespace bgi = boost::geometry::index; +//] + +int main(void) +{ + //[rtree_quickstart_valuetype + typedef bg::model::point point; + typedef bg::model::box box; + typedef std::pair value; + //] + + //[rtree_quickstart_create + // create the rtree using default constructor + bgi::rtree< value, bgi::quadratic<16> > rtree; + //] + + //[rtree_quickstart_insert + // create some values + for ( unsigned i = 0 ; i < 10 ; ++i ) + { + // create a box + box b(point(i, i), point(i + 0.5f, i + 0.5f)); + // insert new value + rtree.insert(std::make_pair(b, i)); + } + //] + + //[rtree_quickstart_spatial_query + // find values intersecting some area defined by a box + box query_box(point(0, 0), point(5, 5)); + std::vector result_s; + rtree.query(bgi::intersects(query_box), std::back_inserter(result_s)); + //] + + //[rtree_quickstart_nearest_query + // find 5 nearest values to a point + std::vector result_n; + rtree.query(bgi::nearest(point(0, 0), 5), std::back_inserter(result_n)); + //] + + //[rtree_quickstart_output + // display results + std::cout << "spatial query box:" << std::endl; + std::cout << bg::wkt(query_box) << std::endl; + std::cout << "spatial query result:" << std::endl; + BOOST_FOREACH(value const& v, result_s) + std::cout << bg::wkt(v.first) << " - " << v.second << std::endl; + + std::cout << "knn query point:" << std::endl; + std::cout << bg::wkt(point(0, 0)) << std::endl; + std::cout << "knn query result:" << std::endl; + BOOST_FOREACH(value const& v, result_n) + std::cout << bg::wkt(v.first) << " - " << v.second << std::endl; + //] + + return 0; +} + +//] diff --git a/doc/index/src/examples/rtree/value_index.cpp b/doc/index/src/examples/rtree/value_index.cpp new file mode 100644 index 0000000000..32f3069095 --- /dev/null +++ b/doc/index/src/examples/rtree/value_index.cpp @@ -0,0 +1,97 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// +// 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) + +//[rtree_value_index + +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace bg = boost::geometry; +namespace bgi = boost::geometry::index; + +template +class my_indexable +{ + typedef typename Container::size_type size_t; + typedef typename Container::const_reference cref; + Container const& container; + +public: + typedef cref result_type; + explicit my_indexable(Container const& c) : container(c) {} + result_type operator()(size_t i) const { return container[i]; } +}; + +int main(void) +{ + typedef bg::model::point point; + typedef bg::model::box box; + typedef std::vector::size_type value; + typedef bgi::rstar<16, 4> parameters; + typedef my_indexable< std::vector > indexable_getter; + + // boxes + std::vector boxes; + + // create some boxes + for ( unsigned i = 0 ; i < 10 ; ++i ) + { + // add a box + boxes.push_back(box(point(i, i), point(i+0.5f, i+0.5f))); + } + + // display boxes + std::cout << "generated boxes:" << std::endl; + BOOST_FOREACH(box const& b, boxes) + std::cout << bg::wkt(b) << std::endl; + + // create the rtree + parameters params; + indexable_getter ind(boxes); + bgi::rtree rtree(params, ind); + + // fill the spatial index + for ( size_t i = 0 ; i < boxes.size() ; ++i ) + rtree.insert(i); + + // find values intersecting some area defined by a box + box query_box(point(0, 0), point(5, 5)); + std::vector result_s; + rtree.query(bgi::intersects(query_box), std::back_inserter(result_s)); + + // find 5 nearest values to a point + std::vector result_n; + rtree.query(bgi::nearest(point(0, 0), 5), std::back_inserter(result_n)); + + // display results + std::cout << "spatial query box:" << std::endl; + std::cout << bg::wkt(query_box) << std::endl; + std::cout << "spatial query result:" << std::endl; + BOOST_FOREACH(value i, result_s) + std::cout << bg::wkt(boxes[i]) << std::endl; + + std::cout << "knn query point:" << std::endl; + std::cout << bg::wkt(point(0, 0)) << std::endl; + std::cout << "knn query result:" << std::endl; + BOOST_FOREACH(value i, result_n) + std::cout << bg::wkt(boxes[i]) << std::endl; + + return 0; +} + +//] diff --git a/doc/index/src/examples/rtree/value_shared_ptr.cpp b/doc/index/src/examples/rtree/value_shared_ptr.cpp new file mode 100644 index 0000000000..e2ff55737c --- /dev/null +++ b/doc/index/src/examples/rtree/value_shared_ptr.cpp @@ -0,0 +1,91 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// +// 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) + +//[rtree_value_shared_ptr + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace bg = boost::geometry; +namespace bgi = boost::geometry::index; + +namespace boost { namespace geometry { namespace index { + +template +struct indexable< boost::shared_ptr > +{ + typedef boost::shared_ptr V; + + typedef Box const& result_type; + result_type operator()(V const& v) const { return *v; } +}; + +}}} // namespace boost::geometry::index + +int main(void) +{ + typedef bg::model::point point; + typedef bg::model::box box; + typedef boost::shared_ptr shp; + typedef shp value; + + // create the rtree using default constructor + bgi::rtree< value, bgi::linear<16, 4> > rtree; + + std::cout << "filling index with boxes shared pointers:" << std::endl; + + // fill the spatial index + for ( unsigned i = 0 ; i < 10 ; ++i ) + { + // create a box + shp b(new box(point(i, i), point(i+0.5f, i+0.5f))); + + // display new box + std::cout << bg::wkt(*b) << std::endl; + + // insert new value + rtree.insert(b); + } + + // find values intersecting some area defined by a box + box query_box(point(0, 0), point(5, 5)); + std::vector result_s; + rtree.query(bgi::intersects(query_box), std::back_inserter(result_s)); + + // find 5 nearest values to a point + std::vector result_n; + rtree.query(bgi::nearest(point(0, 0), 5), std::back_inserter(result_n)); + + // display results + std::cout << "spatial query box:" << std::endl; + std::cout << bg::wkt(query_box) << std::endl; + std::cout << "spatial query result:" << std::endl; + BOOST_FOREACH(value const& v, result_s) + std::cout << bg::wkt(*v) << std::endl; + + std::cout << "knn query point:" << std::endl; + std::cout << bg::wkt(point(0, 0)) << std::endl; + std::cout << "knn query result:" << std::endl; + BOOST_FOREACH(value const& v, result_n) + std::cout << bg::wkt(*v) << std::endl; + + return 0; +} + +//] diff --git a/doc/index/src/examples/rtree/variants_map.cpp b/doc/index/src/examples/rtree/variants_map.cpp new file mode 100644 index 0000000000..462795002e --- /dev/null +++ b/doc/index/src/examples/rtree/variants_map.cpp @@ -0,0 +1,143 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// +// 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) + +//[rtree_variants_map + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace bg = boost::geometry; +namespace bgi = boost::geometry::index; + +typedef bg::model::point point; +typedef bg::model::box box; +typedef bg::model::polygon polygon; // ccw, open polygon +typedef bg::model::ring ring; // ccw, open ring +typedef bg::model::linestring linestring; +typedef boost::variant geometry; + +typedef std::map map; +typedef std::pair value; + +template +void fill(unsigned i, Container & container) +{ + for ( float a = 0 ; a < 6.28316f ; a += 1.04720f ) + { + float x = i + int(10*::cos(a))*0.1f; + float y = i + int(10*::sin(a))*0.1f; + container.push_back(point(x, y)); + } +} + +struct print_visitor : public boost::static_visitor<> +{ + void operator()(polygon const& g) const { std::cout << bg::wkt(g) << std::endl; } + void operator()(ring const& g) const { std::cout << bg::wkt(g) << std::endl; } + void operator()(linestring const& g) const { std::cout << bg::wkt(g) << std::endl; } +}; + +struct envelope_visitor : public boost::static_visitor +{ + box operator()(polygon const& g) const { return bg::return_envelope(g); } + box operator()(ring const& g) const { return bg::return_envelope(g); } + box operator()(linestring const& g) const { return bg::return_envelope(g); } +}; + + +int main(void) +{ + // geometries container + map geometries; + + // create some geometries + for ( unsigned i = 0 ; i < 10 ; ++i ) + { + unsigned c = rand() % 3; + + if ( 0 == c ) + { + // create polygon + polygon p; + fill(i, p.outer()); + geometries.insert(std::make_pair(i, geometry(p))); + } + else if ( 1 == c ) + { + // create ring + ring r; + fill(i, r); + geometries.insert(std::make_pair(i, geometry(r))); + } + else if ( 2 == c ) + { + // create linestring + linestring l; + fill(i, l); + geometries.insert(std::make_pair(i, geometry(l))); + } + } + + // display geometries + std::cout << "generated geometries:" << std::endl; + BOOST_FOREACH(map::value_type const& p, geometries) + boost::apply_visitor(print_visitor(), p.second); + + // create the rtree using default constructor + bgi::rtree< value, bgi::quadratic<16, 4> > rtree; + + // fill the spatial index + for ( map::iterator it = geometries.begin() ; it != geometries.end() ; ++it ) + { + // calculate polygon bounding box + box b = boost::apply_visitor(envelope_visitor(), it->second); + // insert new value + rtree.insert(std::make_pair(b, it)); + } + + // find values intersecting some area defined by a box + box query_box(point(0, 0), point(5, 5)); + std::vector result_s; + rtree.query(bgi::intersects(query_box), std::back_inserter(result_s)); + + // find 5 nearest values to a point + std::vector result_n; + rtree.query(bgi::nearest(point(0, 0), 5), std::back_inserter(result_n)); + + // display results + std::cout << "spatial query box:" << std::endl; + std::cout << bg::wkt(query_box) << std::endl; + std::cout << "spatial query result:" << std::endl; + BOOST_FOREACH(value const& v, result_s) + boost::apply_visitor(print_visitor(), v.second->second); + + std::cout << "knn query point:" << std::endl; + std::cout << bg::wkt(point(0, 0)) << std::endl; + std::cout << "knn query result:" << std::endl; + BOOST_FOREACH(value const& v, result_n) + boost::apply_visitor(print_visitor(), v.second->second); + + return 0; +} + +//] diff --git a/doc/make_qbk.py b/doc/make_qbk.py index 74aa52995c..1a01bf2b95 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -148,4 +148,9 @@ def cs_to_quickbook(section): group_to_quickbook("register") group_to_quickbook("enum") -os.system("../../../b2") +os.chdir("index") +execfile("make_qbk.py") +os.chdir("..") + +# Use either bjam or b2 or ../../../b2 (the last should be done on Release branch) +os.system("bjam") diff --git a/doc/quickref.xml b/doc/quickref.xml index 2a70b4612f..98c9ef2032 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -8,6 +8,7 @@ Copyright (c) 2009-2011 Mateusz Loskot, London, UK. Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. Copyright (c) 2009-2011 Bruno Lalande, Paris, France. + Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -624,5 +625,128 @@ + + + + + + + + + + Spatial indexes + + + + + + + R-tree + + boost::geometry::index::rtree + + R-tree parameters + + boost::geometry::index::linear + boost::geometry::index::quadratic + boost::geometry::index::rstar + boost::geometry::index::dynamic_linear + boost::geometry::index::dynamic_quadratic + boost::geometry::index::dynamic_rstar + + R-tree constructors and destructor + + rtree() + rtree(parameters_type const &, indexable_getter const &, value_equal const &, allocator_type const &) + rtree(Iterator, Iterator) + rtree(Range const &) + rtree(rtree const &) + rtree(rtree const &, allocator_type const &) + rtree(rtree &&) + rtree(rtree &&, allocator_type const &) + ~rtree() + + + + R-tree member functions + + operator=(const rtree &) + operator=(rtree &&) + swap(rtree &) + insert(value_type const &) + insert(Iterator, Iterator) + insert(Range const &) + remove(value_type const &) + remove(Iterator, Iterator) + remove(Range const &) + query(Predicates const &, OutIter) + size() + empty() + clear() + bounds() + count(ValueOrIndexable const &) + parameters() + indexable_get() + value_eq() + get_allocator() + + + + R-tree free functions (boost::geometry::index::) + + insert(rtree<...> &, Value const &) + insert(rtree<...> &, Iterator, Iterator) + insert(rtree<...> &, Range const &) + remove(rtree<...> &, Value const &) + remove(rtree<...> &, Iterator, Iterator) + remove(rtree<...> &, Range const &) + query(rtree<...> const &, Predicates const &, OutIter) + clear(rtree<...> &) + size(rtree<...> const &) + empty(rtree<...> const &) + bounds(rtree<...> const &) + swap(rtree<...> &, rtree<...> &) + + + + + + Observers (boost::geometry::index::) + + boost::geometry::index::indexable + boost::geometry::index::equal_to + + Inserters (boost::geometry::index::) + + inserter(Container &) + + Adaptors (boost::geometry::index::adaptors::) + + queried(Predicates const &) + + + + Predicates (boost::geometry::index::) + + covered_by(Geometry const &) + disjoint(Geometry const &) + intersects(Geometry const &) + overlaps(Geometry const &) + within(Geometry const &) + satisfies(UnaryPredicate const &) + nearest(Point const &, unsigned) + + + + + + diff --git a/doc/readme.txt b/doc/readme.txt index f1d17d1523..3d04faf18c 100644 --- a/doc/readme.txt +++ b/doc/readme.txt @@ -15,9 +15,10 @@ and that it translates from Doxygen-XML output to Quickbook (without xslt) 1) install Doxygen 2) install QuickBook using http://www.boost.org/doc/libs/1_45_0/doc/html/quickbook/install.html#quickbook.install.linux -3) compile doxygen_xml2qbk, in src/docutils/tools/doxygen_xml2qbk -4) put binary somewhere, e.g. in /usr/local/bin/doxygen_xml2qbk -5) execute python file "make_qbk.py" (calling doxygen, doxygen_xml2qbk, bjam) +3) unpack RapidXML, see src/docutils/tools/doxygen_xml2qbk/contrib/readme.txt +4) compile doxygen_xml2qbk, in src/docutils/tools/doxygen_xml2qbk +5) put binary somewhere, e.g. in /usr/local/bin/doxygen_xml2qbk +6) execute python file "make_qbk.py" (calling doxygen, doxygen_xml2qbk, bjam) Folders in this folder: concept: manually written documentation QBK files, on concept diff --git a/doc/reference.qbk b/doc/reference.qbk index a9a2192b94..563f589ef8 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -4,6 +4,7 @@ Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Copyright (c) 2009-2012 Bruno Lalande, Paris, France. + Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -241,6 +242,34 @@ [endsect] +[section:spatial_indexes Spatial indexes] + +[section:rtree R-tree] +[include index/generated/rtree.qbk] +[include index/generated/rtree_functions.qbk] +[section:parameters R-tree parameters (boost::geometry::index::)] +[include index/generated/rtree_linear.qbk] +[include index/generated/rtree_quadratic.qbk] +[include index/generated/rtree_rstar.qbk] +[include index/generated/rtree_dynamic_linear.qbk] +[include index/generated/rtree_dynamic_quadratic.qbk] +[include index/generated/rtree_dynamic_rstar.qbk] +[endsect] +[endsect] + +[section:observers Observers (boost::geometry::index::)] +[include index/generated/indexable.qbk] +[include index/generated/equal_to.qbk] +[endsect] +[include index/generated/inserters.qbk] +[include index/generated/adaptors.qbk] + +[include index/generated/predicates.qbk] +[/include index/generated/nearest_relations.qbk] + +[endsect] + + [section:strategies Strategies] [include generated/distance_pythagoras.qbk] [include generated/distance_haversine.qbk] diff --git a/doc/reference/core/max_corner.qbk b/doc/reference/core/max_corner.qbk index e3d69aaa0f..1d56590ec6 100644 --- a/doc/reference/core/max_corner.qbk +++ b/doc/reference/core/max_corner.qbk @@ -19,8 +19,8 @@ Indicates the maximal corner (upper right) of a box to be get, set or processed [heading See also] * [link geometry.reference.constants.min_corner min_corner] -* [link geometry.reference.access.get.get_2_with_index get with index] -* [link geometry.reference.access.set.set_3_with_index set with index] +* [link geometry.reference.access.get.get_1_with_index get with index] +* [link geometry.reference.access.set.set_2_with_index set with index] [endsect] diff --git a/doc/reference/core/min_corner.qbk b/doc/reference/core/min_corner.qbk index 061412bd97..a169b04752 100644 --- a/doc/reference/core/min_corner.qbk +++ b/doc/reference/core/min_corner.qbk @@ -19,7 +19,7 @@ Indicates the minimal corner (lower left) of a box to be get, set or processed [heading See also] * [link geometry.reference.constants.max_corner max_corner] -* [link geometry.reference.access.get.get_2_with_index get with index] -* [link geometry.reference.access.set.set_3_with_index set with index] +* [link geometry.reference.access.get.get_1_with_index get with index] +* [link geometry.reference.access.set.set_2_with_index set with index] [endsect] diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 1bb40e2bc5..879ca5fdeb 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -1,9 +1,10 @@ [/============================================================================ Boost.Geometry (aka GGL, Generic Geometry Library) - Copyright (c) 2009-2012 Barend Gehrels, Geodan, Amsterdam, the Netherlands. - Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net) - Copyright (c) 2009-2012 Mateusz Lalande, Paris, France. + Copyright (c) 2009-2013 Barend Gehrels, Geodan, Amsterdam, the Netherlands. + Copyright (c) 2009-2013 Mateusz Loskot (mateusz@loskot.net) + Copyright (c) 2009-2013 Mateusz Lalande, Paris, France. + Copyright (c) 2011-2013 Adam Wulkiewicz Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -12,6 +13,27 @@ [section:release_notes Release Notes] +[/=================] +[heading Boost 1.54] +[/=================] + +[*Additional functionality] + +* added Spatial Index, developed for Boost.Geometry by Adam Wulkiewicz. The spatial index was originally started by Federico J. Fernandez during the Google Summer of Code 2008 program, mentored by Hartmut Kaiser. + +[*Bugfixes] +* collinear opposite segments did sometimes (in circles) have a robustness issue, fixed + +[*Solved tickets] + +* [@https://svn.boost.org/trac/boost/ticket/7462 7462] degenerate union result for float, fixed +* [@https://svn.boost.org/trac/boost/ticket/7465 7465] wrong construtors access type in scale_transformer class, fixed +* [@https://svn.boost.org/trac/boost/ticket/7802 7802] cart_intersect.hpp unused parameter warnings, fixed +* [@https://svn.boost.org/trac/boost/ticket/8254 8254] faulty intersection, fixed +* [@https://svn.boost.org/trac/boost/ticket/8393 8393] polygon model doesn't adhere to stated Polygon concept rules, doc updated. +* [@https://svn.boost.org/trac/boost/ticket/8403 8403] silenced compiler warning C4127: conditional expression is constant +* [@https://svn.boost.org/trac/boost/ticket/8405 8405] silenced compiler warning C4189: '...' : local variable is initialized but not referenced + [/=================] [heading Boost 1.53] diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/configuration.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/configuration.hpp index 96cf8104cd..3cb8ddf83d 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/configuration.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/configuration.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) @@ -14,6 +15,7 @@ #include + struct configuration { // To transfer e.g. c:/_svn/boost/trunk/boost/geometry/algorithms/area.hpp @@ -27,6 +29,10 @@ struct configuration std::vector convenience_headers; std::string skip_namespace; + + enum output_style_type {def, alt}; + output_style_type output_style; + configuration() : output_style(def) {} }; diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/license.txt b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/license.txt new file mode 100644 index 0000000000..140983180b --- /dev/null +++ b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/license.txt @@ -0,0 +1,52 @@ +Use of this software is granted under one of the following two licenses, +to be chosen freely by the user. + +1. Boost Software License - Version 1.0 - August 17th, 2003 +=============================================================================== + +Copyright (c) 2006, 2007 Marcin Kalicinski + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +2. The MIT License +=============================================================================== + +Copyright (c) 2006, 2007 Marcin Kalicinski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/manual.html b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/manual.html new file mode 100644 index 0000000000..2c422703f4 --- /dev/null +++ b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/manual.html @@ -0,0 +1,406 @@ +

    RAPIDXML Manual

    Version 1.13

    Copyright (C) 2006, 2009 Marcin Kalicinski
    See accompanying file license.txt for license information.

    Table of Contents

    1. What is RapidXml?
    1.1 Dependencies And Compatibility
    1.2 Character Types And Encodings
    1.3 Error Handling
    1.4 Memory Allocation
    1.5 W3C Compliance
    1.6 API Design
    1.7 Reliability
    1.8 Acknowledgements
    2. Two Minute Tutorial
    2.1 Parsing
    2.2 Accessing The DOM Tree
    2.3 Modifying The DOM Tree
    2.4 Printing XML
    3. Differences From Regular XML Parsers
    3.1 Lifetime Of Source Text
    3.2 Ownership Of Strings
    3.3 Destructive Vs Non-Destructive Mode
    4. Performance
    4.1 Comparison With Other Parsers
    5. Reference

    1. What is RapidXml?

    RapidXml is an attempt to create the fastest XML DOM parser possible, while retaining useability, portability and reasonable W3C compatibility. It is an in-situ parser written in C++, with parsing speed approaching that of strlen() function executed on the same data.

    + Entire parser is contained in a single header file, so no building or linking is neccesary. To use it you just need to copy rapidxml.hpp file to a convenient place (such as your project directory), and include it where needed. You may also want to use printing functions contained in header rapidxml_print.hpp.

    1.1 Dependencies And Compatibility

    RapidXml has no dependencies other than a very small subset of standard C++ library (<cassert>, <cstdlib>, <new> and <exception>, unless exceptions are disabled). It should compile on any reasonably conformant compiler, and was tested on Visual C++ 2003, Visual C++ 2005, Visual C++ 2008, gcc 3, gcc 4, and Comeau 4.3.3. Care was taken that no warnings are produced on these compilers, even with highest warning levels enabled.

    1.2 Character Types And Encodings

    RapidXml is character type agnostic, and can work both with narrow and wide characters. Current version does not fully support UTF-16 or UTF-32, so use of wide characters is somewhat incapacitated. However, it should succesfully parse wchar_t strings containing UTF-16 or UTF-32 if endianness of the data matches that of the machine. UTF-8 is fully supported, including all numeric character references, which are expanded into appropriate UTF-8 byte sequences (unless you enable parse_no_utf8 flag).

    + Note that RapidXml performs no decoding - strings returned by name() and value() functions will contain text encoded using the same encoding as source file. Rapidxml understands and expands the following character references: &apos; &amp; &quot; &lt; &gt; &#...; Other character references are not expanded.

    1.3 Error Handling

    By default, RapidXml uses C++ exceptions to report errors. If this behaviour is undesirable, RAPIDXML_NO_EXCEPTIONS can be defined to suppress exception code. See parse_error class and parse_error_handler() function for more information.

    1.4 Memory Allocation

    RapidXml uses a special memory pool object to allocate nodes and attributes, because direct allocation using new operator would be far too slow. Underlying memory allocations performed by the pool can be customized by use of memory_pool::set_allocator() function. See class memory_pool for more information.

    1.5 W3C Compliance

    RapidXml is not a W3C compliant parser, primarily because it ignores DOCTYPE declarations. There is a number of other, minor incompatibilities as well. Still, it can successfully parse and produce complete trees of all valid XML files in W3C conformance suite (over 1000 files specially designed to find flaws in XML processors). In destructive mode it performs whitespace normalization and character entity substitution for a small set of built-in entities.

    1.6 API Design

    RapidXml API is minimalistic, to reduce code size as much as possible, and facilitate use in embedded environments. Additional convenience functions are provided in separate headers: rapidxml_utils.hpp and rapidxml_print.hpp. Contents of these headers is not an essential part of the library, and is currently not documented (otherwise than with comments in code).

    1.7 Reliability

    RapidXml is very robust and comes with a large harness of unit tests. Special care has been taken to ensure stability of the parser no matter what source text is thrown at it. One of the unit tests produces 100,000 randomly corrupted variants of XML document, which (when uncorrupted) contains all constructs recognized by RapidXml. RapidXml passes this test when it correctly recognizes that errors have been introduced, and does not crash or loop indefinitely.

    + Another unit test puts RapidXml head-to-head with another, well estabilished XML parser, and verifies that their outputs match across a wide variety of small and large documents.

    + Yet another test feeds RapidXml with over 1000 test files from W3C compliance suite, and verifies that correct results are obtained. There are also additional tests that verify each API function separately, and test that various parsing modes work as expected.

    1.8 Acknowledgements

    I would like to thank Arseny Kapoulkine for his work on pugixml, which was an inspiration for this project. Additional thanks go to Kristen Wegner for creating pugxml, from which pugixml was derived. Janusz Wohlfeil kindly ran RapidXml speed tests on hardware that I did not have access to, allowing me to expand performance comparison table.

    2. Two Minute Tutorial

    2.1 Parsing

    The following code causes RapidXml to parse a zero-terminated string named text:
    using namespace rapidxml;
    +xml_document<> doc;    // character type defaults to char
    +doc.parse<0>(text);    // 0 means default parse flags
    +
    doc object is now a root of DOM tree containing representation of the parsed XML. Because all RapidXml interface is contained inside namespace rapidxml, users must either bring contents of this namespace into scope, or fully qualify all the names. Class xml_document represents a root of the DOM hierarchy. By means of public inheritance, it is also an xml_node and a memory_pool. Template parameter of xml_document::parse() function is used to specify parsing flags, with which you can fine-tune behaviour of the parser. Note that flags must be a compile-time constant.

    2.2 Accessing The DOM Tree

    To access the DOM tree, use methods of xml_node and xml_attribute classes:
    cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
    +xml_node<> *node = doc.first_node("foobar");
    +cout << "Node foobar has value " << node->value() << "\n";
    +for (xml_attribute<> *attr = node->first_attribute();
    +     attr; attr = attr->next_attribute())
    +{
    +    cout << "Node foobar has attribute " << attr->name() << " ";
    +    cout << "with value " << attr->value() << "\n";
    +}
    +

    2.3 Modifying The DOM Tree

    DOM tree produced by the parser is fully modifiable. Nodes and attributes can be added/removed, and their contents changed. The below example creates a HTML document, whose sole contents is a link to google.com website:
    xml_document<> doc;
    +xml_node<> *node = doc.allocate_node(node_element, "a", "Google");
    +doc.append_node(node);
    +xml_attribute<> *attr = doc.allocate_attribute("href", "google.com");
    +node->append_attribute(attr);
    +
    One quirk is that nodes and attributes do not own the text of their names and values. This is because normally they only store pointers to the source text. So, when assigning a new name or value to the node, care must be taken to ensure proper lifetime of the string. The easiest way to achieve it is to allocate the string from the xml_document memory pool. In the above example this is not necessary, because we are only assigning character constants. But the code below uses memory_pool::allocate_string() function to allocate node name (which will have the same lifetime as the document), and assigns it to a new node:
    xml_document<> doc;
    +char *node_name = doc.allocate_string(name);        // Allocate string and copy name into it
    +xml_node<> *node = doc.allocate_node(node_element, node_name);  // Set node name to node_name
    +
    Check Reference section for description of the entire interface.

    2.4 Printing XML

    You can print xml_document and xml_node objects into an XML string. Use print() function or operator <<, which are defined in rapidxml_print.hpp header.
    using namespace rapidxml;
    +xml_document<> doc;    // character type defaults to char
    +// ... some code to fill the document
    +
    +// Print to stream using operator <<
    +std::cout << doc;   
    +
    +// Print to stream using print function, specifying printing flags
    +print(std::cout, doc, 0);   // 0 means default printing flags
    +
    +// Print to string using output iterator
    +std::string s;
    +print(std::back_inserter(s), doc, 0);
    +
    +// Print to memory buffer using output iterator
    +char buffer[4096];                      // You are responsible for making the buffer large enough!
    +char *end = print(buffer, doc, 0);      // end contains pointer to character after last printed character
    +*end = 0;                               // Add string terminator after XML
    +

    3. Differences From Regular XML Parsers

    RapidXml is an in-situ parser, which allows it to achieve very high parsing speed. In-situ means that parser does not make copies of strings. Instead, it places pointers to the source text in the DOM hierarchy.

    3.1 Lifetime Of Source Text

    In-situ parsing requires that source text lives at least as long as the document object. If source text is destroyed, names and values of nodes in DOM tree will become destroyed as well. Additionally, whitespace processing, character entity translation, and zero-termination of strings require that source text be modified during parsing (but see non-destructive mode). This makes the text useless for further processing once it was parsed by RapidXml.

    + In many cases however, these are not serious issues.

    3.2 Ownership Of Strings

    Nodes and attributes produced by RapidXml do not own their name and value strings. They merely hold the pointers to them. This means you have to be careful when setting these values manually, by using xml_base::name(const Ch *) or xml_base::value(const Ch *) functions. Care must be taken to ensure that lifetime of the string passed is at least as long as lifetime of the node/attribute. The easiest way to achieve it is to allocate the string from memory_pool owned by the document. Use memory_pool::allocate_string() function for this purpose.

    3.3 Destructive Vs Non-Destructive Mode

    By default, the parser modifies source text during the parsing process. This is required to achieve character entity translation, whitespace normalization, and zero-termination of strings.

    + In some cases this behaviour may be undesirable, for example if source text resides in read only memory, or is mapped to memory directly from file. By using appropriate parser flags (parse_non_destructive), source text modifications can be disabled. However, because RapidXml does in-situ parsing, it obviously has the following side-effects:

    4. Performance

    RapidXml achieves its speed through use of several techniques:
    • In-situ parsing. When building DOM tree, RapidXml does not make copies of string data, such as node names and values. Instead, it stores pointers to interior of the source text.
    • Use of template metaprogramming techniques. This allows it to move much of the work to compile time. Through magic of the templates, C++ compiler generates a separate copy of parsing code for any combination of parser flags you use. In each copy, all possible decisions are made at compile time and all unused code is omitted.
    • Extensive use of lookup tables for parsing.
    • Hand-tuned C++ with profiling done on several most popular CPUs.
    This results in a very small and fast code: a parser which is custom tailored to exact needs with each invocation.

    4.1 Comparison With Other Parsers

    The table below compares speed of RapidXml to some other parsers, and to strlen() function executed on the same data. On a modern CPU (as of 2007), you can expect parsing throughput to be close to 1 GB/s. As a rule of thumb, parsing speed is about 50-100x faster than Xerces DOM, 30-60x faster than TinyXml, 3-12x faster than pugxml, and about 5% - 30% faster than pugixml, the fastest XML parser I know of.
    • The test file is a real-world, 50kB large, moderately dense XML file.
    • All timing is done by using RDTSC instruction present in Pentium-compatible CPUs.
    • No profile-guided optimizations are used.
    • All parsers are running in their fastest modes.
    • The results are given in CPU cycles per character, so frequency of CPUs is irrelevant.
    • The results are minimum values from a large number of runs, to minimize effects of operating system activity, task switching, interrupt handling etc.
    • A single parse of the test file takes about 1/10th of a millisecond, so with large number of runs there is a good chance of hitting at least one no-interrupt streak, and obtaining undisturbed results.
    Platform
    Compiler
    strlen() RapidXml pugixml 0.3 pugxml TinyXml
    Pentium 4
    MSVC 8.0
    2.5
    5.4
    7.0
    61.7
    298.8
    Pentium 4
    gcc 4.1.1
    0.8
    6.1
    9.5
    67.0
    413.2
    Core 2
    MSVC 8.0
    1.0
    4.5
    5.0
    24.6
    154.8
    Core 2
    gcc 4.1.1
    0.6
    4.6
    5.4
    28.3
    229.3
    Athlon XP
    MSVC 8.0
    3.1
    7.7
    8.0
    25.5
    182.6
    Athlon XP
    gcc 4.1.1
    0.9
    8.2
    9.2
    33.7
    265.2
    Pentium 3
    MSVC 8.0
    2.0
    6.3
    7.0
    30.9
    211.9
    Pentium 3
    gcc 4.1.1
    1.0
    6.7
    8.9
    35.3
    316.0
    (*) All results are in CPU cycles per character of source text

    5. Reference

    This section lists all classes, functions, constants etc. and describes them in detail.
    class + template + rapidxml::memory_pool
    + constructor + memory_pool()
    + destructor + ~memory_pool()
    function allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
    function allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
    function allocate_string(const Ch *source=0, std::size_t size=0)
    function clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0)
    function clear()
    function set_allocator(alloc_func *af, free_func *ff)

    class rapidxml::parse_error
    + constructor + parse_error(const char *what, void *where)
    function what() const
    function where() const

    class + template + rapidxml::xml_attribute
    + constructor + xml_attribute()
    function document() const
    function previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const

    class + template + rapidxml::xml_base
    + constructor + xml_base()
    function name() const
    function name_size() const
    function value() const
    function value_size() const
    function name(const Ch *name, std::size_t size)
    function name(const Ch *name)
    function value(const Ch *value, std::size_t size)
    function value(const Ch *value)
    function parent() const

    class + template + rapidxml::xml_document
    + constructor + xml_document()
    function parse(Ch *text)
    function clear()

    class + template + rapidxml::xml_node
    + constructor + xml_node(node_type type)
    function type() const
    function document() const
    function first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function type(node_type type)
    function prepend_node(xml_node< Ch > *child)
    function append_node(xml_node< Ch > *child)
    function insert_node(xml_node< Ch > *where, xml_node< Ch > *child)
    function remove_first_node()
    function remove_last_node()
    function remove_node(xml_node< Ch > *where)
    function remove_all_nodes()
    function prepend_attribute(xml_attribute< Ch > *attribute)
    function append_attribute(xml_attribute< Ch > *attribute)
    function insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute)
    function remove_first_attribute()
    function remove_last_attribute()
    function remove_attribute(xml_attribute< Ch > *where)
    function remove_all_attributes()

    namespace rapidxml
    enum node_type
    function parse_error_handler(const char *what, void *where)
    function print(OutIt out, const xml_node< Ch > &node, int flags=0)
    function print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0)
    function operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node)
    + constant + parse_no_data_nodes
    + constant + parse_no_element_values
    + constant + parse_no_string_terminators
    + constant + parse_no_entity_translation
    + constant + parse_no_utf8
    + constant + parse_declaration_node
    + constant + parse_comment_nodes
    + constant + parse_doctype_node
    + constant + parse_pi_nodes
    + constant + parse_validate_closing_tags
    + constant + parse_trim_whitespace
    + constant + parse_normalize_whitespace
    + constant + parse_default
    + constant + parse_non_destructive
    + constant + parse_fastest
    + constant + parse_full
    + constant + print_no_indenting


    class + template + rapidxml::memory_pool

    + + Defined in rapidxml.hpp
    + Base class for + xml_document

    Description

    This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. In most cases, you will not need to use this class directly. However, if you need to create nodes manually or modify names/values of nodes, you are encouraged to use memory_pool of relevant xml_document to allocate the memory. Not only is this faster than allocating them by using new operator, but also their lifetime will be tied to the lifetime of document, possibly simplyfing memory management.

    + Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. You can also call allocate_string() function to allocate strings. Such strings can then be used as names or values of nodes without worrying about their lifetime. Note that there is no free() function -- all allocations are freed at once when clear() function is called, or when the pool is destroyed.

    + It is also possible to create a standalone memory_pool, and use it to allocate nodes, whose lifetime will not be tied to any document.

    + Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. Until static memory is exhausted, no dynamic memory allocations are done. When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, by using global new[] and delete[] operators. This behaviour can be changed by setting custom allocation routines. Use set_allocator() function to set them.

    + Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. This value defaults to the size of pointer on target architecture.

    + To obtain absolutely top performance from the parser, it is important that all nodes are allocated from a single, contiguous block of memory. Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT to obtain best wasted memory to performance compromise. To do it, define their values before rapidxml.hpp file is included.

    Parameters

    Ch
    Character type of created nodes.

    + constructor + memory_pool::memory_pool

    Synopsis

    memory_pool(); +

    Description

    Constructs empty pool with default allocator functions.

    + destructor + memory_pool::~memory_pool

    Synopsis

    ~memory_pool(); +

    Description

    Destroys pool and frees all the memory. This causes memory occupied by nodes allocated by the pool to be freed. Nodes allocated from the pool are no longer valid.

    function memory_pool::allocate_node

    Synopsis

    xml_node<Ch>* allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); +

    Description

    Allocates a new node from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

    Parameters

    type
    Type of node to create.
    name
    Name to assign to the node, or 0 to assign no name.
    value
    Value to assign to the node, or 0 to assign no value.
    name_size
    Size of name to assign, or 0 to automatically calculate size from name string.
    value_size
    Size of value to assign, or 0 to automatically calculate size from value string.

    Returns

    Pointer to allocated node. This pointer will never be NULL.

    function memory_pool::allocate_attribute

    Synopsis

    xml_attribute<Ch>* allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); +

    Description

    Allocates a new attribute from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

    Parameters

    name
    Name to assign to the attribute, or 0 to assign no name.
    value
    Value to assign to the attribute, or 0 to assign no value.
    name_size
    Size of name to assign, or 0 to automatically calculate size from name string.
    value_size
    Size of value to assign, or 0 to automatically calculate size from value string.

    Returns

    Pointer to allocated attribute. This pointer will never be NULL.

    function memory_pool::allocate_string

    Synopsis

    Ch* allocate_string(const Ch *source=0, std::size_t size=0); +

    Description

    Allocates a char array of given size from the pool, and optionally copies a given string to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

    Parameters

    source
    String to initialize the allocated memory with, or 0 to not initialize it.
    size
    Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.

    Returns

    Pointer to allocated char array. This pointer will never be NULL.

    function memory_pool::clone_node

    Synopsis

    xml_node<Ch>* clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0); +

    Description

    Clones an xml_node and its hierarchy of child nodes and attributes. Nodes and attributes are allocated from this memory pool. Names and values are not cloned, they are shared between the clone and the source. Result node can be optionally specified as a second parameter, in which case its contents will be replaced with cloned source node. This is useful when you want to clone entire document.

    Parameters

    source
    Node to clone.
    result
    Node to put results in, or 0 to automatically allocate result node

    Returns

    Pointer to cloned node. This pointer will never be NULL.

    function memory_pool::clear

    Synopsis

    void clear(); +

    Description

    Clears the pool. This causes memory occupied by nodes allocated by the pool to be freed. Any nodes or strings allocated from the pool will no longer be valid.

    function memory_pool::set_allocator

    Synopsis

    void set_allocator(alloc_func *af, free_func *ff); +

    Description

    Sets or resets the user-defined memory allocation functions for the pool. This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. Allocation function must not return invalid pointer on failure. It should either throw, stop the program, or use longjmp() function to pass control to other place of program. If it returns invalid pointer, results are undefined.

    + User defined allocation functions must have the following forms:

    +void *allocate(std::size_t size);
    +void free(void *pointer);

    Parameters

    af
    Allocation function, or 0 to restore default function
    ff
    Free function, or 0 to restore default function

    class rapidxml::parse_error

    + + Defined in rapidxml.hpp

    Description

    Parse error exception. This exception is thrown by the parser when an error occurs. Use what() function to get human-readable error message. Use where() function to get a pointer to position within source text where error was detected.

    + If throwing exceptions by the parser is undesirable, it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. This function must be defined by the user.

    + This class derives from std::exception class.

    + constructor + parse_error::parse_error

    Synopsis

    parse_error(const char *what, void *where); +

    Description

    Constructs parse error.

    function parse_error::what

    Synopsis

    virtual const char* what() const; +

    Description

    Gets human readable description of error.

    Returns

    Pointer to null terminated description of the error.

    function parse_error::where

    Synopsis

    Ch* where() const; +

    Description

    Gets pointer to character data where error happened. Ch should be the same as char type of xml_document that produced the error.

    Returns

    Pointer to location within the parsed string where error occured.

    class + template + rapidxml::xml_attribute

    + + Defined in rapidxml.hpp
    + Inherits from + xml_base

    Description

    Class representing attribute node of XML document. Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). Note that after parse, both name and value of attribute will point to interior of source text used for parsing. Thus, this text must persist in memory for the lifetime of attribute.

    Parameters

    Ch
    Character type to use.

    + constructor + xml_attribute::xml_attribute

    Synopsis

    xml_attribute(); +

    Description

    Constructs an empty attribute with the specified type. Consider using memory_pool of appropriate xml_document if allocating attributes manually.

    function xml_attribute::document

    Synopsis

    xml_document<Ch>* document() const; +

    Description

    Gets document of which attribute is a child.

    Returns

    Pointer to document that contains this attribute, or 0 if there is no parent document.

    function xml_attribute::previous_attribute

    Synopsis

    xml_attribute<Ch>* previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets previous attribute, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    function xml_attribute::next_attribute

    Synopsis

    xml_attribute<Ch>* next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets next attribute, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    class + template + rapidxml::xml_base

    + + Defined in rapidxml.hpp
    + Base class for + xml_attribute xml_node

    Description

    Base class for xml_node and xml_attribute implementing common functions: name(), name_size(), value(), value_size() and parent().

    Parameters

    Ch
    Character type to use

    + constructor + xml_base::xml_base

    Synopsis

    xml_base(); +

    function xml_base::name

    Synopsis

    Ch* name() const; +

    Description

    Gets name of the node. Interpretation of name depends on type of node. Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

    + Use name_size() function to determine length of the name.

    Returns

    Name of node, or empty string if node has no name.

    function xml_base::name_size

    Synopsis

    std::size_t name_size() const; +

    Description

    Gets size of node name, not including terminator character. This function works correctly irrespective of whether name is or is not zero terminated.

    Returns

    Size of node name, in characters.

    function xml_base::value

    Synopsis

    Ch* value() const; +

    Description

    Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

    + Use value_size() function to determine length of the value.

    Returns

    Value of node, or empty string if node has no value.

    function xml_base::value_size

    Synopsis

    std::size_t value_size() const; +

    Description

    Gets size of node value, not including terminator character. This function works correctly irrespective of whether value is or is not zero terminated.

    Returns

    Size of node value, in characters.

    function xml_base::name

    Synopsis

    void name(const Ch *name, std::size_t size); +

    Description

    Sets name of node to a non zero-terminated string. See Ownership Of Strings .

    + Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

    + Size of name must be specified separately, because name does not have to be zero terminated. Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).

    Parameters

    name
    Name of node to set. Does not have to be zero terminated.
    size
    Size of name, in characters. This does not include zero terminator, if one is present.

    function xml_base::name

    Synopsis

    void name(const Ch *name); +

    Description

    Sets name of node to a zero-terminated string. See also Ownership Of Strings and xml_node::name(const Ch *, std::size_t).

    Parameters

    name
    Name of node to set. Must be zero terminated.

    function xml_base::value

    Synopsis

    void value(const Ch *value, std::size_t size); +

    Description

    Sets value of node to a non zero-terminated string. See Ownership Of Strings .

    + Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

    + Size of value must be specified separately, because it does not have to be zero terminated. Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).

    + If an element has a child node of type node_data, it will take precedence over element value when printing. If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.

    Parameters

    value
    value of node to set. Does not have to be zero terminated.
    size
    Size of value, in characters. This does not include zero terminator, if one is present.

    function xml_base::value

    Synopsis

    void value(const Ch *value); +

    Description

    Sets value of node to a zero-terminated string. See also Ownership Of Strings and xml_node::value(const Ch *, std::size_t).

    Parameters

    value
    Vame of node to set. Must be zero terminated.

    function xml_base::parent

    Synopsis

    xml_node<Ch>* parent() const; +

    Description

    Gets node parent.

    Returns

    Pointer to parent node, or 0 if there is no parent.

    class + template + rapidxml::xml_document

    + + Defined in rapidxml.hpp
    + Inherits from + xml_node memory_pool

    Description

    This class represents root of the DOM hierarchy. It is also an xml_node and a memory_pool through public inheritance. Use parse() function to build a DOM tree from a zero-terminated XML text string. parse() function allocates memory for nodes and attributes by using functions of xml_document, which are inherited from memory_pool. To access root node of the document, use the document itself, as if it was an xml_node.

    Parameters

    Ch
    Character type to use.

    + constructor + xml_document::xml_document

    Synopsis

    xml_document(); +

    Description

    Constructs empty XML document.

    function xml_document::parse

    Synopsis

    void parse(Ch *text); +

    Description

    Parses zero-terminated XML string according to given flags. Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. The string must persist for the lifetime of the document. In case of error, rapidxml::parse_error exception will be thrown.

    + If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. Make sure that data is zero-terminated.

    + Document can be parsed into multiple times. Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.

    Parameters

    text
    XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.

    function xml_document::clear

    Synopsis

    void clear(); +

    Description

    Clears the document by deleting all nodes and clearing the memory pool. All nodes owned by document pool are destroyed.

    class + template + rapidxml::xml_node

    + + Defined in rapidxml.hpp
    + Inherits from + xml_base
    + Base class for + xml_document

    Description

    Class representing a node of XML document. Each node may have associated name and value strings, which are available through name() and value() functions. Interpretation of name and value depends on type of the node. Type of node can be determined by using type() function.

    + Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. Thus, this text must persist in the memory for the lifetime of node.

    Parameters

    Ch
    Character type to use.

    + constructor + xml_node::xml_node

    Synopsis

    xml_node(node_type type); +

    Description

    Constructs an empty node with the specified type. Consider using memory_pool of appropriate document to allocate nodes manually.

    Parameters

    type
    Type of node to construct.

    function xml_node::type

    Synopsis

    node_type type() const; +

    Description

    Gets type of node.

    Returns

    Type of node.

    function xml_node::document

    Synopsis

    xml_document<Ch>* document() const; +

    Description

    Gets document of which node is a child.

    Returns

    Pointer to document that contains this node, or 0 if there is no parent document.

    function xml_node::first_node

    Synopsis

    xml_node<Ch>* first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets first child node, optionally matching node name.

    Parameters

    name
    Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found child, or 0 if not found.

    function xml_node::last_node

    Synopsis

    xml_node<Ch>* last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets last child node, optionally matching node name. Behaviour is undefined if node has no children. Use first_node() to test if node has children.

    Parameters

    name
    Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found child, or 0 if not found.

    function xml_node::previous_sibling

    Synopsis

    xml_node<Ch>* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets previous sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

    Parameters

    name
    Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found sibling, or 0 if not found.

    function xml_node::next_sibling

    Synopsis

    xml_node<Ch>* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets next sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

    Parameters

    name
    Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found sibling, or 0 if not found.

    function xml_node::first_attribute

    Synopsis

    xml_attribute<Ch>* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets first attribute of node, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    function xml_node::last_attribute

    Synopsis

    xml_attribute<Ch>* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets last attribute of node, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    function xml_node::type

    Synopsis

    void type(node_type type); +

    Description

    Sets type of node.

    Parameters

    type
    Type of node to set.

    function xml_node::prepend_node

    Synopsis

    void prepend_node(xml_node< Ch > *child); +

    Description

    Prepends a new child node. The prepended child becomes the first child, and all existing children are moved one position back.

    Parameters

    child
    Node to prepend.

    function xml_node::append_node

    Synopsis

    void append_node(xml_node< Ch > *child); +

    Description

    Appends a new child node. The appended child becomes the last child.

    Parameters

    child
    Node to append.

    function xml_node::insert_node

    Synopsis

    void insert_node(xml_node< Ch > *where, xml_node< Ch > *child); +

    Description

    Inserts a new child node at specified place inside the node. All children after and including the specified node are moved one position back.

    Parameters

    where
    Place where to insert the child, or 0 to insert at the back.
    child
    Node to insert.

    function xml_node::remove_first_node

    Synopsis

    void remove_first_node(); +

    Description

    Removes first child node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

    function xml_node::remove_last_node

    Synopsis

    void remove_last_node(); +

    Description

    Removes last child of the node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

    function xml_node::remove_node

    Synopsis

    void remove_node(xml_node< Ch > *where); +

    Description

    Removes specified child from the node.

    function xml_node::remove_all_nodes

    Synopsis

    void remove_all_nodes(); +

    Description

    Removes all child nodes (but not attributes).

    function xml_node::prepend_attribute

    Synopsis

    void prepend_attribute(xml_attribute< Ch > *attribute); +

    Description

    Prepends a new attribute to the node.

    Parameters

    attribute
    Attribute to prepend.

    function xml_node::append_attribute

    Synopsis

    void append_attribute(xml_attribute< Ch > *attribute); +

    Description

    Appends a new attribute to the node.

    Parameters

    attribute
    Attribute to append.

    function xml_node::insert_attribute

    Synopsis

    void insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute); +

    Description

    Inserts a new attribute at specified place inside the node. All attributes after and including the specified attribute are moved one position back.

    Parameters

    where
    Place where to insert the attribute, or 0 to insert at the back.
    attribute
    Attribute to insert.

    function xml_node::remove_first_attribute

    Synopsis

    void remove_first_attribute(); +

    Description

    Removes first attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

    function xml_node::remove_last_attribute

    Synopsis

    void remove_last_attribute(); +

    Description

    Removes last attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

    function xml_node::remove_attribute

    Synopsis

    void remove_attribute(xml_attribute< Ch > *where); +

    Description

    Removes specified attribute from node.

    Parameters

    where
    Pointer to attribute to be removed.

    function xml_node::remove_all_attributes

    Synopsis

    void remove_all_attributes(); +

    Description

    Removes all attributes of node.

    enum node_type

    Description

    Enumeration listing all node types produced by the parser. Use xml_node::type() function to query node type.

    Values

    node_document
    A document node. Name and value are empty.
    node_element
    An element node. Name contains element name. Value contains text of first data node.
    node_data
    A data node. Name is empty. Value contains data text.
    node_cdata
    A CDATA node. Name is empty. Value contains data text.
    node_comment
    A comment node. Name is empty. Value contains comment text.
    node_declaration
    A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
    node_doctype
    A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
    node_pi
    A PI node. Name contains target. Value contains instructions.

    function parse_error_handler

    Synopsis

    void rapidxml::parse_error_handler(const char *what, void *where); +

    Description

    When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function is called to notify user about the error. It must be defined by the user.

    + This function cannot return. If it does, the results are undefined.

    + A very simple definition might look like that: + void rapidxml::parse_error_handler(const char *what, void *where) + { + std::cout << "Parse error: " << what << "\n"; + std::abort(); + } +

    Parameters

    what
    Human readable description of the error.
    where
    Pointer to character data where error was detected.

    function print

    Synopsis

    OutIt rapidxml::print(OutIt out, const xml_node< Ch > &node, int flags=0); +

    Description

    Prints XML to given output iterator.

    Parameters

    out
    Output iterator to print to.
    node
    Node to be printed. Pass xml_document to print entire document.
    flags
    Flags controlling how XML is printed.

    Returns

    Output iterator pointing to position immediately after last character of printed text.

    function print

    Synopsis

    std::basic_ostream<Ch>& rapidxml::print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0); +

    Description

    Prints XML to given output stream.

    Parameters

    out
    Output stream to print to.
    node
    Node to be printed. Pass xml_document to print entire document.
    flags
    Flags controlling how XML is printed.

    Returns

    Output stream.

    function operator<<

    Synopsis

    std::basic_ostream<Ch>& rapidxml::operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node); +

    Description

    Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.

    Parameters

    out
    Output stream to print to.
    node
    Node to be printed.

    Returns

    Output stream.

    + constant + parse_no_data_nodes

    Synopsis

    const int parse_no_data_nodes + = 0x1; +

    Description

    Parse flag instructing the parser to not create data nodes. Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_no_element_values

    Synopsis

    const int parse_no_element_values + = 0x2; +

    Description

    Parse flag instructing the parser to not use text of first data node as a value of parent element. Can be combined with other flags by use of | operator. Note that child data nodes of element node take precendence over its value when printing. That is, if element has one or more child data nodes and a value, the value will be ignored. Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.

    + See xml_document::parse() function.

    + constant + parse_no_string_terminators

    Synopsis

    const int parse_no_string_terminators + = 0x4; +

    Description

    Parse flag instructing the parser to not place zero terminators after strings in the source text. By default zero terminators are placed, modifying source text. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_no_entity_translation

    Synopsis

    const int parse_no_entity_translation + = 0x8; +

    Description

    Parse flag instructing the parser to not translate entities in the source text. By default entities are translated, modifying source text. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_no_utf8

    Synopsis

    const int parse_no_utf8 + = 0x10; +

    Description

    Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. By default, UTF-8 handling is enabled. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_declaration_node

    Synopsis

    const int parse_declaration_node + = 0x20; +

    Description

    Parse flag instructing the parser to create XML declaration node. By default, declaration node is not created. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_comment_nodes

    Synopsis

    const int parse_comment_nodes + = 0x40; +

    Description

    Parse flag instructing the parser to create comments nodes. By default, comment nodes are not created. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_doctype_node

    Synopsis

    const int parse_doctype_node + = 0x80; +

    Description

    Parse flag instructing the parser to create DOCTYPE node. By default, doctype node is not created. Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_pi_nodes

    Synopsis

    const int parse_pi_nodes + = 0x100; +

    Description

    Parse flag instructing the parser to create PI nodes. By default, PI nodes are not created. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_validate_closing_tags

    Synopsis

    const int parse_validate_closing_tags + = 0x200; +

    Description

    Parse flag instructing the parser to validate closing tag names. If not set, name inside closing tag is irrelevant to the parser. By default, closing tags are not validated. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_trim_whitespace

    Synopsis

    const int parse_trim_whitespace + = 0x400; +

    Description

    Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. By default, whitespace is not trimmed. This flag does not cause the parser to modify source text. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_normalize_whitespace

    Synopsis

    const int parse_normalize_whitespace + = 0x800; +

    Description

    Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. By default, whitespace is not normalized. If this flag is specified, source text will be modified. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_default

    Synopsis

    const int parse_default + = 0; +

    Description

    Parse flags which represent default behaviour of the parser. This is always equal to 0, so that all other flags can be simply ored together. Normally there is no need to inconveniently disable flags by anding with their negated (~) values. This also means that meaning of each flag is a negation of the default setting. For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, and using the flag will disable it.

    + See xml_document::parse() function.

    + constant + parse_non_destructive

    Synopsis

    const int parse_non_destructive + = parse_no_string_terminators | parse_no_entity_translation; +

    Description

    A combination of parse flags that forbids any modifications of the source text. This also results in faster parsing. However, note that the following will occur:
    • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
    • entities will not be translated
    • whitespace will not be normalized
    +See xml_document::parse() function.

    + constant + parse_fastest

    Synopsis

    const int parse_fastest + = parse_non_destructive | parse_no_data_nodes; +

    Description

    A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.

    + See xml_document::parse() function.

    + constant + parse_full

    Synopsis

    const int parse_full + = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; +

    Description

    A combination of parse flags resulting in largest amount of data being extracted. This usually results in slowest parsing.

    + See xml_document::parse() function.

    + constant + print_no_indenting

    Synopsis

    const int print_no_indenting + = 0x1; +

    Description

    Printer flag instructing the printer to suppress indenting of XML. See print() function.

    \ No newline at end of file diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml.hpp new file mode 100644 index 0000000000..ae91e081d0 --- /dev/null +++ b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml.hpp @@ -0,0 +1,2596 @@ +#ifndef RAPIDXML_HPP_INCLUDED +#define RAPIDXML_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation + +// If standard library is disabled, user must provide implementations of required functions and typedefs +#if !defined(RAPIDXML_NO_STDLIB) + #include // For std::size_t + #include // For assert + #include // For placement new +#endif + +// On MSVC, disable "conditional expression is constant" warning (level 4). +// This warning is almost impossible to avoid with certain types of templated code +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4127) // Conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////// +// RAPIDXML_PARSE_ERROR + +#if defined(RAPIDXML_NO_EXCEPTIONS) + +#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } + +namespace rapidxml +{ + //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, + //! this function is called to notify user about the error. + //! It must be defined by the user. + //!

    + //! This function cannot return. If it does, the results are undefined. + //!

    + //! A very simple definition might look like that: + //!

    +    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
    +    //! {
    +    //!     std::cout << "Parse error: " << what << "\n";
    +    //!     std::abort();
    +    //! }
    +    //! 
    + //! \param what Human readable description of the error. + //! \param where Pointer to character data where error was detected. + void parse_error_handler(const char *what, void *where); +} + +#else + +#include // For std::exception + +#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) + +namespace rapidxml +{ + + //! Parse error exception. + //! This exception is thrown by the parser when an error occurs. + //! Use what() function to get human-readable error message. + //! Use where() function to get a pointer to position within source text where error was detected. + //!

    + //! If throwing exceptions by the parser is undesirable, + //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. + //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. + //! This function must be defined by the user. + //!

    + //! This class derives from std::exception class. + class parse_error: public std::exception + { + + public: + + //! Constructs parse error + parse_error(const char *what, void *where) + : m_what(what) + , m_where(where) + { + } + + //! Gets human readable description of error. + //! \return Pointer to null terminated description of the error. + virtual const char *what() const throw() + { + return m_what; + } + + //! Gets pointer to character data where error happened. + //! Ch should be the same as char type of xml_document that produced the error. + //! \return Pointer to location within the parsed string where error occured. + template + Ch *where() const + { + return reinterpret_cast(m_where); + } + + private: + + const char *m_what; + void *m_where; + + }; +} + +#endif + +/////////////////////////////////////////////////////////////////////////// +// Pool sizes + +#ifndef RAPIDXML_STATIC_POOL_SIZE + // Size of static memory block of memory_pool. + // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // No dynamic memory allocations are performed by memory_pool until static memory is exhausted. + #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_DYNAMIC_POOL_SIZE + // Size of dynamic memory block of memory_pool. + // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. + #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_ALIGNMENT + // Memory allocation alignment. + // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. + // All memory allocations for nodes, attributes and strings will be aligned to this value. + // This must be a power of 2 and at least 1, otherwise memory_pool will not work. + #define RAPIDXML_ALIGNMENT sizeof(void *) +#endif + +namespace rapidxml +{ + // Forward declarations + template class xml_node; + template class xml_attribute; + template class xml_document; + + //! Enumeration listing all node types produced by the parser. + //! Use xml_node::type() function to query node type. + enum node_type + { + node_document, //!< A document node. Name and value are empty. + node_element, //!< An element node. Name contains element name. Value contains text of first data node. + node_data, //!< A data node. Name is empty. Value contains data text. + node_cdata, //!< A CDATA node. Name is empty. Value contains data text. + node_comment, //!< A comment node. Name is empty. Value contains comment text. + node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. + node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. + node_pi //!< A PI node. Name contains target. Value contains instructions. + }; + + /////////////////////////////////////////////////////////////////////// + // Parsing flags + + //! Parse flag instructing the parser to not create data nodes. + //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_data_nodes = 0x1; + + //! Parse flag instructing the parser to not use text of first data node as a value of parent element. + //! Can be combined with other flags by use of | operator. + //! Note that child data nodes of element node take precendence over its value when printing. + //! That is, if element has one or more child data nodes and a value, the value will be ignored. + //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. + //!

    + //! See xml_document::parse() function. + const int parse_no_element_values = 0x2; + + //! Parse flag instructing the parser to not place zero terminators after strings in the source text. + //! By default zero terminators are placed, modifying source text. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_string_terminators = 0x4; + + //! Parse flag instructing the parser to not translate entities in the source text. + //! By default entities are translated, modifying source text. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_entity_translation = 0x8; + + //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. + //! By default, UTF-8 handling is enabled. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_utf8 = 0x10; + + //! Parse flag instructing the parser to create XML declaration node. + //! By default, declaration node is not created. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_declaration_node = 0x20; + + //! Parse flag instructing the parser to create comments nodes. + //! By default, comment nodes are not created. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_comment_nodes = 0x40; + + //! Parse flag instructing the parser to create DOCTYPE node. + //! By default, doctype node is not created. + //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_doctype_node = 0x80; + + //! Parse flag instructing the parser to create PI nodes. + //! By default, PI nodes are not created. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_pi_nodes = 0x100; + + //! Parse flag instructing the parser to validate closing tag names. + //! If not set, name inside closing tag is irrelevant to the parser. + //! By default, closing tags are not validated. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_validate_closing_tags = 0x200; + + //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. + //! By default, whitespace is not trimmed. + //! This flag does not cause the parser to modify source text. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_trim_whitespace = 0x400; + + //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. + //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. + //! By default, whitespace is not normalized. + //! If this flag is specified, source text will be modified. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_normalize_whitespace = 0x800; + + // Compound flags + + //! Parse flags which represent default behaviour of the parser. + //! This is always equal to 0, so that all other flags can be simply ored together. + //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. + //! This also means that meaning of each flag is a negation of the default setting. + //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, + //! and using the flag will disable it. + //!

    + //! See xml_document::parse() function. + const int parse_default = 0; + + //! A combination of parse flags that forbids any modifications of the source text. + //! This also results in faster parsing. However, note that the following will occur: + //!
      + //!
    • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
    • + //!
    • entities will not be translated
    • + //!
    • whitespace will not be normalized
    • + //!
    + //! See xml_document::parse() function. + const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation; + + //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. + //!

    + //! See xml_document::parse() function. + const int parse_fastest = parse_non_destructive | parse_no_data_nodes; + + //! A combination of parse flags resulting in largest amount of data being extracted. + //! This usually results in slowest parsing. + //!

    + //! See xml_document::parse() function. + const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; + + /////////////////////////////////////////////////////////////////////// + // Internals + + //! \cond internal + namespace internal + { + + // Struct that contains lookup tables for the parser + // It must be a template to allow correct linking (because it has static data members, which are defined in a header file). + template + struct lookup_tables + { + static const unsigned char lookup_whitespace[256]; // Whitespace table + static const unsigned char lookup_node_name[256]; // Node name table + static const unsigned char lookup_text[256]; // Text table + static const unsigned char lookup_text_pure_no_ws[256]; // Text table + static const unsigned char lookup_text_pure_with_ws[256]; // Text table + static const unsigned char lookup_attribute_name[256]; // Attribute name table + static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes + static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes + static const unsigned char lookup_digits[256]; // Digits + static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters + }; + + // Find length of the string + template + inline std::size_t measure(const Ch *p) + { + const Ch *tmp = p; + while (*tmp) + ++tmp; + return tmp - p; + } + + // Compare strings for equality + template + inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive) + { + if (size1 != size2) + return false; + if (case_sensitive) + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (*p1 != *p2) + return false; + } + else + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) + return false; + } + return true; + } + } + //! \endcond + + /////////////////////////////////////////////////////////////////////// + // Memory pool + + //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. + //! In most cases, you will not need to use this class directly. + //! However, if you need to create nodes manually or modify names/values of nodes, + //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. + //! Not only is this faster than allocating them by using new operator, + //! but also their lifetime will be tied to the lifetime of document, + //! possibly simplyfing memory management. + //!

    + //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. + //! You can also call allocate_string() function to allocate strings. + //! Such strings can then be used as names or values of nodes without worrying about their lifetime. + //! Note that there is no free() function -- all allocations are freed at once when clear() function is called, + //! or when the pool is destroyed. + //!

    + //! It is also possible to create a standalone memory_pool, and use it + //! to allocate nodes, whose lifetime will not be tied to any document. + //!

    + //! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. + //! Until static memory is exhausted, no dynamic memory allocations are done. + //! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, + //! by using global new[] and delete[] operators. + //! This behaviour can be changed by setting custom allocation routines. + //! Use set_allocator() function to set them. + //!

    + //! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. + //! This value defaults to the size of pointer on target architecture. + //!

    + //! To obtain absolutely top performance from the parser, + //! it is important that all nodes are allocated from a single, contiguous block of memory. + //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. + //! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT + //! to obtain best wasted memory to performance compromise. + //! To do it, define their values before rapidxml.hpp file is included. + //! \param Ch Character type of created nodes. + template + class memory_pool + { + + public: + + //! \cond internal + typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (free_func)(void *); // Type of user-defined function used to free memory + //! \endcond + + //! Constructs empty pool with default allocator functions. + memory_pool() + : m_alloc_func(0) + , m_free_func(0) + { + init(); + } + + //! Destroys pool and frees all the memory. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Nodes allocated from the pool are no longer valid. + ~memory_pool() + { + clear(); + } + + //! Allocates a new node from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param type Type of node to create. + //! \param name Name to assign to the node, or 0 to assign no name. + //! \param value Value to assign to the node, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated node. This pointer will never be NULL. + xml_node *allocate_node(node_type type, + const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_node)); + xml_node *node = new(memory) xml_node(type); + if (name) + { + if (name_size > 0) + node->name(name, name_size); + else + node->name(name); + } + if (value) + { + if (value_size > 0) + node->value(value, value_size); + else + node->value(value); + } + return node; + } + + //! Allocates a new attribute from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param name Name to assign to the attribute, or 0 to assign no name. + //! \param value Value to assign to the attribute, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated attribute. This pointer will never be NULL. + xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_attribute)); + xml_attribute *attribute = new(memory) xml_attribute; + if (name) + { + if (name_size > 0) + attribute->name(name, name_size); + else + attribute->name(name); + } + if (value) + { + if (value_size > 0) + attribute->value(value, value_size); + else + attribute->value(value); + } + return attribute; + } + + //! Allocates a char array of given size from the pool, and optionally copies a given string to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param source String to initialize the allocated memory with, or 0 to not initialize it. + //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. + //! \return Pointer to allocated char array. This pointer will never be NULL. + Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) + { + assert(source || size); // Either source or size (or both) must be specified + if (size == 0) + size = internal::measure(source) + 1; + Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); + if (source) + for (std::size_t i = 0; i < size; ++i) + result[i] = source[i]; + return result; + } + + //! Clones an xml_node and its hierarchy of child nodes and attributes. + //! Nodes and attributes are allocated from this memory pool. + //! Names and values are not cloned, they are shared between the clone and the source. + //! Result node can be optionally specified as a second parameter, + //! in which case its contents will be replaced with cloned source node. + //! This is useful when you want to clone entire document. + //! \param source Node to clone. + //! \param result Node to put results in, or 0 to automatically allocate result node + //! \return Pointer to cloned node. This pointer will never be NULL. + xml_node *clone_node(const xml_node *source, xml_node *result = 0) + { + // Prepare result node + if (result) + { + result->remove_all_attributes(); + result->remove_all_nodes(); + result->type(source->type()); + } + else + result = allocate_node(source->type()); + + // Clone name and value + result->name(source->name(), source->name_size()); + result->value(source->value(), source->value_size()); + + // Clone child nodes and attributes + for (xml_node *child = source->first_node(); child; child = child->next_sibling()) + result->append_node(clone_node(child)); + for (xml_attribute *attr = source->first_attribute(); attr; attr = attr->next_attribute()) + result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size())); + + return result; + } + + //! Clears the pool. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Any nodes or strings allocated from the pool will no longer be valid. + void clear() + { + while (m_begin != m_static_memory) + { + char *previous_begin = reinterpret_cast
    (align(m_begin))->previous_begin; + if (m_free_func) + m_free_func(m_begin); + else + delete[] m_begin; + m_begin = previous_begin; + } + init(); + } + + //! Sets or resets the user-defined memory allocation functions for the pool. + //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. + //! Allocation function must not return invalid pointer on failure. It should either throw, + //! stop the program, or use longjmp() function to pass control to other place of program. + //! If it returns invalid pointer, results are undefined. + //!

    + //! User defined allocation functions must have the following forms: + //!
    + //!
    void *allocate(std::size_t size); + //!
    void free(void *pointer); + //!

    + //! \param af Allocation function, or 0 to restore default function + //! \param ff Free function, or 0 to restore default function + void set_allocator(alloc_func *af, free_func *ff) + { + assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + m_alloc_func = af; + m_free_func = ff; + } + + private: + + struct header + { + char *previous_begin; + }; + + void init() + { + m_begin = m_static_memory; + m_ptr = align(m_begin); + m_end = m_static_memory + sizeof(m_static_memory); + } + + char *align(char *ptr) + { + std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1)); + return ptr + alignment; + } + + char *allocate_raw(std::size_t size) + { + // Allocate + void *memory; + if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] + { + memory = m_alloc_func(size); + assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + } + else + { + memory = new char[size]; +#ifdef RAPIDXML_NO_EXCEPTIONS + if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc + RAPIDXML_PARSE_ERROR("out of memory", 0); +#endif + } + return static_cast(memory); + } + + void *allocate_aligned(std::size_t size) + { + // Calculate aligned pointer + char *result = align(m_ptr); + + // If not enough memory left in current pool, allocate a new pool + if (result + size > m_end) + { + // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + if (pool_size < size) + pool_size = size; + + // Allocate + std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + char *raw_memory = allocate_raw(alloc_size); + + // Setup new pool in allocated memory + char *pool = align(raw_memory); + header *new_header = reinterpret_cast
    (pool); + new_header->previous_begin = m_begin; + m_begin = raw_memory; + m_ptr = pool + sizeof(header); + m_end = raw_memory + alloc_size; + + // Calculate aligned pointer again using new pool + result = align(m_ptr); + } + + // Update pool and return aligned pointer + m_ptr = result + size; + return result; + } + + char *m_begin; // Start of raw memory making up current pool + char *m_ptr; // First free byte in current pool + char *m_end; // One past last available byte in current pool + char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + free_func *m_free_func; // Free function, or 0 if default is to be used + }; + + /////////////////////////////////////////////////////////////////////////// + // XML base + + //! Base class for xml_node and xml_attribute implementing common functions: + //! name(), name_size(), value(), value_size() and parent(). + //! \param Ch Character type to use + template + class xml_base + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + // Construct a base with empty name, value and parent + xml_base() + : m_name(0) + , m_value(0) + , m_parent(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets name of the node. + //! Interpretation of name depends on type of node. + //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

    + //! Use name_size() function to determine length of the name. + //! \return Name of node, or empty string if node has no name. + Ch *name() const + { + return m_name ? m_name : nullstr(); + } + + //! Gets size of node name, not including terminator character. + //! This function works correctly irrespective of whether name is or is not zero terminated. + //! \return Size of node name, in characters. + std::size_t name_size() const + { + return m_name ? m_name_size : 0; + } + + //! Gets value of node. + //! Interpretation of value depends on type of node. + //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

    + //! Use value_size() function to determine length of the value. + //! \return Value of node, or empty string if node has no value. + Ch *value() const + { + return m_value ? m_value : nullstr(); + } + + //! Gets size of node value, not including terminator character. + //! This function works correctly irrespective of whether value is or is not zero terminated. + //! \return Size of node value, in characters. + std::size_t value_size() const + { + return m_value ? m_value_size : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets name of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

    + //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

    + //! Size of name must be specified separately, because name does not have to be zero terminated. + //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! \param name Name of node to set. Does not have to be zero terminated. + //! \param size Size of name, in characters. This does not include zero terminator, if one is present. + void name(const Ch *name, std::size_t size) + { + m_name = const_cast(name); + m_name_size = size; + } + + //! Sets name of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). + //! \param name Name of node to set. Must be zero terminated. + void name(const Ch *name) + { + this->name(name, internal::measure(name)); + } + + //! Sets value of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

    + //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

    + //! Size of value must be specified separately, because it does not have to be zero terminated. + //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //!

    + //! If an element has a child node of type node_data, it will take precedence over element value when printing. + //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. + //! \param value value of node to set. Does not have to be zero terminated. + //! \param size Size of value, in characters. This does not include zero terminator, if one is present. + void value(const Ch *value, std::size_t size) + { + m_value = const_cast(value); + m_value_size = size; + } + + //! Sets value of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). + //! \param value Vame of node to set. Must be zero terminated. + void value(const Ch *value) + { + this->value(value, internal::measure(value)); + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets node parent. + //! \return Pointer to parent node, or 0 if there is no parent. + xml_node *parent() const + { + return m_parent; + } + + protected: + + // Return empty string + static Ch *nullstr() + { + static Ch zero = Ch('\0'); + return &zero; + } + + Ch *m_name; // Name of node, or 0 if no name + Ch *m_value; // Value of node, or 0 if no value + std::size_t m_name_size; // Length of node name, or undefined of no name + std::size_t m_value_size; // Length of node value, or undefined if no value + xml_node *m_parent; // Pointer to parent node, or 0 if none + + }; + + //! Class representing attribute node of XML document. + //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). + //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. + //! Thus, this text must persist in memory for the lifetime of attribute. + //! \param Ch Character type to use. + template + class xml_attribute: public xml_base + { + + friend class xml_node; + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty attribute with the specified type. + //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. + xml_attribute() + { + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which attribute is a child. + //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. + xml_document *document() const + { + if (xml_node *node = this->parent()) + { + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast *>(node) : 0; + } + else + return 0; + } + + //! Gets previous attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_prev_attribute : 0; + } + + //! Gets next attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_next_attribute : 0; + } + + private: + + xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero + xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML node + + //! Class representing a node of XML document. + //! Each node may have associated name and value strings, which are available through name() and value() functions. + //! Interpretation of name and value depends on type of the node. + //! Type of node can be determined by using type() function. + //!

    + //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. + //! Thus, this text must persist in the memory for the lifetime of node. + //! \param Ch Character type to use. + template + class xml_node: public xml_base + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty node with the specified type. + //! Consider using memory_pool of appropriate document to allocate nodes manually. + //! \param type Type of node to construct. + xml_node(node_type type) + : m_type(type) + , m_first_node(0) + , m_first_attribute(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets type of node. + //! \return Type of node. + node_type type() const + { + return m_type; + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which node is a child. + //! \return Pointer to document that contains this node, or 0 if there is no parent document. + xml_document *document() const + { + xml_node *node = const_cast *>(this); + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast *>(node) : 0; + } + + //! Gets first child node, optionally matching node name. + //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *child = m_first_node; child; child = child->next_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_first_node; + } + + //! Gets last child node, optionally matching node name. + //! Behaviour is undefined if node has no children. + //! Use first_node() to test if node has children. + //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(m_first_node); // Cannot query for last child if node has no children + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *child = m_last_node; child; child = child->previous_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_last_node; + } + + //! Gets previous sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_prev_sibling; + } + + //! Gets next sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_next_sibling; + } + + //! Gets first attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute; + } + + //! Gets last attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute ? m_last_attribute : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets type of node. + //! \param type Type of node to set. + void type(node_type type) + { + m_type = type; + } + + /////////////////////////////////////////////////////////////////////////// + // Node manipulation + + //! Prepends a new child node. + //! The prepended child becomes the first child, and all existing children are moved one position back. + //! \param child Node to prepend. + void prepend_node(xml_node *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_next_sibling = m_first_node; + m_first_node->m_prev_sibling = child; + } + else + { + child->m_next_sibling = 0; + m_last_node = child; + } + m_first_node = child; + child->m_parent = this; + child->m_prev_sibling = 0; + } + + //! Appends a new child node. + //! The appended child becomes the last child. + //! \param child Node to append. + void append_node(xml_node *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_prev_sibling = m_last_node; + m_last_node->m_next_sibling = child; + } + else + { + child->m_prev_sibling = 0; + m_first_node = child; + } + m_last_node = child; + child->m_parent = this; + child->m_next_sibling = 0; + } + + //! Inserts a new child node at specified place inside the node. + //! All children after and including the specified node are moved one position back. + //! \param where Place where to insert the child, or 0 to insert at the back. + //! \param child Node to insert. + void insert_node(xml_node *where, xml_node *child) + { + assert(!where || where->parent() == this); + assert(child && !child->parent() && child->type() != node_document); + if (where == m_first_node) + prepend_node(child); + else if (where == 0) + append_node(child); + else + { + child->m_prev_sibling = where->m_prev_sibling; + child->m_next_sibling = where; + where->m_prev_sibling->m_next_sibling = child; + where->m_prev_sibling = child; + child->m_parent = this; + } + } + + //! Removes first child node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_first_node() + { + assert(first_node()); + xml_node *child = m_first_node; + m_first_node = child->m_next_sibling; + if (child->m_next_sibling) + child->m_next_sibling->m_prev_sibling = 0; + else + m_last_node = 0; + child->m_parent = 0; + } + + //! Removes last child of the node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_last_node() + { + assert(first_node()); + xml_node *child = m_last_node; + if (child->m_prev_sibling) + { + m_last_node = child->m_prev_sibling; + child->m_prev_sibling->m_next_sibling = 0; + } + else + m_first_node = 0; + child->m_parent = 0; + } + + //! Removes specified child from the node + // \param where Pointer to child to be removed. + void remove_node(xml_node *where) + { + assert(where && where->parent() == this); + assert(first_node()); + if (where == m_first_node) + remove_first_node(); + else if (where == m_last_node) + remove_last_node(); + else + { + where->m_prev_sibling->m_next_sibling = where->m_next_sibling; + where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; + where->m_parent = 0; + } + } + + //! Removes all child nodes (but not attributes). + void remove_all_nodes() + { + for (xml_node *node = first_node(); node; node = node->m_next_sibling) + node->m_parent = 0; + m_first_node = 0; + } + + //! Prepends a new attribute to the node. + //! \param attribute Attribute to prepend. + void prepend_attribute(xml_attribute *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_next_attribute = m_first_attribute; + m_first_attribute->m_prev_attribute = attribute; + } + else + { + attribute->m_next_attribute = 0; + m_last_attribute = attribute; + } + m_first_attribute = attribute; + attribute->m_parent = this; + attribute->m_prev_attribute = 0; + } + + //! Appends a new attribute to the node. + //! \param attribute Attribute to append. + void append_attribute(xml_attribute *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_prev_attribute = m_last_attribute; + m_last_attribute->m_next_attribute = attribute; + } + else + { + attribute->m_prev_attribute = 0; + m_first_attribute = attribute; + } + m_last_attribute = attribute; + attribute->m_parent = this; + attribute->m_next_attribute = 0; + } + + //! Inserts a new attribute at specified place inside the node. + //! All attributes after and including the specified attribute are moved one position back. + //! \param where Place where to insert the attribute, or 0 to insert at the back. + //! \param attribute Attribute to insert. + void insert_attribute(xml_attribute *where, xml_attribute *attribute) + { + assert(!where || where->parent() == this); + assert(attribute && !attribute->parent()); + if (where == m_first_attribute) + prepend_attribute(attribute); + else if (where == 0) + append_attribute(attribute); + else + { + attribute->m_prev_attribute = where->m_prev_attribute; + attribute->m_next_attribute = where; + where->m_prev_attribute->m_next_attribute = attribute; + where->m_prev_attribute = attribute; + attribute->m_parent = this; + } + } + + //! Removes first attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_first_attribute() + { + assert(first_attribute()); + xml_attribute *attribute = m_first_attribute; + if (attribute->m_next_attribute) + { + attribute->m_next_attribute->m_prev_attribute = 0; + } + else + m_last_attribute = 0; + attribute->m_parent = 0; + m_first_attribute = attribute->m_next_attribute; + } + + //! Removes last attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_last_attribute() + { + assert(first_attribute()); + xml_attribute *attribute = m_last_attribute; + if (attribute->m_prev_attribute) + { + attribute->m_prev_attribute->m_next_attribute = 0; + m_last_attribute = attribute->m_prev_attribute; + } + else + m_first_attribute = 0; + attribute->m_parent = 0; + } + + //! Removes specified attribute from node. + //! \param where Pointer to attribute to be removed. + void remove_attribute(xml_attribute *where) + { + assert(first_attribute() && where->parent() == this); + if (where == m_first_attribute) + remove_first_attribute(); + else if (where == m_last_attribute) + remove_last_attribute(); + else + { + where->m_prev_attribute->m_next_attribute = where->m_next_attribute; + where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; + where->m_parent = 0; + } + } + + //! Removes all attributes of node. + void remove_all_attributes() + { + for (xml_attribute *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute) + attribute->m_parent = 0; + m_first_attribute = 0; + } + + private: + + /////////////////////////////////////////////////////////////////////////// + // Restrictions + + // No copying + xml_node(const xml_node &); + void operator =(const xml_node &); + + /////////////////////////////////////////////////////////////////////////// + // Data members + + // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. + // This is required for maximum performance, as it allows the parser to omit initialization of + // unneded/redundant values. + // + // The rules are as follows: + // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively + // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage + // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage + + node_type m_type; // Type of node; always valid + xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid + xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero + xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid + xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero + xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML document + + //! This class represents root of the DOM hierarchy. + //! It is also an xml_node and a memory_pool through public inheritance. + //! Use parse() function to build a DOM tree from a zero-terminated XML text string. + //! parse() function allocates memory for nodes and attributes by using functions of xml_document, + //! which are inherited from memory_pool. + //! To access root node of the document, use the document itself, as if it was an xml_node. + //! \param Ch Character type to use. + template + class xml_document: public xml_node, public memory_pool + { + + public: + + //! Constructs empty XML document + xml_document() + : xml_node(node_document) + { + } + + //! Parses zero-terminated XML string according to given flags. + //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. + //! The string must persist for the lifetime of the document. + //! In case of error, rapidxml::parse_error exception will be thrown. + //!

    + //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. + //! Make sure that data is zero-terminated. + //!

    + //! Document can be parsed into multiple times. + //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. + //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. + template + void parse(Ch *text) + { + assert(text); + + // Remove current contents + this->remove_all_nodes(); + this->remove_all_attributes(); + + // Parse BOM, if any + parse_bom(text); + + // Parse children + while (1) + { + // Skip whitespace before node + skip(text); + if (*text == 0) + break; + + // Parse and append new child + if (*text == Ch('<')) + { + ++text; // Skip '<' + if (xml_node *node = parse_node(text)) + this->append_node(node); + } + else + RAPIDXML_PARSE_ERROR("expected <", text); + } + + } + + //! Clears the document by deleting all nodes and clearing the memory pool. + //! All nodes owned by document pool are destroyed. + void clear() + { + this->remove_all_nodes(); + this->remove_all_attributes(); + memory_pool::clear(); + } + + private: + + /////////////////////////////////////////////////////////////////////// + // Internal character utility functions + + // Detect whitespace character + struct whitespace_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; + } + }; + + // Detect node name character + struct node_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; + } + }; + + // Detect attribute name character + struct attribute_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) + struct text_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_no_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_with_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; + } + }; + + // Detect attribute value character + template + struct attribute_value_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Detect attribute value character + template + struct attribute_value_pure_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Insert coded character, using UTF8 or 8-bit ASCII + template + static void insert_coded_character(Ch *&text, unsigned long code) + { + if (Flags & parse_no_utf8) + { + // Insert 8-bit ASCII character + // Todo: possibly verify that code is less than 256 and use replacement char otherwise? + text[0] = static_cast(code); + text += 1; + } + else + { + // Insert UTF8 sequence + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast(code); + text += 1; + } + else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xC0); + text += 2; + } + else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xE0); + text += 3; + } + else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xF0); + text += 4; + } + else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + } + } + } + + // Skip characters until predicate evaluates to true + template + static void skip(Ch *&text) + { + Ch *tmp = text; + while (StopPred::test(*tmp)) + ++tmp; + text = tmp; + } + + // Skip characters until predicate evaluates to true while doing the following: + // - replacing XML character entity references with proper characters (' & " < > &#...;) + // - condensing whitespace sequences to single space character + template + static Ch *skip_and_expand_character_refs(Ch *&text) + { + // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip + if (Flags & parse_no_entity_translation && + !(Flags & parse_normalize_whitespace) && + !(Flags & parse_trim_whitespace)) + { + skip(text); + return text; + } + + // Use simple skip until first modification is detected + skip(text); + + // Use translation skip + Ch *src = text; + Ch *dest = src; + while (StopPred::test(*src)) + { + // If entity translation is enabled + if (!(Flags & parse_no_entity_translation)) + { + // Test if replacement is needed + if (src[0] == Ch('&')) + { + switch (src[1]) + { + + // & ' + case Ch('a'): + if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) + { + *dest = Ch('&'); + ++dest; + src += 5; + continue; + } + if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';')) + { + *dest = Ch('\''); + ++dest; + src += 6; + continue; + } + break; + + // " + case Ch('q'): + if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';')) + { + *dest = Ch('"'); + ++dest; + src += 6; + continue; + } + break; + + // > + case Ch('g'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('>'); + ++dest; + src += 4; + continue; + } + break; + + // < + case Ch('l'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('<'); + ++dest; + src += 4; + continue; + } + break; + + // &#...; - assumes ASCII + case Ch('#'): + if (src[2] == Ch('x')) + { + unsigned long code = 0; + src += 3; // Skip &#x + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) + break; + code = code * 16 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + else + { + unsigned long code = 0; + src += 2; // Skip &# + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) + break; + code = code * 10 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + if (*src == Ch(';')) + ++src; + else + RAPIDXML_PARSE_ERROR("expected ;", src); + continue; + + // Something else + default: + // Ignore, just copy '&' verbatim + break; + + } + } + } + + // If whitespace condensing is enabled + if (Flags & parse_normalize_whitespace) + { + // Test if condensing is needed + if (whitespace_pred::test(*src)) + { + *dest = Ch(' '); ++dest; // Put single space in dest + ++src; // Skip first whitespace char + // Skip remaining whitespace chars + while (whitespace_pred::test(*src)) + ++src; + continue; + } + } + + // No replacement, only copy character + *dest++ = *src++; + + } + + // Return new end + text = src; + return dest; + + } + + /////////////////////////////////////////////////////////////////////// + // Internal parsing functions + + // Parse BOM, if any + template + void parse_bom(Ch *&text) + { + // UTF-8? + if (static_cast(text[0]) == 0xEF && + static_cast(text[1]) == 0xBB && + static_cast(text[2]) == 0xBF) + { + text += 3; // Skup utf-8 bom + } + } + + // Parse XML declaration ( + xml_node *parse_xml_declaration(Ch *&text) + { + // If parsing of declaration is disabled + if (!(Flags & parse_declaration_node)) + { + // Skip until end of declaration + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + + // Create declaration + xml_node *declaration = this->allocate_node(node_declaration); + + // Skip whitespace before attributes or ?> + skip(text); + + // Parse declaration attributes + parse_node_attributes(text, declaration); + + // Skip ?> + if (text[0] != Ch('?') || text[1] != Ch('>')) + RAPIDXML_PARSE_ERROR("expected ?>", text); + text += 2; + + return declaration; + } + + // Parse XML comment (' + return 0; // Do not produce comment node + } + + // Remember value start + Ch *value = text; + + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create comment node + xml_node *comment = this->allocate_node(node_comment); + comment->value(value, text - value); + + // Place zero terminator after comment value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip '-->' + return comment; + } + + // Parse DOCTYPE + template + xml_node *parse_doctype(Ch *&text) + { + // Remember value start + Ch *value = text; + + // Skip to > + while (*text != Ch('>')) + { + // Determine character type + switch (*text) + { + + // If '[' encountered, scan for matching ending ']' using naive algorithm with depth + // This works for all W3C test files except for 2 most wicked + case Ch('['): + { + ++text; // Skip '[' + int depth = 1; + while (depth > 0) + { + switch (*text) + { + case Ch('['): ++depth; break; + case Ch(']'): --depth; break; + case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); + } + ++text; + } + break; + } + + // Error on end of text + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Other character, skip it + default: + ++text; + + } + } + + // If DOCTYPE nodes enabled + if (Flags & parse_doctype_node) + { + // Create a new doctype node + xml_node *doctype = this->allocate_node(node_doctype); + doctype->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 1; // skip '>' + return doctype; + } + else + { + text += 1; // skip '>' + return 0; + } + + } + + // Parse PI + template + xml_node *parse_pi(Ch *&text) + { + // If creation of PI nodes is enabled + if (Flags & parse_pi_nodes) + { + // Create pi node + xml_node *pi = this->allocate_node(node_pi); + + // Extract PI target name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(name, text - name); + + // Skip whitespace between pi target and pi + skip(text); + + // Remember start of pi + Ch *value = text; + + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Set pi value (verbatim, no entity expansion or whitespace normalization) + pi->value(value, text - value); + + // Place zero terminator after name and value + if (!(Flags & parse_no_string_terminators)) + { + pi->name()[pi->name_size()] = Ch('\0'); + pi->value()[pi->value_size()] = Ch('\0'); + } + + text += 2; // Skip '?>' + return pi; + } + else + { + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + } + + // Parse and append data + // Return character that ends data. + // This is necessary because this character might have been overwritten by a terminating 0 + template + Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) + { + // Backup to contents start if whitespace trimming is disabled + if (!(Flags & parse_trim_whitespace)) + text = contents_start; + + // Skip until end of data + Ch *value = text, *end; + if (Flags & parse_normalize_whitespace) + end = skip_and_expand_character_refs(text); + else + end = skip_and_expand_character_refs(text); + + // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > + if (Flags & parse_trim_whitespace) + { + if (Flags & parse_normalize_whitespace) + { + // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end + if (*(end - 1) == Ch(' ')) + --end; + } + else + { + // Backup until non-whitespace character is found + while (whitespace_pred::test(*(end - 1))) + --end; + } + } + + // If characters are still left between end and value (this test is only necessary if normalization is enabled) + // Create new data node + if (!(Flags & parse_no_data_nodes)) + { + xml_node *data = this->allocate_node(node_data); + data->value(value, end - value); + node->append_node(data); + } + + // Add data to parent node if no data exists yet + if (!(Flags & parse_no_element_values)) + if (*node->value() == Ch('\0')) + node->value(value, end - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + { + Ch ch = *text; + *end = Ch('\0'); + return ch; // Return character that ends data; this is required because zero terminator overwritten it + } + + // Return character that ends data + return *text; + } + + // Parse CDATA + template + xml_node *parse_cdata(Ch *&text) + { + // If CDATA is disabled + if (Flags & parse_no_data_nodes) + { + // Skip until end of cdata + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip ]]> + return 0; // Do not produce CDATA node + } + + // Skip until end of cdata + Ch *value = text; + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create new cdata node + xml_node *cdata = this->allocate_node(node_cdata); + cdata->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip ]]> + return cdata; + } + + // Parse element node + template + xml_node *parse_element(Ch *&text) + { + // Create element node + xml_node *element = this->allocate_node(node_element); + + // Extract element name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(name, text - name); + + // Skip whitespace between element name and attributes or > + skip(text); + + // Parse attributes, if any + parse_node_attributes(text, element); + + // Determine ending type + if (*text == Ch('>')) + { + ++text; + parse_node_contents(text, element); + } + else if (*text == Ch('/')) + { + ++text; + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; + } + else + RAPIDXML_PARSE_ERROR("expected >", text); + + // Place zero terminator after name + if (!(Flags & parse_no_string_terminators)) + element->name()[element->name_size()] = Ch('\0'); + + // Return parsed element + return element; + } + + // Determine node type, and parse it + template + xml_node *parse_node(Ch *&text) + { + // Parse proper node type + switch (text[0]) + { + + // <... + default: + // Parse and append element node + return parse_element(text); + + // (text); + } + else + { + // Parse PI + return parse_pi(text); + } + + // (text); + } + break; + + // (text); + } + break; + + // (text); + } + + } // switch + + // Attempt to skip other, unrecognized node types starting with ')) + { + if (*text == 0) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + ++text; // Skip '>' + return 0; // No node recognized + + } + } + + // Parse contents of the node - children, data etc. + template + void parse_node_contents(Ch *&text, xml_node *node) + { + // For all children and text + while (1) + { + // Skip whitespace between > and node contents + Ch *contents_start = text; // Store start of node contents before whitespace is skipped + skip(text); + Ch next_char = *text; + + // After data nodes, instead of continuing the loop, control jumps here. + // This is because zero termination inside parse_and_append_data() function + // would wreak havoc with the above code. + // Also, skipping whitespace after data nodes is unnecessary. + after_data_node: + + // Determine what comes next: node closing, child node, data node, or 0? + switch (next_char) + { + + // Node closing or child node + case Ch('<'): + if (text[1] == Ch('/')) + { + // Node closing + text += 2; // Skip '(text); + if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true)) + RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + } + else + { + // No validation, just skip name + skip(text); + } + // Skip remaining whitespace after node name + skip(text); + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; // Skip '>' + return; // Node closed, finished parsing contents + } + else + { + // Child node + ++text; // Skip '<' + if (xml_node *child = parse_node(text)) + node->append_node(child); + } + break; + + // End of data - error + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Data node + default: + next_char = parse_and_append_data(node, text, contents_start); + goto after_data_node; // Bypass regular processing after data nodes + + } + } + } + + // Parse XML attributes of the node + template + void parse_node_attributes(Ch *&text, xml_node *node) + { + // For all attributes + while (attribute_name_pred::test(*text)) + { + // Extract attribute name + Ch *name = text; + ++text; // Skip first character of attribute name + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected attribute name", name); + + // Create new attribute + xml_attribute *attribute = this->allocate_attribute(); + attribute->name(name, text - name); + node->append_attribute(attribute); + + // Skip whitespace after attribute name + skip(text); + + // Skip = + if (*text != Ch('=')) + RAPIDXML_PARSE_ERROR("expected =", text); + ++text; + + // Add terminating zero after name + if (!(Flags & parse_no_string_terminators)) + attribute->name()[attribute->name_size()] = 0; + + // Skip whitespace after = + skip(text); + + // Skip quote and remember if it was ' or " + Ch quote = *text; + if (quote != Ch('\'') && quote != Ch('"')) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; + + // Extract attribute value and expand char refs in it + Ch *value = text, *end; + const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes + if (quote == Ch('\'')) + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + else + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + + // Set attribute value + attribute->value(value, end - value); + + // Make sure that end quote is present + if (*text != quote) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; // Skip quote + + // Add terminating zero after value + if (!(Flags & parse_no_string_terminators)) + attribute->value()[attribute->value_size()] = 0; + + // Skip whitespace after attribute value + skip(text); + } + } + + }; + + //! \cond internal + namespace internal + { + + // Whitespace (space \n \r \t) + template + const unsigned char lookup_tables::lookup_whitespace[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + }; + + // Node name (anything but space \n \r \t / > ? \0) + template + const unsigned char lookup_tables::lookup_node_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) (anything but < \0) + template + const unsigned char lookup_tables::lookup_text[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled + // (anything but < \0 &) + template + const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled + // (anything but < \0 & space \n \r \t) + template + const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute name (anything but space \n \r \t / < > = ? ! \0) + template + const unsigned char lookup_tables::lookup_attribute_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote (anything but ' \0) + template + const unsigned char lookup_tables::lookup_attribute_data_1[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote that does not require processing (anything but ' \0 &) + template + const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote (anything but " \0) + template + const unsigned char lookup_tables::lookup_attribute_data_2[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote that does not require processing (anything but " \0 &) + template + const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Digits (dec and hex, 255 denotes end of numeric character reference) + template + const unsigned char lookup_tables::lookup_digits[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F + }; + + // Upper case conversion + template + const unsigned char lookup_tables::lookup_upcase[256] = + { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7 + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8 + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9 + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F + }; + } + //! \endcond + +} + +// Undefine internal macros +#undef RAPIDXML_PARSE_ERROR + +// On MSVC, restore warnings state +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#endif diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_iterators.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_iterators.hpp new file mode 100644 index 0000000000..52ebc298aa --- /dev/null +++ b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_iterators.hpp @@ -0,0 +1,174 @@ +#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED +#define RAPIDXML_ITERATORS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_iterators.hpp This file contains rapidxml iterators + +#include "rapidxml.hpp" + +namespace rapidxml +{ + + //! Iterator of child nodes of xml_node + template + class node_iterator + { + + public: + + typedef typename xml_node value_type; + typedef typename xml_node &reference; + typedef typename xml_node *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + node_iterator() + : m_node(0) + { + } + + node_iterator(xml_node *node) + : m_node(node->first_node()) + { + } + + reference operator *() const + { + assert(m_node); + return *m_node; + } + + pointer operator->() const + { + assert(m_node); + return m_node; + } + + node_iterator& operator++() + { + assert(m_node); + m_node = m_node->next_sibling(); + return *this; + } + + node_iterator operator++(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + node_iterator& operator--() + { + assert(m_node && m_node->previous_sibling()); + m_node = m_node->previous_sibling(); + return *this; + } + + node_iterator operator--(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const node_iterator &rhs) + { + return m_node == rhs.m_node; + } + + bool operator !=(const node_iterator &rhs) + { + return m_node != rhs.m_node; + } + + private: + + xml_node *m_node; + + }; + + //! Iterator of child attributes of xml_node + template + class attribute_iterator + { + + public: + + typedef typename xml_attribute value_type; + typedef typename xml_attribute &reference; + typedef typename xml_attribute *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + attribute_iterator() + : m_attribute(0) + { + } + + attribute_iterator(xml_node *node) + : m_attribute(node->first_attribute()) + { + } + + reference operator *() const + { + assert(m_attribute); + return *m_attribute; + } + + pointer operator->() const + { + assert(m_attribute); + return m_attribute; + } + + attribute_iterator& operator++() + { + assert(m_attribute); + m_attribute = m_attribute->next_attribute(); + return *this; + } + + attribute_iterator operator++(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + attribute_iterator& operator--() + { + assert(m_attribute && m_attribute->previous_attribute()); + m_attribute = m_attribute->previous_attribute(); + return *this; + } + + attribute_iterator operator--(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const attribute_iterator &rhs) + { + return m_attribute == rhs.m_attribute; + } + + bool operator !=(const attribute_iterator &rhs) + { + return m_attribute != rhs.m_attribute; + } + + private: + + xml_attribute *m_attribute; + + }; + +} + +#endif diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_print.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_print.hpp new file mode 100644 index 0000000000..0ae2b14faa --- /dev/null +++ b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_print.hpp @@ -0,0 +1,421 @@ +#ifndef RAPIDXML_PRINT_HPP_INCLUDED +#define RAPIDXML_PRINT_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_print.hpp This file contains rapidxml printer implementation + +#include "rapidxml.hpp" + +// Only include streams if not disabled +#ifndef RAPIDXML_NO_STREAMS + #include + #include +#endif + +namespace rapidxml +{ + + /////////////////////////////////////////////////////////////////////// + // Printing flags + + const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. + + /////////////////////////////////////////////////////////////////////// + // Internal + + //! \cond internal + namespace internal + { + + /////////////////////////////////////////////////////////////////////////// + // Internal character operations + + // Copy characters from given range to given output iterator + template + inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) + { + while (begin != end) + *out++ = *begin++; + return out; + } + + // Copy characters from given range to given output iterator and expand + // characters into references (< > ' " &) + template + inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) + { + while (begin != end) + { + if (*begin == noexpand) + { + *out++ = *begin; // No expansion, copy character + } + else + { + switch (*begin) + { + case Ch('<'): + *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('>'): + *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('\''): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); + break; + case Ch('"'): + *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('&'): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); + break; + default: + *out++ = *begin; // No expansion, copy character + } + } + ++begin; // Step to next character + } + return out; + } + + // Fill given output iterator with repetitions of the same character + template + inline OutIt fill_chars(OutIt out, int n, Ch ch) + { + for (int i = 0; i < n; ++i) + *out++ = ch; + return out; + } + + // Find character + template + inline bool find_char(const Ch *begin, const Ch *end) + { + while (begin != end) + if (*begin++ == ch) + return true; + return false; + } + + /////////////////////////////////////////////////////////////////////////// + // Internal printing operations + + // Print node + template + inline OutIt print_node(OutIt out, const xml_node *node, int flags, int indent) + { + // Print proper node type + switch (node->type()) + { + + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + + // Return modified iterator + return out; + } + + // Print children of the node + template + inline OutIt print_children(OutIt out, const xml_node *node, int flags, int indent) + { + for (xml_node *child = node->first_node(); child; child = child->next_sibling()) + out = print_node(out, child, flags, indent); + return out; + } + + // Print attributes of the node + template + inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) + { + for (xml_attribute *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) + { + if (attribute->name() && attribute->value()) + { + // Print attribute name + *out = Ch(' '), ++out; + out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out); + *out = Ch('='), ++out; + // Print attribute value using appropriate quote type + if (find_char(attribute->value(), attribute->value() + attribute->value_size())) + { + *out = Ch('\''), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out); + *out = Ch('\''), ++out; + } + else + { + *out = Ch('"'), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out); + *out = Ch('"'), ++out; + } + } + } + return out; + } + + // Print data node + template + inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_data); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + return out; + } + + // Print data node + template + inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_cdata); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'); ++out; + *out = Ch('!'); ++out; + *out = Ch('['); ++out; + *out = Ch('C'); ++out; + *out = Ch('D'); ++out; + *out = Ch('A'); ++out; + *out = Ch('T'); ++out; + *out = Ch('A'); ++out; + *out = Ch('['); ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch(']'); ++out; + *out = Ch(']'); ++out; + *out = Ch('>'); ++out; + return out; + } + + // Print element node + template + inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_element); + + // Print element name and attributes, if any + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + out = print_attributes(out, node, flags); + + // If node is childless + if (node->value_size() == 0 && !node->first_node()) + { + // Print childless node tag ending + *out = Ch('/'), ++out; + *out = Ch('>'), ++out; + } + else + { + // Print normal node tag ending + *out = Ch('>'), ++out; + + // Test if node contains a single data node only (and no other nodes) + xml_node *child = node->first_node(); + if (!child) + { + // If node has no children, only print its value without indenting + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + } + else if (child->next_sibling() == 0 && child->type() == node_data) + { + // If node has a sole data child, only print its value without indenting + out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out); + } + else + { + // Print all children with full indenting + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + out = print_children(out, node, flags, indent + 1); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + } + + // Print node end + *out = Ch('<'), ++out; + *out = Ch('/'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch('>'), ++out; + } + return out; + } + + // Print declaration node + template + inline OutIt print_declaration_node(OutIt out, const xml_node *node, int flags, int indent) + { + // Print declaration start + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + *out = Ch('x'), ++out; + *out = Ch('m'), ++out; + *out = Ch('l'), ++out; + + // Print attributes + out = print_attributes(out, node, flags); + + // Print declaration end + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + + return out; + } + + // Print comment node + template + inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_comment); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + *out = Ch('>'), ++out; + return out; + } + + // Print doctype node + template + inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_doctype); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('D'), ++out; + *out = Ch('O'), ++out; + *out = Ch('C'), ++out; + *out = Ch('T'), ++out; + *out = Ch('Y'), ++out; + *out = Ch('P'), ++out; + *out = Ch('E'), ++out; + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('>'), ++out; + return out; + } + + // Print pi node + template + inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_pi); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + return out; + } + + } + //! \endcond + + /////////////////////////////////////////////////////////////////////////// + // Printing + + //! Prints XML to given output iterator. + //! \param out Output iterator to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output iterator pointing to position immediately after last character of printed text. + template + inline OutIt print(OutIt out, const xml_node &node, int flags = 0) + { + return internal::print_node(out, &node, flags, 0); + } + +#ifndef RAPIDXML_NO_STREAMS + + //! Prints XML to given output stream. + //! \param out Output stream to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output stream. + template + inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) + { + print(std::ostream_iterator(out), node, flags); + return out; + } + + //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. + //! \param out Output stream to print to. + //! \param node Node to be printed. + //! \return Output stream. + template + inline std::basic_ostream &operator <<(std::basic_ostream &out, const xml_node &node) + { + return print(out, node); + } + +#endif + +} + +#endif diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_utils.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_utils.hpp new file mode 100644 index 0000000000..37c29535f4 --- /dev/null +++ b/doc/src/docutils/tools/doxygen_xml2qbk/contrib/rapidxml-1.13/rapidxml_utils.hpp @@ -0,0 +1,122 @@ +#ifndef RAPIDXML_UTILS_HPP_INCLUDED +#define RAPIDXML_UTILS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful +//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. + +#include "rapidxml.hpp" +#include +#include +#include +#include + +namespace rapidxml +{ + + //! Represents data loaded from a file + template + class file + { + + public: + + //! Loads file into the memory. Data will be automatically destroyed by the destructor. + //! \param filename Filename to load. + file(const char *filename) + { + using namespace std; + + // Open stream + basic_ifstream stream(filename, ios::binary); + if (!stream) + throw runtime_error(string("cannot open file ") + filename); + stream.unsetf(ios::skipws); + + // Determine stream size + stream.seekg(0, ios::end); + size_t size = stream.tellg(); + stream.seekg(0); + + // Load data and add terminating 0 + m_data.resize(size + 1); + stream.read(&m_data.front(), static_cast(size)); + m_data[size] = 0; + } + + //! Loads file into the memory. Data will be automatically destroyed by the destructor + //! \param stream Stream to load from + file(std::basic_istream &stream) + { + using namespace std; + + // Load data and add terminating 0 + stream.unsetf(ios::skipws); + m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); + if (stream.fail() || stream.bad()) + throw runtime_error("error reading stream"); + m_data.push_back(0); + } + + //! Gets file data. + //! \return Pointer to data of file. + Ch *data() + { + return &m_data.front(); + } + + //! Gets file data. + //! \return Pointer to data of file. + const Ch *data() const + { + return &m_data.front(); + } + + //! Gets file data size. + //! \return Size of file data, in characters. + std::size_t size() const + { + return m_data.size(); + } + + private: + + std::vector m_data; // File data + + }; + + //! Counts children of node. Time complexity is O(n). + //! \return Number of children of node + template + inline std::size_t count_children(xml_node *node) + { + xml_node *child = node->first_node(); + std::size_t count = 0; + while (child) + { + ++count; + child = child->next_sibling(); + } + return count; + } + + //! Counts attributes of node. Time complexity is O(n). + //! \return Number of attributes of node + template + inline std::size_t count_attributes(xml_node *node) + { + xml_attribute *attr = node->first_attribute(); + std::size_t count = 0; + while (attr) + { + ++count; + attr = attr->next_attribute(); + } + return count; + } + +} + +#endif diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_elements.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_elements.hpp index 2667ed50b0..04d50dcfaa 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_elements.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_elements.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) @@ -22,18 +23,20 @@ enum function_type { function_unknown, function_define, - function_constructor, + function_constructor_destructor, function_member, - function_free + function_free, }; struct base_element { std::string name; std::string brief_description; - + bool skip; + std::string id; + base_element(std::string const& n = "") : name(n) , skip(false) @@ -47,6 +50,7 @@ struct parameter : public base_element std::string type; std::string default_value; // for template parameters std::string fulltype; // post-processed + std::string fulltype_without_links; }; struct enumeration_value : public base_element @@ -85,6 +89,12 @@ struct markup } }; +struct paragraph +{ + std::string title; + std::string text; +}; + // Base of a class/struct, function, define struct element : public base_element { @@ -103,6 +113,10 @@ struct element : public base_element std::vector template_parameters; std::vector parameters; + std::vector paragraphs; + std::string warning; + std::string note; + element() : line(0) {} @@ -114,12 +128,17 @@ struct function : public element function_type type; std::string definition, argsstring; std::string return_type, return_description; + std::string precondition; + + std::string return_type_without_links; + bool is_static, is_const, is_explicit, is_virtual; bool unique; function() : type(function_unknown) , unique(true) + , is_static(false), is_const(false), is_explicit(false), is_virtual(false) {} }; @@ -153,6 +172,9 @@ struct class_or_struct : public element struct documentation { + std::string group_id; + std::string group_title; + // Only one expected (no grouping) class_or_struct cos; diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml2qbk.cpp b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml2qbk.cpp index b436c523f9..87ac68e070 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml2qbk.cpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml2qbk.cpp @@ -1,6 +1,7 @@ // doxml2qbk (developed in the context of Boost.Geometry documentation) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) @@ -18,8 +19,6 @@ // to an example. // - currently still in draft -// Aug 14/15: added classes, defines, various enhancements. - #include #include #include @@ -43,6 +42,23 @@ #include #include +static const std::string version = "1.1.0"; + +inline std::string program_description(bool decorated) +{ + std::string result; + if (decorated) + { + result = "=== "; + } + result += "doxygen_xml2qbk "; + result += version; + if (decorated) + { + result += " ==="; + } + return result; +} int main(int argc, char** argv) @@ -52,17 +68,18 @@ int main(int argc, char** argv) { configuration config; std::string copyright_filename; + std::string output_style; // Read/get configuration { namespace po = boost::program_options; - po::options_description description("=== doxml2qbk ===\nAllowed options"); - + po::options_description description; std::string convenience_headers; description.add_options() ("help", "Help message") + ("version", "Version description") ("xml", po::value(&filename), "Name of XML file written by Doxygen") ("start_include", po::value(&config.start_include), @@ -72,9 +89,12 @@ int main(int argc, char** argv) ("convenience_headers", po::value(&convenience_headers), "Convenience header(s) (comma-separated)") ("skip_namespace", po::value(&config.skip_namespace), - "Namespace to skip (e.g. boost::mylib::") + "Namespace to skip (e.g. boost::mylib::)") ("copyright", po::value(©right_filename), "Name of QBK file including (commented) copyright and license") + + ("output_style", po::value(&output_style), + "Docbook output style. Available values: 'alt'") ; po::variables_map varmap; @@ -92,9 +112,25 @@ int main(int argc, char** argv) po::notify(varmap); - if (varmap.count("help") || filename.empty()) + if (varmap.count("version")) + { + std::cout << version << std::endl; + return 0; + } + else if (varmap.count("help")) { - std::cout << description << std::endl; + std::cout + << program_description(true) << std::endl + << "Available options:" << std::endl + << description << std::endl; + return 0; + } + else if (filename.empty()) + { + std::cout + << program_description(true) << std::endl + << "Allowed options:" << std::endl + << description << std::endl; return 1; } @@ -105,6 +141,10 @@ int main(int argc, char** argv) } } + // Set output style + if ( "alt" == output_style ) + config.output_style = configuration::alt; + // Read files into strings std::string xml_string = file_to_string(filename); std::string license = copyright_filename.empty() @@ -146,29 +186,42 @@ int main(int argc, char** argv) // Write warning comment std::cout - << "[/ Generated by doxygen_xml2qbk, don't change, will be overwritten automatically]" << std::endl + << "[/ Generated by " << program_description(false) << ", don't change, will be overwritten automatically]" << std::endl << "[/ Generated from " << filename << "]" << std::endl; - // Write the rest: functions, defines, classes or structs - BOOST_FOREACH(function const& f, doc.functions) + if ( configuration::def == config.output_style ) { - quickbook_output(f, config, std::cout); - } - BOOST_FOREACH(function const& f, doc.defines) - { - quickbook_output(f, config, std::cout); + // Write the rest: functions, defines, classes or structs + BOOST_FOREACH(function const& f, doc.functions) + { + quickbook_output(f, config, std::cout); + } + BOOST_FOREACH(function const& f, doc.defines) + { + quickbook_output(f, config, std::cout); + } + BOOST_FOREACH(enumeration const& e, doc.enumerations) + { + quickbook_output(e, config, std::cout); + } + + if (! doc.cos.name.empty()) + { + std::sort(doc.cos.functions.begin(), doc.cos.functions.end(), sort_on_line()); + quickbook_output(doc.cos, config, std::cout); + } } - BOOST_FOREACH(enumeration const& e, doc.enumerations) + else if ( configuration::alt == config.output_style ) { - quickbook_output(e, config, std::cout); - } + if (! doc.cos.name.empty()) + { + std::sort(doc.cos.functions.begin(), doc.cos.functions.end(), sort_on_line()); + quickbook_output_alt(doc.cos, config, std::cout); + } - if (! doc.cos.name.empty()) - { - std::sort(doc.cos.functions.begin(), doc.cos.functions.end(), sort_on_line()); - quickbook_output(doc.cos, config, std::cout); + if ( !doc.group_id.empty() ) + quickbook_output_alt(doc, config, std::cout); } - } catch(std::exception const& e) { diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp index aa8b902192..0a98f42965 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/doxygen_xml_parser.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) @@ -62,7 +63,16 @@ This is used for different purposes within Doxygen. So we have to list explicitly either where to recurse, or where not to... */ -static void parse_para(rapidxml::xml_node<>* node, std::string& contents, bool& skip, bool first = true) + +// Type used to store parsing state. It indicates if QBK formatting block was opened - [*...], [^...], etc. +enum text_block +{ + not_in_block, + in_code_block, + in_block +}; + +static void parse_para(rapidxml::xml_node<>* node, configuration const& config, std::string& contents, bool& skip, bool first = true, text_block tb = not_in_block) { if (node != NULL) { @@ -70,18 +80,73 @@ static void parse_para(rapidxml::xml_node<>* node, std::string& contents, bool& { //std::cout << "ELEMENT: " << node->name() << "=" << node->value() << std::endl; std::string name = node->name(); - if (boost::equals(name, "qbk.skip")) + if ( boost::equals(name, "itemizedlist") ) + { + contents += "\n\n"; + parse_para(node->first_node(), config, contents, skip, true, tb); + contents += "\n"; + parse_para(node->next_sibling(), config, contents, skip, true, tb); + return; + } + else if ( boost::equals(name, "listitem") ) + { + contents += "* "; + parse_para(node->first_node(), config, contents, skip, true, tb); + contents += "\n"; + parse_para(node->next_sibling(), config, contents, skip, true, tb); + return; + } + else if ( boost::equals(name, "verbatim") ) + { + contents += "\n``\n"; + parse_para(node->first_node(), config, contents, skip, false, tb); + contents += "``\n"; + parse_para(node->next_sibling(), config, contents, skip, false, tb); + return; + } + else if ( boost::equals(name, "bold") ) + { + contents += "[*"; + parse_para(node->first_node(), config, contents, skip, false, in_block); + contents += "]"; + parse_para(node->next_sibling(), config, contents, skip, false, tb); + return; + } + else if ( boost::equals(name, "emphasis") ) { - skip = true; + contents += "['"; + parse_para(node->first_node(), config, contents, skip, false, in_block); + contents += "]"; + parse_para(node->next_sibling(), config, contents, skip, false, tb); return; } + else if ( boost::equals(name, "computeroutput") ) + { + contents += "[^"; + parse_para(node->first_node(), config, contents, skip, false, tb == in_block ? in_block : in_code_block); + contents += "]"; + parse_para(node->next_sibling(), config, contents, skip, false, tb); + return; + } + else if ( boost::equals(name, "ref") ) + { + // If alternative output is used - insert links + if ( configuration::alt == config.output_style ) + { + std::string refid = node->first_attribute("refid")->value(); + if ( !refid.empty() ) + { + contents += std::string("[link ") + refid + " "; + parse_para(node->first_node(), config, contents, skip, false, in_block); + contents += "]"; + parse_para(node->next_sibling(), config, contents, skip, false, tb); + return; + } + } + } else if (! ( (boost::equals(name, "para") && first) - || boost::equals(name, "ref") || boost::equals(name, "defval") - || boost::equals(name, "verbatim") - || boost::equals(name, "bold") - || boost::equals(name, "emphasis") || boost::equals(name, "linebreak") )) { @@ -90,20 +155,33 @@ static void parse_para(rapidxml::xml_node<>* node, std::string& contents, bool& } else if (node->type() == rapidxml::node_data) { - contents += node->value(); + std::string str = node->value(); + if ( tb == in_block ) + { + boost::replace_all(str, "\\", "\\\\"); + boost::replace_all(str, "[", "\\["); + boost::replace_all(str, "]", "\\]"); + } + else if ( tb == in_code_block ) + { + if ( str.find('`') == std::string::npos ) + str = std::string("`") + str + "`"; + } + contents += str; //std::cout << "DATA: " << node->name() << "=" << node->value() << std::endl; } else { //std::cout << "OTHER: " << node->name() << "=" << node->value() << std::endl; } - parse_para(node->first_node(), contents, skip, false); - parse_para(node->next_sibling(), contents, skip, false); + + parse_para(node->first_node(), config, contents, skip, false, tb); + parse_para(node->next_sibling(), config, contents, skip, false, tb); } } -static void parse_parameter(rapidxml::xml_node<>* node, parameter& p) +static void parse_parameter(rapidxml::xml_node<>* node, configuration const& config, parameter& p) { // #define: Point // template: typenameCoordinateTypeCoordinateType @@ -121,25 +199,33 @@ static void parse_parameter(rapidxml::xml_node<>* node, parameter& p) boost::replace_all(p.type, "&", ""); boost::replace_all(p.type, "*", ""); boost::trim(p.type); + + // If alt output is used retrieve type with QBK links + if ( configuration::alt == config.output_style ) + { + p.fulltype_without_links = p.fulltype; + p.fulltype.clear(); + parse_para(node->first_node(), config, p.fulltype, p.skip); + } } else if (name == "declname") p.name = node->value(); else if (name == "parametername") p.name = node->value(); else if (name == "defname") p.name = node->value(); else if (name == "defval") { - parse_para(node, p.default_value, p.skip); + parse_para(node, config, p.default_value, p.skip); } else if (name == "para") { - parse_para(node, p.brief_description, p.skip); + parse_para(node, config, p.brief_description, p.skip); } - parse_parameter(node->first_node(), p); - parse_parameter(node->next_sibling(), p); + parse_parameter(node->first_node(), config, p); + parse_parameter(node->next_sibling(), config, p); } } -static void parse_enumeration_value(rapidxml::xml_node<>* node, enumeration_value& value) +static void parse_enumeration_value(rapidxml::xml_node<>* node, configuration const& config, enumeration_value& value) { // green 2 // ... @@ -153,21 +239,21 @@ static void parse_enumeration_value(rapidxml::xml_node<>* node, enumeration_valu else if (node_name == "para") { // Parses both brief AND detailed into this description - parse_para(node, value.brief_description, value.skip); + parse_para(node, config, value.brief_description, value.skip); } else if (node_name == "initializer") { value.initializer = node->value(); } - parse_enumeration_value(node->first_node(), value); - parse_enumeration_value(node->next_sibling(), value); + parse_enumeration_value(node->first_node(), config, value); + parse_enumeration_value(node->next_sibling(), config, value); } } // Definition is a function or a class/struct template -static void parse_parameter_list(rapidxml::xml_node<>* node, Parameters& parameters) +static void parse_parameter_list(rapidxml::xml_node<>* node, configuration const& config, Parameters& parameters) { if (node != NULL) { @@ -176,7 +262,7 @@ static void parse_parameter_list(rapidxml::xml_node<>* node, Parameters& paramet if (name == "parameteritem") { parameter p; - parse_parameter(node->first_node(), p); + parse_parameter(node->first_node(), config, p); if (! p.name.empty()) { // Copy its description @@ -196,7 +282,7 @@ static void parse_parameter_list(rapidxml::xml_node<>* node, Parameters& paramet { // Element of 'templateparamlist.param (.type,.declname,.defname)' parameter p; - parse_parameter(node->first_node(), p); + parse_parameter(node->first_node(), config, p); // Doxygen handles templateparamlist param's differently: // @@ -223,8 +309,8 @@ static void parse_parameter_list(rapidxml::xml_node<>* node, Parameters& paramet add_or_set(parameters, p); } - parse_parameter_list(node->first_node(), parameters); - parse_parameter_list(node->next_sibling(), parameters); + parse_parameter_list(node->first_node(), config, parameters); + parse_parameter_list(node->next_sibling(), config, parameters); } } @@ -279,12 +365,12 @@ static void parse_element(rapidxml::xml_node<>* node, configuration const& confi if (full == ".briefdescription.para") { - parse_para(node, el.brief_description, el.skip); + parse_para(node, config, el.brief_description, el.skip); } else if (full == ".detaileddescription.para") { std::string para; - parse_para(node, para, el.skip); + parse_para(node, config, para, el.skip); if (!para.empty() && !el.detailed_description.empty()) { el.detailed_description += "\n\n"; @@ -323,7 +409,7 @@ static void parse_element(rapidxml::xml_node<>* node, configuration const& confi } else if (full == ".templateparamlist") { - parse_parameter_list(node->first_node(), el.template_parameters); + parse_parameter_list(node->first_node(), config, el.template_parameters); } else if (full == ".detaileddescription.para.parameterlist") { @@ -333,19 +419,43 @@ static void parse_element(rapidxml::xml_node<>* node, configuration const& confi // Parse parameters and their descriptions. // NOTE: they are listed here, but the order might not be the order in the function call std::vector parameters; - parse_parameter_list(node->first_node(), parameters); + parse_parameter_list(node->first_node(), config, parameters); copy_parameters_properties(parameters, el.parameters); } else if (kind == "templateparam") { - parse_parameter_list(node->first_node(), el.template_parameters); + parse_parameter_list(node->first_node(), config, el.template_parameters); + } + } + else if (full == ".detaileddescription.para.simplesect") + { + std::string kind = get_attribute(node, "kind"); + if (kind == "par") + { + paragraph p; + + rapidxml::xml_node<> * title_node = node->first_node("title"); + if ( title_node ) + p.title = title_node->value(); + + parse_para(node->first_node("para"), config, p.text, el.skip); + + el.paragraphs.push_back(p); + } + else if (kind == "warning") + { + parse_para(node->first_node("para"), config, el.warning, el.skip); + } + else if (kind == "note") + { + parse_para(node->first_node("para"), config, el.note, el.skip); } } else if (full == ".param") { // Parse one parameter, and add it to el.parameters parameter p; - parse_parameter(node->first_node(), p); + parse_parameter(node->first_node(), config, p); el.parameters.push_back(p); } @@ -375,24 +485,37 @@ static void parse_function(rapidxml::xml_node<>* node, configuration const& conf else if (full == ".param") { parameter p; - parse_parameter(node->first_node(), p); + parse_parameter(node->first_node(), config, p); add_or_set(f.parameters, p); } else if (full == ".type") { get_contents(node->first_node(), f.return_type); + + // If alt output is used, retrieve return type with links + if ( configuration::alt == config.output_style ) + { + f.return_type_without_links = f.return_type; + bool dummy_skip; + f.return_type.clear(); + parse_para(node->first_node(), config, f.return_type, dummy_skip); + } } else if (full == ".detaileddescription.para.simplesect") { std::string kind = get_attribute(node, "kind"); if (kind == "return") { - get_contents(node->first_node(), f.return_description); + parse_para(node->first_node(), config, f.return_description, f.skip); } /*else if (kind == "param") { get_contents(node->first_node(), f.paragraphs); }*/ + else if (kind == "pre") + { + parse_para(node->first_node(), config, f.precondition, f.skip); + } } else if (full == ".detaileddescription.para.image") { @@ -414,7 +537,7 @@ static void parse_enumeration(rapidxml::xml_node<>* node, configuration const& c else if (full == ".enumvalue") { enumeration_value value; - parse_enumeration_value(node->first_node(), value); + parse_enumeration_value(node->first_node(), config, value); e.enumeration_values.push_back(value); } @@ -479,35 +602,54 @@ static void parse(rapidxml::xml_node<>* node, configuration const& config, docum else if (nodename == "compounddef") { std::string kind = get_attribute(node, "kind"); + std::string id = get_attribute(node, "id"); if (kind == "group") { recurse = true; + doc.group_id = id; + rapidxml::xml_node<> * n = node->first_node("title"); + if ( n ) + doc.group_title = n->value(); } else if (kind == "struct") { recurse = true; doc.cos.is_class = false; + doc.cos.id = id; parse_element(node->first_node(), config, "", doc.cos); } else if (kind == "class") { recurse = true; doc.cos.is_class = true; + doc.cos.id = id; parse_element(node->first_node(), config, "", doc.cos); } } else if (nodename == "memberdef") { std::string kind = get_attribute(node, "kind"); + std::string id = get_attribute(node, "id"); + if (kind == "function") { function f; + f.id = id; + f.is_static = get_attribute(node, "static") == "yes" ? true : false; + f.is_const = get_attribute(node, "const") == "yes" ? true : false; + f.is_explicit = get_attribute(node, "explicit") == "yes" ? true : false; + f.is_virtual = get_attribute(node, "virt") == "virtual" ? true : false; + parse_element(node->first_node(), config, "", f); parse_function(node->first_node(), config, "", f); + if (member) { - f.type = boost::equals(f.name, doc.cos.name) - ? function_constructor + bool c_or_d = boost::equals(f.name, doc.cos.name) || + boost::equals(f.name, std::string("~") + doc.cos.name); + + f.type = c_or_d + ? function_constructor_destructor : function_member; doc.cos.functions.push_back(f); } @@ -520,14 +662,16 @@ static void parse(rapidxml::xml_node<>* node, configuration const& config, docum else if (kind == "define") { function f; + f.id = id; f.type = function_define; parse_element(node->first_node(), config, "", f); parse_function(node->first_node(), config, "", f); - doc.functions.push_back(f); + doc.defines.push_back(f); } else if (kind == "enum") { enumeration e; + e.id = id; parse_element(node->first_node(), config, "", e); parse_enumeration(node->first_node(), config, "", e); doc.enumerations.push_back(e); @@ -538,6 +682,11 @@ static void parse(rapidxml::xml_node<>* node, configuration const& config, docum { std::string name = parse_named_node(node->first_node(), "name"); doc.cos.typedefs.push_back(base_element(name)); + doc.cos.typedefs.back().id = id; + + element dummy; + parse_element(node->first_node(), config, "", dummy); + doc.cos.typedefs.back().brief_description = dummy.brief_description; } } else if (kind == "variable") @@ -548,6 +697,7 @@ static void parse(rapidxml::xml_node<>* node, configuration const& config, docum { std::string name = parse_named_node(node->first_node(), "name"); doc.cos.variables.push_back(base_element(name)); + doc.cos.variables.back().id = id; } } diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/file_to_string.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/file_to_string.hpp index e889fc75fd..5af013056c 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/file_to_string.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/file_to_string.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/parameter_predicates.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/parameter_predicates.hpp index 8cbb55e740..8d58709fbd 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/parameter_predicates.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/parameter_predicates.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp index 81714d8d59..6fe48a05a2 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/quickbook_output.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) @@ -58,7 +59,7 @@ std::string qbk_escaped(std::string const& s) -void quickbook_template_parameter_list(std::vector const& parameters, std::ostream& out, bool name = false) +void quickbook_template_parameter_list(std::vector const& parameters, std::ostream& out) { if (!parameters.empty()) { @@ -78,9 +79,10 @@ void quickbook_synopsis(function const& f, std::ostream& out) { out << "``"; quickbook_template_parameter_list(f.template_parameters, out); + switch(f.type) { - case function_constructor : + case function_constructor_destructor : out << f.name; break; case function_member : @@ -96,7 +98,7 @@ void quickbook_synopsis(function const& f, std::ostream& out) // do nothing break; } - + // Output the parameters // Because we want to be able to skip, we cannot use the argstring { @@ -139,7 +141,9 @@ void quickbook_synopsis(enumeration const& e, std::ostream& out) out << (first ? " {" : ", ") << value.name; if (! value.initializer.empty()) { - out << " = " << boost::trim_copy(value.initializer); + // Doxygen 1.6 does not include "=" in the tag, Doxygen 1.8 does. + // We just remove the "=" to have consisten output + out << " = " << boost::trim_copy(boost::replace_all_copy(value.initializer, "=", "")); } first = false; } @@ -418,7 +422,6 @@ void quickbook_output(function const& f, configuration const& config, std::ostre out << std::endl; } - void quickbook_output(enumeration const& e, configuration const& config, std::ostream& out) { out << "[section:" << to_section_name(e.name); @@ -469,12 +472,12 @@ void quickbook_output(enumeration const& e, configuration const& config, std::os out << std::endl; } -void quickbook_output_member(std::vector const& functions, - function_type type, - std::string const& title, - configuration const& config, std::ostream& out) +void quickbook_output_function(std::vector const& functions, + function_type type, + std::string const& title, + configuration const& config, std::ostream& out) { - std::string returns = type == function_constructor ? "" : " [Returns]"; + std::string returns = type == function_constructor_destructor ? "" : " [Returns]"; out << "[heading " << title << "(s)]" << std::endl << "[table" << std::endl << "[[Function] [Description] [Parameters] " << returns << "]" << std::endl; @@ -494,7 +497,6 @@ void quickbook_output_member(std::vector const& functions, << std::endl; } - void quickbook_output(class_or_struct const& cos, configuration const& config, std::ostream& out) { // Skip namespace @@ -584,14 +586,14 @@ void quickbook_output(class_or_struct const& cos, configuration const& config, s counts[f.type]++; } - if (counts[function_constructor] > 0) + if (counts[function_constructor_destructor] > 0) { - quickbook_output_member(cos.functions, function_constructor, "Constructor", config, out); + quickbook_output_function(cos.functions, function_constructor_destructor, "Constructor", config, out); } if (counts[function_member] > 0) { - quickbook_output_member(cos.functions, function_member, "Member Function", config, out); + quickbook_output_function(cos.functions, function_member, "Member Function", config, out); } quickbook_header(cos.location, config, out); @@ -602,4 +604,780 @@ void quickbook_output(class_or_struct const& cos, configuration const& config, s } +// ----------------------------------------------------------------------------------------------- // +// ALT +// ----------------------------------------------------------------------------------------------- // + +std::string remove_template_parameters(std::string const& name) +{ + std::string res; + std::string::size_type prev_i = 0, i = 0; + int blocks_counter = 0; + for ( ;; ) + { + std::string::size_type next_begin = name.find('<', i); + std::string::size_type next_end = name.find('>', i); + + if ( next_begin == next_end ) + { + res += name.substr(prev_i, next_begin - prev_i); + break; + } + else if ( next_begin < next_end ) + { + i = next_begin + 1; + if ( blocks_counter == 0 ) + res += name.substr(prev_i, next_begin - prev_i) + "<...>"; + blocks_counter++; + } + else + { + i = next_end + 1; + blocks_counter--; + if ( blocks_counter == 0 ) + prev_i = i; + } + } + + return res; +} + +std::string replace_brackets(std::string const& str) +{ + return boost::replace_all_copy(boost::replace_all_copy(str, "[", "\\["), "]", "\\]"); +} + +void quickbook_output_enumerations(std::vector const& enumerations, + configuration const& config, + std::ostream& out) +{ + out << "[table" << std::endl + << "[[Enumeration][Description]]" << std::endl; + + for ( size_t i = 0 ; i < enumerations.size() ; ++i ) + { + enumeration const& e = enumerations[i]; + + out << "[[[link " << e.id << " `"; + out << e.name; + out << "`]][" << e.brief_description << "]]" << std::endl; + } + out << "]" << std::endl + << std::endl; +} + +void quickbook_synopsis_short(function const& f, std::ostream& out) +{ + if ( f.type != function_unknown ) + out << f.name; + + bool first = true; + BOOST_FOREACH(parameter const& p, f.parameters) + { + if ( !p.skip && p.default_value.empty() ) + { + out << (first ? "(" : ", ") << remove_template_parameters(p.fulltype_without_links); + first = false; + } + } + + + if (! first) + out << ")"; + else if (f.type != function_define) + out << "()"; +} + +void quickbook_output_functions(std::vector const& functions, + function_type type, + configuration const& config, + std::ostream& out, + bool display_all = false, + std::string const& ColTitle = "Function") +{ + bool show_modifiers = false; + BOOST_FOREACH(function const& f, functions) + { + if ( (display_all || f.type == type) && (f.is_const || f.is_static) && !f.brief_description.empty() ) + show_modifiers = true; + } + + out << "[table\n" + << "["; + if ( show_modifiers ) + out << "[Modifier]"; + out << "[" << ColTitle << "]"; + out << "[Description]"; + out << "]" << std::endl; + + for ( size_t i = 0 ; i < functions.size() ; ++i ) + { + function const& f = functions[i]; + + if ( f.brief_description.empty() ) + continue; + + if (display_all || f.type == type) + { + out << "["; + if ( show_modifiers ) + { + out << "["; + out << (f.is_static ? "`static`" : ""); + out << (f.is_const ? " `const`" : ""); + out << "]"; + } + out << "[[link " << f.id << " `"; + quickbook_synopsis_short(f, out); + out << "`]]"; + out << "[" << f.brief_description << "]"; + out << "]" << std::endl; + } + } + out << "]" << std::endl + << std::endl; +} + +void output_paragraphs_note_warning(element const& el, std::ostream & out) +{ + // Additional paragraphs + if ( !el.paragraphs.empty() ) + { + BOOST_FOREACH(paragraph const& p, el.paragraphs) + { + if ( !p.title.empty() ) + out << "[heading " << p.title << "]" << std::endl; + else + out << "\n\n" << std::endl; + out << p.text << std::endl; + out << std::endl; + } + } + + // Note + if ( !el.note.empty() ) + { + out << "[note " << el.note << "]" << std::endl; + out << std::endl; + } + + // Warning + if ( !el.warning.empty() ) + { + out << "[warning " << el.warning << "]" << std::endl; + out << std::endl; + } +} + +void inline_str_with_links(std::string const& str, std::ostream & out) +{ + typedef std::string::size_type ST; + + bool link_started = false; + bool first = true; + for ( ST i = 0 ; i < str.size() ; ++i ) + { + if ( !link_started ) + { + if ( str[i] == '[' && str.substr(i, 6) == "[link " ) + { + if ( !first ) + { + out << "`"; + first = true; + } + link_started = true; + out << "[^[link "; + i += 5; // (+ 6 - 1) + } + else + { + if ( first ) + { + out << "`"; + first = false; + } + out << str[i]; + } + } + else + { + if ( str[i] == '\\' ) + { + out << str[i]; + ++i; + if ( i < str.size() ) + out << str[i]; + } + else if ( str[i] == ']' ) + { + out << "]]"; + link_started = false; + } + else + out << str[i]; + } + } + + if ( !first ) + out << "`"; + if ( link_started ) + out << "]]"; +} + +void quickbook_template_parameter_list_alt(std::vector const& parameters, std::ostream& out) +{ + std::string next_param; + + if ( 2 < parameters.size() ) + next_param = std::string("`,`\n") + " "; + else + next_param = "`,` "; + + if (!parameters.empty()) + { + out << "`template<`" ; + bool first = true; + BOOST_FOREACH(parameter const& p, parameters) + { + out << (first ? "" : next_param.c_str()); + inline_str_with_links(p.fulltype, out); + + if ( !p.default_value.empty() ) + { + out << " = "; + inline_str_with_links(p.default_value, out); + } + + first = false; + } + out << "`>`"; + } +} + +void quickbook_synopsis_alt(function const& f, std::ostream& out) +{ + out << "[pre\n"; + quickbook_template_parameter_list_alt(f.template_parameters, out); + out << "\n"; + + std::size_t offset = 1; // '(' + switch(f.type) + { + case function_constructor_destructor : + out << "`" << f.name << "`"; + offset += f.name.size(); + break; + case function_member : + inline_str_with_links(f.return_type, out); + out << " `" << f.name << "`"; + offset += f.return_type_without_links.size() + 1 + f.name.size(); + break; + case function_free : + inline_str_with_links(f.definition, out); + offset += f.definition.size(); + break; + case function_define : + out << "`#define " << f.name << "`"; + offset += 8 + f.name.size(); + break; + case function_unknown : + // do nothing + break; + } + + std::string par_end("`,` "); + if ( 2 < f.parameters.size() ) + par_end = std::string("`,`\n") + std::string(offset, ' '); + + // Output the parameters + // Because we want to be able to skip, we cannot use the argstring + { + bool first = true; + BOOST_FOREACH(parameter const& p, f.parameters) + { + if (! p.skip) + { + out << (first ? "`(`" : par_end); + if ( !p.fulltype.empty() ) + { + inline_str_with_links(p.fulltype, out); + out << " "; + } + if ( !p.name.empty() ) + out << "`" << p.name << "`"; + if ( !p.default_value.empty() ) + { + out << " = "; + inline_str_with_links(p.default_value, out); + } + first = false; + } + } + + if (! first) + out << "`)`\n"; + else if (f.type != function_define) + out << "`()`\n"; + } + + out << "]" + << std::endl + << std::endl; +} + +void quickbook_synopsis_alt(class_or_struct const& cos, configuration const& config, std::ostream & out) +{ + std::string short_name = namespace_skipped(cos.fullname, config); + + out << "[pre\n"; + + quickbook_template_parameter_list_alt(cos.template_parameters, out); + out << "\n"; + + out << (cos.is_class ? "`class " : "`struct "); + { + std::string::size_type last_scope = std::string::npos; + std::string::size_type i = short_name.find("<"); + for(std::string::size_type j = short_name.find("::") ; j < i ; j = short_name.find("::", j+1)) + last_scope = j; + if ( last_scope == std::string::npos ) + out << short_name << "`" << std::endl; + else + out << short_name.substr(last_scope + 2) << "`" << std::endl; + } + + if (! cos.base_classes.empty()) + { + out << "` : "; + bool first = true; + BOOST_FOREACH(base_class const& bc, cos.base_classes) + { + if (! first) + { + out << std::endl << " , "; + } + out << output_if_different(bc.derivation, "private") + << output_if_different(bc.virtuality, "non-virtual") + << namespace_skipped(bc.name, config); + first = false; + } + out << "`" << std::endl; + } + + out << "`{`" << std::endl + << "` // ...`" << std::endl + << "`};`" << std::endl + << "]" << std::endl << std::endl; +} + +void quickbook_synopsis_alt(enumeration const& e, std::ostream& out) +{ + std::string values_separator = + e.enumeration_values.size() <= 2 ? + std::string(", ") : + ( std::string(",\n") + std::string(e.name.size() + 7, ' ') ); + + out << "``enum " << e.name << " "; + bool first = true; + BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) + { + out << (first ? "{" : values_separator.c_str()); + out << value.name; + if ( !value.initializer.empty() ) + { + out << " = " << boost::trim_copy(boost::replace_all_copy(value.initializer, "=", "")); + } + first = false; + } + if (! first) + { + out << "};"; + } + out << "``" + << std::endl + << std::endl; +} + +template +bool has_brief_description(Range const& rng) +{ + typedef typename Range::value_type V; + BOOST_FOREACH(V const& bc, rng) + { + if ( !bc.brief_description.empty() ) + return true; + } + return false; +} + +template +bool has_brief_description(Range const& rng, function_type t) +{ + typedef typename Range::value_type V; + BOOST_FOREACH(V const& bc, rng) + { + if ( bc.type == t && !bc.brief_description.empty() ) + return true; + } + return false; +} + +void quickbook_output_functions_details(std::vector const& functions, + function_type type, + configuration const& config, + std::ostream& out, + bool display_all = false) +{ + for ( size_t i = 0 ; i < functions.size() ; ++i ) + { + function const& f = functions[i]; + + if ( f.brief_description.empty() ) + continue; + + if ( display_all || f.type == type ) + { + // Section + std::stringstream ss; + quickbook_synopsis_short(f, ss); + out << "[#" << f.id << "]" << std::endl; + out << "[section " << replace_brackets(ss.str()) << "]" << std::endl; + + quickbook_output_indexterm(f.name, out); + + // Brief description + out << f.brief_description << std::endl; + out << std::endl; + + // Detail description + if ( !f.detailed_description.empty() ) + { + out << "[heading Description]" << std::endl; + out << f.detailed_description; + } + + // Synopsis + quickbook_markup(f.qbk_markup, markup_before, markup_synopsis, out); + out << "[heading Synopsis]" << std::endl; + quickbook_synopsis_alt(f, out); + quickbook_markup(f.qbk_markup, markup_after, markup_synopsis, out); + + if ( f.is_static || f.is_virtual || f.is_explicit || f.is_const ) + { + out << "[heading Modifier(s)]" << std::endl; + out << "``" + << (f.is_static ? "static " : "") + << (f.is_virtual ? "virtual " : "") + << (f.is_explicit ? "explicit " : "") + << (f.is_const ? "const " : "") + << "``"; + } + + // Template parameters + if ( !f.template_parameters.empty() && has_brief_description(f.template_parameters) ) + { + out << "[heading Template parameter(s)]" << std::endl + << "[table" << std::endl + << "[[Parameter] [Description]]" << std::endl; + + BOOST_FOREACH(parameter const& p, f.template_parameters) + { + if ( p.brief_description.empty() ) + continue; + + out << "[[`"; + if ( p.fulltype.find("typename ") == 0 ) + out << p.fulltype.substr(9); + else if ( p.fulltype.find("class ") == 0 ) + out << p.fulltype.substr(6); + else + out << p.fulltype; + out << "`][" << p.brief_description << "]]" << std::endl; + } + out << "]" << std::endl + << std::endl; + } + + // Parameters + if ( !f.parameters.empty() && has_brief_description(f.parameters) ) + { + out << "[heading Parameter(s)]" << std::endl; + out << "[table " << std::endl; + out << "["; + if ( f.type != function_define ) + out << "[Type]"; + out << "[Name][Description]]" << std::endl; + BOOST_FOREACH(parameter const& p, f.parameters) + { + if (!p.skip) + { + out << "["; + if ( f.type != function_define ) + { + out << "["; + inline_str_with_links(p.fulltype, out); + out << "]"; + } + out << "[ `" << p.name << "` ][" << p.brief_description << "]]"<< std::endl; + } + } + out << "]" << std::endl; + } + + // Precondition + if ( !f.precondition.empty() ) + { + out << "[heading Precondition(s)]" << std::endl; + out << f.precondition << std::endl; + out << std::endl; + } + + // Return + if ( !f.return_description.empty() ) + { + out << "[heading Returns]" << std::endl; + out << f.return_description << std::endl; + } + + // Additional paragraphs, note, warning + output_paragraphs_note_warning(f, out); + + // QBK markup + quickbook_markup(f.qbk_markup, markup_any, markup_default, out); + + // Section end + out << "[endsect]" << std::endl + //<< "[br]" << std::endl + << std::endl; + } + } +} + +void quickbook_output_enumeration_details(enumeration const& e, configuration const& config, std::ostream& out) +{ + out << "[#" << e.id << "]\n"; + out << "[section " << e.name << "]" << std::endl + << std::endl; + + quickbook_output_indexterm(e.name, out); + BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) + { + quickbook_output_indexterm(value.name, out); + } + + out << e.brief_description << std::endl; + out << std::endl; + + if ( !e.detailed_description.empty() ) + { + out << "[heading Description]\n\n"; + out << e.detailed_description << "\n\n"; + } + + // Additional paragraphs, note, warning + output_paragraphs_note_warning(e, out); + + quickbook_markup(e.qbk_markup, markup_any, markup_default, out); + + // Synopsis + quickbook_markup(e.qbk_markup, markup_before, markup_synopsis, out); + out << "[heading Synopsis]" << std::endl; + quickbook_synopsis_alt(e, out); + quickbook_markup(e.qbk_markup, markup_after, markup_synopsis, out); + + + out << "[heading Values]" << std::endl + << std::endl; + + out << "[table" << std::endl << "["; + out << "[Value] [Description] ]" << std::endl; + + BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) + { + out << "[[" << value.name << "] [" << value.brief_description << "]]\n"; + } + out << "]\n\n\n"; + + out << std::endl; + out << "[endsect]" << std::endl; + out << std::endl; +} + +void quickbook_output_alt(documentation const& doc, configuration const& config, std::ostream& out) +{ + if ( !doc.group_id.empty() ) + { + std::cout << "[section:" << doc.group_id << " " << doc.group_title << "]" << std::endl; + } + + if ( !doc.enumerations.empty() ) + { + std::cout << "[heading Enumerations]\n"; + quickbook_output_enumerations(doc.enumerations, config, out); + } + + if ( !doc.defines.empty() ) + { + std::cout << "[heading Defines]\n"; + quickbook_output_functions(doc.defines, function_unknown, config, out, true, "Define"); + } + + if ( !doc.functions.empty() ) + { + std::cout << "[heading Functions]\n"; + quickbook_output_functions(doc.functions, function_unknown, config, out, true, "Function"); + } + + BOOST_FOREACH(enumeration const& e, doc.enumerations) + { + quickbook_output_enumeration_details(e, config, out); + } + + quickbook_output_functions_details(doc.defines, function_unknown, config, out, true); + quickbook_output_functions_details(doc.functions, function_unknown, config, out, true); + + if ( !doc.group_id.empty() ) + { + out << "[endsect]" << std::endl + << std::endl; + } +} + +void quickbook_output_alt(class_or_struct const& cos, configuration const& config, std::ostream& out) +{ + // Skip namespace + std::string short_name = namespace_skipped(cos.fullname, config); + + BOOST_ASSERT(configuration::alt == config.output_style); + + if ( !cos.id.empty() ) + out << "[#" << cos.id << "]" << std::endl; + out << "[section " << short_name << "]" << std::endl << std::endl; + + // WARNING! Can't be used in the case of specializations + quickbook_output_indexterm(short_name, out); + + // Brief + + out << cos.brief_description << std::endl; + out << std::endl; + + // Description + + quickbook_string_with_heading_if_present("Description", cos.detailed_description, out); + + // Additional paragraphs, note, warning + output_paragraphs_note_warning(cos, out); + + // Markup + quickbook_markup(cos.qbk_markup, markup_any, markup_default, out); + + // Header + + quickbook_header(cos.location, config, out); + + // Class synposis + + quickbook_markup(cos.qbk_markup, markup_before, markup_synopsis, out); + out << "[heading Synopsis]" << std::endl; + quickbook_synopsis_alt(cos, config, out); + quickbook_markup(cos.qbk_markup, markup_after, markup_synopsis, out); + + // Template parameters + + if (! cos.template_parameters.empty()) + { + if ( has_brief_description(cos.template_parameters) ) + { + out << "[heading Template parameter(s)]" << std::endl + << "[table" << std::endl + << "[[Parameter] [Description]]" << std::endl; + + BOOST_FOREACH(parameter const& p, cos.template_parameters) + { + if ( p.brief_description.empty() ) + continue; + + out << "[[`"; + if ( p.fulltype.find("typename ") == 0 ) + out << p.fulltype.substr(9); + else if ( p.fulltype.find("class ") == 0 ) + out << p.fulltype.substr(6); + else + out << p.fulltype; + out << "`][" << p.brief_description << "]]" << std::endl; + } + out << "]" << std::endl + << std::endl; + } + } + + // Typedefs + + if ( !cos.typedefs.empty() ) + { + if ( has_brief_description(cos.typedefs) ) + { + out << "[heading Typedef(s)]" << std::endl + << "[table" << std::endl + << "[[Type]"; + out << " [Description]]" << std::endl; + + BOOST_FOREACH(base_element const& e, cos.typedefs) + { + if ( e.brief_description.empty() ) + continue; + + out << "[["; + if ( !e.id.empty() ) + out << "[#" << e.id << "]" << " "; + out << "`" << e.name << "`"; + out << "][" << e.brief_description << "]]" << std::endl; + } + out << "]" << std::endl + << std::endl; + } + } + + // Members + + bool display_ctors = has_brief_description(cos.functions, function_constructor_destructor); + bool display_members = has_brief_description(cos.functions, function_member); + + std::map counts; + BOOST_FOREACH(function const& f, cos.functions) + { + counts[f.type]++; + } + + if (display_ctors && counts[function_constructor_destructor] > 0) + { + out << "[heading Constructor(s) and destructor]" << std::endl; + quickbook_output_functions(cos.functions, function_constructor_destructor, config, out); + } + + if (display_members && counts[function_member] > 0) + { + out << "[heading Member(s)]" << std::endl; + quickbook_output_functions(cos.functions, function_member, config, out); + } + + // Details start + + //if ( display_ctors || display_members ) + // out << "[br]" << std::endl; + + if (display_ctors && counts[function_constructor_destructor] > 0) + quickbook_output_functions_details(cos.functions, function_constructor_destructor, config, out); + + if (display_members && counts[function_member] > 0) + quickbook_output_functions_details(cos.functions, function_member, config, out); + + // Details end + + out << "[endsect]" << std::endl + << std::endl; +} + #endif // QUICKBOOK_OUTPUT_HPP diff --git a/doc/src/docutils/tools/doxygen_xml2qbk/rapidxml_util.hpp b/doc/src/docutils/tools/doxygen_xml2qbk/rapidxml_util.hpp index 6acdaab5b1..eea1f463c1 100644 --- a/doc/src/docutils/tools/doxygen_xml2qbk/rapidxml_util.hpp +++ b/doc/src/docutils/tools/doxygen_xml2qbk/rapidxml_util.hpp @@ -1,6 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. // 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) diff --git a/doc/src/docutils/tools/support_status/support_status.cpp b/doc/src/docutils/tools/support_status/support_status.cpp index d3c788db32..5a8fa1e354 100644 --- a/doc/src/docutils/tools/support_status/support_status.cpp +++ b/doc/src/docutils/tools/support_status/support_status.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ #include #include #include +#include #include #include "text_outputter.hpp" @@ -132,6 +134,7 @@ DECLARE_UNARY_ALGORITHM(simplify) DECLARE_BINARY_ALGORITHM(transform) DECLARE_UNARY_ALGORITHM(unique) DECLARE_BINARY_ALGORITHM(within) +DECLARE_UNARY_ALGORITHM(wkt) template

    {}; #endif /*! - \brief Meta-function which defines coordinate dimensions, i.e. the number of axes of any geometry - \ingroup core +\brief \brief_meta{value, number of coordinates (the number of axes of any geometry), \meta_point_type} +\tparam Geometry \tparam_geometry +\ingroup core + +\qbk{[include reference/core/coordinate_dimension.qbk]} */ -template +template struct dimension : core_dispatch::dimension < - typename tag::type, - typename boost::remove_const::type + typename tag::type, + typename boost::remove_const::type > {}; /*! - \brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected - \ingroup utility +\brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected +\ingroup utility */ -template +template inline void assert_dimension() { BOOST_STATIC_ASSERT(( boost::mpl::equal_to < - geometry::dimension, - boost::mpl::int_ + geometry::dimension, + boost::mpl::int_ >::type::value )); } /*! - \brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected - \ingroup utility +\brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected +\ingroup utility */ -template +template inline void assert_dimension_less_equal() { - BOOST_STATIC_ASSERT(( dimension::type::value <= D )); + BOOST_STATIC_ASSERT(( dimension::type::value <= Dimensions )); } -template +template inline void assert_dimension_greater_equal() { - BOOST_STATIC_ASSERT(( dimension::type::value >= D )); + BOOST_STATIC_ASSERT(( dimension::type::value >= Dimensions )); } /*! - \brief assert_dimension_equal, enables compile-time checking if coordinate dimensions of two geometries are equal - \ingroup utility +\brief assert_dimension_equal, enables compile-time checking if coordinate dimensions of two geometries are equal +\ingroup utility */ template inline void assert_dimension_equal() diff --git a/include/boost/geometry/core/coordinate_system.hpp b/include/boost/geometry/core/coordinate_system.hpp index e3b5718a9a..9c0920cd67 100644 --- a/include/boost/geometry/core/coordinate_system.hpp +++ b/include/boost/geometry/core/coordinate_system.hpp @@ -73,16 +73,19 @@ namespace core_dispatch /*! - \brief Meta-function which defines coordinate system for any geometry - \ingroup core +\brief \brief_meta{type, coordinate system (cartesian\, spherical\, etc), \meta_point_type} +\tparam Geometry \tparam_geometry +\ingroup core + +\qbk{[include reference/core/coordinate_system.qbk]} */ -template +template struct coordinate_system { - typedef typename boost::remove_const::type ncg; + typedef typename boost::remove_const::type ncg; typedef typename core_dispatch::coordinate_system < - typename tag::type, + typename tag::type, ncg >::type type; }; diff --git a/include/boost/geometry/core/coordinate_type.hpp b/include/boost/geometry/core/coordinate_type.hpp index 720ec9128f..ae4300a658 100644 --- a/include/boost/geometry/core/coordinate_type.hpp +++ b/include/boost/geometry/core/coordinate_type.hpp @@ -70,8 +70,11 @@ struct coordinate_type #endif // DOXYGEN_NO_DISPATCH /*! - \brief Meta-function which defines coordinate type (int, float, double, etc) of any geometry - \ingroup core +\brief \brief_meta{type, coordinate type (int\, float\, double\, etc), \meta_point_type} +\tparam Geometry \tparam_geometry +\ingroup core + +\qbk{[include reference/core/coordinate_type.qbk]} */ template struct coordinate_type diff --git a/include/boost/geometry/core/cs.hpp b/include/boost/geometry/core/cs.hpp index fcbad5ae2e..93e0eec776 100644 --- a/include/boost/geometry/core/cs.hpp +++ b/include/boost/geometry/core/cs.hpp @@ -27,16 +27,20 @@ namespace boost { namespace geometry /*! \brief Unit of plane angle: Degrees -\ingroup cs -\note Might be replaced by Boost.Units +\details Tag defining the unit of plane angle for spherical coordinate systems. + This tag specifies that coordinates are defined in degrees (-180 .. 180). + It has to be specified for some coordinate systems. +\qbk{[include reference/core/degree_radian.qbk]} */ struct degree {}; /*! \brief Unit of plane angle: Radians -\ingroup cs -\note Might be replaced by Boost.Units +\details Tag defining the unit of plane angle for spherical coordinate systems. + This tag specifies that coordinates are defined in radians (-PI .. PI). + It has to be specified for some coordinate systems. +\qbk{[include reference/core/degree_radian.qbk]} */ struct radian {}; diff --git a/include/boost/geometry/core/point_order.hpp b/include/boost/geometry/core/point_order.hpp index 7dd55634bf..675fee8022 100644 --- a/include/boost/geometry/core/point_order.hpp +++ b/include/boost/geometry/core/point_order.hpp @@ -138,19 +138,15 @@ struct point_order /*! -\brief Metafunction which defines point order of a geometry type +\brief \brief_meta{value, point order (clockwise\, counterclockwise), \meta_geometry_type} +\tparam Geometry \tparam_geometry \ingroup core -\details -\qbk{ -[heading See also] -[link geometry.reference.enumerations.closure_selector The closure_selector enumeration] -} +\qbk{[include reference/core/point_order.qbk]} */ template struct point_order { - /// metafunction implementation static const order_selector value = core_dispatch::point_order < typename tag::type, diff --git a/include/boost/geometry/core/point_type.hpp b/include/boost/geometry/core/point_type.hpp index efaaead928..4217afdad5 100644 --- a/include/boost/geometry/core/point_type.hpp +++ b/include/boost/geometry/core/point_type.hpp @@ -106,8 +106,11 @@ struct point_type /*! - \brief Meta-function which defines point type of any geometry - \ingroup core +\brief \brief_meta{type, point_type, \meta_geometry_type} +\tparam Geometry \tparam_geometry +\ingroup core + +\qbk{[include reference/core/point_type.qbk]} */ template struct point_type diff --git a/include/boost/geometry/core/tag.hpp b/include/boost/geometry/core/tag.hpp index 702ab3ec12..f8f622e746 100644 --- a/include/boost/geometry/core/tag.hpp +++ b/include/boost/geometry/core/tag.hpp @@ -48,11 +48,11 @@ struct tag /*! -\brief Meta-function to get the tag of any geometry type -\details All geometries tell their geometry type (point, linestring, polygon, etc) by implementing - a tag traits class. This meta-function uses that traits class to retrieve the tag. -\tparam Geometry geometry +\brief \brief_meta{type, tag, \meta_geometry_type} +\tparam Geometry \tparam_geometry \ingroup core + +\qbk{[include reference/core/tag.qbk]} */ template struct tag diff --git a/include/boost/geometry/core/tag_cast.hpp b/include/boost/geometry/core/tag_cast.hpp index 1318f265f0..cf1bd0b6e2 100644 --- a/include/boost/geometry/core/tag_cast.hpp +++ b/include/boost/geometry/core/tag_cast.hpp @@ -21,7 +21,25 @@ namespace boost { namespace geometry { -/// Generic tag_cast utility +/*! +\brief Metafunction defining a type being either the specified tag, or one + of the specified basetags if the type inherits from them. +\details Tags can inherit each other. A multi_point inherits, for example, + both the multi_tag and the pointlike tag. Often behaviour can be shared + between different geometry types. A tag, found by the metafunction tag, + can be casted to a more basic tag, and then dispatched by that tag. +\ingroup core +\tparam Tag The tag to be casted to one of the base tags +\tparam BaseTag First base tag +\tparam BaseTag2 Optional second base tag +\tparam BaseTag3 Optional third base tag +\tparam BaseTag4 Optional fourth base tag +\tparam BaseTag5 Optional fifth base tag +\tparam BaseTag6 Optional sixth base tag +\tparam BaseTag7 Optional seventh base tag + +\qbk{[include reference/core/tag_cast.qbk]} +*/ template < typename Tag, @@ -48,6 +66,8 @@ struct tag_cast >::type type; }; +#ifndef DOXYGEN_NO_SPECIALIZATIONS + // Specialization for last one template struct tag_cast @@ -56,6 +76,8 @@ struct tag_cast typedef Tag type; }; +#endif // DOXYGEN_NO_SPECIALIZATIONS + }} // namespace boost::geometry diff --git a/include/boost/geometry/domains/gis/io/wkt/read_wkt.hpp b/include/boost/geometry/domains/gis/io/wkt/read_wkt.hpp index 8b70c1a658..bc534a2113 100644 --- a/include/boost/geometry/domains/gis/io/wkt/read_wkt.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/read_wkt.hpp @@ -531,8 +531,8 @@ struct box_parser throw read_wkt_exception("Box should have 2,4 or 5 points", wkt); } - assign_point_to_index(points.front(), box); - assign_point_to_index(points[index], box); + geometry::detail::assign_point_to_index(points.front(), box); + geometry::detail::assign_point_to_index(points[index], box); } }; @@ -570,8 +570,8 @@ struct segment_parser if (boost::size(points) == 2) { - assign_point_to_index<0>(points.front(), segment); - assign_point_to_index<1>(points.back(), segment); + geometry::detail::assign_point_to_index<0>(points.front(), segment); + geometry::detail::assign_point_to_index<1>(points.back(), segment); } else { diff --git a/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp b/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp index fcf168aa7b..7bf52c13c6 100644 --- a/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp +++ b/include/boost/geometry/domains/gis/io/wkt/write_wkt.hpp @@ -24,7 +24,7 @@ #include -#include +#include #include #include #include @@ -199,7 +199,7 @@ struct wkt_box // Convert to ring, then stream typedef model::ring ring_type; ring_type ring; - geometry::detail::convert(box, ring); + geometry::convert(box, ring); os << "POLYGON("; wkt_sequence::apply(os, ring); os << ")"; @@ -228,8 +228,8 @@ struct wkt_segment typedef boost::array sequence; sequence points; - assign_point_from_index<0>(segment, points[0]); - assign_point_from_index<1>(segment, points[1]); + geometry::detail::assign_point_from_index<0>(segment, points[0]); + geometry::detail::assign_point_from_index<1>(segment, points[1]); // In Boost.Geometry a segment is represented // in WKT-format like (for 2D): LINESTRING(x y,x y) diff --git a/include/boost/geometry/geometries/box.hpp b/include/boost/geometry/geometries/box.hpp index 6537f12980..a42e72c91b 100644 --- a/include/boost/geometry/geometries/box.hpp +++ b/include/boost/geometry/geometries/box.hpp @@ -18,7 +18,7 @@ #include -#include +#include #include @@ -57,8 +57,8 @@ class box */ inline box(Point const& min_corner, Point const& max_corner) { - geometry::detail::convert(min_corner, m_min_corner); - geometry::detail::convert(max_corner, m_max_corner); + geometry::convert(min_corner, m_min_corner); + geometry::convert(max_corner, m_max_corner); } inline Point const& min_corner() const { return m_min_corner; } diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp index e8405f7a7b..c5586eeafa 100644 --- a/include/boost/geometry/geometry.hpp +++ b/include/boost/geometry/geometry.hpp @@ -19,6 +19,7 @@ #include #include +#include #include // Core algorithms @@ -42,6 +43,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/geometry/iterators/box_iterator.hpp b/include/boost/geometry/iterators/box_iterator.hpp index d9fa8fae8c..735e90db32 100644 --- a/include/boost/geometry/iterators/box_iterator.hpp +++ b/include/boost/geometry/iterators/box_iterator.hpp @@ -95,9 +95,7 @@ struct box_iterator inline void init(Box const& box) { - // asb -> lower_left, lower_right, upper_left, upper_right - // we want: clockwise - assign_box_corners(box, m_points[0], m_points[3], m_points[1], m_points[2]); + detail::assign_box_corners_oriented(box, m_points); } // Copy points here - box might define them otherwise diff --git a/include/boost/geometry/iterators/segment_range_iterator.hpp b/include/boost/geometry/iterators/segment_range_iterator.hpp index 0eaa7300ab..55c1f50468 100644 --- a/include/boost/geometry/iterators/segment_range_iterator.hpp +++ b/include/boost/geometry/iterators/segment_range_iterator.hpp @@ -115,8 +115,8 @@ struct segment_range_iterator inline void init(Segment const& segment) { - assign_point_from_index<0>(segment, m_points[0]); - assign_point_from_index<1>(segment, m_points[1]); + geometry::detail::assign_point_from_index<0>(segment, m_points[0]); + geometry::detail::assign_point_from_index<1>(segment, m_points[1]); } // We HAVE TO copy the points, because a segment does not need diff --git a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp index d0293c4b6c..52eb4bd694 100644 --- a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -132,8 +132,8 @@ public : // For consistency we define w also in FP fp_vector_type v, w; - geometry::detail::convert(p2, v); - geometry::detail::convert(p, w); + geometry::convert(p2, v); + geometry::convert(p, w); subtract_point(v, p1); subtract_point(w, p1); @@ -163,7 +163,7 @@ public : >::apply(strategy); fp_point_type projected; - geometry::detail::convert(p1, projected); + geometry::convert(p1, projected); multiply_value(v, b); add_point(projected, v); diff --git a/include/boost/geometry/strategies/strategy_transform.hpp b/include/boost/geometry/strategies/strategy_transform.hpp index 3961ee276a..35c6a4526e 100644 --- a/include/boost/geometry/strategies/strategy_transform.hpp +++ b/include/boost/geometry/strategies/strategy_transform.hpp @@ -20,7 +20,7 @@ #include -#include +#include #include #include #include @@ -104,7 +104,7 @@ struct copy_per_coordinate // Defensive check, dimensions are equal, selected by specialization assert_dimension_equal(); - geometry::detail::convert(p1, p2); + geometry::convert(p1, p2); return true; } }; From 5a25db7b350c2512554dee9de6d529a2e93128a0 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 16 Apr 2011 23:21:23 +0000 Subject: [PATCH 013/135] Added boost/geometry.hpp to release branch [SVN r71338] --- include/boost/geometry.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 include/boost/geometry.hpp diff --git a/include/boost/geometry.hpp b/include/boost/geometry.hpp new file mode 100644 index 0000000000..a4756e7146 --- /dev/null +++ b/include/boost/geometry.hpp @@ -0,0 +1,19 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_HPP +#define BOOST_GEOMETRY_HPP + +#include + +#endif // BOOST_GEOMETRY_HPP From ac0807a26f999e9e770559f27602dce6bbedee68 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 16 Apr 2011 23:24:35 +0000 Subject: [PATCH 014/135] Merged Boost.Geometry from revision 71123 to 71336 [SVN r71339] --- doc/doxy/Doxyfile | 3 + doc/doxy/doxygen_output/html/doxygen.css | 380 +---- doc/doxy/doxygen_output/html/doxygen.png | Bin 3942 -> 1281 bytes doc/doxy/doxygen_output/html/tabs.css | 132 +- doc/generated/equals_status.qbk | 10 + doc/geometry.qbk | 4 +- doc/html/img/algorithms/convex_hull.png | Bin 0 -> 19017 bytes ...{make_envelope.png => return_envelope.png} | Bin doc/imports.qbk | 4 + doc/quickref.xml | 4 - doc/reference.qbk | 4 - doc/reference/algorithms/append.qbk | 2 +- .../algorithms/comparable_distance.qbk | 25 + doc/reference/algorithms/convert.qbk | 27 + doc/reference/algorithms/convex_hull.qbk | 18 + doc/reference/algorithms/correct.qbk | 33 + doc/reference/algorithms/difference.qbk | 6 +- doc/reference/algorithms/distance.qbk | 21 + doc/reference/algorithms/equals.qbk | 21 + doc/reference/algorithms/intersection.qbk | 6 +- doc/reference/algorithms/sym_difference.qbk | 6 +- doc/reference/algorithms/transform.qbk | 28 + .../algorithms/transform_with_strategy.qbk | 19 + doc/reference/algorithms/union.qbk | 6 +- doc/reference/core/closure.qbk | 23 + doc/reference/core/coordinate_dimension.qbk | 16 + doc/reference/core/coordinate_system.qbk | 16 + doc/reference/core/coordinate_type.qbk | 16 + doc/reference/core/degree_radian.qbk | 14 + doc/reference/core/max_corner.qbk | 26 + doc/reference/core/min_corner.qbk | 25 + doc/reference/core/min_max_corner.qbk | 31 + doc/reference/core/point_order.qbk | 24 + doc/reference/core/point_type.qbk | 17 + doc/reference/core/tag.qbk | 20 + doc/reference/core/tag_cast.qbk | 26 + .../implementation_status.cpp | 9 +- doc/src/examples/algorithms/Jamfile.v2 | 36 +- doc/src/examples/algorithms/assign.cpp | 61 + .../examples/algorithms/assign_2d_point.cpp | 6 +- .../examples/algorithms/assign_3d_point.cpp | 2 +- .../algorithms/assign_box_corners.cpp | 2 +- .../algorithms/assign_point_from_index.cpp | 2 +- ...ssign_with_range.cpp => assign_points.cpp} | 8 +- doc/src/examples/algorithms/clear.cpp | 4 +- .../algorithms/comparable_distance.cpp | 66 + doc/src/examples/algorithms/convert.cpp | 59 + doc/src/examples/algorithms/convex_hull.cpp | 54 + doc/src/examples/algorithms/correct.cpp | 65 + doc/src/examples/algorithms/distance.cpp | 13 +- doc/src/examples/algorithms/equals.cpp | 59 + doc/src/examples/algorithms/expand.cpp | 46 + .../algorithms/num_interior_rings.cpp | 2 +- doc/src/examples/algorithms/transform.cpp | 53 + .../algorithms/transform_with_strategy.cpp | 63 + doc/src/examples/core/Jamfile.v2 | 11 + doc/src/examples/core/closure.cpp | 42 + .../examples/core/coordinate_dimension.cpp | 43 + doc/src/examples/core/coordinate_system.cpp | 39 + doc/src/examples/core/coordinate_type.cpp | 39 + doc/src/examples/core/degree_radian.cpp | 47 + doc/src/examples/core/point_order.cpp | 42 + doc/src/examples/core/point_type.cpp | 40 + doc/src/examples/core/tag.cpp | 48 + doc/src/examples/core/tag_cast.cpp | 43 + .../examples/geometries/register/point.cpp | 4 +- example/01_point_example.cpp | 24 +- example/02_linestring_example.cpp | 4 +- example/03_polygon_example.cpp | 4 +- example/05_a_overlay_polygon_example.cpp | 4 +- ...5_b_overlay_linestring_polygon_example.cpp | 4 +- example/06_a_transformation_example.cpp | 2 +- example/c01_custom_point_example.cpp | 12 +- .../x05_shapelib_example.cpp | 2 +- test/algorithms/Jamfile.v2 | 1 + test/algorithms/algorithms_tests.sln | 6 + test/algorithms/assign.cpp | 94 +- test/algorithms/{detail => }/convert.cpp | 12 +- test/algorithms/{detail => }/convert.vcproj | 8 +- test/algorithms/detail/Jamfile.v2 | 1 - test/algorithms/detail/detail.sln | 6 - test/algorithms/detail/partition.cpp | 255 +++- test/algorithms/intersection.cpp | 2 +- test/algorithms/make.cpp | 4 +- test/algorithms/transform.cpp | 4 +- test/arithmetic/arithmetic.cpp | 34 +- test/arithmetic/dot_product.cpp | 4 +- test/compile_test.cpp | 220 --- test/compile_test.sln | 29 - test/compile_test.vcproj | 300 ---- test/custom_tests.sln | 37 - test/geometries/boost_polygon.cpp | 4 +- test/geometries/box.cpp | 4 +- test/ggl_headers.sln | 20 - test/ggl_headers.vcproj | 1339 ----------------- test/strategies/cross_track.cpp | 6 +- test/strategies/haversine.cpp | 12 +- test/strategies/projected_point.cpp | 6 +- test/strategies/pythagoras.cpp | 28 +- test/strategies/segment_intersection.cpp | 8 +- .../segment_intersection_collinear.cpp | 8 +- test/strategies/side_by_cross_track.cpp | 6 +- test/strategies/transformer.cpp | 2 +- test/util/for_each_coordinate.cpp | 2 +- 104 files changed, 2044 insertions(+), 2495 deletions(-) create mode 100644 doc/generated/equals_status.qbk create mode 100644 doc/html/img/algorithms/convex_hull.png rename doc/html/img/algorithms/{make_envelope.png => return_envelope.png} (100%) create mode 100644 doc/reference/algorithms/comparable_distance.qbk create mode 100644 doc/reference/algorithms/convert.qbk create mode 100644 doc/reference/algorithms/convex_hull.qbk create mode 100644 doc/reference/algorithms/correct.qbk create mode 100644 doc/reference/algorithms/distance.qbk create mode 100644 doc/reference/algorithms/equals.qbk create mode 100644 doc/reference/algorithms/transform.qbk create mode 100644 doc/reference/algorithms/transform_with_strategy.qbk create mode 100644 doc/reference/core/closure.qbk create mode 100644 doc/reference/core/coordinate_dimension.qbk create mode 100644 doc/reference/core/coordinate_system.qbk create mode 100644 doc/reference/core/coordinate_type.qbk create mode 100644 doc/reference/core/degree_radian.qbk create mode 100644 doc/reference/core/max_corner.qbk create mode 100644 doc/reference/core/min_corner.qbk create mode 100644 doc/reference/core/min_max_corner.qbk create mode 100644 doc/reference/core/point_order.qbk create mode 100644 doc/reference/core/point_type.qbk create mode 100644 doc/reference/core/tag.qbk create mode 100644 doc/reference/core/tag_cast.qbk create mode 100644 doc/src/examples/algorithms/assign.cpp rename doc/src/examples/algorithms/{assign_with_range.cpp => assign_points.cpp} (81%) create mode 100644 doc/src/examples/algorithms/comparable_distance.cpp create mode 100644 doc/src/examples/algorithms/convert.cpp create mode 100644 doc/src/examples/algorithms/convex_hull.cpp create mode 100644 doc/src/examples/algorithms/correct.cpp create mode 100644 doc/src/examples/algorithms/equals.cpp create mode 100644 doc/src/examples/algorithms/expand.cpp create mode 100644 doc/src/examples/algorithms/transform.cpp create mode 100644 doc/src/examples/algorithms/transform_with_strategy.cpp create mode 100644 doc/src/examples/core/closure.cpp create mode 100644 doc/src/examples/core/coordinate_dimension.cpp create mode 100644 doc/src/examples/core/coordinate_system.cpp create mode 100644 doc/src/examples/core/coordinate_type.cpp create mode 100644 doc/src/examples/core/degree_radian.cpp create mode 100644 doc/src/examples/core/point_order.cpp create mode 100644 doc/src/examples/core/point_type.cpp create mode 100644 doc/src/examples/core/tag.cpp create mode 100644 doc/src/examples/core/tag_cast.cpp rename test/algorithms/{detail => }/convert.cpp (92%) rename test/algorithms/{detail => }/convert.vcproj (92%) delete mode 100644 test/compile_test.cpp delete mode 100644 test/compile_test.sln delete mode 100644 test/compile_test.vcproj delete mode 100644 test/custom_tests.sln delete mode 100644 test/ggl_headers.sln delete mode 100644 test/ggl_headers.vcproj diff --git a/doc/doxy/Doxyfile b/doc/doxy/Doxyfile index 22d7a0a3b4..7c34fb5e0c 100644 --- a/doc/doxy/Doxyfile +++ b/doc/doxy/Doxyfile @@ -50,6 +50,7 @@ ALIASES = qbk{1}="\xmlonly \1 \endxmlonly" \ brief_macro{1}="Macro to register a \1" \ brief_macro_const=" (const version)" \ brief_macro_getset=" (having separate get/set methods)" \ + brief_meta{3}="Metafunction defining [*\1] as the specified \2 of the \3" \ tparam_allocator="container-allocator-type" \ tparam_box="Any type fulfilling a Box Concept" \ tparam_box_or_segment="Any type fulfilling a Box Concept or a Segment Concept" \ @@ -107,6 +108,8 @@ ALIASES = qbk{1}="\xmlonly \1 \endxmlonly" \ return_check{1}="Returns true if the geometry \1" \ return_check2{1}="Returns true if two geometries \1" \ return_out="The output iterator" \ + meta_geometry_type="specified geometry type" \ + meta_point_type="point type making up the specified geometry type" \ brf_for_each{1}="Applies function [*f] to each \1" \ det_envelope="envelope (also known as axis aligned bounding box, aabb, or minimum bounding rectangle, mbr)" \ det_buffer="buffer (a polygon being the spatial point set collection within a specified maximum distance from a geometry)" \ diff --git a/doc/doxy/doxygen_output/html/doxygen.css b/doc/doxy/doxygen_output/html/doxygen.css index 74445fe1fe..d6aaf2804c 100644 --- a/doc/doxy/doxygen_output/html/doxygen.css +++ b/doc/doxy/doxygen_output/html/doxygen.css @@ -8,15 +8,10 @@ body, table, div, p, dl { /* @group Heading Levels */ h1 { + text-align: center; font-size: 150%; } -.title { - font-size: 150%; - font-weight: bold; - margin: 10px 2px; -} - h2 { font-size: 120%; } @@ -69,8 +64,8 @@ h3.version { } div.qindex, div.navtab{ - background-color: #EBEFF6; - border: 1px solid #A3B4D7; + background-color: #e8eef2; + border: 1px solid #84b0c7; text-align: center; margin: 2px; padding: 2px; @@ -88,13 +83,13 @@ div.navtab { /* @group Link Styling */ a { - color: #3D578C; + color: #153788; font-weight: normal; text-decoration: none; } .contents a:visited { - color: #4665A2; + color: #1b77c5; } a:hover { @@ -107,9 +102,9 @@ a.qindex { a.qindexHL { font-weight: bold; - background-color: #9CAFD4; + background-color: #6666cc; color: #ffffff; - border: 1px double #869DCA; + border: 1px double #9295C2; } .contents a.qindexHL:visited { @@ -124,11 +119,11 @@ a.elRef { } a.code { - color: #4665A2; + color: #3030f0; } a.codeRef { - color: #4665A2; + color: #3030f0; } /* @end */ @@ -143,8 +138,8 @@ dl.el { } pre.fragment { - border: 1px solid #C4CFE5; - background-color: #FBFCFD; + border: 1px solid #CCCCCC; + background-color: #f5f5f5; padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; @@ -158,22 +153,13 @@ div.ah { font-weight: bold; color: #ffffff; margin-bottom: 3px; - margin-top: 3px; - padding: 0.2em; - border: solid thin #333; - border-radius: 0.5em; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - box-shadow: 2px 2px 3px #999; - -webkit-box-shadow: 2px 2px 3px #999; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); - background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); + margin-top: 3px } div.groupHeader { margin-left: 16px; margin-top: 12px; + margin-bottom: 6px; font-weight: bold; } @@ -185,32 +171,27 @@ div.groupText { body { background: white; color: black; - margin: 0; -} - -div.contents { - margin-top: 10px; - margin-left: 10px; - margin-right: 5px; + margin-right: 20px; + margin-left: 20px; } td.indexkey { - background-color: #EBEFF6; + background-color: #e8eef2; font-weight: bold; - border: 1px solid #C4CFE5; + border: 1px solid #CCCCCC; margin: 2px 0px 2px 0; padding: 2px 10px; } td.indexvalue { - background-color: #EBEFF6; - border: 1px solid #C4CFE5; + background-color: #e8eef2; + border: 1px solid #CCCCCC; padding: 2px 10px; margin: 2px 0px; } tr.memlist { - background-color: #EEF1F7; + background-color: #f0f0f0; } p.formulaDsp { @@ -236,11 +217,6 @@ div.center img { border: 0px; } -address.footer { - text-align: right; - padding-right: 12px; -} - img.footer { border: 0px; vertical-align: middle; @@ -294,7 +270,6 @@ span.vhdllogic { /* @end */ -/* .search { color: #003399; font-weight: bold; @@ -311,7 +286,6 @@ input.search { font-weight: normal; background-color: #e8eef2; } -*/ td.tiny { font-size: 75%; @@ -320,18 +294,18 @@ td.tiny { .dirtab { padding: 4px; border-collapse: collapse; - border: 1px solid #A3B4D7; + border: 1px solid #84b0c7; } th.dirtab { - background: #EBEFF6; + background: #e8eef2; font-weight: bold; } hr { height: 0px; border: none; - border-top: 1px solid #4A6AAA; + border-top: 1px solid #666; } hr.footer { @@ -340,15 +314,10 @@ hr.footer { /* @group Member Descriptions */ -table.memberdecls { - border-spacing: 0px; - padding: 0px; -} - .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #F9FAFC; + background-color: #FAFAFA; border: none; margin: 4px; padding: 1px 0 0 8px; @@ -360,19 +329,15 @@ table.memberdecls { } .memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #C4CFE5; + border-top: 1px solid #ccc; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } -.memItemRight { - width: 100%; -} - .memTemplParams { - color: #4665A2; + color: #606060; white-space: nowrap; } @@ -384,28 +349,23 @@ table.memberdecls { .memtemplate { font-size: 80%; - color: #4665A2; + color: #606060; font-weight: normal; - margin-left: 9px; + margin-left: 3px; } .memnav { - background-color: #EBEFF6; - border: 1px solid #A3B4D7; + background-color: #e8eef2; + border: 1px solid #84b0c7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } -.mempage { - width: 100%; -} - .memitem { padding: 0; margin-bottom: 10px; - margin-right: 5px; } .memname { @@ -415,52 +375,40 @@ table.memberdecls { } .memproto { - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 0px 6px 0px; - color: #253555; + border-top: 1px solid #84b0c7; + border-left: 1px solid #84b0c7; + border-right: 1px solid #84b0c7; + padding: 0; + background-color: #d5e1e8; font-weight: bold; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 8px; - border-top-left-radius: 8px; /* firefox specific markup */ + background-image: -moz-linear-gradient(rgba(228, 233, 245, 1.0) 0%, rgba(193, 205, 232, 1.0) 100%); -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 8px; -moz-border-radius-topleft: 8px; /* webkit specific markup */ + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(228, 233, 245, 1.0)), to(rgba(193, 205, 232, 1.0))); -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 8px; -webkit-border-top-left-radius: 8px; - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; } .memdoc { - border-bottom: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #84b0c7; + border-left: 1px solid #84b0c7; + border-right: 1px solid #84b0c7; padding: 2px 5px; - background-color: #FBFCFD; + background-color: #eef3f5; border-top-width: 0; - /* opera specific markup */ - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ -moz-border-radius-bottomleft: 8px; -moz-border-radius-bottomright: 8px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); /* webkit specific markup */ -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); } .paramkey { @@ -479,28 +427,6 @@ table.memberdecls { font-style: normal; } -.params, .retval, .exception, .tparams { - border-spacing: 6px 2px; -} - -.params .paramname, .retval .paramname { - font-weight: bold; - vertical-align: top; -} - -.params .paramtype { - font-style: italic; - vertical-align: top; -} - -.params .paramdir { - font-family: "courier new",courier,monospace; - vertical-align: top; -} - - - - /* @end */ /* @group Directory (tree) */ @@ -509,7 +435,7 @@ table.memberdecls { .ftvtree { font-family: sans-serif; - margin: 0px; + margin: 0.5em; } /* these are for tree view when used as main index */ @@ -517,7 +443,6 @@ table.memberdecls { .directory { font-size: 9pt; font-weight: bold; - margin: 5px; } .directory h3 { @@ -595,13 +520,9 @@ proper pixel height of your image. /* @end */ -div.dynheader { - margin-top: 8px; -} - address { font-style: normal; - color: #2A3D61; + color: #333; } table.doxtable { @@ -609,12 +530,12 @@ table.doxtable { } table.doxtable td, table.doxtable th { - border: 1px solid #2D4068; + border: 1px solid #153788; padding: 3px 7px 2px; } table.doxtable th { - background-color: #374F7F; + background-color: #254798; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; @@ -622,214 +543,3 @@ table.doxtable th { text-align:left; } -.tabsearch { - top: 0px; - left: 10px; - height: 36px; - background-image: url('tab_b.png'); - z-index: 101; - overflow: hidden; - font-size: 13px; -} - -.navpath ul -{ - font-size: 11px; - background-image:url('tab_b.png'); - background-repeat:repeat-x; - height:30px; - line-height:30px; - color:#8AA0CC; - border:solid 1px #C2CDE4; - overflow:hidden; - margin:0px; - padding:0px; -} - -.navpath li -{ - list-style-type:none; - float:left; - padding-left:10px; - padding-right:15px; - background-image:url('bc_s.png'); - background-repeat:no-repeat; - background-position:right; - color:#364D7C; -} - -.navpath li.navelem a -{ - height:32px; - display:block; - text-decoration: none; - outline: none; -} - -.navpath li.navelem a:hover -{ - color:#6884BD; -} - -.navpath li.footer -{ - list-style-type:none; - float:right; - padding-left:10px; - padding-right:15px; - background-image:none; - background-repeat:no-repeat; - background-position:right; - color:#364D7C; - font-size: 8pt; -} - - -div.summary -{ - float: right; - font-size: 8pt; - padding-right: 5px; - width: 50%; - text-align: right; -} - -div.summary a -{ - white-space: nowrap; -} - -div.ingroups -{ - font-size: 8pt; - padding-left: 5px; - width: 50%; - text-align: left; -} - -div.ingroups a -{ - white-space: nowrap; -} - -div.header -{ - background-image:url('nav_h.png'); - background-repeat:repeat-x; - background-color: #F9FAFC; - margin: 0px; - border-bottom: 1px solid #C4CFE5; -} - -div.headertitle -{ - padding: 5px 5px 5px 10px; -} - -dl -{ - padding: 0 0 0 10px; -} - -dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug -{ - border-left:4px solid; - padding: 0 0 0 6px; -} - -dl.note -{ - border-color: #D0C000; -} - -dl.warning, dl.attention -{ - border-color: #FF0000; -} - -dl.pre, dl.post, dl.invariant -{ - border-color: #00D000; -} - -dl.deprecated -{ - border-color: #505050; -} - -dl.todo -{ - border-color: #00C0E0; -} - -dl.test -{ - border-color: #3030E0; -} - -dl.bug -{ - border-color: #C08050; -} - -#projectlogo -{ - text-align: center; - vertical-align: bottom; - border-collapse: separate; -} - -#projectlogo img -{ - border: 0px none; -} - -#projectname -{ - font: 300% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 2px 0px; -} - -#projectbrief -{ - font: 120% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#projectnumber -{ - font: 50% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#titlearea -{ - padding: 0px; - margin: 0px; - width: 100%; - border-bottom: 1px solid #5373B4; -} - -.image -{ - text-align: center; -} - -.dotgraph -{ - text-align: center; -} - -.mscgraph -{ - text-align: center; -} - -.caption -{ - font-weight: bold; -} - diff --git a/doc/doxy/doxygen_output/html/doxygen.png b/doc/doxy/doxygen_output/html/doxygen.png index 635ed52fce7057ac24df92ec7664088a881fa5d0..f0a274bbaffdd67f6d784c894d9cf28729db0e14 100644 GIT binary patch literal 1281 zcmaJ>ZA?>F7(Vx-ms?uoS`b@hdRtpo6o^%HU>M$hfGrBvQnk$LE?p^P!kn&ikhyq! zX~V@&tPF5Qt@V?oTL96Bi%aRiwbe1)9DWQI#?)=HxS7QSw`J`5fAJ*eJbB;uNuKA& zdERDo*{Y<(If(#(B$Lr#;nB(8Y#ia=ZCeW?JfPLuQY`=@cW$k}Rivq|vbxGrRq1Tl9;+(gNt?}UtVKM2`T5t1jLzuL@0UIs`S#vlhl4)^ zLgSYrPj@$+`|j?eSbXTmiHGkWxV8V}BzNR?pl9k_s4pDu9vd5a_UzZEPk)}Ad{AV_ zzddrjrh4=Imr`E06;LY{)YYt?o}L~H@7C}F^WB!Ra=v`Q0bj{>5&$66CWF>mf6vjP z2N>RRY6ZYa=K`76>+|_)Xdwko+7wv}7cN|btOhWb(*{sta~6b?S8Omrxw}!4`NhGr zZVpNqpu1@BE`QGWNTpEpcJVW5izu~2B^GlM?1(OPg)zwW;QcP@Ltcclm>XbJL9C|j z=9!2?ua=uIlf0%AndzHsRC}IyTL$EhAee(fdKB`?27KeS^2M8M_7b~PiCFO&r5LC7 z7gl1*a<8;SjNaw#h=843_AV9iZbWQOAp5YOC^&_F*9K0> zB|6%IDb?aM#3viTxkLU4aXg&@+CkNTOnQ1iMP*^?b|^lJy$4C)Zk4isV!|RZ*XhXh zw8q3$=*0LeGC!XI_Wc?dkT~3+*Gu%%yIqP+Wr3H$=&ROMQU6q}Ag^P~>c5vAEO;a- z_dK-3PPeKar%)6$j~vI2#*-YH!1h6HYVtwCX5_wM`iF#UKz&&@9Oo5w3%XGYrX zW>dY~)SG-((Yim%`InwgTvyRC?e=Wh^8KCao!R6Eg&TpVWUY1sN~4G}V?nFnEGo-; zHZ_$eW9-GnC%^WS9b z@p;-$oH#MtC0v>Q$HX%4^JdFdO$0cbv-W)Q TtK}Eh@>>I#ipmV1>S*>q-hkC} literal 3942 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 A+yDRo diff --git a/doc/doxy/doxygen_output/html/tabs.css b/doc/doxy/doxygen_output/html/tabs.css index 21920562a8..a444163416 100644 --- a/doc/doxy/doxygen_output/html/tabs.css +++ b/doc/doxy/doxygen_output/html/tabs.css @@ -1,59 +1,105 @@ -.tabs, .tabs2, .tabs3 { - background-image: url('tab_b.png'); - width: 100%; - z-index: 101; - font-size: 13px; +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; } -.tabs2 { - font-size: 10px; +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84B0C7; + font-size : 80%; + font-weight : bold; + text-decoration : none; } -.tabs3 { - font-size: 9px; + +DIV.tabs A:hover +{ + background-position: 100% -150px; } -.tablist { - margin: 0; - padding: 0; - display: table; +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1A419D; } -.tablist li { - float: left; - display: table-cell; - background-image: url('tab_b.png'); - line-height: 36px; - list-style: none; +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; } -.tablist a { - display: block; - padding: 0 20px; - font-weight: bold; - background-image:url('tab_s.png'); - background-repeat:no-repeat; - background-position:right; - color: #283A5D; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; - outline: none; +DIV.tabs #MSearchBox +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : 80%; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; } -.tabs3 .tablist a { - padding: 0 10px; +DIV.tabs LI.current A +{ + background-position: 100% -150px; + border-width : 0px; } -.tablist a:hover { - background-image: url('tab_h.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); - text-decoration: none; +DIV.tabs LI.current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; } -.tablist li.current a { - background-image: url('tab_a.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +DIV.navpath +{ + background : none; + border : none; + border-bottom : 1px solid #84B0C7; + text-align : center; + margin : 2px; + padding : 2px; } diff --git a/doc/generated/equals_status.qbk b/doc/generated/equals_status.qbk new file mode 100644 index 0000000000..6dc8bc0b20 --- /dev/null +++ b/doc/generated/equals_status.qbk @@ -0,0 +1,10 @@ +[heading Supported geometries] +[table +[[ ][Point][Box][Linestring][Ring][Polygon][MultiPolygon]] +[[Point][[$img/ok.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]]] +[[Box][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]][[$img/nyi.png]]] +[[Linestring][[$img/nyi.png]][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]]] +[[Ring][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]][[$img/nyi.png]]] +[[Polygon][[$img/nyi.png]][[$img/ok.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]][[$img/ok.png]]] +[[MultiPolygon][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/nyi.png]][[$img/ok.png]][[$img/ok.png]]] +] diff --git a/doc/geometry.qbk b/doc/geometry.qbk index 52ef199ebc..3519723ef1 100644 --- a/doc/geometry.qbk +++ b/doc/geometry.qbk @@ -42,7 +42,8 @@ [def __linestring__ Linestring] [def __polygon__ Polygon] [def __ring__ Ring] -[def __multi_point__ Multi point] +[def __multi_point__ Multi Point] +[def __multi_linestring__ Multi Linestring] [def __multi_polygon__ Multi Polygon] [def __range__ Rangelike (linestring, ring)] [def __other__ Other geometries] @@ -51,6 +52,7 @@ [/Parts] [def __ret_zero__ Returns zero] [def __ret_one__ Returns 1] +[def __does_nothing__ Nothing happens, geometry is unchanged] [def __cs_units__ in the same units as the input coordinates] [def __sph1__ on a unit sphere (or another sphere, if specified as such in the constructor of the strategy)] [template qbk_ret[what] Returns [what]] diff --git a/doc/html/img/algorithms/convex_hull.png b/doc/html/img/algorithms/convex_hull.png new file mode 100644 index 0000000000000000000000000000000000000000..77f3213aa95f7214f6de5ef3b05abcac7b922ee1 GIT binary patch literal 19017 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 literal 0 HcmV?d00001 diff --git a/doc/html/img/algorithms/make_envelope.png b/doc/html/img/algorithms/return_envelope.png similarity index 100% rename from doc/html/img/algorithms/make_envelope.png rename to doc/html/img/algorithms/return_envelope.png diff --git a/doc/imports.qbk b/doc/imports.qbk index 708d276c40..788bc68d3d 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -21,10 +21,12 @@ [import src/examples/algorithms/assign_with_range.cpp] [import src/examples/algorithms/assign_point_to_index.cpp] [import src/examples/algorithms/assign_point_from_index.cpp] +[import src/examples/algorithms/clear.cpp] [import src/examples/algorithms/centroid.cpp] [import src/examples/algorithms/distance.cpp] [import src/examples/algorithms/difference.cpp] [import src/examples/algorithms/envelope.cpp] +[import src/examples/algorithms/expand.cpp] [import src/examples/algorithms/for_each_point.cpp] [import src/examples/algorithms/for_each_point_const.cpp] [import src/examples/algorithms/for_each_segment_const.cpp] @@ -41,10 +43,12 @@ [import src/examples/algorithms/num_geometries.cpp] [import src/examples/algorithms/num_interior_rings.cpp] [import src/examples/algorithms/num_points.cpp] +[import src/examples/algorithms/reverse.cpp] [import src/examples/algorithms/return_envelope.cpp] [import src/examples/algorithms/simplify.cpp] [import src/examples/algorithms/sym_difference.cpp] [import src/examples/algorithms/union.cpp] +[import src/examples/algorithms/unique.cpp] [import src/examples/algorithms/within.cpp] [import src/examples/core/get_point.cpp] [import src/examples/core/get_box.cpp] diff --git a/doc/quickref.xml b/doc/quickref.xml index 1da360c6f0..268fcfaa5e 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -315,10 +315,6 @@ clear - Convert - - convert - Convex Hull convex_hull diff --git a/doc/reference.qbk b/doc/reference.qbk index d5a0453654..40d5ca87db 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -69,10 +69,6 @@ [include generated/clear.qbk] [endsect] -[section:convert convert] -[include generated/convert.qbk] -[endsect] - [section:convex_hull convex_hull] [include generated/convex_hull.qbk] [endsect] diff --git a/doc/reference/algorithms/append.qbk b/doc/reference/algorithms/append.qbk index 51bd98273c..1663ed65e0 100644 --- a/doc/reference/algorithms/append.qbk +++ b/doc/reference/algorithms/append.qbk @@ -30,4 +30,4 @@ Linear [append_output] [heading See also] -* [link geometry.reference.algorithms.assign.assign_2_with_a_range assign] +* [link geometry.reference.algorithms.assign.assign_points assign] diff --git a/doc/reference/algorithms/comparable_distance.qbk b/doc/reference/algorithms/comparable_distance.qbk new file mode 100644 index 0000000000..304b97ad64 --- /dev/null +++ b/doc/reference/algorithms/comparable_distance.qbk @@ -0,0 +1,25 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[heading Behaviour] +There is no (not yet) version with a strategy. + +It depends on the coordinate system of the geometry's point type if there is +a strategy available which can determine (more efficient than the standard +strategy) a measure of comparable distance. + +[heading Complexity] +Linear + +[heading Example] +[comparable_distance] +[comparable_distance_output] diff --git a/doc/reference/algorithms/convert.qbk b/doc/reference/algorithms/convert.qbk new file mode 100644 index 0000000000..651d56d2c1 --- /dev/null +++ b/doc/reference/algorithms/convert.qbk @@ -0,0 +1,27 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[tip convert is not defined within OGC or ISO] +[tip convert is modelled as source -> target + (where assign is modelled as target := source)] + +[heading Complexity] +Linear + +[heading Example] +[convert] +[convert_output] + +[heading See also] +* [link geometry.reference.algorithms.assign.assign assign] + + diff --git a/doc/reference/algorithms/convex_hull.qbk b/doc/reference/algorithms/convex_hull.qbk new file mode 100644 index 0000000000..2a1de18920 --- /dev/null +++ b/doc/reference/algorithms/convex_hull.qbk @@ -0,0 +1,18 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[heading Complexity] +Linear + +[heading Example] +[convex_hull] +[convex_hull_output] diff --git a/doc/reference/algorithms/correct.qbk b/doc/reference/algorithms/correct.qbk new file mode 100644 index 0000000000..6af7f74dc7 --- /dev/null +++ b/doc/reference/algorithms/correct.qbk @@ -0,0 +1,33 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[def __corrected__ is corrected] + +[heading Behavior] +[table +[[Case] [Behavior] ] +[[__ring__][__ring__ __corrected__]] +[[__polygon__][__polygon__ __corrected__]] +[[__multi_polygon__][__multi_polygon__ __corrected__]] +[[__box__][__box__ __corrected__ with respect to minimal and maximal corners]] +[[__other__][__does_nothing__]] +] + +[tip Correct is not defined within OGC or ISO] + +[heading Complexity] +Linear + +[heading Example] +[correct] +[correct_output] + diff --git a/doc/reference/algorithms/difference.qbk b/doc/reference/algorithms/difference.qbk index 6552d3abbc..2a2869a669 100644 --- a/doc/reference/algorithms/difference.qbk +++ b/doc/reference/algorithms/difference.qbk @@ -14,7 +14,7 @@ [difference] [difference_output] [heading See also] -* [link geometry.reference.algorithms.sym_difference.sym_difference sym_difference (symmetric difference)] -* [link geometry.reference.algorithms.intersection.intersection intersection] -* [link geometry.reference.algorithms.union.union_ union] +* [link geometry.reference.algorithms.sym_difference sym_difference (symmetric difference)] +* [link geometry.reference.algorithms.intersection intersection] +* [link geometry.reference.algorithms.union_ union] diff --git a/doc/reference/algorithms/distance.qbk b/doc/reference/algorithms/distance.qbk new file mode 100644 index 0000000000..f92a385eeb --- /dev/null +++ b/doc/reference/algorithms/distance.qbk @@ -0,0 +1,21 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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 generated/distance_status.qbk] + +[heading Complexity] +Linear +For multi-geometry to multi-geometry: currently quadratic + +[heading Example] +[distance] +[distance_output] diff --git a/doc/reference/algorithms/equals.qbk b/doc/reference/algorithms/equals.qbk new file mode 100644 index 0000000000..cc5dedcb7f --- /dev/null +++ b/doc/reference/algorithms/equals.qbk @@ -0,0 +1,21 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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 generated/equals_status.qbk] + +[heading Complexity] +Linear + +[heading Example] +[equals] +[equals_output] + diff --git a/doc/reference/algorithms/intersection.qbk b/doc/reference/algorithms/intersection.qbk index e513778749..cb688c839c 100644 --- a/doc/reference/algorithms/intersection.qbk +++ b/doc/reference/algorithms/intersection.qbk @@ -23,6 +23,6 @@ [intersection_output] [heading See also] -* [link geometry.reference.algorithms.union.union_ union] -* [link geometry.reference.algorithms.difference.difference difference] -* [link geometry.reference.algorithms.sym_difference.sym_difference sym_difference (symmetric difference)] +* [link geometry.reference.algorithms.union_ union] +* [link geometry.reference.algorithms.difference difference] +* [link geometry.reference.algorithms.sym_difference sym_difference (symmetric difference)] diff --git a/doc/reference/algorithms/sym_difference.qbk b/doc/reference/algorithms/sym_difference.qbk index 2058ca2d93..89915a2562 100644 --- a/doc/reference/algorithms/sym_difference.qbk +++ b/doc/reference/algorithms/sym_difference.qbk @@ -23,7 +23,7 @@ [sym_difference_output] [heading See also] -* [link geometry.reference.algorithms.difference.difference difference] -* [link geometry.reference.algorithms.intersection.intersection intersection] -* [link geometry.reference.algorithms.union.union_ union] +* [link geometry.reference.algorithms.difference difference] +* [link geometry.reference.algorithms.intersection intersection] +* [link geometry.reference.algorithms.union_ union] diff --git a/doc/reference/algorithms/transform.qbk b/doc/reference/algorithms/transform.qbk new file mode 100644 index 0000000000..5028f9a671 --- /dev/null +++ b/doc/reference/algorithms/transform.qbk @@ -0,0 +1,28 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[heading Behavior] +[table +[[Case] [Behavior] ] +[[__sph__ (degree) / __sph__ (radian)][Transforms coordinates from degree to radian, or vice versa]] +[[__sph__ / __cart__ (3D)][Transforms coordinates from spherical coordinates to X,Y,Z, or vice versa, on a unit sphere]] +[[__sph__ (degree, with radius) / __sph__ (radian, with radius)][Transforms coordinates from degree to radian, or vice versa. Third coordinate (radius) is untouched]] +[[__sph__ (with radius) / __cart__ (3D)][Transforms coordinates from spherical coordinates to X,Y,Z, or vice versa, on a unit sphere. Third coordinate (radius) is taken into account]] +] + +[heading Complexity] +Linear + +[heading Example] +[transform] +[transform_output] + diff --git a/doc/reference/algorithms/transform_with_strategy.qbk b/doc/reference/algorithms/transform_with_strategy.qbk new file mode 100644 index 0000000000..b1045823d5 --- /dev/null +++ b/doc/reference/algorithms/transform_with_strategy.qbk @@ -0,0 +1,19 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + Copyright (c) 2009-2011 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) +=============================================================================/] + +[heading Complexity] +Linear + +[heading Example] +[transform_with_strategy] +[transform_with_strategy_output] + diff --git a/doc/reference/algorithms/union.qbk b/doc/reference/algorithms/union.qbk index 8c86a61100..d620b24d45 100644 --- a/doc/reference/algorithms/union.qbk +++ b/doc/reference/algorithms/union.qbk @@ -20,6 +20,6 @@ [union_output] [heading See also] -* [link geometry.reference.algorithms.intersection.intersection intersection] -* [link geometry.reference.algorithms.difference.difference difference] -* [link geometry.reference.algorithms.sym_difference.sym_difference sym_difference (symmetric difference)] +* [link geometry.reference.algorithms.intersection intersection] +* [link geometry.reference.algorithms.difference difference] +* [link geometry.reference.algorithms.sym_difference sym_difference (symmetric difference)] diff --git a/doc/reference/core/closure.qbk b/doc/reference/core/closure.qbk new file mode 100644 index 0000000000..76db82a75c --- /dev/null +++ b/doc/reference/core/closure.qbk @@ -0,0 +1,23 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[note The closure is defined for any geometry type, but only has a real meaning + for areal geometry types (ring, polygon, multi_polygon) +] + +[heading Complexity] +Compile time + +[heading Example] +[closure] +[closure_output] + +[heading See also] +* [link geometry.reference.enumerations.closure_selector The closure_selector enumeration] diff --git a/doc/reference/core/coordinate_dimension.qbk b/doc/reference/core/coordinate_dimension.qbk new file mode 100644 index 0000000000..4b599defe7 --- /dev/null +++ b/doc/reference/core/coordinate_dimension.qbk @@ -0,0 +1,16 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[heading Complexity] +Compile time + +[heading Example] +[dimension] +[dimension_output] diff --git a/doc/reference/core/coordinate_system.qbk b/doc/reference/core/coordinate_system.qbk new file mode 100644 index 0000000000..8d636c39f8 --- /dev/null +++ b/doc/reference/core/coordinate_system.qbk @@ -0,0 +1,16 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[heading Complexity] +Compile time + +[heading Example] +[coordinate_system] +[coordinate_system_output] diff --git a/doc/reference/core/coordinate_type.qbk b/doc/reference/core/coordinate_type.qbk new file mode 100644 index 0000000000..49df07d3d6 --- /dev/null +++ b/doc/reference/core/coordinate_type.qbk @@ -0,0 +1,16 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[heading Complexity] +Compile time + +[heading Example] +[coordinate_type] +[coordinate_type_output] diff --git a/doc/reference/core/degree_radian.qbk b/doc/reference/core/degree_radian.qbk new file mode 100644 index 0000000000..cf4990b359 --- /dev/null +++ b/doc/reference/core/degree_radian.qbk @@ -0,0 +1,14 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + + +[heading example] +[degree_radian] +[degree_radian_output] \ No newline at end of file diff --git a/doc/reference/core/max_corner.qbk b/doc/reference/core/max_corner.qbk new file mode 100644 index 0000000000..fabe2ab200 --- /dev/null +++ b/doc/reference/core/max_corner.qbk @@ -0,0 +1,26 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[section:max_corner max_corner] + +Indicates the maximal corner (upper right) of a box to be get, set or processed + +[heading Synopsis] +`` int const max_corner = 1; `` + +[include reference/core/min_max_corner.qbk] + +[heading See also] +* [link geometry.reference.constants.min_corner min_corner] +* [link geometry.reference.access.get.get_2_with_index get with index] +* [link geometry.reference.access.set.set_3_with_index set with index] + +[endsect] + diff --git a/doc/reference/core/min_corner.qbk b/doc/reference/core/min_corner.qbk new file mode 100644 index 0000000000..eacb918b35 --- /dev/null +++ b/doc/reference/core/min_corner.qbk @@ -0,0 +1,25 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[section:min_corner min_corner] + +Indicates the minimal corner (lower left) of a box to be get, set or processed + +[heading Synopsis] +`` int const min_corner = 0; `` + +[include reference/core/min_max_corner.qbk] + +[heading See also] +* [link geometry.reference.constants.max_corner max_corner] +* [link geometry.reference.access.get.get_2_with_index get with index] +* [link geometry.reference.access.set.set_3_with_index set with index] + +[endsect] diff --git a/doc/reference/core/min_max_corner.qbk b/doc/reference/core/min_max_corner.qbk new file mode 100644 index 0000000000..118b0fbcad --- /dev/null +++ b/doc/reference/core/min_max_corner.qbk @@ -0,0 +1,31 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[/File included by min_corner.qbk and max_corner.qbk] + +[heading Header] +Either + +`#include ` + +Or + +`#include ` + +[note min_corner and max_corner are only applicable for boxes and not for, + e.g., a segment] +[note min_corner should be the minimal corner of a box, but that is not + guaranteed. Use correct to make min_corner the minimal corner. + The same applies for max_corner.] + +[/Share sample with get_box] +[heading Example] +[get_box] +[get_box_output] diff --git a/doc/reference/core/point_order.qbk b/doc/reference/core/point_order.qbk new file mode 100644 index 0000000000..775ede73c7 --- /dev/null +++ b/doc/reference/core/point_order.qbk @@ -0,0 +1,24 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[note The point order is defined for any geometry type, but only has a real meaning + for areal geometry types (ring, polygon, multi_polygon) +] + +[heading Complexity] +Compile time + +[heading Example] +[point_order] +[point_order_output] + +[heading See also] +* [link geometry.reference.enumerations.order_selector The order_selector enumeration] + diff --git a/doc/reference/core/point_type.qbk b/doc/reference/core/point_type.qbk new file mode 100644 index 0000000000..2f568ab699 --- /dev/null +++ b/doc/reference/core/point_type.qbk @@ -0,0 +1,17 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + + +[heading Complexity] +Compile time + +[heading Example] +[point_type] +[point_type_output] diff --git a/doc/reference/core/tag.qbk b/doc/reference/core/tag.qbk new file mode 100644 index 0000000000..c7d7711aea --- /dev/null +++ b/doc/reference/core/tag.qbk @@ -0,0 +1,20 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[note With Boost.Geometry, tags are the driving force of the tag dispatching + mechanism. The tag metafunction is therefore used in every free function. +] + +[heading Complexity] +Compile time + +[heading Example] +[tag] +[tag_output] diff --git a/doc/reference/core/tag_cast.qbk b/doc/reference/core/tag_cast.qbk new file mode 100644 index 0000000000..cfe02dd6a1 --- /dev/null +++ b/doc/reference/core/tag_cast.qbk @@ -0,0 +1,26 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2011 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) +=============================================================================/] + +[note The specified tag list is handled in the specified order: as soon as a tag + inheriting the specified tag is found, it is defined as the metafunction + typedef [*type]. +] + +[note If none of the specified possible base tags is a base class of the + specified tag, the tag itself is defined as the [*type] result of the + metafunction. +] +[heading Complexity] +Compile time + +[heading Example] +[tag_cast] +[tag_cast_output] + diff --git a/doc/src/docutils/tools/implementation_status/implementation_status.cpp b/doc/src/docutils/tools/implementation_status/implementation_status.cpp index 3ce54c2897..6f59fc3d72 100644 --- a/doc/src/docutils/tools/implementation_status/implementation_status.cpp +++ b/doc/src/docutils/tools/implementation_status/implementation_status.cpp @@ -71,8 +71,9 @@ struct compile_msvc command << "u"; } - command << "implementation_status.hpp tmp/t.cpp > tmp/t.out"; - // For debugging: << type1 << "_" << type2 << ".out"; + 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; @@ -300,7 +301,9 @@ int main(int argc, char** argv) algorithms.push_back(algorithm("correct")); algorithms.push_back(algorithm("distance", 2)); algorithms.push_back(algorithm("centroid", 2)); - //algorithms.push_back(algorithm("within", 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; diff --git a/doc/src/examples/algorithms/Jamfile.v2 b/doc/src/examples/algorithms/Jamfile.v2 index d1be69fb9f..ebc5081afa 100644 --- a/doc/src/examples/algorithms/Jamfile.v2 +++ b/doc/src/examples/algorithms/Jamfile.v2 @@ -13,22 +13,34 @@ project boost-geometry-doc-example-algorithms : # requirements ; +exe append : append.cpp ; + exe area : area.cpp ; exe area_with_strategy : area_with_strategy.cpp ; +exe assign : assign.cpp ; exe assign_2d_point : assign_2d_point.cpp ; exe assign_3d_point : assign_3d_point.cpp ; exe assign_inverse : assign_inverse.cpp ; -exe assign_with_range : assign_with_range.cpp ; -exe assign_box_corners : assign_box_corners.cpp ; -exe assign_point_from_index : assign_point_from_index.cpp ; -exe assign_point_to_index : assign_point_to_index.cpp ; +exe assign_points : assign_points.cpp ; +# exe assign_box_corners : assign_box_corners.cpp ; +# exe assign_point_from_index : assign_point_from_index.cpp ; +# exe assign_point_to_index : assign_point_to_index.cpp ; exe centroid : centroid.cpp ; exe clear : clear.cpp ; +exe comparable_distance : comparable_distance.cpp ; +exe convert : convert.cpp ; +exe convex_hull : convex_hull.cpp ; +exe correct : correct.cpp ; +exe difference : difference.cpp ; exe distance : distance.cpp ; +exe envelope : envelope.cpp ; +exe equals : equals.cpp ; +exe expand : expand.cpp ; + exe for_each_point : for_each_point.cpp ; exe for_each_point_const : for_each_point_const.cpp ; exe for_each_segment_const : for_each_segment_const.cpp ; @@ -38,19 +50,29 @@ exe intersection_segment : intersection_segment.cpp ; exe intersects_linestring : intersects_linestring.cpp ; +exe length : length.cpp ; +exe length_with_strategy : length_with_strategy.cpp ; + exe make_2d_point : make_2d_point.cpp ; exe make_3d_point : make_3d_point.cpp ; exe make_inverse : make_inverse.cpp ; -exe make_with_range : make_with_range.cpp ; +# exe make_with_range : make_with_range.cpp ; exe num_geometries : num_geometries.cpp ; exe num_interior_rings : num_interior_rings.cpp ; exe num_points : num_points.cpp ; +exe return_envelope : return_envelope.cpp ; -exe length : length.cpp ; -exe length_with_strategy : length_with_strategy.cpp ; +exe reverse : reverse.cpp ; exe simplify : length.cpp ; +exe sym_difference : sym_difference.cpp ; + +exe transform : transform.cpp ; +exe transform_with_strategy : transform_with_strategy.cpp ; + +exe union : union.cpp ; +exe unique : unique.cpp ; exe within : within.cpp ; diff --git a/doc/src/examples/algorithms/assign.cpp b/doc/src/examples/algorithms/assign.cpp new file mode 100644 index 0000000000..bc5b4cdc56 --- /dev/null +++ b/doc/src/examples/algorithms/assign.cpp @@ -0,0 +1,61 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[assign +//` Shows how to assign a geometry from another geometry + +#include + +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point; + typedef boost::geometry::model::box box; + typedef boost::geometry::model::polygon polygon; + + point p1; + box b; + boost::geometry::assign_values(p1, 1, 1); + boost::geometry::assign_values(b, 1, 1, 2, 2); + + // Assign a box to a polygon (target = source) + polygon p; + boost::geometry::assign(p, b); + + // Assign a point to another point type (conversion of point-type) + boost::tuple p2; + boost::geometry::assign(p2, p1); + + using boost::geometry::dsv; + std::cout + << "box: " << dsv(b) << std::endl + << "polygon: " << dsv(p) << std::endl + << "point: " << dsv(p1) << std::endl + << "point tuples: " << dsv(p2) << std::endl + ; + + return 0; +} + +//] + + +//[assign_output +/*` +Output: +[pre +box: ((1, 1), (2, 2)) +polygon: (((1, 1), (1, 2), (2, 2), (2, 1), (1, 1))) +point: (1, 1) +point tuples: (1, 1) +] +*/ +//] diff --git a/doc/src/examples/algorithms/assign_2d_point.cpp b/doc/src/examples/algorithms/assign_2d_point.cpp index e01da8d7af..e32f5b5c75 100644 --- a/doc/src/examples/algorithms/assign_2d_point.cpp +++ b/doc/src/examples/algorithms/assign_2d_point.cpp @@ -23,15 +23,15 @@ int main() { - using boost::geometry::assign; + using boost::geometry::assign_values; boost::geometry::model::d2::point_xy p1; - assign(p1, 1.2345, 2.3456); + assign_values(p1, 1.2345, 2.3456); #if defined(HAVE_TTMATH) boost::geometry::model::d2::point_xy > p2; - assign(p2, "1.2345", "2.3456"); /*< It is possible to assign coordinates with other types than the coordinate type. + assign_values(p2, "1.2345", "2.3456"); /*< It is possible to assign coordinates with other types than the coordinate type. For ttmath, you can e.g. conveniently use strings. The advantage is that it then has higher precision, because if doubles are used for assignments the double-precision is used. >*/ diff --git a/doc/src/examples/algorithms/assign_3d_point.cpp b/doc/src/examples/algorithms/assign_3d_point.cpp index 51e91ff312..aa3ddb683c 100644 --- a/doc/src/examples/algorithms/assign_3d_point.cpp +++ b/doc/src/examples/algorithms/assign_3d_point.cpp @@ -19,7 +19,7 @@ int main() { boost::geometry::model::point p; - boost::geometry::assign(p, 1.2345, 2.3456, 3.4567); + boost::geometry::assign_values(p, 1.2345, 2.3456, 3.4567); std::cout << boost::geometry::dsv(p) << std::endl; diff --git a/doc/src/examples/algorithms/assign_box_corners.cpp b/doc/src/examples/algorithms/assign_box_corners.cpp index 01ec6ae15c..f6588194f5 100644 --- a/doc/src/examples/algorithms/assign_box_corners.cpp +++ b/doc/src/examples/algorithms/assign_box_corners.cpp @@ -23,7 +23,7 @@ int main() typedef model::box box; box b; - assign(b, 2, 2, 5, 5); + assign_values(b, 2, 2, 5, 5); point ll, lr, ul, ur; assign_box_corners(b, ll, lr, ul, ur); diff --git a/doc/src/examples/algorithms/assign_point_from_index.cpp b/doc/src/examples/algorithms/assign_point_from_index.cpp index 9b2da934b4..2f52846938 100644 --- a/doc/src/examples/algorithms/assign_point_from_index.cpp +++ b/doc/src/examples/algorithms/assign_point_from_index.cpp @@ -23,7 +23,7 @@ int main() typedef model::segment segment; segment s; - assign(s, 1, 1, 2, 2); + assign_values(s, 1, 1, 2, 2); point first, second; assign_point_from_index<0>(s, first); diff --git a/doc/src/examples/algorithms/assign_with_range.cpp b/doc/src/examples/algorithms/assign_points.cpp similarity index 81% rename from doc/src/examples/algorithms/assign_with_range.cpp rename to doc/src/examples/algorithms/assign_points.cpp index 1a212245fa..c747759631 100644 --- a/doc/src/examples/algorithms/assign_with_range.cpp +++ b/doc/src/examples/algorithms/assign_points.cpp @@ -7,7 +7,7 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -//[assign_with_range +//[assign_points //` Shows usage of Boost.Geometry's assign, Boost.Assign, and Boost.Range to assign ranges of a linestring #include @@ -46,8 +46,8 @@ int main() ls line1, line2, line3; line1 = tuple_list_of(0, 0)(2, 3)(4, 0)(6, 3)(8, 0)(10, 3)(12, 0); /*< tuple_list_of is part of Boost.Assign and can be used for Boost.Geometry if points are tuples >*/ - boost::geometry::assign(line2, tuple_list_of(0, 0)(2, 2)(4, 0)(6, 2)(8, 0)); /*< tuple_list_of delivers a range and can therefore be used in boost::geometry::assign >*/ - boost::geometry::assign(line3, line1 | boost::adaptors::filtered(x_between(4, 8))); /*< Boost.Range adaptors can also be used in boost::geometry::assign >*/ + boost::geometry::assign_points(line2, tuple_list_of(0, 0)(2, 2)(4, 0)(6, 2)(8, 0)); /*< tuple_list_of delivers a range and can therefore be used in boost::geometry::assign >*/ + boost::geometry::assign_points(line3, line1 | boost::adaptors::filtered(x_between(4, 8))); /*< Boost.Range adaptors can also be used in boost::geometry::assign >*/ std::cout << "line 1: " << boost::geometry::dsv(line1) << std::endl; std::cout << "line 2: " << boost::geometry::dsv(line2) << std::endl; @@ -59,7 +59,7 @@ int main() //] -//[assign_with_range_output +//[assign_points_output /*` Output: [pre diff --git a/doc/src/examples/algorithms/clear.cpp b/doc/src/examples/algorithms/clear.cpp index 1bca324f44..f9932ed261 100644 --- a/doc/src/examples/algorithms/clear.cpp +++ b/doc/src/examples/algorithms/clear.cpp @@ -29,8 +29,8 @@ int main() polygon poly; // Fill the polygon (using its own methods + Boost.Assign) - poly.outer() = tuple_list_of(0, 0)(0, 10)(11, 11)(0, 0); - poly.inners().push_back(tuple_list_of(0, 0)(0, 10)(11, 11)(0, 0)); + poly.outer() = tuple_list_of(0, 0)(0, 9)(10, 10)(0, 0); + poly.inners().push_back(tuple_list_of(1, 2)(4, 6)(2, 8)(1, 2)); std::cout << boost::geometry::dsv(poly) << std::endl; boost::geometry::clear(poly); diff --git a/doc/src/examples/algorithms/comparable_distance.cpp b/doc/src/examples/algorithms/comparable_distance.cpp new file mode 100644 index 0000000000..0ed9a04908 --- /dev/null +++ b/doc/src/examples/algorithms/comparable_distance.cpp @@ -0,0 +1,66 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[comparable_distance +//` Shows how to efficiently get the closest point + +#include + +#include + +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + + point_type p(1.4, 2.6); + + std::vector v; + for (double x = 0.0; x <= 4.0; x++) + { + for (double y = 0.0; y <= 4.0; y++) + { + v.push_back(point_type(x, y)); + } + } + + point_type min_p; + double min_d = boost::numeric::bounds::highest(); + BOOST_FOREACH(point_type const& pv, v) + { + double d = boost::geometry::comparable_distance(p, pv); + if (d < min_d) + { + min_d = d; + min_p = pv; + } + } + + std::cout + << "Closest: " << boost::geometry::dsv(min_p) << std::endl + << "At: " << boost::geometry::distance(p, min_p) << std::endl; + + return 0; +} + +//] + + +//[comparable_distance_output +/*` +Output: +[pre +Closest: (1, 3) +At: 0.565685 +] +*/ +//] + diff --git a/doc/src/examples/algorithms/convert.cpp b/doc/src/examples/algorithms/convert.cpp new file mode 100644 index 0000000000..5b6e377e18 --- /dev/null +++ b/doc/src/examples/algorithms/convert.cpp @@ -0,0 +1,59 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[convert +//` Shows how to convert a geometry into another geometry + +#include + +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point; + typedef boost::geometry::model::box box; + typedef boost::geometry::model::polygon polygon; + + point p1(1, 1); + box bx = boost::geometry::make(1, 1, 2, 2); + + // Assign a box to a polygon (conversion box->poly) + polygon poly; + boost::geometry::convert(bx, poly); + + // Convert a point to another point type (conversion of point-type) + boost::tuple p2; + boost::geometry::convert(p1, p2); // source -> target + + using boost::geometry::dsv; + std::cout + << "box: " << dsv(bx) << std::endl + << "polygon: " << dsv(poly) << std::endl + << "point: " << dsv(p1) << std::endl + << "point tuples: " << dsv(p2) << std::endl + ; + + return 0; +} + +//] + + +//[convert_output +/*` +Output: +[pre +box: ((1, 1), (2, 2)) +polygon: (((1, 1), (1, 2), (2, 2), (2, 1), (1, 1))) +point: (1, 1) +point tuples: (1, 1) +] +*/ +//] diff --git a/doc/src/examples/algorithms/convex_hull.cpp b/doc/src/examples/algorithms/convex_hull.cpp new file mode 100644 index 0000000000..f6963f0928 --- /dev/null +++ b/doc/src/examples/algorithms/convex_hull.cpp @@ -0,0 +1,54 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[convex_hull +//` Shows how to generate the convex_hull of a geometry + +#include + +#include +#include + +/*<-*/ #include "create_svg_two.hpp" /*->*/ +int main() +{ + typedef boost::tuple point; + typedef boost::geometry::model::polygon polygon; + + polygon poly; + boost::geometry::read_wkt("polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0" + ", 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", poly); + + polygon hull; + boost::geometry::convex_hull(poly, hull); + + using boost::geometry::dsv; + std::cout + << "polygon: " << dsv(poly) << std::endl + << "hull: " << dsv(hull) << std::endl + ; + + /*<-*/ create_svg("envelope.svg", poly, hull); /*->*/ + return 0; +} + +//] + + +//[convex_hull_output +/*` +Output: +[pre +polygon: (((2, 1.3), (2.4, 1.7), (2.8, 1.8), (3.4, 1.2), (3.7, 1.6), (3.4, 2), (4.1, 3), (5.3, 2.6), (5.4, 1.2), (4.9, 0.8), (2.9, 0.7), (2, 1.3))) +hull: (((2, 1.3), (2.4, 1.7), (4.1, 3), (5.3, 2.6), (5.4, 1.2), (4.9, 0.8), (2.9, 0.7), (2, 1.3))) + +[$img/algorithms/convex_hull.png] +] +*/ +//] diff --git a/doc/src/examples/algorithms/correct.cpp b/doc/src/examples/algorithms/correct.cpp new file mode 100644 index 0000000000..add7304289 --- /dev/null +++ b/doc/src/examples/algorithms/correct.cpp @@ -0,0 +1,65 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[correct +//` Shows how to correct a polygon with respect to its orientation and closure + +#include + +#include +#include + +#include + +int main() +{ + using boost::assign::tuple_list_of; + + typedef boost::geometry::model::polygon + < + boost::tuple + > clockwise_closed_polygon; + + clockwise_closed_polygon cwcp; + + // Fill it counterclockwise (so wrongly), forgetting the closing point + boost::geometry::exterior_ring(cwcp) = tuple_list_of(0, 0)(10, 10)(0, 9); + + // Add a counterclockwise closed inner ring (this is correct) + boost::geometry::interior_rings(cwcp).push_back(tuple_list_of(1, 2)(4, 6)(2, 8)(1, 2)); + + // Its area should be negative (because of wrong orientation) + // and wrong (because of omitted closing point) + double area_before = boost::geometry::area(cwcp); + + // Correct it! + boost::geometry::correct(cwcp); + + // Check its new area + double area_after = boost::geometry::area(cwcp); + + // And output it + std::cout << boost::geometry::dsv(cwcp) << std::endl; + std::cout << area_before << " -> " << area_after << std::endl; + + return 0; +} + +//] + + +//[correct_output +/*` +Output: +[pre +(((0, 0), (0, 9), (10, 10), (0, 0)), ((1, 2), (4, 6), (2, 8), (1, 2))) +-7 -> 38 +] +*/ +//] diff --git a/doc/src/examples/algorithms/distance.cpp b/doc/src/examples/algorithms/distance.cpp index 2676af350f..3d4e71d5a7 100644 --- a/doc/src/examples/algorithms/distance.cpp +++ b/doc/src/examples/algorithms/distance.cpp @@ -41,9 +41,10 @@ int main() mp.push_back(point_type(0,0)); mp.push_back(point_type(3,3)); - std::cout << "distance: " << boost::geometry::distance(p, poly) << std::endl; - std::cout << "distance: " << boost::geometry::distance(p, line) << std::endl; - std::cout << "distance: " << boost::geometry::distance(p, mp) << std::endl; + std::cout + << "Point-Poly: " << boost::geometry::distance(p, poly) << std::endl + << "Point-Line: " << boost::geometry::distance(p, line) << std::endl + << "Point-MultiPoint: " << boost::geometry::distance(p, mp) << std::endl; return 0; } @@ -55,9 +56,9 @@ int main() /*` Output: [pre -distance: 1.22066 -distance: 1 -distance: 2.23607 +Point-Poly: 1.22066 +Point-Line: 1 +Point-MultiPoint: 2.23607 ] */ //] diff --git a/doc/src/examples/algorithms/equals.cpp b/doc/src/examples/algorithms/equals.cpp new file mode 100644 index 0000000000..27b087125e --- /dev/null +++ b/doc/src/examples/algorithms/equals.cpp @@ -0,0 +1,59 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[equals +//` Shows the predicate equals, which returns true if two geometries are spatially equal + +#include + +#include +#include +#include + +#include + +int main() +{ + using boost::assign::tuple_list_of; + + typedef boost::tuple point; + + boost::geometry::model::polygon poly1, poly2; + boost::geometry::exterior_ring(poly1) = tuple_list_of(0, 0)(0, 5)(5, 5)(5, 0)(0, 0); + boost::geometry::exterior_ring(poly2) = tuple_list_of(5, 0)(0, 0)(0, 5)(5, 5)(5, 0); + + std::cout + << "polygons are spatially " + << (boost::geometry::equals(poly1, poly2) ? "equal" : "not equal") + << std::endl; + + boost::geometry::model::box box; + boost::geometry::assign_values(box, 0, 0, 5, 5); + + std::cout + << "polygon and box are spatially " + << (boost::geometry::equals(box, poly2) ? "equal" : "not equal") + << std::endl; + + + return 0; +} + +//] + + +//[equals_output +/*` +Output: +[pre +polygons are spatially equal +polygon and box are spatially equal +] +*/ +//] diff --git a/doc/src/examples/algorithms/expand.cpp b/doc/src/examples/algorithms/expand.cpp new file mode 100644 index 0000000000..449b48fd97 --- /dev/null +++ b/doc/src/examples/algorithms/expand.cpp @@ -0,0 +1,46 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[expand +//` Shows the usage of expand + +#include +#include + +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::box box_type; + + using boost::geometry::expand; + + box_type box = boost::geometry::make_inverse(); /*< expand is usually preceded by a call to assign_inverse or make_inverse >*/ + + expand(box, point_type(0, 0)); + expand(box, point_type(1, 2)); + expand(box, point_type(5, 4)); + expand(box, boost::geometry::make(3, 3, 5, 5)); + + std::cout << boost::geometry::dsv(box) << std::endl; + + return 0; +} + +//] + +//[expand_output +/*` +Output: +[pre +((0, 0), (5, 5)) +] +*/ +//] diff --git a/doc/src/examples/algorithms/num_interior_rings.cpp b/doc/src/examples/algorithms/num_interior_rings.cpp index ca09fb57a1..b4aa82940a 100644 --- a/doc/src/examples/algorithms/num_interior_rings.cpp +++ b/doc/src/examples/algorithms/num_interior_rings.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt) //[num_interior_rings -//` Get the number of interior rings in a polygon or multi-polygon +//` Get the number of interior rings in a multi-polygon #include diff --git a/doc/src/examples/algorithms/transform.cpp b/doc/src/examples/algorithms/transform.cpp new file mode 100644 index 0000000000..8eea3be30c --- /dev/null +++ b/doc/src/examples/algorithms/transform.cpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[transform +//` Shows how points can be transformed using the default strategy + +#include +#include + + +int main() +{ + namespace bg = boost::geometry; + + bg::model::point > p1(5.0, 52.0); + + // Transform from degree to radian. Default strategy is automatically selected, + // it will convert from degree to radian + bg::model::point > p2; + bg::transform(p1, p2); + + // Transform from degree (lon-lat) to 3D (x,y,z). Default strategy is automatically selected, + // it will consider points on a unit sphere + bg::model::point p3; + bg::transform(p1, p3); + + std::cout + << "p1: " << bg::dsv(p1) << std::endl + << "p2: " << bg::dsv(p2) << std::endl + << "p3: " << bg::dsv(p3) << std::endl; + + return 0; +} + +//] + + +//[transform_output +/*` +Output: +[pre +p1: (5, 52) +p2: (0.0872665, 0.907571) +p3: (0.785012, 0.0686797, 0.615661) +] +*/ +//] diff --git a/doc/src/examples/algorithms/transform_with_strategy.cpp b/doc/src/examples/algorithms/transform_with_strategy.cpp new file mode 100644 index 0000000000..2fcfc57f45 --- /dev/null +++ b/doc/src/examples/algorithms/transform_with_strategy.cpp @@ -0,0 +1,63 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[transform_with_strategy +//` Shows how points can be scaled, translated or rotated + +#include +#include + + +int main() +{ + namespace trans = boost::geometry::strategy::transform; + using boost::geometry::dsv; + + typedef boost::geometry::model::point point_type; + + point_type p1(1.0, 1.0); + + // Translate over (1.5, 1.5) + point_type p2; + trans::translate_transformer translate(1.5, 1.5); + boost::geometry::transform(p1, p2, translate); + + // Scale with factor 3.0 + point_type p3; + trans::scale_transformer scale(3.0); + boost::geometry::transform(p1, p3, scale); + + // Rotate with respect to the origin (0,0) over 90 degrees (clockwise) + point_type p4; + trans::rotate_transformer rotate(90.0); + boost::geometry::transform(p1, p4, rotate); + + std::cout + << "p1: " << dsv(p1) << std::endl + << "p2: " << dsv(p2) << std::endl + << "p3: " << dsv(p3) << std::endl + << "p4: " << dsv(p4) << std::endl; + + return 0; +} + +//] + + +//[transform_with_strategy_output +/*` +Output: +[pre +p1: (1, 1) +p2: (2.5, 2.5) +p3: (3, 3) +p4: (1, -1) +] +*/ +//] diff --git a/doc/src/examples/core/Jamfile.v2 b/doc/src/examples/core/Jamfile.v2 index 9575b21cc6..53d08c43a2 100644 --- a/doc/src/examples/core/Jamfile.v2 +++ b/doc/src/examples/core/Jamfile.v2 @@ -17,3 +17,14 @@ exe get_point : get_point.cpp ; exe get_box : get_box.cpp ; exe set_point : set_point.cpp ; exe set_box : set_box.cpp ; +exe degree_radian : degree_radian.cpp ; + +exe coordinate_type : coordinate_type.cpp ; +exe coordinate_system : coordinate_system.cpp ; +exe coordinate_dimension : coordinate_dimension.cpp ; +exe point_order : point_order.cpp ; +exe closure : closure.cpp ; + +exe point_type : point_type.cpp ; +exe tag : tag.cpp ; +exe tag_cast : tag_cast.cpp ; diff --git a/doc/src/examples/core/closure.cpp b/doc/src/examples/core/closure.cpp new file mode 100644 index 0000000000..47c40adcc4 --- /dev/null +++ b/doc/src/examples/core/closure.cpp @@ -0,0 +1,42 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[closure +//` Examine if a polygon is defined as "should be closed" + +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::polygon polygon_type; + + boost::geometry::closure_selector clos = boost::geometry::closure::value; + + std::cout << "closure: " << clos << std::endl + << "(open = " << boost::geometry::open + << ", closed = " << boost::geometry::closed + << ") "<< std::endl; + + return 0; +} + +//] + + +//[closure_output +/*` +Output: +[pre +closure: 1 +(open = 0, closed = 1) +] +*/ +//] diff --git a/doc/src/examples/core/coordinate_dimension.cpp b/doc/src/examples/core/coordinate_dimension.cpp new file mode 100644 index 0000000000..5061c46ce0 --- /dev/null +++ b/doc/src/examples/core/coordinate_dimension.cpp @@ -0,0 +1,43 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[dimension +//` Examine the number of coordinates making up the points in a linestring type + +#include +#include +#include +#include + +int main() +{ + int dim = boost::geometry::dimension + < + std::vector + < + boost::tuple + > + >::value; + + std::cout << "dimensions: " << dim << std::endl; + + return 0; +} + +//] + + +//[dimension_output +/*` +Output: +[pre +dimensions: 3 +] +*/ +//] diff --git a/doc/src/examples/core/coordinate_system.cpp b/doc/src/examples/core/coordinate_system.cpp new file mode 100644 index 0000000000..0152aabf44 --- /dev/null +++ b/doc/src/examples/core/coordinate_system.cpp @@ -0,0 +1,39 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[coordinate_system +//` Examine the coordinate system of a point + +#include +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::polygon polygon_type; + + typedef boost::geometry::coordinate_system::type system; + + std::cout << "system: " << typeid(system).name() << std::endl; + + return 0; +} + +//] + + +//[coordinate_system_output +/*` +Output (using MSVC): +[pre +system: struct boost::geometry::cs::cartesian +] +*/ +//] diff --git a/doc/src/examples/core/coordinate_type.cpp b/doc/src/examples/core/coordinate_type.cpp new file mode 100644 index 0000000000..ebeea7e3c0 --- /dev/null +++ b/doc/src/examples/core/coordinate_type.cpp @@ -0,0 +1,39 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[coordinate_type +//` Examine the coordinate type of a point + +#include +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::polygon polygon_type; + + typedef boost::geometry::coordinate_type::type ctype; + + std::cout << "type: " << typeid(ctype).name() << std::endl; + + return 0; +} + +//] + + +//[coordinate_type_output +/*` +Output (using MSVC): +[pre +type: double +] +*/ +//] diff --git a/doc/src/examples/core/degree_radian.cpp b/doc/src/examples/core/degree_radian.cpp new file mode 100644 index 0000000000..3b84110684 --- /dev/null +++ b/doc/src/examples/core/degree_radian.cpp @@ -0,0 +1,47 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[degree_radian +//` Specify two coordinate systems, one in degrees, one in radians. + +#include +#include + +using namespace boost::geometry; + +int main() +{ + typedef model::point > degree_point; + typedef model::point > radian_point; + + degree_point d(4.893, 52.373); + radian_point r(0.041, 0.8527); + + double dist = distance(d, r); + std::cout + << "distance:" << std::endl + << dist << " over unit sphere" << std::endl + << dist * 3959 << " over a spherical earth, in miles" << std::endl; + + return 0; +} + +//] + + +//[degree_radian_output +/*` +Output: +[pre +distance: +0.0675272 over unit sphere +267.34 over a spherical earth, in miles +] +*/ +//] diff --git a/doc/src/examples/core/point_order.cpp b/doc/src/examples/core/point_order.cpp new file mode 100644 index 0000000000..34e371209d --- /dev/null +++ b/doc/src/examples/core/point_order.cpp @@ -0,0 +1,42 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[point_order +//` Examine the expected point order of a polygon type + +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::polygon polygon_type; + + boost::geometry::order_selector order = boost::geometry::point_order::value; + + std::cout << "order: " << order << std::endl + << "(clockwise = " << boost::geometry::clockwise + << ", counterclockwise = " << boost::geometry::counterclockwise + << ") "<< std::endl; + + return 0; +} + +//] + + +//[point_order_output +/*` +Output: +[pre +order: 2 +(clockwise = 1, counterclockwise = 2) +] +*/ +//] diff --git a/doc/src/examples/core/point_type.cpp b/doc/src/examples/core/point_type.cpp new file mode 100644 index 0000000000..2f1b499b7a --- /dev/null +++ b/doc/src/examples/core/point_type.cpp @@ -0,0 +1,40 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[point_type +//` Examine the point type of a multi_polygon + +#include +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::polygon polygon_type; + typedef boost::geometry::model::multi_polygon mp_type; + + typedef boost::geometry::point_type::type ptype; + + std::cout << "point type: " << typeid(ptype).name() << std::endl; + + return 0; +} + +//] + + +//[point_type_output +/*` +Output (in MSVC): +[pre +point type: class boost::geometry::model::d2::point_xy +] +*/ +//] diff --git a/doc/src/examples/core/tag.cpp b/doc/src/examples/core/tag.cpp new file mode 100644 index 0000000000..895c528bbe --- /dev/null +++ b/doc/src/examples/core/tag.cpp @@ -0,0 +1,48 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[tag +//` Examine the tag of some geometry types + +#include +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::polygon polygon_type; + typedef boost::geometry::model::multi_polygon mp_type; + + typedef boost::geometry::tag::type tag1; + typedef boost::geometry::tag::type tag2; + typedef boost::geometry::tag::type tag3; + + std::cout + << "tag 1: " << typeid(tag1).name() << std::endl + << "tag 2: " << typeid(tag2).name() << std::endl + << "tag 3: " << typeid(tag3).name() << std::endl + ; + + return 0; +} + +//] + + +//[tag_output +/*` +Output (in MSVC): +[pre +tag 1: struct boost::geometry::point_tag +tag 2: struct boost::geometry::polygon_tag +tag 3: struct boost::geometry::multi_polygon_tag +] +*/ +//] diff --git a/doc/src/examples/core/tag_cast.cpp b/doc/src/examples/core/tag_cast.cpp new file mode 100644 index 0000000000..7f4ab3e0e0 --- /dev/null +++ b/doc/src/examples/core/tag_cast.cpp @@ -0,0 +1,43 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011 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) + +//[tag_cast +//` Check if the polygon_tag can be casted to the areal_tag + +#include +#include +#include + +namespace geo = boost::geometry; +int main() +{ + typedef geo::model::d2::point_xy point_type; + typedef geo::model::polygon polygon_type; + + typedef geo::tag::type tag; + typedef geo::tag_cast::type base_tag; + + std::cout << "tag: " << typeid(tag).name() << std::endl + << "base tag: " << typeid(base_tag).name() << std::endl; + + return 0; +} + +//] + + +//[tag_cast_output +/*` +Output (in MSVC): +[pre +tag: struct boost::geometry::polygon_tag +base tag: struct boost::geometry::areal_tag +] +*/ +//] diff --git a/doc/src/examples/geometries/register/point.cpp b/doc/src/examples/geometries/register/point.cpp index d4a27c545f..bfac67d885 100644 --- a/doc/src/examples/geometries/register/point.cpp +++ b/doc/src/examples/geometries/register/point.cpp @@ -29,8 +29,8 @@ int main() namespace bg = boost::geometry; /*< Any Boost.Geometry function can be used for legacy point now. Here: assign and distance >*/ - bg::assign(p1, 1, 1); - bg::assign(p2, 2, 2); + bg::assign_values(p1, 1, 1); + bg::assign_values(p2, 2, 2); double d = bg::distance(p1, p2); diff --git a/example/01_point_example.cpp b/example/01_point_example.cpp index ee5698de24..574831e468 100644 --- a/example/01_point_example.cpp +++ b/example/01_point_example.cpp @@ -53,13 +53,13 @@ int main() // All these types are handled the same way. We show here // assigning them and calculating distances. - assign(pt1, 1, 1); - assign(pt2, 2, 2); - assign(pt3, 3, 3); - assign(pt4, 4, 4); - assign(pt5, 5, 5); - assign(pt6, 6, 6); - assign(pt7, 7, 7); + assign_values(pt1, 1, 1); + assign_values(pt2, 2, 2); + assign_values(pt3, 3, 3); + assign_values(pt4, 4, 4); + assign_values(pt5, 5, 5); + assign_values(pt6, 6, 6); + assign_values(pt7, 7, 7); double d1 = distance(pt1, pt2); @@ -76,13 +76,13 @@ int main() // 1: default, empty constructor, causing no initialization at all model::d2::point_xy p1; - // 2: as shown above, assign + // 2: as shown above, assign_values model::d2::point_xy p2; - assign(p2, 1, 1); + assign_values(p2, 1, 1); // 3: using "set" function // set uses the concepts behind, such that it can be applied for - // every point-type (like assign) + // every point-type (like assign_values) model::d2::point_xy p3; set<0>(p3, 1); set<1>(p3, 1); @@ -118,8 +118,8 @@ int main() // There are 3-dimensional points too model::point d3a, d3b; - assign(d3a, 1, 2, 3); - assign(d3b, 4, 5, 6); + assign_values(d3a, 1, 2, 3); + assign_values(d3b, 4, 5, 6); d3 = distance(d3a, d3b); diff --git a/example/02_linestring_example.cpp b/example/02_linestring_example.cpp index 014aaa2a8d..3299935290 100644 --- a/example/02_linestring_example.cpp +++ b/example/02_linestring_example.cpp @@ -79,9 +79,9 @@ int main(void) // points can be created using "make" and added to a linestring using the std:: "push_back" ls.push_back(make(1.1, 1.1)); - // points can also be assigned using "assign" and added to a linestring using "append" + // points can also be assigned using "assign_values" and added to a linestring using "append" point_2d lp; - assign(lp, 2.5, 2.1); + assign_values(lp, 2.5, 2.1); append(ls, lp); // Lines can be streamed using DSV (delimiter separated values) diff --git a/example/03_polygon_example.cpp b/example/03_polygon_example.cpp index 0e36dd73dd..780221a93d 100644 --- a/example/03_polygon_example.cpp +++ b/example/03_polygon_example.cpp @@ -41,7 +41,7 @@ int main(void) {3.4, 2.0}, {4.1, 3.0}, {5.3, 2.6}, {5.4, 1.2}, {4.9, 0.8}, {2.9, 0.7}, {2.0, 1.3} // closing point is opening point }; - assign(poly, coor); + assign_points(poly, coor); } // Polygons should be closed, and directed clockwise. If you're not sure if that is the case, @@ -77,7 +77,7 @@ int main(void) model::ring& inner = poly.inners().back(); const double coor[][2] = { {4.0, 2.0}, {4.2, 1.4}, {4.8, 1.9}, {4.4, 2.2}, {4.0, 2.0} }; - assign(inner, coor); + assign_points(inner, coor); } correct(poly); diff --git a/example/05_a_overlay_polygon_example.cpp b/example/05_a_overlay_polygon_example.cpp index 9d74b8273d..625b0f4974 100644 --- a/example/05_a_overlay_polygon_example.cpp +++ b/example/05_a_overlay_polygon_example.cpp @@ -45,7 +45,7 @@ int main(void) const double c[][2] = { {160, 330}, {60, 260}, {20, 150}, {60, 40}, {190, 20}, {270, 130}, {260, 250}, {160, 330} }; - bg::assign(a, c); + bg::assign_points(a, c); } bg::correct(a); std::cout << "A: " << bg::dsv(a) << std::endl; @@ -55,7 +55,7 @@ int main(void) const double c[][2] = { {300, 330}, {190, 270}, {150, 170}, {150, 110}, {250, 30}, {380, 50}, {380, 250}, {300, 330} }; - bg::assign(b, c); + bg::assign_points(b, c); } bg::correct(b); std::cout << "B: " << bg::dsv(b) << std::endl; diff --git a/example/05_b_overlay_linestring_polygon_example.cpp b/example/05_b_overlay_linestring_polygon_example.cpp index 16eff548ed..8e0dc7483e 100644 --- a/example/05_b_overlay_linestring_polygon_example.cpp +++ b/example/05_b_overlay_linestring_polygon_example.cpp @@ -35,13 +35,13 @@ int main(void) bg::model::linestring ls; { const double c[][2] = { {0, 1}, {2, 5}, {5, 3} }; - bg::assign(ls, c); + bg::assign_points(ls, c); } bg::model::polygon p; { const double c[][2] = { {3, 0}, {0, 3}, {4, 5}, {3, 0} }; - bg::assign(p, c); + bg::assign_points(p, c); } bg::correct(p); diff --git a/example/06_a_transformation_example.cpp b/example/06_a_transformation_example.cpp index 2c13911e2f..ef7d279d3c 100644 --- a/example/06_a_transformation_example.cpp +++ b/example/06_a_transformation_example.cpp @@ -35,7 +35,7 @@ int main() const double coor[][2] = { {0, 0}, {0, 7}, {2, 2}, {2, 0}, {0, 0} }; // note that for this syntax you have to include the two // include files above (c_array_cartesian.hpp, std_as_linestring.hpp) - assign(poly, coor); + assign_points(poly, coor); //read_wkt("POLYGON((0 0,0 7,4 2,2 0,0 0))", poly); transform(poly, poly2, translate); diff --git a/example/c01_custom_point_example.cpp b/example/c01_custom_point_example.cpp index 0534feb049..c6f3a64952 100644 --- a/example/c01_custom_point_example.cpp +++ b/example/c01_custom_point_example.cpp @@ -108,8 +108,8 @@ int main() my_array_point a1 = {{0}}; my_array_point a2 = {{0}}; - boost::geometry::assign(a1, 1, 2, 3); - boost::geometry::assign(a2, 3, 2, 1); + boost::geometry::assign_values(a1, 1, 2, 3); + boost::geometry::assign_values(a2, 3, 2, 1); std::cout << "color distance " << boost::geometry::dsv(a1) << " to " @@ -132,8 +132,8 @@ int main() my_class_rw crw1; my_class_rw crw2; - boost::geometry::assign(crw1, 1, 2); - boost::geometry::assign(crw2, 3, 4); + boost::geometry::assign_values(crw1, 1, 2); + boost::geometry::assign_values(crw2, 3, 4); std::cout << "class r/w distance " << boost::geometry::dsv(crw1) << " to " << boost::geometry::dsv(crw2) << " is " @@ -141,8 +141,8 @@ int main() my_class_gs cgs1; my_class_gs cgs2; - boost::geometry::assign(cgs1, 1, 2); - boost::geometry::assign(cgs2, 3, 4); + boost::geometry::assign_values(cgs1, 1, 2); + boost::geometry::assign_values(cgs2, 3, 4); std::cout << "class g/s distance " << boost::geometry::dsv(crw1) << " to " << boost::geometry::dsv(crw2) << " is " diff --git a/example/with_external_libs/x05_shapelib_example.cpp b/example/with_external_libs/x05_shapelib_example.cpp index c096c9b8b8..a136240e19 100644 --- a/example/with_external_libs/x05_shapelib_example.cpp +++ b/example/with_external_libs/x05_shapelib_example.cpp @@ -73,7 +73,7 @@ void convert(SHPObject* psShape, T& polygon) for (int v = 0; v < psShape->nVertices; v++) { typename point_type::type point; - assign(point, x[v], y[v]); + assign_values(point, x[v], y[v]); append(polygon, point); } } diff --git a/test/algorithms/Jamfile.v2 b/test/algorithms/Jamfile.v2 index daf06b6d42..7058f6753b 100644 --- a/test/algorithms/Jamfile.v2 +++ b/test/algorithms/Jamfile.v2 @@ -18,6 +18,7 @@ test-suite boost-geometry-algorithms [ run comparable_distance.cpp ] [ run convex_hull.cpp ] [ run correct.cpp ] + [ run convert.cpp ] [ run difference.cpp ] [ run disjoint.cpp ] [ run distance.cpp ] diff --git a/test/algorithms/algorithms_tests.sln b/test/algorithms/algorithms_tests.sln index f929e0ba5a..6880312aa9 100644 --- a/test/algorithms/algorithms_tests.sln +++ b/test/algorithms/algorithms_tests.sln @@ -54,6 +54,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reverse", "reverse.vcproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "comparable_distance", "comparable_distance.vcproj", "{F11970B5-BE16-4FF5-9780-4C15082B76A0}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convert", "convert.vcproj", "{FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -168,6 +170,10 @@ Global {F11970B5-BE16-4FF5-9780-4C15082B76A0}.Debug|Win32.Build.0 = Debug|Win32 {F11970B5-BE16-4FF5-9780-4C15082B76A0}.Release|Win32.ActiveCfg = Release|Win32 {F11970B5-BE16-4FF5-9780-4C15082B76A0}.Release|Win32.Build.0 = Release|Win32 + {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Debug|Win32.ActiveCfg = Debug|Win32 + {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Debug|Win32.Build.0 = Debug|Win32 + {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Release|Win32.ActiveCfg = Release|Win32 + {FABF1AA7-F695-49F8-92F6-AB6C4B0C088A}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/algorithms/assign.cpp b/test/algorithms/assign.cpp index 96bd35e0a0..ab4ee31b04 100644 --- a/test/algorithms/assign.cpp +++ b/test/algorithms/assign.cpp @@ -14,6 +14,7 @@ #include +#include #include #include @@ -48,25 +49,25 @@ void test_assign_linestring_2d() { bg::model::linestring line; - // Test assignment of plain array (note that this is only possible if adapted c-array is included! + // Test assignment of plain array (note that this is only possible if adapted c-array is included!) const double coors[3][2] = { {1, 2}, {3, 4}, {5, 6} }; - bg::assign(line, coors); + bg::assign_points(line, coors); check_linestring_2d(line); // Test assignment of point array Point points[3]; - bg::assign(points[0], 1, 2); - bg::assign(points[1], 3, 4); - bg::assign(points[2], 5, 6); - bg::assign(line, points); + bg::assign_values(points[0], 1, 2); + bg::assign_values(points[1], 3, 4); + bg::assign_values(points[2], 5, 6); + bg::assign_points(line, points); check_linestring_2d(line); - // Test assignment of array with different point-type + // Test assignment of array with different point-type (tuple adaption should be included) boost::tuple tuples[3]; tuples[0] = boost::make_tuple(1, 2); tuples[1] = boost::make_tuple(3, 4); tuples[2] = boost::make_tuple(5, 6); - bg::assign(line, tuples); + bg::assign_points(line, tuples); check_linestring_2d(line); } @@ -76,7 +77,7 @@ namespace detail void test_assign_box_or_segment_2d() { BoxOrSegment geometry; - bg::assign(geometry, 1, 2, 3, 4); + bg::assign_values(geometry, 1, 2, 3, 4); BOOST_CHECK((bg::get(geometry) == 1)); BOOST_CHECK((bg::get(geometry) == 2)); BOOST_CHECK((bg::get(geometry) == 3)); @@ -114,12 +115,12 @@ template void test_assign_point_3d() { Point p; - bg::assign(p, 1, 2, 3); + bg::assign_values(p, 1, 2, 3); BOOST_CHECK(bg::get<0>(p) == 1); BOOST_CHECK(bg::get<1>(p) == 2); BOOST_CHECK(bg::get<2>(p) == 3); - bg::detail::assign::assign_value(p, 123); + bg::assign_value(p, 123); BOOST_CHECK(bg::get<0>(p) == 123); BOOST_CHECK(bg::get<1>(p) == 123); BOOST_CHECK(bg::get<2>(p) == 123); @@ -131,15 +132,75 @@ void test_assign_point_3d() } +template +void test_assign_conversion() +{ + typedef bg::model::box