diff --git a/doc/concept/polygon.qbk b/doc/concept/polygon.qbk
index 8cce35ff5f..89ab172d79 100644
--- a/doc/concept/polygon.qbk
+++ b/doc/concept/polygon.qbk
@@ -15,7 +15,7 @@
[heading Description]
[concept Polygon..polygon]
-A polygon is ['A polygon is a planar surface defined by one exterior boundary and zero or more interior boundaries]
+['A polygon is a planar surface defined by one exterior boundary and zero or more interior boundaries]
(__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
diff --git a/doc/concept/polyhedral_surface.qbk b/doc/concept/polyhedral_surface.qbk
new file mode 100644
index 0000000000..1ac5055b28
--- /dev/null
+++ b/doc/concept/polyhedral_surface.qbk
@@ -0,0 +1,47 @@
+[/============================================================================
+ Boost.Geometry (aka GGL, Generic Geometry Library)
+
+ Copyright (c) 2025 Oracle and/or its affiliates.
+ Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+ 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:concept_polyhedral_surface PolyhedralSurface Concept]
+
+[heading Description]
+[concept PolyhedralSurface..polyhedral surface]
+
+['A PolyhedralSurface is a contiguous collection of polygons, which share common boundary segments] (__ogc_sf__).
+
+[heading Concept Definition]
+
+The PolyhedralSurface Concept is defined as following:
+
+* There must be a specialization of the metafunction `traits::tag`, defining `polyhedral_surface_tag` as type
+* It must behave like a Boost.Range Random Access Range
+* The type defined by the metafunction `range_value<...>::type` must fulfill
+ the [link geometry.reference.concepts.concept_polygon Polygon Concept]
+
+[heading Rules]
+
+Besides the Concepts, which are checks on compile-time, there are
+rules that valid PolyhedralSurfaces must fulfill. See the
+[link geometry.reference.concepts.concept_polygon Polygon Concept] for more information
+on the rules a polygon (and also a polyhedral surface) must fulfill.
+
+Additionally:
+
+* It is a contiguous collection of polygons, which share common boundary segments.
+* For any two polygons that share a common boundary, the “top” of the polygon shall be consistent.
+ This means that when two LinearRings from these two Polygons traverse the common boundary segment,
+ they do so in opposite directions.
+
+[heading Available Models]
+* [link geometry.reference.models.model_polyhedral_surface model::polyhedral_surface]
+
+
+[endsect]
diff --git a/doc/geometry.qbk b/doc/geometry.qbk
index a48aa66226..c224c26e98 100644
--- a/doc/geometry.qbk
+++ b/doc/geometry.qbk
@@ -29,6 +29,7 @@
[def __0dim__ pointlike (e.g. point)]
[def __1dim__ linear (e.g. linestring)]
[def __2dim__ areal (e.g. polygon)]
+[def __3dim__ volumetric (e.g. polyhedral_surface)]
[def __single__ single (e.g. point, polygon)]
[def __multi__ multiple (e.g. multi_point, multi_polygon)]
[def __cart__ Cartesian]
diff --git a/doc/html/img/geometries/triangular_pyramid.png b/doc/html/img/geometries/triangular_pyramid.png
new file mode 100644
index 0000000000..b69999205b
Binary files /dev/null and b/doc/html/img/geometries/triangular_pyramid.png differ
diff --git a/doc/html/index.html b/doc/html/index.html
index d1e399c5a3..b5ae9640bc 100644
--- a/doc/html/index.html
+++ b/doc/html/index.html
@@ -3,7 +3,7 @@
Chapter 1. Geometry
-
+
@@ -52,7 +52,7 @@
Boost.Geometry contains contributions by:
-
+
Akira Takahashi (adaption of Boost.Fusion)
diff --git a/doc/imports.qbk b/doc/imports.qbk
index 81b8122636..a868144ffb 100644
--- a/doc/imports.qbk
+++ b/doc/imports.qbk
@@ -120,6 +120,7 @@
[import src/examples/geometries/point_xyz.cpp]
[import src/examples/geometries/point.cpp]
[import src/examples/geometries/polygon.cpp]
+[import src/examples/geometries/polyhedral_surface.cpp]
[import src/examples/geometries/ring.cpp]
[import src/examples/geometries/segment.cpp]
diff --git a/doc/make_qbk.py b/doc/make_qbk.py
index 7396a360b7..73e7adcda9 100755
--- a/doc/make_qbk.py
+++ b/doc/make_qbk.py
@@ -6,9 +6,10 @@
# Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net), London, UK
# Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland
#
-# Copyright (c) 2018-2021, Oracle and/or its affiliates.
+# Copyright (c) 2018-2025, Oracle and/or its affiliates.
# Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+#
# 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)
@@ -141,7 +142,7 @@ def cs_to_quickbook(section):
, "ever_circling_iterator"]
models = ["point", "linestring", "box"
- , "polygon", "segment", "ring"
+ , "polygon", "segment", "ring", "polyhedral_surface"
, "multi_linestring", "multi_point", "multi_polygon", "referring_segment"]
srs = ["spheroid"]
diff --git a/doc/quickref.xml b/doc/quickref.xml
index 5fe37f0525..0029d27a43 100644
--- a/doc/quickref.xml
+++ b/doc/quickref.xml
@@ -25,7 +25,7 @@
-->
-
+
@@ -64,6 +64,12 @@
MultiPolygon
+
+ 3-dimensional
+
+ PolyhedralSurface
+
+
@@ -109,6 +115,12 @@
multi_polygon
+
+ 3-dimensional
+
+ polyhedral_surface
+
+
@@ -144,10 +156,10 @@
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
-
+
@@ -207,7 +219,7 @@
Access Functions
-
get
set
@@ -349,7 +361,7 @@
Area
- area
+ area
Assign
@@ -366,7 +378,7 @@
Azimuth
- azimuth
+ azimuth
Buffer
@@ -466,7 +478,7 @@
Similarity
discrete_frechet_distance
- discrete_hausdorff_distance
+ discrete_hausdorff_distance
Simplify
@@ -483,7 +495,7 @@
Unique
unique
-
+
@@ -737,7 +749,7 @@
-
+
@@ -770,7 +782,7 @@
rtree()
rtree(parameters_type const &, indexable_getter const &, value_equal const &, allocator_type const &)
- rtree(Iterator, Iterator)
+ rtree(Iterator, Iterator)
rtree(Range const &)
rtree(Iterator, Iterator, parameters_type const &, indexable_getter const &, value_equal const &, allocator_type const &, PackAlloc const &)
rtree(Range const &, parameters_type const &, indexable_getter const &, value_equal const &, allocator_type const &, PackAlloc const &)
@@ -790,7 +802,7 @@
operator=(const rtree &)
operator=(rtree &&)
- swap(rtree &)
+ swap(rtree &)
insert(value_type const &)
insert(Iterator, Iterator)
insert(ConvertibleOrRange const &)
diff --git a/doc/reference.qbk b/doc/reference.qbk
index fe8b890635..705a779838 100644
--- a/doc/reference.qbk
+++ b/doc/reference.qbk
@@ -23,7 +23,7 @@
[section:access Access Functions]
-[/ This section is not ordered alfabetically
+[/ This section is not ordered alfabetically
to have get/set first and then the rings]
[section:get get]
@@ -240,12 +240,13 @@
[section:arithmetic Arithmetic]
[include generated/arithmetic.qbk]
-[endsect]
+[endsect]
[section:concepts Concepts]
[include concept/point.qbk]
[include concept/linestring.qbk]
[include concept/polygon.qbk]
+[include concept/polyhedral_surface.qbk]
[include concept/multi_point.qbk]
[include concept/multi_linestring.qbk]
[include concept/multi_polygon.qbk]
@@ -257,7 +258,7 @@
[section:constants Constants]
[include reference/core/min_corner.qbk]
[include reference/core/max_corner.qbk]
-[endsect]
+[endsect]
[section:cs Coordinate Systems]
[include generated/cartesian.qbk]
@@ -286,16 +287,16 @@
[include generated/de9im_mask.qbk]
[include generated/de9im_matrix.qbk]
[include generated/de9im_static_mask.qbk]
-[endsect]
+[endsect]
[section:enumerations Enumerations]
[include generated/enum.qbk]
-[endsect]
+[endsect]
[section:exceptions Exceptions]
[include generated/exception.qbk]
[include generated/centroid_exception.qbk]
-[endsect]
+[endsect]
[section:io IO (input/output)]
@@ -310,14 +311,14 @@
[include generated/svg.qbk]
[include generated/svg_mapper.qbk]
[endsect]
-[endsect]
+[endsect]
[section:iterators Iterators]
[include generated/closing_iterator.qbk]
[include generated/circular_iterator.qbk]
[include generated/ever_circling_iterator.qbk]
-[endsect]
+[endsect]
[section:models Models]
@@ -327,6 +328,7 @@
[include generated/point_xyz.qbk]
[include generated/linestring.qbk]
[include generated/polygon.qbk]
+[include generated/polyhedral_surface.qbk]
[include generated/multi_point.qbk]
[include generated/multi_linestring.qbk]
[include generated/multi_polygon.qbk]
@@ -411,7 +413,7 @@
[include generated/within_winding.qbk]
[include generated/within_franklin.qbk]
[include generated/within_crossings_multiply.qbk]
-[endsect]
+[endsect]
[section:views Views]
@@ -420,7 +422,7 @@
[include generated/closeable_view.qbk]
[include generated/reversible_view.qbk]
[include generated/identity_view.qbk]
-[endsect]
+[endsect]
[endsect] [/reference]
diff --git a/doc/reference/geometries/polyhedral_surface.qbk b/doc/reference/geometries/polyhedral_surface.qbk
new file mode 100644
index 0000000000..cd901592a3
--- /dev/null
+++ b/doc/reference/geometries/polyhedral_surface.qbk
@@ -0,0 +1,14 @@
+[/============================================================================
+ Boost.Geometry (aka GGL, Generic Geometry Library)
+
+ Copyright (c) 2025 Oracle and/or its affiliates.
+ Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+ 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 Examples]
+[polyhedral_surface]
+[polyhedral_surface_output]
diff --git a/doc/src/examples/geometries/polyhedral_surface.cpp b/doc/src/examples/geometries/polyhedral_surface.cpp
new file mode 100644
index 0000000000..e568d50ad6
--- /dev/null
+++ b/doc/src/examples/geometries/polyhedral_surface.cpp
@@ -0,0 +1,82 @@
+// Boost.Geometry
+// QuickBook Example
+
+// Copyright (c) 2025 Siddharth Kumar, Roorkee, India.
+
+// Copyright (c) 2025 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// 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)
+
+//[polyhedral_surface
+//` Declaration and use of the Boost.Geometry model::polyhedral_surface, modelling the PolyhedralSurface Concept
+
+#include
+#include
+#include
+
+namespace bg = boost::geometry;
+
+int main()
+{
+ using point_t = bg::model::point;
+ using polygon_t = bg::model::polygon;
+ using polyhedral_t = bg::model::polyhedral_surface;
+
+ polyhedral_t polyhedral0; /*< Initializing an empty polyhedral surface (default constructor) >*/
+
+ 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}}}}; /*< Creating a polyhedral surface (cube) using standard initialized list >*/
+
+
+ polyhedral0.resize(4);
+ bg::append(polyhedral0[0].outer(), point_t(0.0, 0.0, 0.0));
+ bg::append(polyhedral0[0].outer(), point_t(5.0, 0.0, 0.0));
+ bg::append(polyhedral0[0].outer(), point_t(0.0, 5.0, 0.0));
+ bg::append(polyhedral0[1].outer(), point_t(0.0, 0.0, 0.0));
+ bg::append(polyhedral0[1].outer(), point_t(0.0, 5.0, 0.0));
+ bg::append(polyhedral0[1].outer(), point_t(0.0, 0.0, 5.0));
+ bg::append(polyhedral0[2].outer(), point_t(0.0, 0.0, 0.0));
+ bg::append(polyhedral0[2].outer(), point_t(5.0, 0.0, 0.0));
+ bg::append(polyhedral0[2].outer(), point_t(0.0, 0.0, 5.0));
+ bg::append(polyhedral0[3].outer(), point_t(5.0, 0.0, 0.0));
+ bg::append(polyhedral0[3].outer(), point_t(0.0, 5.0, 0.0));
+ bg::append(polyhedral0[3].outer(), point_t(0.0, 0.0, 5.0)); /*< Creating a polyhedral surface (triangular pyramid) using append and resize. See figure below.>*/
+
+ polyhedral_t polyhedral2;
+ bg::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); /*< Initialize polyhedral surface (cube) with wkt >*/
+
+ std::cout << bg::wkt(polyhedral0) << std::endl; /*< Write polyhedral surface wkt >*/
+ std::cout << bg::wkt(polyhedral1) << std::endl;
+ std::cout << bg::wkt(polyhedral2) << std::endl;
+
+ return 0;
+}
+
+//]
+
+
+//[polyhedral_surface_output
+/*`
+Output:
+[pre
+POLYHEDRALSURFACE(((0 0 0,5 0 0,0 5 0,0 0 0)),((0 0 0,0 5 0,0 0 5,0 0 0)),((0 0 0,5 0 0,0 0 5,0 0 0)),((5 0 0,0 5 0,0 0 5,5 0 0)))
+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)))
+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)))
+]
+
+[$img/geometries/triangular_pyramid.png]
+
+*/
+//]
diff --git a/include/boost/geometry/algorithms/clear.hpp b/include/boost/geometry/algorithms/clear.hpp
index efaa93d184..9a053edde9 100644
--- a/include/boost/geometry/algorithms/clear.hpp
+++ b/include/boost/geometry/algorithms/clear.hpp
@@ -72,6 +72,18 @@ struct polygon_clear
}
};
+template
+struct polyhedral_surface_clear
+{
+ static inline void apply(PolyhedralSurface& polyhedral_surface)
+ {
+ traits::clear
+ <
+ typename std::remove_reference::type
+ >::apply(polyhedral_surface);
+ }
+};
+
template
struct no_action
{
@@ -122,6 +134,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 89c572c241..524aeea493 100644
--- a/include/boost/geometry/core/point_type.hpp
+++ b/include/boost/geometry/core/point_type.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2024 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2025.
+// Modifications copyright (c) 2020-2025 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -95,6 +96,16 @@ struct point_type
using type = typename boost::range_value::type;
};
+// Specialization for PolyhedralSurface: the point-type is the point-type of its polygon type
+template
+struct point_type
+{
+ using type = typename point_type
+ <
+ polygon_tag,
+ typename boost::range_value::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 e382c61172..f040f35fa9 100644
--- a/include/boost/geometry/core/ring_type.hpp
+++ b/include/boost/geometry/core/ring_type.hpp
@@ -24,7 +24,6 @@
#include
#include
-
#include
#include
#include
@@ -62,7 +61,6 @@ struct ring_mutable_type
Geometry);
};
-
} // namespace traits
@@ -88,6 +86,20 @@ struct ring_return_type
typedef Ring& type;
};
+template
+struct ring_return_type
+{
+ using type = typename ring_return_type
+ <
+ polygon_tag,
+ std::conditional_t
+ <
+ std::is_const::value,
+ typename boost::range_value::type const,
+ typename boost::range_value::type
+ >
+ >::type;
+};
template
struct ring_return_type
@@ -153,6 +165,14 @@ struct ring_type
typedef Ring type;
};
+template
+struct ring_type
+{
+ using type = std::remove_reference_t
+ <
+ typename ring_return_type::type
+ >;
+};
template
struct ring_type
diff --git a/include/boost/geometry/core/tags.hpp b/include/boost/geometry/core/tags.hpp
index 88422e4e07..16c4445211 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 34eb740329..08232ed7d4 100644
--- a/include/boost/geometry/geometries/concepts/check.hpp
+++ b/include/boost/geometry/geometries/concepts/check.hpp
@@ -36,7 +36,7 @@
#include
#include
#include
-
+#include
namespace boost { namespace geometry { namespace concepts
{
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..a78403a609
--- /dev/null
+++ b/include/boost/geometry/geometries/concepts/polyhedral_surface_concept.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry
+
+// Copyright (c) 2025 Siddharth Kumar, Roorkee, India.
+// Copyright (c) 2025 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// 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_CONCEPTS_POLYHEDRAL_SURFACE_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYHEDRAL_SURFACE_CONCEPT_HPP
+
+#include
+#include
+
+#include
+#include
+#include
+
+namespace boost { namespace geometry { namespace concepts
+{
+
+template
+class PolyhedralSurface
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ using polygon_type = typename boost::range_value::type;
+
+ BOOST_CONCEPT_ASSERT( (concepts::Polygon) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) );
+
+public:
+
+ BOOST_CONCEPT_USAGE(PolyhedralSurface)
+ {
+ Geometry* ps = 0;
+ traits::clear::apply(*ps);
+ traits::resize::apply(*ps, 0);
+ // The concept should support the second version of push_back, using &&
+ polygon_type* poly = 0;
+ traits::push_back::apply(*ps, std::move(*poly));
+ }
+#endif
+};
+
+// polyhedral surface(constant version)
+template
+class ConstPolyhedralSurface
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ using polygon_type = typename boost::range_value::type;
+
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPolygon) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) );
+
+public:
+
+ BOOST_CONCEPT_USAGE(ConstPolyhedralSurface)
+ {}
+
+#endif
+};
+
+template
+struct concept_type
+{
+ using type = PolyhedralSurface;
+};
+
+template
+struct concept_type
+{
+ using type = ConstPolyhedralSurface;
+};
+
+}}} // namespace boost::geometry::concepts
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYHEDRAL_SURFACE_CONCEPT_HPP
diff --git a/include/boost/geometry/geometries/geometries.hpp b/include/boost/geometry/geometries/geometries.hpp
index 50e700f6f0..1d3e1c5eeb 100644
--- a/include/boost/geometry/geometries/geometries.hpp
+++ b/include/boost/geometry/geometries/geometries.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2025.
+// Modifications copyright (c) 2020-2025, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -28,6 +29,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/include/boost/geometry/geometries/polyhedral_surface.hpp b/include/boost/geometry/geometries/polyhedral_surface.hpp
new file mode 100644
index 0000000000..0dc60819d5
--- /dev/null
+++ b/include/boost/geometry/geometries/polyhedral_surface.hpp
@@ -0,0 +1,103 @@
+// Boost.Geometry
+
+// Copyright (c) 2025 Siddharth Kumar, Roorkee, India.
+// Copyright (c) 2025 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// 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_POLYHEDRAL_SURFACE_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_POLYHEDRAL_SURFACE_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace boost { namespace geometry
+{
+namespace model
+{
+
+/*!
+\brief A Polyhedral Surface is a contiguous collection of polygons in 3-dimensional space,
+ which share common boundary segments. The concepts and the constructors don't check if the
+ boundary segments are common but is_valid() does.
+\ingroup geometries
+\tparam Polygon polygon type
+\tparam Container container type for polygons,
+ default std::vector
+\tparam Allocator container-allocator-type, for the polygons
+
+\qbk{[include reference/geometries/polyhedral_surface.qbk]}
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_polyhedral_surface PolyhedralSurface Concept]
+}
+
+*/
+
+//TODO: add is_valid() check
+template
+<
+ typename Polygon,
+ template class Container = std::vector,
+ template class Allocator = std::allocator
+
+>
+class polyhedral_surface : public Container >
+{
+ BOOST_CONCEPT_ASSERT( (concepts::Polygon) );
+
+public :
+ using polygon_type = Polygon;
+ using polygon_container = Container >;
+
+ /// \constructor_default{polyhedron}
+ inline polyhedral_surface()
+ : polygon_container()
+ {}
+
+ /// \constructor_initialized_list{polyhedron}
+ inline polyhedral_surface(std::initializer_list l)
+ : polygon_container(l.begin(), l.end())
+ {}
+
+};
+} // namespace model
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Polygon,
+ template class Container,
+ template class Allocator
+>
+struct tag
+<
+ model::polyhedral_surface
+ <
+ Polygon,
+ Container, Allocator
+ >
+>
+{
+ using type = polyhedral_surface_tag;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_POLYHEDRAL_SURFACE_HPP
diff --git a/include/boost/geometry/io/wkt/detail/prefix.hpp b/include/boost/geometry/io/wkt/detail/prefix.hpp
index a61b8ae0f6..fb4e139a37 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 9d96dffeb1..e8db2b464a 100644
--- a/include/boost/geometry/io/wkt/read.hpp
+++ b/include/boost/geometry/io/wkt/read.hpp
@@ -458,6 +458,35 @@ struct polygon_parser
}
};
+template
+struct polyhedral_surface_parser
+{
+ using polygon_t = typename PolyhedralSurface::polygon_type;
+
+ template
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
+ std::string const& wkt,
+ PolyhedralSurface& polyhedral)
+ {
+ handle_open_parenthesis(it, end, wkt);
+
+ // Parse polygons
+ while (it != end && *it != ")")
+ {
+ traits::resize::apply(polyhedral, boost::size(polyhedral) + 1);
+ polygon_parser::apply(it, end, wkt, *(boost::end(polyhedral) - 1));
+ if (it != end && *it == ",")
+ {
+ // Skip "," after multi-element is parsed
+ ++it;
+ }
+ }
+
+ handle_close_parenthesis(it, end, wkt);
+ }
+};
+
template
inline bool one_of(TokenizerIterator const& it,
@@ -1063,6 +1092,15 @@ struct read_wkt
>
{};
+template
+struct read_wkt
+ : detail::wkt::geometry_parser
+ <
+ Geometry,
+ detail::wkt::polyhedral_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 e1e9a03ef4..8326c29dc5 100644
--- a/include/boost/geometry/io/wkt/write.hpp
+++ b/include/boost/geometry/io/wkt/write.hpp
@@ -228,6 +228,30 @@ struct wkt_poly
};
+template
+struct wkt_polyhedral_surface
+{
+ template
+ static inline void apply(std::basic_ostream& os,
+ PolyhedralSurface const& polyhedral, bool force_closure)
+ {
+ using polygon = typename PolyhedralSurface::polygon_type;
+
+ os << PrefixPolicy::apply();
+
+ os << "(";
+ for (auto it = boost::begin(polyhedral); it != boost::end(polyhedral); ++it)
+ {
+ if (it != boost::begin(polyhedral))
+ {
+ os << ",";
+ }
+ wkt_poly::apply(os, *it, force_closure);
+ }
+ os << ")";
+ }
+};
+
template
struct wkt_multi
{
@@ -396,6 +420,15 @@ struct wkt
>
{};
+template
+struct wkt
+ : detail::wkt::wkt_polyhedral_surface
+ <
+ PolyhedralSurface,
+ detail::wkt::prefix_polyhedral_surface
+ >
+{};
+
template
struct wkt
: detail::wkt::wkt_multi
diff --git a/test/geometries/CMakeLists.txt b/test/geometries/CMakeLists.txt
index ea88f035d4..8157cc1cc2 100644
--- a/test/geometries/CMakeLists.txt
+++ b/test/geometries/CMakeLists.txt
@@ -24,6 +24,7 @@ foreach(item IN ITEMS
point_xy
point_xyz
polygon
+ polyhedral_surface
ring
segment
infinite_line
diff --git a/test/geometries/Jamfile b/test/geometries/Jamfile
index b67d5c5336..69c872464a 100644
--- a/test/geometries/Jamfile
+++ b/test/geometries/Jamfile
@@ -14,7 +14,7 @@ test-suite boost-geometry-geometries
[ run adapted.cpp : : : : geometries_adapted ]
[ run boost_array_as_point.cpp : : : : geometries_boost_array_as_point ]
[ run boost_fusion.cpp : : : : geometries_boost_fusion ]
- [ run boost_polygon.cpp : : : : geometries_boost_polygon ]
+ [ run boost_polygon.cpp : : : : geometries_boost_polygon ]
[ run boost_range.cpp : : : : geometries_boost_range ]
[ run boost_tuple.cpp : : : : geometries_boost_tuple ]
[ run box.cpp : : : : geometries_box ]
@@ -34,6 +34,7 @@ test-suite boost-geometry-geometries
[ run point_xy.cpp : : : : geometries_point_xy ]
[ run point_xyz.cpp : : : : geometries_point_xyz ]
[ run polygon.cpp : : : : geometries_polygon ]
+ [ run polyhedral_surface.cpp : : : : geometries_polyhedral_surface ]
[ run ring.cpp : : : : geometries_ring ]
[ run segment.cpp : : : : geometries_segment ]
[ run infinite_line.cpp : : : : geometries_infinite_line ]
diff --git a/test/geometries/polyhedral_surface.cpp b/test/geometries/polyhedral_surface.cpp
new file mode 100644
index 0000000000..3e775b17a0
--- /dev/null
+++ b/test/geometries/polyhedral_surface.cpp
@@ -0,0 +1,86 @@
+// Boost.Geometry
+// Unit Test
+
+// Copyright (c) 2025 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// 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)
+
+// Polyhedral surface tests
+
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+
+int test_main(int, char* [])
+{
+ namespace bg = boost::geometry;
+ using point_t = bg::model::point;
+ using polygon_t = bg::model::polygon;
+ using polyhedral_t = bg::model::polyhedral_surface;
+ using const_polyhedral_t = bg::model::polyhedral_surface const;
+
+ // Intializing an empty polyhedral surface (default constructor)
+ polyhedral_t polyhedral0;
+ BOOST_CHECK_EQUAL(boost::size(polyhedral0), 0);
+
+ // Creating a polyhedral surface using standard initialized 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}}}};
+
+ // Modify polyhedral1 by adding a new polygon
+ polygon_t new_polygon = {{{0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1}, {0, 0, 1}}};
+ polyhedral1.push_back(new_polygon);
+ // Modify polyhedral1 by removing the last polygon
+ polyhedral1.pop_back();
+ // Modify polyhedral1 by changing the first point of the first polygon
+ polyhedral1[0].outer()[0] = point_t(0, 2, 0);
+
+ // Test that the polyhedral surface has 6 polygons
+ BOOST_CHECK_EQUAL(boost::size(polyhedral1), 6);
+
+ // Test that each polygon has 5 points
+ for (const auto& polygon : polyhedral1)
+ {
+ BOOST_CHECK_EQUAL(boost::size(polygon.outer()), 5);
+ }
+
+ // clear polyhedral surface
+ bg::clear(polyhedral1);
+ BOOST_CHECK_EQUAL(boost::size(polyhedral1), 0);
+
+ // read/write polyhedral surface wkt
+ polyhedral_t polyhedral2;
+ std::string 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)))";
+ bg::read_wkt(wkt, polyhedral2);
+ std::ostringstream oss;
+ oss << bg::wkt(polyhedral2);
+ BOOST_CHECK_EQUAL(oss.str(), wkt);
+
+ // Custom polyhedral surface
+ std::initializer_list IL = {{{{0, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0}, {0, 0, 0}}}};
+ bg::model::polyhedral_surface ps1(IL);
+ std::ostringstream out;
+ out << bg::wkt(ps1);
+ BOOST_CHECK_EQUAL(out.str(), "POLYHEDRALSURFACE(((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)))");
+ // Test that the polyhedral surface has 1 polygon
+ BOOST_CHECK_EQUAL(boost::size(ps1), 1);
+
+ // Test concepts
+ BOOST_CONCEPT_ASSERT( (bg::concepts::PolyhedralSurface) );
+ BOOST_CONCEPT_ASSERT( (bg::concepts::ConstPolyhedralSurface) );
+
+ return 0;
+}