diff --git a/example/08_polyhedralsurface_example.cpp b/example/08_polyhedralsurface_example.cpp new file mode 100644 index 0000000000..44cd61bd56 --- /dev/null +++ b/example/08_polyhedralsurface_example.cpp @@ -0,0 +1,36 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Polyhedral surface example + +#include +#include + +int main() +{ + using namespace boost::geometry; + using point_t = model::point; + using ring_t = model::ring; + using polyhedral_t = model::polyhedral_surface; + + // intializing an empty polyhedral surface (deafault constructor) + polyhedral_t polyhedral2; + + // creating a polyhderal surface using standard initiallized list + polyhedral_t polyhedral1 = {{{0,0,0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0}, {0, 0, 0}}, {{0, 0, 0}, {0, 1, 0}, {0, 1, 1}, {0, 0, 1}, {0, 0, 0}}, + {{0, 0, 0}, {1, 0, 0}, {1, 0, 1}, {0, 0, 1}, {0, 0, 0}}, {{1, 1, 1}, {1, 0, 1}, {0, 0, 1}, {0, 1, 1}, {1, 1, 1}}, {{1, 1, 1}, {1, 0, 1}, {1, 0, 0}, {1, 1, 0}, {1, 1, 1}}, + {{1, 1, 1}, {1, 1, 0}, {0, 1, 0}, {0, 1, 1}, {1, 1, 1}}}; + + // modifying a polyhedral surface + polyhedral1[0][1] = {1, 1, 1}; + + // read polyhedral surface wkt + read_wkt("POLYHEDRALSURFACE(((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1)))", polyhedral2); + + // write polyhedral surface wkt + std::cout << wkt(polyhedral1) << std::endl; + + std::cout << wkt(polyhedral2) << std::endl; + + // clear polyhedral surface + clear(polyhedral1); +} diff --git a/example/Jamfile b/example/Jamfile index 17fae5000c..de9ced96d5 100644 --- a/example/Jamfile +++ b/example/Jamfile @@ -23,6 +23,7 @@ exe 06_a_transformation_example : 06_a_transformation_example.cpp ; exe 06_b_transformation_example : 06_b_transformation_example.cpp ; exe 07_a_graph_route_example : 07_a_graph_route_example.cpp ; exe 07_b_graph_route_example : 07_b_graph_route_example.cpp ; +exe 08_polyhedralsurface_example : 08_polyhedralsurface_example.cpp ; exe c01_custom_point_example : c01_custom_point_example.cpp ; exe c02_custom_box_example : c02_custom_box_example.cpp ; diff --git a/include/boost/geometry/algorithms/clear.hpp b/include/boost/geometry/algorithms/clear.hpp index 05c910f2e2..656105e4c7 100644 --- a/include/boost/geometry/algorithms/clear.hpp +++ b/include/boost/geometry/algorithms/clear.hpp @@ -73,6 +73,18 @@ struct polygon_clear } }; +template +struct polyhedral_surface_clear +{ + static inline void apply(Polyhedral_surface& polyhedral_surface) + { + traits::clear + < + typename std::remove_reference::type + >::apply(polyhedral_surface); + } +}; + template struct no_action { @@ -123,6 +135,11 @@ struct clear : detail::clear::collection_clear {}; +// Clear for Polyhedral surface +template +struct clear + : detail::clear::polyhedral_surface_clear +{}; // Polygon can (indirectly) use std for clear template diff --git a/include/boost/geometry/core/point_type.hpp b/include/boost/geometry/core/point_type.hpp index 696e1e56ad..33cb2e1953 100644 --- a/include/boost/geometry/core/point_type.hpp +++ b/include/boost/geometry/core/point_type.hpp @@ -92,6 +92,12 @@ struct point_type typedef typename boost::range_value::type type; }; +// Specialization for PolyhedralSurface: the point-type is the point-type of its poly_ring_type +template +struct point_type +{ + using type = typename point_type::type>::type; +}; // Specialization for polygon: the point-type is the point-type of its rings template diff --git a/include/boost/geometry/core/ring_type.hpp b/include/boost/geometry/core/ring_type.hpp index 726b14ca5e..42bb3bb185 100644 --- a/include/boost/geometry/core/ring_type.hpp +++ b/include/boost/geometry/core/ring_type.hpp @@ -23,7 +23,6 @@ #include #include - #include #include #include @@ -61,6 +60,13 @@ struct ring_mutable_type Geometry); }; +template +struct poly_ring_type +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Geometry type.", + Geometry); +}; } // namespace traits @@ -87,6 +93,11 @@ struct ring_return_type typedef Ring& type; }; +template +struct ring_return_type +{ + using type = typename traits::poly_ring_type::type; +}; template struct ring_return_type @@ -145,6 +156,12 @@ struct ring_type typedef Ring type; }; +template +struct ring_type +{ + using type = typename std::remove_reference::type>::type; +}; + template struct ring_type diff --git a/include/boost/geometry/core/tags.hpp b/include/boost/geometry/core/tags.hpp index 6c33042f5c..d58b419e4d 100644 --- a/include/boost/geometry/core/tags.hpp +++ b/include/boost/geometry/core/tags.hpp @@ -105,6 +105,9 @@ struct box_tag : single_tag, areal_tag {}; /// Convenience segment (2-points) identifying tag struct segment_tag : single_tag, linear_tag {}; +/// OGC Polyhedral surface identifying tag +struct polyhedral_surface_tag : single_tag, volumetric_tag {}; + /// OGC Multi point identifying tag struct multi_point_tag : multi_tag, pointlike_tag {}; diff --git a/include/boost/geometry/geometries/concepts/check.hpp b/include/boost/geometry/geometries/concepts/check.hpp index 5b49f38843..d2d2bf404f 100644 --- a/include/boost/geometry/geometries/concepts/check.hpp +++ b/include/boost/geometry/geometries/concepts/check.hpp @@ -39,7 +39,7 @@ #include #include #include - +#include #include namespace boost { namespace geometry @@ -121,6 +121,15 @@ struct check : detail::concept_check::check > {}; +template +struct check + : detail::concept_check::check> +{}; + +template +struct check + : detail::concept_check::check> +{}; template struct check diff --git a/include/boost/geometry/geometries/concepts/polyhedral_surface_concept.hpp b/include/boost/geometry/geometries/concepts/polyhedral_surface_concept.hpp new file mode 100644 index 0000000000..ad86e2446e --- /dev/null +++ b/include/boost/geometry/geometries/concepts/polyhedral_surface_concept.hpp @@ -0,0 +1,48 @@ +#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYHEDRALSURFACE_HPP +#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYHEDRALSURFACE_HPP + +#include +#include +#include +#include +#include + +namespace boost { namespace geometry { namespace concepts +{ + +template +class PolyhedralSurface +{ +#ifndef DOXYGEN_NO_CONCEPT_MEMBERS + using ring_type = typename ring_type::type; + + BOOST_CONCEPT_ASSERT( (concepts::Ring) ); +public: + + BOOST_CONCEPT_USAGE(PolyhedralSurface) + { + } +#endif +}; + +// polyhedral surface(constant version) +template +class ConstPolyhedralSurface +{ +#ifndef DOXYGEN_NO_CONCEPT_MEMBERS + using const_polyhedral_type = typename std::remove_const::type; + using ring_type = typename ring_type::type; + + BOOST_CONCEPT_ASSERT( (concepts::ConstRing) ); + +public: + + BOOST_CONCEPT_USAGE(ConstPolyhedralSurface) + { + } + +#endif +}; + +}}} // namespace boost::geometry::concepts +#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYHEDRALSURFACE_HPP diff --git a/include/boost/geometry/geometries/geometries.hpp b/include/boost/geometry/geometries/geometries.hpp index a116b20cb8..076b11cef6 100644 --- a/include/boost/geometry/geometries/geometries.hpp +++ b/include/boost/geometry/geometries/geometries.hpp @@ -29,5 +29,6 @@ #include #include #include +#include #endif // BOOST_GEOMETRY_GEOMETRIES_HPP diff --git a/include/boost/geometry/geometries/polyhedral_surface.hpp b/include/boost/geometry/geometries/polyhedral_surface.hpp new file mode 100644 index 0000000000..785cb5a608 --- /dev/null +++ b/include/boost/geometry/geometries/polyhedral_surface.hpp @@ -0,0 +1,104 @@ +#ifndef BOOST_GEOMETRY_GEOMETRIES_POLYHEDRALSURFACE_HPP +#define BOOST_GEOMETRY_GEOMETRIES_POLYHEDRALSURFACE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#include +#endif + +namespace boost { namespace geometry +{ +namespace model +{ + +template +< + typename Ring, + template class Container = std::vector, + template class Allocator = std::allocator + +> +class polyhedral_surface : public Container > +{ + BOOST_CONCEPT_ASSERT( (concepts::Ring) ); + +public : + + using point_type = model::point; + using ring_type = ring; + using ph = Container >; + +#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST + + /// \constructor_default{polyhedron} + inline polyhedral_surface() + : ph() + {} + + /// \constructor_initialized_list{polyhedron} + inline polyhedral_surface(std::initializer_list l) + : ph(l.begin(), l.end()) + {} + +#endif + +}; +} // namespace model + +#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS +namespace traits +{ + +template +< + typename Ring, + template class Container, + template class Allocator +> +struct tag +< + model::polyhedral_surface + < + Ring, + Container, Allocator + > +> +{ + using type = polyhedral_surface_tag; +}; + +template +< + typename Ring, + template class Container, + template class Allocator +> +struct poly_ring_type +< + model::polyhedral_surface + < + Ring, + Container, Allocator + > +> +{ + using type = typename model::polyhedral_surface + < + Ring, + Container, Allocator + >::ring_type&; +}; + +} // namespace traits +#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS + +}} // namespace boost::geometry + +#endif diff --git a/include/boost/geometry/io/wkt/detail/prefix.hpp b/include/boost/geometry/io/wkt/detail/prefix.hpp index b566e02aa6..56fdcd4a8e 100644 --- a/include/boost/geometry/io/wkt/detail/prefix.hpp +++ b/include/boost/geometry/io/wkt/detail/prefix.hpp @@ -42,6 +42,11 @@ struct prefix_linestring static inline const char* apply() { return "LINESTRING"; } }; +struct prefix_polyhedral_surface +{ + static inline const char* apply() { return "POLYHEDRALSURFACE"; } +}; + struct prefix_multipoint { static inline const char* apply() { return "MULTIPOINT"; } diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp index 7d73adf731..7462b8afd3 100644 --- a/include/boost/geometry/io/wkt/read.hpp +++ b/include/boost/geometry/io/wkt/read.hpp @@ -453,6 +453,42 @@ struct polygon_parser } }; +template +struct polyhderal_surface_parser +{ + using ring_return_type = typename ring_return_type::type; + using appender = container_appender; + + static inline void apply(tokenizer::iterator& it, + tokenizer::iterator const& end, + std::string const& wkt, + PolyhedralSurface& Poly) + { + handle_open_parenthesis(it, end, wkt); + while(it != end && *it != ")") + { + handle_open_parenthesis(it, end, wkt); + + typename ring_type::type ring; + + appender::apply(it, end, wkt, ring); + traits::push_back + < + typename std::remove_reference::type + >::apply(Poly, ring); + + handle_close_parenthesis(it, end, wkt); + 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, @@ -844,6 +880,15 @@ struct read_wkt > {}; +template +struct read_wkt + : detail::wkt::geometry_parser + < + Geometry, + detail::wkt::polyhderal_surface_parser, + detail::wkt::prefix_polyhedral_surface + > +{}; template struct read_wkt diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 6bd584b222..4791b74690 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -235,6 +235,34 @@ struct wkt_poly }; +template +struct wkt_polyhedral +{ + template + static inline void apply(std::basic_ostream& os, + Polyhedral_surface const& polyhedral, bool force_closure) + { + using const_polyhedral_type = typename std::remove_const::type; + using ring = typename ring_type::type; + + os << PrefixPolicy::apply(); + + os << "("; + for(auto it = boost::begin(polyhedral); it != boost::end(polyhedral); ++it) + { + if(it != boost::begin(polyhedral)) + { + os << ","; + } + os << "("; + + wkt_sequence::apply(os, *it, force_closure); + os << ")"; + } + os << ")"; + } +}; + template struct wkt_multi { @@ -409,6 +437,15 @@ struct wkt > {}; +template +struct wkt + : detail::wkt::wkt_polyhedral + < + Polyhedral_surface, + detail::wkt::prefix_polyhedral_surface + > +{}; + template struct wkt : detail::wkt::wkt_multi