• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

boostorg / geometry / 20212

28 Jul 2023 09:16AM UTC coverage: 94.211% (-0.2%) from 94.458%
20212

push

circle-ci

vissarion
Merge branch 'develop'

39303 of 41718 relevant lines covered (94.21%)

1319371.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.86
include/boost/geometry/algorithms/transform.hpp
1
// Boost.Geometry (aka GGL, Generic Geometry Library)
2

3
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
7

8
// This file was modified by Oracle on 2020-2023.
9
// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
10
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
11
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12

13
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
15

16
// Use, modification and distribution is subject to the Boost Software License,
17
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18
// http://www.boost.org/LICENSE_1_0.txt)
19

20
#ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
21
#define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
22

23
#include <type_traits>
24

25
#include <boost/range/begin.hpp>
26
#include <boost/range/end.hpp>
27
#include <boost/range/size.hpp>
28
#include <boost/range/value_type.hpp>
29

30
#include <boost/variant/static_visitor.hpp>
31
#include <boost/variant/variant_fwd.hpp>
32

33
#include <boost/geometry/algorithms/clear.hpp>
34
#include "boost/geometry/algorithms/detail/assign_indexed_point.hpp"
35
#include "boost/geometry/algorithms/detail/assign_values.hpp"
36
#include <boost/geometry/algorithms/num_interior_rings.hpp>
37

38
#include <boost/geometry/core/cs.hpp>
39
#include <boost/geometry/core/exterior_ring.hpp>
40
#include <boost/geometry/core/interior_rings.hpp>
41
#include <boost/geometry/core/mutable_range.hpp>
42
#include <boost/geometry/core/tag_cast.hpp>
43
#include <boost/geometry/core/tags.hpp>
44
#include <boost/geometry/geometries/concepts/check.hpp>
45
#include <boost/geometry/strategies/default_strategy.hpp>
46
#include <boost/geometry/strategies/transform.hpp>
47

48

49
namespace boost { namespace geometry
50
{
51

52
#ifndef DOXYGEN_NO_DETAIL
53
namespace detail { namespace transform
54
{
55

56
struct transform_point
57
{
58
    template <typename Point1, typename Point2, typename Strategy>
59
    static inline bool apply(Point1 const& p1, Point2& p2,
9,361,841✔
60
                Strategy const& strategy)
61
    {
62
        return strategy.apply(p1, p2);
9,361,841✔
63
    }
64
};
65

66

67
struct transform_box
68
{
69
    template <typename Box1, typename Box2, typename Strategy>
70
    static inline bool apply(Box1 const& b1, Box2& b2,
3✔
71
                Strategy const& strategy)
72
    {
73
        typedef typename point_type<Box1>::type point_type1;
74
        typedef typename point_type<Box2>::type point_type2;
75

76
        point_type1 lower_left, upper_right;
77
        geometry::detail::assign::assign_box_2d_corner<min_corner, min_corner>(
3✔
78
                    b1, lower_left);
79
        geometry::detail::assign::assign_box_2d_corner<max_corner, max_corner>(
3✔
80
                    b1, upper_right);
81

82
        point_type2 p1, p2;
83
        if (strategy.apply(lower_left, p1) && strategy.apply(upper_right, p2))
3✔
84
        {
85
            // Create a valid box and therefore swap if necessary
86
            typedef typename coordinate_type<point_type2>::type coordinate_type;
87
            coordinate_type x1 = geometry::get<0>(p1)
3✔
88
                    , y1  = geometry::get<1>(p1)
3✔
89
                    , x2  = geometry::get<0>(p2)
3✔
90
                    , y2  = geometry::get<1>(p2);
3✔
91

92
            if (x1 > x2) { std::swap(x1, x2); }
3✔
93
            if (y1 > y2) { std::swap(y1, y2); }
3✔
94

95
            geometry::set<min_corner, 0>(b2, x1);
3✔
96
            geometry::set<min_corner, 1>(b2, y1);
3✔
97
            geometry::set<max_corner, 0>(b2, x2);
3✔
98
            geometry::set<max_corner, 1>(b2, y2);
3✔
99

100
            return true;
3✔
101
        }
102
        return false;
×
103
    }
104
};
105

106
struct transform_box_or_segment
107
{
108
    template <typename Geometry1, typename Geometry2, typename Strategy>
109
    static inline bool apply(Geometry1 const& source, Geometry2& target,
3✔
110
                Strategy const& strategy)
111
    {
112
        typedef typename point_type<Geometry1>::type point_type1;
113
        typedef typename point_type<Geometry2>::type point_type2;
114

115
        point_type1 source_point[2];
9✔
116
        geometry::detail::assign_point_from_index<0>(source, source_point[0]);
3✔
117
        geometry::detail::assign_point_from_index<1>(source, source_point[1]);
3✔
118

119
        point_type2 target_point[2];
9✔
120
        if (strategy.apply(source_point[0], target_point[0])
3✔
121
            && strategy.apply(source_point[1], target_point[1]))
3✔
122
        {
123
            geometry::detail::assign_point_to_index<0>(target_point[0], target);
3✔
124
            geometry::detail::assign_point_to_index<1>(target_point[1], target);
3✔
125
            return true;
3✔
126
        }
127
        return false;
×
128
    }
129
};
130

131

132
template
133
<
134
    typename PointOut,
135
    typename OutputIterator,
136
    typename Range,
137
    typename Strategy
138
>
139
inline bool transform_range_out(Range const& range,
71✔
140
    OutputIterator out, Strategy const& strategy)
141
{
142
    PointOut point_out;
143
    for (auto it = boost::begin(range); it != boost::end(range); ++it)
339✔
144
    {
145
        if (! transform_point::apply(*it, point_out, strategy))
268✔
146
        {
147
            return false;
×
148
        }
149
        *out++ = point_out;
268✔
150
    }
151
    return true;
71✔
152
}
153

154

155
struct transform_polygon
156
{
157
    template <typename Polygon1, typename Polygon2, typename Strategy>
158
    static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,
17✔
159
                Strategy const& strategy)
160
    {
161
        typedef typename point_type<Polygon2>::type point2_type;
162

163
        geometry::clear(poly2);
17✔
164

165
        if (!transform_range_out<point2_type>(geometry::exterior_ring(poly1),
17✔
166
                    range::back_inserter(geometry::exterior_ring(poly2)), strategy))
17✔
167
        {
168
            return false;
×
169
        }
170

171
        // Note: here a resizeable container is assumed.
172
        traits::resize
173
            <
174
                typename std::remove_reference
175
                <
176
                    typename traits::interior_mutable_type<Polygon2>::type
177
                >::type
178
            >::apply(geometry::interior_rings(poly2),
17✔
179
                     geometry::num_interior_rings(poly1));
180

181
        auto const& rings1 = geometry::interior_rings(poly1);
17✔
182
        auto&& rings2 = geometry::interior_rings(poly2);
17✔
183

184
        auto it1 = boost::begin(rings1);
17✔
185
        auto it2 = boost::begin(rings2);
17✔
186
        for ( ; it1 != boost::end(rings1); ++it1, ++it2)
26✔
187
        {
188
            if ( ! transform_range_out<point2_type>(*it1,
9✔
189
                                                    range::back_inserter(*it2),
9✔
190
                                                    strategy) )
191
            {
192
                return false;
×
193
            }
194
        }
195

196
        return true;
17✔
197
    }
198
};
199

200

201
template <typename Point1, typename Point2>
202
struct select_strategy
203
{
204
    typedef typename strategy::transform::services::default_strategy
205
        <
206
            typename cs_tag<Point1>::type,
207
            typename cs_tag<Point2>::type,
208
            typename coordinate_system<Point1>::type,
209
            typename coordinate_system<Point2>::type,
210
            dimension<Point1>::type::value,
211
            dimension<Point2>::type::value,
212
            typename point_type<Point1>::type,
213
            typename point_type<Point2>::type
214
        >::type type;
215
};
216

217
struct transform_range
218
{
219
    template <typename Range1, typename Range2, typename Strategy>
220
    static inline bool apply(Range1 const& range1,
45✔
221
            Range2& range2, Strategy const& strategy)
222
    {
223
        typedef typename point_type<Range2>::type point_type;
224

225
        // Should NOT be done here!
226
        // geometry::clear(range2);
227
        return transform_range_out<point_type>(range1,
45✔
228
                range::back_inserter(range2), strategy);
45✔
229
    }
230
};
231

232

233
/*!
234
    \brief Is able to transform any multi-geometry, calling the single-version as policy
235
*/
236
template <typename Policy>
237
struct transform_multi
238
{
239
    template <typename Multi1, typename Multi2, typename S>
240
    static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy)
3✔
241
    {
242
        traits::resize<Multi2>::apply(multi2, boost::size(multi1));
3✔
243

244
        auto it1 = boost::begin(multi1);
3✔
245
        auto it2 = boost::begin(multi2);
3✔
246

247
        for (; it1 != boost::end(multi1); ++it1, ++it2)
7✔
248
        {
249
            if (! Policy::apply(*it1, *it2, strategy))
4✔
250
            {
251
                return false;
×
252
            }
253
        }
254

255
        return true;
3✔
256
    }
257
};
258

259

260
}} // namespace detail::transform
261
#endif // DOXYGEN_NO_DETAIL
262

263

264
#ifndef DOXYGEN_NO_DISPATCH
265
namespace dispatch
266
{
267

268
template
269
<
270
    typename Geometry1, typename Geometry2,
271
    typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
272
    typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type
273
>
274
struct transform {};
275

276
template <typename Point1, typename Point2>
277
struct transform<Point1, Point2, point_tag, point_tag>
278
    : detail::transform::transform_point
279
{
280
};
281

282

283
template <typename Linestring1, typename Linestring2>
284
struct transform
285
    <
286
        Linestring1, Linestring2,
287
        linestring_tag, linestring_tag
288
    >
289
    : detail::transform::transform_range
290
{
291
};
292

293
template <typename Range1, typename Range2>
294
struct transform<Range1, Range2, ring_tag, ring_tag>
295
    : detail::transform::transform_range
296
{
297
};
298

299
template <typename Polygon1, typename Polygon2>
300
struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>
301
    : detail::transform::transform_polygon
302
{
303
};
304

305
template <typename Box1, typename Box2>
306
struct transform<Box1, Box2, box_tag, box_tag>
307
    : detail::transform::transform_box
308
{
309
};
310

311
template <typename Segment1, typename Segment2>
312
struct transform<Segment1, Segment2, segment_tag, segment_tag>
313
    : detail::transform::transform_box_or_segment
314
{
315
};
316

317
template <typename Multi1, typename Multi2>
318
struct transform
319
    <
320
        Multi1, Multi2,
321
        multi_tag, multi_tag
322
    >
323
    : detail::transform::transform_multi
324
        <
325
            dispatch::transform
326
                <
327
                    typename boost::range_value<Multi1>::type,
328
                    typename boost::range_value<Multi2>::type
329
                >
330
        >
331
{};
332

333

334
} // namespace dispatch
335
#endif // DOXYGEN_NO_DISPATCH
336

337

338
namespace resolve_strategy {
339

340
struct transform
341
{
342
    template <typename Geometry1, typename Geometry2, typename Strategy>
343
    static inline bool apply(Geometry1 const& geometry1,
9,361,640✔
344
                             Geometry2& geometry2,
345
                             Strategy const& strategy)
346
    {
347
        concepts::check<Geometry1 const>();
9,361,640✔
348
        concepts::check<Geometry2>();
9,361,640✔
349

350
        return dispatch::transform<Geometry1, Geometry2>::apply(
9,361,640✔
351
            geometry1,
352
            geometry2,
353
            strategy
354
        );
9,361,640✔
355
    }
356

357
    template <typename Geometry1, typename Geometry2>
358
    static inline bool apply(Geometry1 const& geometry1,
9,361,536✔
359
                             Geometry2& geometry2,
360
                             default_strategy)
361
    {
362
        return apply(
18,723,050✔
363
            geometry1,
364
            geometry2,
365
            typename detail::transform::select_strategy<Geometry1, Geometry2>::type()
366
        );
18,723,050✔
367
    }
368
};
369

370
} // namespace resolve_strategy
371

372

373
namespace resolve_variant {
374

375
template <typename Geometry1, typename Geometry2>
376
struct transform
377
{
378
    template <typename Strategy>
379
    static inline bool apply(Geometry1 const& geometry1,
9,361,640✔
380
                             Geometry2& geometry2,
381
                             Strategy const& strategy)
382
    {
383
        return resolve_strategy::transform::apply(
9,361,640✔
384
            geometry1,
385
            geometry2,
386
            strategy
387
        );
9,361,640✔
388
    }
389
};
390

391
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
392
struct transform<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
393
{
394
    template <typename Strategy>
395
    struct visitor: static_visitor<bool>
396
    {
397
        Geometry2& m_geometry2;
398
        Strategy const& m_strategy;
399

400
        visitor(Geometry2& geometry2, Strategy const& strategy)
10✔
401
            : m_geometry2(geometry2)
402
            , m_strategy(strategy)
10✔
403
        {}
10✔
404

405
        template <typename Geometry1>
406
        inline bool operator()(Geometry1 const& geometry1) const
10✔
407
        {
408
            return transform<Geometry1, Geometry2>::apply(
10✔
409
                geometry1,
410
                m_geometry2,
411
                m_strategy
412
            );
10✔
413
        }
414
    };
415

416
    template <typename Strategy>
417
    static inline bool apply(
10✔
418
        boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
419
        Geometry2& geometry2,
420
        Strategy const& strategy
421
    )
422
    {
423
        return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
10✔
424
    }
425
};
426

427
} // namespace resolve_variant
428

429

430
/*!
431
\brief Transforms from one geometry to another geometry  \brief_strategy
432
\ingroup transform
433
\tparam Geometry1 \tparam_geometry
434
\tparam Geometry2 \tparam_geometry
435
\tparam Strategy strategy
436
\param geometry1 \param_geometry
437
\param geometry2 \param_geometry
438
\param strategy The strategy to be used for transformation
439
\return True if the transformation could be done
440

441
\qbk{distinguish,with strategy}
442

443
\qbk{[include reference/algorithms/transform_with_strategy.qbk]}
444
 */
445
template <typename Geometry1, typename Geometry2, typename Strategy>
446
inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
9,361,640✔
447
            Strategy const& strategy)
448
{
449
    return resolve_variant::transform<Geometry1, Geometry2>
450
                          ::apply(geometry1, geometry2, strategy);
9,361,640✔
451
}
452

453

454
/*!
455
\brief Transforms from one geometry to another geometry using a strategy
456
\ingroup transform
457
\tparam Geometry1 \tparam_geometry
458
\tparam Geometry2 \tparam_geometry
459
\param geometry1 \param_geometry
460
\param geometry2 \param_geometry
461
\return True if the transformation could be done
462

463
\qbk{[include reference/algorithms/transform.qbk]}
464
 */
465
template <typename Geometry1, typename Geometry2>
466
inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
9,361,536✔
467
{
468
    return geometry::transform(geometry1, geometry2, default_strategy());
9,361,536✔
469
}
470

471

472
}} // namespace boost::geometry
473

474

475
#endif // BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc