-
Notifications
You must be signed in to change notification settings - Fork 218
/
Copy pathgeometry_of.cpp
154 lines (128 loc) · 4.4 KB
/
geometry_of.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright (c) 2010-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)
//
// Experiment using Proto to construct geometries
#include <vector>
#include <string>
#include <iostream>
#include <type_traits>
#include <boost/proto/core.hpp>
#include <boost/proto/transform.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
namespace bg = boost::geometry;
namespace proto = boost::proto;
using proto::_;
struct proto_geometry_tag {};
// Add a coordinate to a ring or linestring
struct append_point : proto::callable
{
template<typename Sig>
struct result;
template<typename This, typename Geometry, typename T1, typename T2>
struct result<This(Geometry, T1, T2)>
: std::add_reference<Geometry>
{};
template<typename Geometry, typename T1, typename T2>
Geometry& operator()(Geometry& geometry, T1 const& x, T2 const& y) const
{
typedef typename boost::geometry::point_type<Geometry>::type point;
point p;
boost::geometry::set<0>(p, x);
boost::geometry::set<1>(p, y);
geometry.push_back(p);
return geometry;
}
};
// The grammar for valid geometry expressions,
// and a transform that populates the geometry
struct geometry_grammar
: proto::or_
<
proto::when
<
proto::function
<
proto::terminal<proto_geometry_tag>
, proto::terminal<proto::convertible_to< double > >
, proto::terminal<proto::convertible_to< double > >
>
, append_point
(
proto::_data
, proto::_value(proto::_child1)
, proto::_value(proto::_child2)
)
>
, proto::when
<
proto::function
<
geometry_grammar
, proto::terminal<proto::convertible_to< double > >
, proto::terminal<proto::convertible_to< double > >
>
, append_point
(
geometry_grammar(proto::_child0)
, proto::_value(proto::_child1)
, proto::_value(proto::_child2)
)
>
>
{};
template<typename Expr>
struct proto_geometry_expression;
struct proto_geometry_domain
: proto::domain<proto::pod_generator<proto_geometry_expression>, geometry_grammar>
{};
// An expression wrapper that provides a conversion to a
// ring, that uses the geometry_grammar
template<typename Expr>
struct proto_geometry_expression
{
BOOST_PROTO_BASIC_EXTENDS(Expr, proto_geometry_expression, proto_geometry_domain)
BOOST_PROTO_EXTENDS_FUNCTION()
template <typename T>
operator T () const
{
BOOST_MPL_ASSERT((proto::matches<Expr, geometry_grammar>));
T geometry;
return geometry_grammar()(*this, 0, geometry);
}
// NOT finished, need more knowledge about Proto
template <typename T>
inline T inner() const
{
BOOST_MPL_ASSERT((proto::matches<Expr, geometry_grammar>));
T geometry;
return geometry_grammar()(*this, 0, geometry);
}
inline void inner()
{
}
};
int main()
{
proto_geometry_expression<proto::terminal<proto_geometry_tag>::type> const
geometry_of = {{{}}};
// Initialize a ring:
typedef bg::model::ring<bg::model::d2::point_xy<double> > ring_type;
ring_type ring = geometry_of(16, 1)(15,2)(14, 3)(13,4)(12, 3.14)(1,6);
std::cout << bg::wkt(ring) << std::endl;
// Initialize a line
typedef bg::model::linestring<bg::model::d2::point_xy<double> > line_type;
line_type line = geometry_of(1, 1)(2, 2)(3, 3);
std::cout << bg::wkt(line) << std::endl;
// For Polygon (not finished) it should be something like:
typedef bg::model::polygon<bg::model::d2::point_xy<double> > polygon_type;
//polygon_type polygon = geometry_of(0, 0)(0, 10)(10, 10)(10, 0)(0, 0).inner(2, 2)(2, 5)(5, 5)(5, 2)(2, 2);
//std::cout << bg::wkt(polygon) << std::endl;
return 0;
}