~ubuntu-branches/ubuntu/saucy/merkaartor/saucy

« back to all changes in this revision

Viewing changes to include/ggl/algorithms/combine.hpp

Tags: upstream-0.15.3+svn20934
ImportĀ upstreamĀ versionĀ 0.15.3+svn20934

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Generic Geometry Library
2
 
//
3
 
// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
4
 
// Copyright Bruno Lalande 2008, 2009
5
 
// Use, modification and distribution is subject to the Boost Software License,
6
 
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7
 
// http://www.boost.org/LICENSE_1_0.txt)
8
 
 
9
 
#ifndef GGL_ALGORITHMS_COMBINE_HPP
10
 
#define GGL_ALGORITHMS_COMBINE_HPP
11
 
 
12
 
#include <cstddef>
13
 
 
14
 
#include <boost/numeric/conversion/cast.hpp>
15
 
 
16
 
#include <ggl/arithmetic/arithmetic.hpp>
17
 
#include <ggl/core/coordinate_dimension.hpp>
18
 
#include <ggl/core/concepts/box_concept.hpp>
19
 
#include <ggl/core/concepts/point_concept.hpp>
20
 
#include <ggl/util/assign_box_corner.hpp>
21
 
#include <ggl/util/select_coordinate_type.hpp>
22
 
 
23
 
/*!
24
 
\defgroup combine combine: add a geometry to a bounding box
25
 
\par Geometries:
26
 
- BOX + BOX -> BOX: the box will be combined with the other box \image html combine_box_box.png
27
 
- BOX + POINT -> BOX: the box will combined with the point  \image html combine_box_point.png
28
 
\note Previously called "grow"
29
 
*/
30
 
namespace ggl
31
 
{
32
 
 
33
 
#ifndef DOXYGEN_NO_DETAIL
34
 
namespace detail { namespace combine {
35
 
 
36
 
template
37
 
<
38
 
    typename Box, typename Point,
39
 
    std::size_t Dimension, std::size_t DimensionCount
40
 
>
41
 
struct point_loop
42
 
{
43
 
    typedef typename coordinate_type<Point>::type coordinate_type;
44
 
 
45
 
    static inline void apply(Box& box, Point const& source)
46
 
    {
47
 
        coordinate_type const coord = get<Dimension>(source);
48
 
 
49
 
        if (coord < get<min_corner, Dimension>(box))
50
 
        {
51
 
            set<min_corner, Dimension>(box, coord );
52
 
        }
53
 
 
54
 
        if (coord > get<max_corner, Dimension>(box))
55
 
        {
56
 
            set<max_corner, Dimension>(box, coord);
57
 
        }
58
 
 
59
 
        point_loop<Box, Point, Dimension + 1, DimensionCount>::apply(box, source);
60
 
    }
61
 
};
62
 
 
63
 
 
64
 
template
65
 
<
66
 
    typename Box, typename Point,
67
 
    std::size_t DimensionCount
68
 
>
69
 
struct point_loop<Box, Point, DimensionCount, DimensionCount>
70
 
{
71
 
    static inline void apply(Box&, Point const&) {}
72
 
};
73
 
 
74
 
 
75
 
template
76
 
<
77
 
    typename BoxIn, typename BoxOut,
78
 
    std::size_t Corner,
79
 
    std::size_t Dimension, std::size_t DimensionCount
80
 
>
81
 
struct box_loop
82
 
{
83
 
    typedef typename select_coordinate_type<BoxIn, BoxOut>::type coordinate_type;
84
 
 
85
 
    static inline void apply(BoxIn& box, BoxOut const& source)
86
 
    {
87
 
        coordinate_type const coord = get<Corner, Dimension>(source);
88
 
 
89
 
        if (coord < get<min_corner, Dimension>(box))
90
 
        {
91
 
            set<min_corner, Dimension>(box, coord);
92
 
        }
93
 
 
94
 
        if (coord > get<max_corner, Dimension>(box))
95
 
        {
96
 
            set<max_corner, Dimension>(box, coord);
97
 
        }
98
 
 
99
 
        box_loop
100
 
            <
101
 
                BoxIn, BoxOut, Corner, Dimension + 1, DimensionCount
102
 
            >::apply(box, source);
103
 
    }
104
 
};
105
 
 
106
 
 
107
 
template
108
 
<
109
 
    typename BoxIn, typename BoxOut,
110
 
    std::size_t Corner, std::size_t DimensionCount
111
 
>
112
 
struct box_loop<BoxIn, BoxOut, Corner, DimensionCount, DimensionCount>
113
 
{
114
 
    static inline void apply(BoxIn&, BoxOut const&) {}
115
 
};
116
 
 
117
 
 
118
 
// Changes a box b such that it also contains point p
119
 
template<typename Box, typename Point>
120
 
struct combine_box_with_point
121
 
    : point_loop<Box, Point, 0, dimension<Point>::type::value>
122
 
{};
123
 
 
124
 
 
125
 
// Changes a box such that the other box is also contained by the box
126
 
template<typename BoxOut, typename BoxIn>
127
 
struct combine_box_with_box
128
 
{
129
 
    static inline void apply(BoxOut& b, BoxIn const& other)
130
 
    {
131
 
        box_loop<BoxOut, BoxIn, min_corner, 0,
132
 
                    dimension<BoxIn>::type::value>::apply(b, other);
133
 
        box_loop<BoxOut, BoxIn, max_corner, 0,
134
 
                    dimension<BoxIn>::type::value>::apply(b, other);
135
 
    }
136
 
};
137
 
 
138
 
}} // namespace detail::combine
139
 
#endif // DOXYGEN_NO_DETAIL
140
 
 
141
 
#ifndef DOXYGEN_NO_DISPATCH
142
 
namespace dispatch
143
 
{
144
 
 
145
 
template <typename Tag, typename BoxOut, typename Geometry>
146
 
struct combine
147
 
{};
148
 
 
149
 
 
150
 
// Box + point -> new box containing also point
151
 
template <typename BoxOut, typename Point>
152
 
struct combine<point_tag, BoxOut, Point>
153
 
    : detail::combine::combine_box_with_point<BoxOut, Point>
154
 
{};
155
 
 
156
 
 
157
 
// Box + box -> new box containing two input boxes
158
 
template <typename BoxOut, typename BoxIn>
159
 
struct combine<box_tag, BoxOut, BoxIn>
160
 
    : detail::combine::combine_box_with_box<BoxOut, BoxIn>
161
 
{};
162
 
 
163
 
 
164
 
} // namespace dispatch
165
 
#endif // DOXYGEN_NO_DISPATCH
166
 
 
167
 
 
168
 
/*!
169
 
    \brief Combines a box with another geometry (box, point)
170
 
    \ingroup combine
171
 
    \tparam Box type of the box
172
 
    \tparam Geometry of second geometry, to be combined with the box
173
 
    \param box box to combine another geometry with, might be changed
174
 
    \param geometry other geometry
175
 
 */
176
 
template <typename Box, typename Geometry>
177
 
inline void combine(Box& box, Geometry const& geometry)
178
 
{
179
 
    assert_dimension_equal<Box, Geometry>();
180
 
    dispatch::combine
181
 
        <
182
 
            typename tag<Geometry>::type,
183
 
            Box, Geometry
184
 
        >::apply(box, geometry);
185
 
}
186
 
 
187
 
} // namespace ggl
188
 
 
189
 
#endif // GGL_COMBINE_HPP