• 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

98.57
include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
1
// Boost.Geometry (aka GGL, Generic Geometry Library)
2

3
// Copyright (c) 2014-2023, Oracle and/or its affiliates.
4

5
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
6
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
8

9
// Licensed under the Boost Software License version 1.0.
10
// http://www.boost.org/users/license.html
11

12
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP
13
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP
14

15
#include <cstddef>
16

17
#include <set>
18
#include <stack>
19
#include <utility>
20
#include <vector>
21

22
#include <boost/core/addressof.hpp>
23

24
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
25
#include <boost/geometry/core/assert.hpp>
26
#include <boost/geometry/policies/compare.hpp>
27

28

29
namespace boost { namespace geometry
30
{
31

32
namespace detail { namespace is_valid
33
{
34

35

36
template <typename TurnPoint, typename Strategy>
37
class complement_graph_vertex
38
{
39
public:
40
    complement_graph_vertex(std::size_t id)
2,614✔
41
        : m_id(id)
42
        , m_turn_point(NULL)
2,614✔
43
    {}
2,614✔
44

45
    complement_graph_vertex(TurnPoint const* turn_point,
1,307✔
46
                            std::size_t expected_id)
47
        : m_id(expected_id)
48
        , m_turn_point(turn_point)
1,307✔
49
    {}
1,307✔
50

51
    inline std::size_t id() const { return m_id; }
47,369✔
52

53
    inline bool operator<(complement_graph_vertex const& other) const
13,371✔
54
    {
55
        if ( m_turn_point != NULL && other.m_turn_point != NULL )
13,371✔
56
        {
57
            return geometry::less
58
                <
59
                    TurnPoint, -1, Strategy
60
                >()(*m_turn_point, *other.m_turn_point);
2,247✔
61
        }
62
        if ( m_turn_point == NULL && other.m_turn_point == NULL )
11,124✔
63
        {
64
            return m_id < other.m_id;
7,048✔
65
        }
66
        return m_turn_point == NULL;
4,076✔
67
    }
68

69
private:
70
    // the value of m_turn_point determines the type of the vertex
71
    // non-NULL: vertex corresponds to an IP
72
    // NULL    : vertex corresponds to a hole or outer space, and the id
73
    //           is the ring id of the corresponding ring of the polygon
74
    std::size_t m_id;
75
    TurnPoint const* m_turn_point;
76
};
77

78

79

80

81
template <typename TurnPoint, typename Strategy>
82
class complement_graph
83
{
84
private:
85
    typedef complement_graph_vertex<TurnPoint, Strategy> vertex;
86
    typedef std::set<vertex> vertex_container;
87

88
public:
89
    typedef typename vertex_container::const_iterator vertex_handle;
90

91
private:
92
    struct vertex_handle_less
93
    {
94
        inline bool operator()(vertex_handle v1, vertex_handle v2) const
8,148✔
95
        {
96
            return v1->id() < v2->id();
8,148✔
97
        }
98
    };
99

100
    typedef std::set<vertex_handle, vertex_handle_less> neighbor_container;
101

102
    class has_cycles_dfs_data
103
    {
104
    public:
105
        has_cycles_dfs_data(std::size_t num_nodes)
9,534✔
106
            : m_visited(num_nodes, false)
×
107
            , m_parent_id(num_nodes, -1)
9,534✔
108
        {}
9,534✔
109

110
        inline signed_size_type parent_id(vertex_handle v) const
3,738✔
111
        {
112
            return m_parent_id[v->id()];
3,738✔
113
        }
114

115
        inline void set_parent_id(vertex_handle v, signed_size_type id)
1,971✔
116
        {
117
            m_parent_id[v->id()] = id;
1,971✔
118
        }
1,971✔
119

120
        inline bool visited(vertex_handle v) const
3,860✔
121
        {
122
            return m_visited[v->id()];
3,860✔
123
        }
124

125
        inline void set_visited(vertex_handle v, bool value)
2,315✔
126
        {
127
            m_visited[v->id()] = value;
2,315✔
128
        }
2,315✔
129
    private:
130
        std::vector<bool> m_visited;
131
        std::vector<signed_size_type> m_parent_id;
132
    };
133

134

135
    inline bool has_cycles(vertex_handle start_vertex,
548✔
136
                           has_cycles_dfs_data& data) const
137
    {
138
        std::stack<vertex_handle> stack;
1,096✔
139
        stack.push(start_vertex);
548✔
140

141
        while ( !stack.empty() )
2,747✔
142
        {
143
            vertex_handle v = stack.top();
2,315✔
144
            stack.pop();
2,315✔
145

146
            data.set_visited(v, true);
2,315✔
147
            for (typename neighbor_container::const_iterator nit
5,937✔
148
                     = m_neighbors[v->id()].begin();
2,315✔
149
                 nit != m_neighbors[v->id()].end(); ++nit)
9,559✔
150
            {
151
                if ( static_cast<signed_size_type>((*nit)->id()) != data.parent_id(v) )
3,738✔
152
                {
153
                    if ( data.visited(*nit) )
2,087✔
154
                    {
155
                        return true;
116✔
156
                    }
157
                    else
158
                    {
159
                        data.set_parent_id(*nit, static_cast<signed_size_type>(v->id()));
1,971✔
160
                        stack.push(*nit);
1,971✔
161
                    }
162
                }
163
            }
164
        }
165
        return false;
432✔
166
    }
167

168
public:
169
    // num_rings: total number of rings, including the exterior ring
170
    complement_graph(std::size_t num_rings)
9,534✔
171
        : m_num_rings(num_rings)
172
        , m_num_turns(0)
173
        , m_vertices()
174
        , m_neighbors(num_rings)
9,534✔
175
    {}
9,534✔
176

177
    // inserts a ring vertex in the graph and returns its handle
178
    // ring id's are zero-based (so the first interior ring has id 1)
179
    inline vertex_handle add_vertex(signed_size_type id)
2,614✔
180
    {
181
        return m_vertices.insert(vertex(static_cast<std::size_t>(id))).first;
2,614✔
182
    }
183

184
    // inserts an IP in the graph and returns its id
185
    inline vertex_handle add_vertex(TurnPoint const& turn_point)
1,307✔
186
    {
187
        std::pair<vertex_handle, bool> res
1,307✔
188
            = m_vertices.insert(vertex(boost::addressof(turn_point),
189
                                       m_num_rings + m_num_turns)
1,307✔
190
                                );
191

192
        if ( res.second )
1,307✔
193
        {
194
            // a new element is inserted
195
            m_neighbors.push_back(neighbor_container());
909✔
196
            ++m_num_turns;
909✔
197
        }
198
        return res.first;
1,307✔
199
    }
200

201
    inline void add_edge(vertex_handle v1, vertex_handle v2)
2,614✔
202
    {
203
        BOOST_GEOMETRY_ASSERT( v1 != m_vertices.end() );
2,614✔
204
        BOOST_GEOMETRY_ASSERT( v2 != m_vertices.end() );
2,614✔
205
        m_neighbors[v1->id()].insert(v2);
2,614✔
206
        m_neighbors[v2->id()].insert(v1);
2,614✔
207
    }
2,614✔
208

209
    inline bool has_cycles() const
9,534✔
210
    {
211
        // initialize all vertices as non-visited and with no parent set
212
        // this is done by the constructor of has_cycles_dfs_data
213
        has_cycles_dfs_data data(m_num_rings + m_num_turns);
19,068✔
214

215
        // for each non-visited vertex, start a DFS from that vertex
216
        for (vertex_handle it = m_vertices.begin();
11,191✔
217
             it != m_vertices.end(); ++it)
12,848✔
218
        {
219
            if ( !data.visited(it) && has_cycles(it, data) )
1,773✔
220
            {
221
                return true;
116✔
222
            }
223
        }
224
        return false;
9,418✔
225
    }
226

227
#ifdef BOOST_GEOMETRY_TEST_DEBUG
228
    template <typename OutputStream>
229
    friend inline
230
    void debug_print_complement_graph(OutputStream&,
231
                                      complement_graph<TurnPoint, Strategy> const&);
232
#endif // BOOST_GEOMETRY_TEST_DEBUG
233

234
private:
235
    std::size_t m_num_rings, m_num_turns;
236
    vertex_container m_vertices;
237
    std::vector<neighbor_container> m_neighbors;
238
};
239

240

241
}} // namespace detail::is_valid
242

243
}} // namespace boost::geometry
244

245
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_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