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

boostorg / geometry / 22812

29 Oct 2024 01:18PM UTC coverage: 94.262% (-0.006%) from 94.268%
22812

push

circleci

vissarion
Merge branch 'develop'

39179 of 41564 relevant lines covered (94.26%)

1327940.85 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,362,734✔
60
                Strategy const& strategy)
61
    {
62
        return strategy.apply(p1, p2);
9,362,734✔
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
        using point_type1 = point_type_t<Box1>;
74
        using point_type2 = point_type_t<Box2>;
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
            using coordinate_type = coordinate_type_t<point_type2>;
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
        point_type_t<Geometry1> source_point[2];
9✔
113
        geometry::detail::assign_point_from_index<0>(source, source_point[0]);
3✔
114
        geometry::detail::assign_point_from_index<1>(source, source_point[1]);
3✔
115

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

128

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

151

152
struct transform_polygon
153
{
154
    template <typename Polygon1, typename Polygon2, typename Strategy>
155
    static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,
17✔
156
                Strategy const& strategy)
157
    {
158
        using point2_type = point_type_t<Polygon2>;
159

160
        geometry::clear(poly2);
17✔
161

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

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

178
        auto const& rings1 = geometry::interior_rings(poly1);
17✔
179
        auto&& rings2 = geometry::interior_rings(poly2);
17✔
180

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

193
        return true;
17✔
194
    }
195
};
196

197

198
template <typename Geometry1, typename Geometry2>
199
struct select_strategy
200
{
201
    using type = typename strategy::transform::services::default_strategy
202
        <
203
            cs_tag_t<Geometry1>,
204
            cs_tag_t<Geometry2>,
205
            coordinate_system_t<Geometry1>,
206
            coordinate_system_t<Geometry2>,
207
            dimension<Geometry1>::value,
208
            dimension<Geometry2>::value,
209
            point_type_t<Geometry1>,
210
            point_type_t<Geometry2>
211
        >::type;
212
};
213

214
struct transform_range
215
{
216
    template <typename Range1, typename Range2, typename Strategy>
217
    static inline bool apply(Range1 const& range1,
45✔
218
            Range2& range2, Strategy const& strategy)
219
    {
220
        // "clear" should NOT be done here!
221
        // geometry::clear(range2);
222
        return transform_range_out<point_type_t<Range2>>(range1,
45✔
223
                range::back_inserter(range2), strategy);
45✔
224
    }
225
};
226

227

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

239
        auto it1 = boost::begin(multi1);
3✔
240
        auto it2 = boost::begin(multi2);
3✔
241

242
        for (; it1 != boost::end(multi1); ++it1, ++it2)
7✔
243
        {
244
            if (! Policy::apply(*it1, *it2, strategy))
4✔
245
            {
246
                return false;
×
247
            }
248
        }
249

250
        return true;
3✔
251
    }
252
};
253

254

255
}} // namespace detail::transform
256
#endif // DOXYGEN_NO_DETAIL
257

258

259
#ifndef DOXYGEN_NO_DISPATCH
260
namespace dispatch
261
{
262

263
template
264
<
265
    typename Geometry1, typename Geometry2,
266
    typename Tag1 = tag_cast_t<tag_t<Geometry1>, multi_tag>,
267
    typename Tag2 = tag_cast_t<tag_t<Geometry2>, multi_tag>
268
>
269
struct transform {};
270

271
template <typename Point1, typename Point2>
272
struct transform<Point1, Point2, point_tag, point_tag>
273
    : detail::transform::transform_point
274
{
275
};
276

277

278
template <typename Linestring1, typename Linestring2>
279
struct transform
280
    <
281
        Linestring1, Linestring2,
282
        linestring_tag, linestring_tag
283
    >
284
    : detail::transform::transform_range
285
{
286
};
287

288
template <typename Range1, typename Range2>
289
struct transform<Range1, Range2, ring_tag, ring_tag>
290
    : detail::transform::transform_range
291
{
292
};
293

294
template <typename Polygon1, typename Polygon2>
295
struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>
296
    : detail::transform::transform_polygon
297
{
298
};
299

300
template <typename Box1, typename Box2>
301
struct transform<Box1, Box2, box_tag, box_tag>
302
    : detail::transform::transform_box
303
{
304
};
305

306
template <typename Segment1, typename Segment2>
307
struct transform<Segment1, Segment2, segment_tag, segment_tag>
308
    : detail::transform::transform_box_or_segment
309
{
310
};
311

312
template <typename Multi1, typename Multi2>
313
struct transform
314
    <
315
        Multi1, Multi2,
316
        multi_tag, multi_tag
317
    >
318
    : detail::transform::transform_multi
319
        <
320
            dispatch::transform
321
                <
322
                    typename boost::range_value<Multi1>::type,
323
                    typename boost::range_value<Multi2>::type
324
                >
325
        >
326
{};
327

328

329
} // namespace dispatch
330
#endif // DOXYGEN_NO_DISPATCH
331

332

333
namespace resolve_strategy {
334

335
struct transform
336
{
337
    template <typename Geometry1, typename Geometry2, typename Strategy>
338
    static inline bool apply(Geometry1 const& geometry1,
9,362,533✔
339
                             Geometry2& geometry2,
340
                             Strategy const& strategy)
341
    {
342
        concepts::check<Geometry1 const>();
9,362,533✔
343
        concepts::check<Geometry2>();
9,362,533✔
344

345
        return dispatch::transform<Geometry1, Geometry2>::apply(
9,362,533✔
346
            geometry1,
347
            geometry2,
348
            strategy
349
        );
9,362,533✔
350
    }
351

352
    template <typename Geometry1, typename Geometry2>
353
    static inline bool apply(Geometry1 const& geometry1,
9,362,429✔
354
                             Geometry2& geometry2,
355
                             default_strategy)
356
    {
357
        return apply(
18,724,836✔
358
            geometry1,
359
            geometry2,
360
            typename detail::transform::select_strategy<Geometry1, Geometry2>::type()
361
        );
18,724,836✔
362
    }
363
};
364

365
} // namespace resolve_strategy
366

367

368
namespace resolve_variant {
369

370
template <typename Geometry1, typename Geometry2>
371
struct transform
372
{
373
    template <typename Strategy>
374
    static inline bool apply(Geometry1 const& geometry1,
9,362,533✔
375
                             Geometry2& geometry2,
376
                             Strategy const& strategy)
377
    {
378
        return resolve_strategy::transform::apply(
9,362,533✔
379
            geometry1,
380
            geometry2,
381
            strategy
382
        );
9,362,533✔
383
    }
384
};
385

386
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
387
struct transform<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
388
{
389
    template <typename Strategy>
390
    struct visitor: static_visitor<bool>
391
    {
392
        Geometry2& m_geometry2;
393
        Strategy const& m_strategy;
394

395
        visitor(Geometry2& geometry2, Strategy const& strategy)
10✔
396
            : m_geometry2(geometry2)
397
            , m_strategy(strategy)
10✔
398
        {}
10✔
399

400
        template <typename Geometry1>
401
        inline bool operator()(Geometry1 const& geometry1) const
10✔
402
        {
403
            return transform<Geometry1, Geometry2>::apply(
10✔
404
                geometry1,
405
                m_geometry2,
406
                m_strategy
407
            );
10✔
408
        }
409
    };
410

411
    template <typename Strategy>
412
    static inline bool apply(
10✔
413
        boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
414
        Geometry2& geometry2,
415
        Strategy const& strategy
416
    )
417
    {
418
        return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
10✔
419
    }
420
};
421

422
} // namespace resolve_variant
423

424

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

436
\qbk{distinguish,with strategy}
437

438
\qbk{[include reference/algorithms/transform_with_strategy.qbk]}
439
 */
440
template <typename Geometry1, typename Geometry2, typename Strategy>
441
inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
9,362,533✔
442
            Strategy const& strategy)
443
{
444
    return resolve_variant::transform<Geometry1, Geometry2>
445
                          ::apply(geometry1, geometry2, strategy);
9,362,533✔
446
}
447

448

449
/*!
450
\brief Transforms from one geometry to another geometry using a strategy
451
\ingroup transform
452
\tparam Geometry1 \tparam_geometry
453
\tparam Geometry2 \tparam_geometry
454
\param geometry1 \param_geometry
455
\param geometry2 \param_geometry
456
\return True if the transformation could be done
457

458
\qbk{[include reference/algorithms/transform.qbk]}
459
 */
460
template <typename Geometry1, typename Geometry2>
461
inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
9,362,429✔
462
{
463
    return geometry::transform(geometry1, geometry2, default_strategy());
9,362,429✔
464
}
465

466

467
}} // namespace boost::geometry
468

469

470
#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