I would like to apply boost::geometry algorithms for the following immutable 2D model consisting of a point, polygon (open or closed), and polygonal domain class (with arbitrary number of holes) class, respectively, as shown below:
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/linestring.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/range.hpp>
#include <memory>
#include <vector>
namespace NGeometry {
class Point2D {
public:
Point2D( double x, double y ) : m_x( x ), m_y( y ) {}
double getX() const { return m_x; }
double getY() const { return m_y; }
private:
double m_x, m_y;
};
using TyPoints2D = std::vector< Point2D >;
// Either open (first point != last point) or closed (first point == last point) polygon
class Polygon2D {
public:
Polygon2D( TyPoints2D points ) : m_points( std::move( points ) ) {}
const TyPoints2D& getPoints() const { return m_points; }
private:
TyPoints2D m_points;
};
using TyPolygon2D = std::shared_ptr< Polygon2D >;
using TyPolygons2D = std::vector< TyPolygon2D >;
// Polygonal domain with outer cw oriented closed polygon and >= 0 ccw oriented inner polygons
class PolygonalDomain2D {
public:
PolygonalDomain2D( TyPolygon2D outer, TyPolygons2D inners )
: m_outer( std::move( outer ) ), m_inners( std::move( inners ) ) {}
const TyPolygon2D& getOuter() const { return m_outer; }
const TyPolygons2D& getInners() const { return m_inners; }
private:
TyPolygon2D m_outer;
TyPolygons2D m_inners;
};
} // namespace NGeometry
// Provide read only Boost.Range for Polygon2D
namespace boost {
template<>
struct range_const_iterator< NGeometry::Polygon2D >
{
typedef std::vector< NGeometry::Point2D >::const_iterator type;
};
template<>
struct range_value< NGeometry::Polygon2D >
{
typedef NGeometry::Point2D type;
};
} // namespace boost
inline std::vector< NGeometry::Point2D >::const_iterator range_begin( const NGeometry::Polygon2D polygon ) {
return polygon.getPoints().cbegin();
}
inline std::vector< NGeometry::Point2D >::const_iterator range_end( const NGeometry::Polygon2D polygon ) {
return polygon.getPoints().cend();
}
BOOST_GEOMETRY_REGISTER_POINT_2D_CONST( NGeometry::Point2D, double, cs::cartesian, getX(), getY() );
BOOST_GEOMETRY_REGISTER_LINESTRING( NGeometry::Polygon2D );
// How to register PolygonalDomain2D?
int main( int argc, char* argv[] )
{
NGeometry::Point2D point( 0.0, 0.0 );
auto outerPolygonSP = std::make_shared< NGeometry::Polygon2D >(
NGeometry::TyPoints2D { { -2.0, -2.0 }, { -2.0, 2.0 }, { 2.0, 2.0 }, { 2.0, -2.0 }, { -2.0, -2.0 } } );
auto innerPolygonSP = std::make_shared< NGeometry::Polygon2D >(
NGeometry::TyPoints2D { { -1.0, -1.0 }, { 1.0, -1.0 }, { 1.0, 1.0 }, { -1.0, 1.0 }, { -1.0, -1.0 } } );
NGeometry::PolygonalDomain2D domain( outerPolygonSP, { innerPolygonSP } );
double length = boost::geometry::length( *outerPolygonSP );
double area = boost::geometry::area( domain );
bool isInside = boost::geometry::within( point, domain );
return 0;
}
Compared to the first steps described in Problems in adapting a geometry object model using boost geometry classes have been revised and moved to the NGeometry namespace, which results in compiler errors about missing begin and end for NGeometry::Polygon2D. Furthermore, I do not know how to adapt the domain. I would be very grateful for any help.
g++ compiler output:
In file included from /usr/include/boost/geometry/core/closure.hpp:22,
from /usr/include/boost/geometry/geometry.hpp:25,
from /usr/include/boost/geometry.hpp:17,
from main.cpp:1:
/usr/include/boost/geometry/core/point_type.hpp: In instantiation of ‘struct boost::geometry::traits::point_type<NGeometry::PolygonalDomain2D>’:
/usr/include/boost/geometry/core/point_type.hpp:66:17: required from ‘struct boost::geometry::core_dispatch::point_type<void, NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/core/coordinate_system.hpp:58:59: required from ‘struct boost::geometry::core_dispatch::coordinate_system<void, NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/core/coordinate_system.hpp:93:17: required from ‘struct boost::geometry::coordinate_system<NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/core/cs.hpp:244:17: required from ‘struct boost::geometry::cs_tag<NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/strategies/area_result.hpp:59:8: required from ‘struct boost::geometry::area_result<NGeometry::PolygonalDomain2D, boost::geometry::default_strategy>’
/usr/include/boost/geometry/algorithms/area.hpp:320:1: required by substitution of ‘template<class Geometry> typename boost::geometry::area_result<Geometry, boost::geometry::default_strategy>::type boost::geometry::area(const Geometry&) [with Geometry = NGeometry::PolygonalDomain2D]’
main.cpp:78:48: required from here
/usr/include/boost/geometry/core/point_type.hpp:45:5: error: could not convert ‘boost::geometry::traits::point_type<NGeometry::PolygonalDomain2D>::NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE45::assert_arg()’ from ‘mpl_::failed************ (boost::geometry::traits::point_type<NGeometry::PolygonalDomain2D>::NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE::************)(mpl_::assert_::types<NGeometry::PolygonalDomain2D, mpl_::na, mpl_::na, mpl_::na>)’ to ‘mpl_::assert<false>::type’ {aka ‘mpl_::assert<false>’}
45 | BOOST_MPL_ASSERT_MSG
| ^
| |
| mpl_::failed************ (boost::geometry::traits::point_type<NGeometry::PolygonalDomain2D>::NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE::************)(mpl_::assert_::types<NGeometry::PolygonalDomain2D, mpl_::na, mpl_::na, mpl_::na>)
In file included from /usr/include/boost/geometry/core/coordinate_dimension.hpp:23,
from /usr/include/boost/geometry/geometry.hpp:26,
from /usr/include/boost/geometry.hpp:17,
from main.cpp:1:
/usr/include/boost/geometry/core/point_type.hpp: In instantiation of ‘struct boost::geometry::core_dispatch::point_type<void, NGeometry::PolygonalDomain2D>’:
/usr/include/boost/geometry/core/coordinate_system.hpp:58:59: required from ‘struct boost::geometry::core_dispatch::coordinate_system<void, NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/core/coordinate_system.hpp:93:17: required from ‘struct boost::geometry::coordinate_system<NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/core/cs.hpp:244:17: required from ‘struct boost::geometry::cs_tag<NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/strategies/area_result.hpp:59:8: required from ‘struct boost::geometry::area_result<NGeometry::PolygonalDomain2D, boost::geometry::default_strategy>’
/usr/include/boost/geometry/algorithms/area.hpp:320:1: required by substitution of ‘template<class Geometry> typename boost::geometry::area_result<Geometry, boost::geometry::default_strategy>::type boost::geometry::area(const Geometry&) [with Geometry = NGeometry::PolygonalDomain2D]’
main.cpp:78:48: required from here
/usr/include/boost/geometry/core/point_type.hpp:66:17: error: no type named ‘type’ in ‘struct boost::geometry::traits::point_type<NGeometry::PolygonalDomain2D>’
66 | >::type type;
| ^~~~
main.cpp: In function ‘int main(int, char**)’:
main.cpp:78:48: error: no matching function for call to ‘area(NGeometry::PolygonalDomain2D&)’
78 | double area = boost::geometry::area( domain );
| ^
In file included from /usr/include/boost/geometry/geometry.hpp:52,
from /usr/include/boost/geometry.hpp:17,
from main.cpp:1:
/usr/include/boost/geometry/algorithms/area.hpp:320:1: note: candidate: ‘template<class Geometry> typename boost::geometry::area_result<Geometry, boost::geometry::default_strategy>::type boost::geometry::area(const Geometry&)’
320 | area(Geometry const& geometry)
| ^~~~
/usr/include/boost/geometry/algorithms/area.hpp:320:1: note: substitution of deduced template arguments resulted in errors seen above
/usr/include/boost/geometry/algorithms/area.hpp:356:1: note: candidate: ‘template<class Geometry, class Strategy> typename boost::geometry::area_result<Geometry, Strategy>::type boost::geometry::area(const Geometry&, const Strategy&)’
356 | area(Geometry const& geometry, Strategy const& strategy)
| ^~~~
/usr/include/boost/geometry/algorithms/area.hpp:356:1: note: template argument deduction/substitution failed:
main.cpp:78:48: note: candidate expects 2 arguments, 1 provided
78 | double area = boost::geometry::area( domain );
| ^
In file included from /usr/include/boost/geometry/core/closure.hpp:22,
from /usr/include/boost/geometry/geometry.hpp:25,
from /usr/include/boost/geometry.hpp:17,
from main.cpp:1:
/usr/include/boost/geometry/algorithms/not_implemented.hpp: In instantiation of ‘struct boost::geometry::nyi::not_implemented_error<void, void, void>’:
/usr/include/boost/geometry/algorithms/not_implemented.hpp:108:8: required from ‘struct boost::geometry::not_implemented<void, void, void>’
/usr/include/boost/geometry/geometries/concepts/check.hpp:69:8: required from ‘struct boost::geometry::dispatch::check<const NGeometry::PolygonalDomain2D, void, true>’
/usr/include/boost/geometry/geometries/concepts/check.hpp:196:8: required from ‘struct boost::geometry::concepts::detail::checker<const NGeometry::PolygonalDomain2D>’
/usr/include/boost/geometry/geometries/concepts/check.hpp:219:31: required from ‘void boost::geometry::concepts::check() [with Geometry = const NGeometry::PolygonalDomain2D]’
/usr/include/boost/geometry/algorithms/detail/within/interface.hpp:108:41: required from ‘static bool boost::geometry::resolve_variant::within<Geometry1, Geometry2>::apply(const Geometry1&, const Geometry2&, const Strategy&) [with Strategy = boost::geometry::default_strategy; Geometry1 = NGeometry::Point2D; Geometry2 = NGeometry::PolygonalDomain2D]’
/usr/include/boost/geometry/algorithms/detail/within/interface.hpp:255:17: required from ‘bool boost::geometry::within(const Geometry1&, const Geometry2&) [with Geometry1 = NGeometry::Point2D; Geometry2 = NGeometry::PolygonalDomain2D]’
main.cpp:79:59: required from here
/usr/include/boost/geometry/algorithms/not_implemented.hpp:69:5: error: could not convert ‘boost::geometry::nyi::not_implemented_error<void, void, void>::THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED69::assert_arg()’ from ‘mpl_::failed************ (boost::geometry::nyi::not_implemented_error<void, void, void>::THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED::************)(mpl_::assert_::types<void, void, void, mpl_::na>)’ to ‘mpl_::assert<false>::type’ {aka ‘mpl_::assert<false>’}
69 | BOOST_MPL_ASSERT_MSG
| ^
| |
| mpl_::failed************ (boost::geometry::nyi::not_implemented_error<void, void, void>::THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED::************)(mpl_::assert_::types<void, void, void, mpl_::na>)
In file included from /usr/include/boost/geometry/core/coordinate_dimension.hpp:21,
from /usr/include/boost/geometry/geometry.hpp:26,
from /usr/include/boost/geometry.hpp:17,
from main.cpp:1:
/usr/include/boost/geometry/core/coordinate_dimension.hpp: In instantiation of ‘void boost::geometry::assert_dimension_equal() [with G1 = NGeometry::Point2D; G2 = NGeometry::PolygonalDomain2D]’:
/usr/include/boost/geometry/algorithms/detail/within/interface.hpp:109:53: required from ‘static bool boost::geometry::resolve_variant::within<Geometry1, Geometry2>::apply(const Geometry1&, const Geometry2&, const Strategy&) [with Strategy = boost::geometry::default_strategy; Geometry1 = NGeometry::Point2D; Geometry2 = NGeometry::PolygonalDomain2D]’
/usr/include/boost/geometry/algorithms/detail/within/interface.hpp:255:17: required from ‘bool boost::geometry::within(const Geometry1&, const Geometry2&) [with Geometry1 = NGeometry::Point2D; Geometry2 = NGeometry::PolygonalDomain2D]’
main.cpp:79:59: required from here
/usr/include/boost/geometry/core/coordinate_dimension.hpp:122:5: error: no type named ‘type’ in ‘struct boost::geometry::dimension<NGeometry::PolygonalDomain2D>’
122 | BOOST_STATIC_ASSERT(( static_cast<size_t>(dimension<G1>::type::value) == static_cast<size_t>(dimension<G2>::type::value) ));
| ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/range/functions.hpp:18,
from /usr/include/boost/range/iterator_range_core.hpp:38,
from /usr/include/boost/lexical_cast.hpp:30,
from /usr/include/boost/math/tools/convert_from_string.hpp:15,
from /usr/include/boost/math/constants/constants.hpp:13,
from /usr/include/boost/geometry/util/math.hpp:29,
from /usr/include/boost/geometry/core/radian_access.hpp:33,
from /usr/include/boost/geometry/geometry.hpp:42,
from /usr/include/boost/geometry.hpp:17,
from main.cpp:1:
/usr/include/boost/range/begin.hpp: In instantiation of ‘constexpr typename boost::range_iterator<T>::type boost::range_detail::range_begin(C&) [with C = const NGeometry::Polygon2D; typename boost::range_iterator<T>::type = __gnu_cxx::__normal_iterator<const NGeometry::Point2D*, std::vector<NGeometry::Point2D> >]’:
/usr/include/boost/range/begin.hpp:119:23: required from ‘void boost::SinglePassRangeConcept<T>::const_constraints(const Rng&) [with T = const NGeometry::Polygon2D; boost::SinglePassRangeConcept<T>::Rng = const NGeometry::Polygon2D]’
/usr/include/boost/range/concepts.hpp:295:13: required from ‘boost::SinglePassRangeConcept<T>::~SinglePassRangeConcept() [with T = const NGeometry::Polygon2D]’
/usr/include/boost/range/concepts.hpp:318:12: required from ‘static void boost::concepts::requirement<boost::concepts::failed************ Model::************>::failed() [with Model = boost::ForwardRangeConcept<const NGeometry::Polygon2D>]’
/usr/include/boost/geometry/geometries/concepts/linestring_concept.hpp:111:5: required from ‘class boost::geometry::concepts::ConstLinestring<const NGeometry::Polygon2D>’
/usr/include/boost/concept/detail/has_constraints.hpp:32:62: required by substitution of ‘template<class Model> boost::concepts::detail::yes boost::concepts::detail::has_constraints_(Model*, boost::concepts::detail::wrap_constraints<Model, (& Model::constraints)>*) [with Model = boost::geometry::concepts::ConstLinestring<const NGeometry::Polygon2D>]’
/usr/include/boost/concept/detail/has_constraints.hpp:42:5: [ skipping 3 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/concept_check.hpp:50:7: required from ‘class boost::geometry::detail::concept_check::check<boost::geometry::concepts::ConstLinestring<const NGeometry::Polygon2D> >’
/usr/include/boost/geometry/geometries/concepts/check.hpp:86:8: required from ‘struct boost::geometry::dispatch::check<const NGeometry::Polygon2D, boost::geometry::linestring_tag, true>’
/usr/include/boost/geometry/geometries/concepts/check.hpp:196:8: required from ‘struct boost::geometry::concepts::detail::checker<const NGeometry::Polygon2D>’
/usr/include/boost/geometry/geometries/concepts/check.hpp:219:31: required from ‘void boost::geometry::concepts::check() [with Geometry = const NGeometry::Polygon2D]’
/usr/include/boost/geometry/algorithms/length.hpp:282:36: required from ‘typename boost::geometry::default_length_result<Geometry>::type boost::geometry::length(const Geometry&) [with Geometry = NGeometry::Polygon2D; typename boost::geometry::default_length_result<Geometry>::type = long double]’
main.cpp:77:61: required from here
/usr/include/boost/range/concepts.hpp:301:46: in ‘constexpr’ expansion of ‘boost::range_adl_barrier::begin<NGeometry::Polygon2D>((* & const_range))’
/usr/include/boost/range/begin.hpp:49:18: error: ‘const class NGeometry::Polygon2D’ has no member named ‘begin’
49 | return c.begin();
| ~~^~~~~
In file included from /usr/include/boost/range/functions.hpp:19,
from /usr/include/boost/range/iterator_range_core.hpp:38,
from /usr/include/boost/lexical_cast.hpp:30,
from /usr/include/boost/math/tools/convert_from_string.hpp:15,
from /usr/include/boost/math/constants/constants.hpp:13,
from /usr/include/boost/geometry/util/math.hpp:29,
from /usr/include/boost/geometry/core/radian_access.hpp:33,
from /usr/include/boost/geometry/geometry.hpp:42,
from /usr/include/boost/geometry.hpp:17,
from main.cpp:1:
/usr/include/boost/range/end.hpp: In instantiation of ‘constexpr typename boost::range_iterator<T>::type boost::range_detail::range_end(C&) [with C = const NGeometry::Polygon2D; typename boost::range_iterator<T>::type = __gnu_cxx::__normal_iterator<const NGeometry::Point2D*, std::vector<NGeometry::Point2D> >]’:
/usr/include/boost/range/end.hpp:113:21: required from ‘void boost::SinglePassRangeConcept<T>::const_constraints(const Rng&) [with T = const NGeometry::Polygon2D; boost::SinglePassRangeConcept<T>::Rng = const NGeometry::Polygon2D]’
/usr/include/boost/range/concepts.hpp:295:13: required from ‘boost::SinglePassRangeConcept<T>::~SinglePassRangeConcept() [with T = const NGeometry::Polygon2D]’
/usr/include/boost/range/concepts.hpp:318:12: required from ‘static void boost::concepts::requirement<boost::concepts::failed************ Model::************>::failed() [with Model = boost::ForwardRangeConcept<const NGeometry::Polygon2D>]’
/usr/include/boost/geometry/geometries/concepts/linestring_concept.hpp:111:5: required from ‘class boost::geometry::concepts::ConstLinestring<const NGeometry::Polygon2D>’
/usr/include/boost/concept/detail/has_constraints.hpp:32:62: required by substitution of ‘template<class Model> boost::concepts::detail::yes boost::concepts::detail::has_constraints_(Model*, boost::concepts::detail::wrap_constraints<Model, (& Model::constraints)>*) [with Model = boost::geometry::concepts::ConstLinestring<const NGeometry::Polygon2D>]’
/usr/include/boost/concept/detail/has_constraints.hpp:42:5: [ skipping 3 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/concept_check.hpp:50:7: required from ‘class boost::geometry::detail::concept_check::check<boost::geometry::concepts::ConstLinestring<const NGeometry::Polygon2D> >’
/usr/include/boost/geometry/geometries/concepts/check.hpp:86:8: required from ‘struct boost::geometry::dispatch::check<const NGeometry::Polygon2D, boost::geometry::linestring_tag, true>’
/usr/include/boost/geometry/geometries/concepts/check.hpp:196:8: required from ‘struct boost::geometry::concepts::detail::checker<const NGeometry::Polygon2D>’
/usr/include/boost/geometry/geometries/concepts/check.hpp:219:31: required from ‘void boost::geometry::concepts::check() [with Geometry = const NGeometry::Polygon2D]’
/usr/include/boost/geometry/algorithms/length.hpp:282:36: required from ‘typename boost::geometry::default_length_result<Geometry>::type boost::geometry::length(const Geometry&) [with Geometry = NGeometry::Polygon2D; typename boost::geometry::default_length_result<Geometry>::type = long double]’
main.cpp:77:61: required from here
/usr/include/boost/range/concepts.hpp:302:44: in ‘constexpr’ expansion of ‘boost::range_adl_barrier::end<NGeometry::Polygon2D>((* & const_range))’
/usr/include/boost/range/end.hpp:50:22: error: ‘const class NGeometry::Polygon2D’ has no member named ‘end’
50 | return c.end();
| ~~^~~