Coverage Report

Created: 2026-01-17 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/simplify/LinkedLine.cpp
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2022 Paul Ramsey <pramsey@cleverelephant.ca>
7
 * Copyright (c) 2022 Martin Davis.
8
 *
9
 * This is free software; you can redistribute and/or modify it under
10
 * the terms of the GNU Lesser General Public Licence as published
11
 * by the Free Software Foundation.
12
 * See the COPYING file for more information.
13
 *
14
 **********************************************************************/
15
16
#include <geos/simplify/LinkedLine.h>
17
18
#include <geos/geom/Coordinate.h>
19
#include <geos/geom/CoordinateSequence.h>
20
#include <geos/io/WKTWriter.h>
21
#include <geos/constants.h>
22
23
using geos::geom::Coordinate;
24
using geos::geom::CoordinateSequence;
25
using geos::io::WKTWriter;
26
27
28
namespace geos {
29
namespace simplify { // geos.simplify
30
31
32
LinkedLine::LinkedLine(const CoordinateSequence& pts)
33
0
    : m_coord(pts)
34
0
    , m_isRing(pts.isRing())
35
0
    , m_size(pts.isRing() ? pts.size() - 1 : pts.size())
36
0
{
37
0
    createNextLinks(m_size);
38
0
    createPrevLinks(m_size);
39
0
}
40
41
42
/* public */
43
bool
44
LinkedLine::isRing() const
45
0
{
46
0
    return m_isRing;
47
0
}
48
49
/* public */
50
bool
51
LinkedLine::isCorner(std::size_t i) const
52
0
{
53
0
    if (! isRing()
54
0
        && (i == 0 || i == m_coord.size() - 1))
55
0
    {
56
0
        return false;
57
0
    }
58
0
    return true;
59
0
}
60
61
/* private */
62
void
63
LinkedLine::createNextLinks(std::size_t size)
64
0
{
65
0
    m_next.resize(size);
66
0
    for (std::size_t i = 0; i < size; i++) {
67
0
      m_next[i] = i + 1;
68
0
    }
69
0
    m_next[size - 1] = m_isRing ? 0 : NO_COORD_INDEX;
70
0
    return;
71
0
}
72
73
/* private */
74
void
75
LinkedLine::createPrevLinks(std::size_t size)
76
0
{
77
0
    m_prev.resize(size);
78
0
    for (std::size_t i = 1; i < size; i++) {
79
0
      m_prev[i] = i - 1;
80
0
    }
81
0
    m_prev[0] = m_isRing ? size - 1 : NO_COORD_INDEX;
82
0
    return;
83
0
}
84
85
/* public */
86
std::size_t
87
LinkedLine::size() const
88
0
{
89
0
    return m_size;
90
0
}
91
92
/* public */
93
std::size_t
94
LinkedLine::next(std::size_t i) const
95
0
{
96
0
    return m_next[i];
97
0
}
98
99
/* public */
100
std::size_t
101
LinkedLine::prev(std::size_t i) const
102
0
{
103
0
    return m_prev[i];
104
0
}
105
106
/* public */
107
const Coordinate&
108
LinkedLine::getCoordinate(std::size_t index) const
109
0
{
110
0
    return m_coord.getAt(index);
111
0
}
112
113
/* public */
114
const Coordinate&
115
LinkedLine::prevCoordinate(std::size_t index) const
116
0
{
117
0
    return m_coord.getAt(prev(index));
118
0
}
119
120
/* public */
121
const Coordinate&
122
LinkedLine::nextCoordinate(std::size_t index) const
123
0
{
124
0
    return m_coord.getAt(next(index));
125
0
}
126
127
/* public */
128
bool
129
LinkedLine::hasCoordinate(std::size_t index) const
130
0
{
131
    //-- if not a ring, endpoints are always present
132
0
    if (! m_isRing && (index == 0 || index == m_coord.size() - 1))
133
0
        return true;
134
135
0
    return index != NO_COORD_INDEX
136
0
        && index < m_prev.size()
137
0
        && m_prev[index] != NO_COORD_INDEX;
138
0
}
139
140
/* public */
141
void
142
LinkedLine::remove(std::size_t index)
143
0
{
144
0
    std::size_t iprev = m_prev[index];
145
0
    std::size_t inext = m_next[index];
146
0
    if (iprev != NO_COORD_INDEX)
147
0
        m_next[iprev] = inext;
148
0
    if (inext != NO_COORD_INDEX)
149
0
        m_prev[inext] = iprev;
150
0
    m_prev[index] = NO_COORD_INDEX;
151
0
    m_next[index] = NO_COORD_INDEX;
152
0
    m_size = m_size > 0 ? m_size - 1 : m_size;
153
0
}
154
155
/* public */
156
std::unique_ptr<CoordinateSequence>
157
LinkedLine::getCoordinates() const
158
0
{
159
0
    std::unique_ptr<CoordinateSequence> coords(new CoordinateSequence());
160
0
    std::size_t len = m_isRing ? m_coord.size() - 1 : m_coord.size();
161
0
    for (std::size_t i = 0; i < len; i++) {
162
0
        if (hasCoordinate(i)) {
163
0
            coords->add(m_coord.getAt(i), false);
164
0
        }
165
0
    }
166
0
    if (m_isRing) {
167
0
        coords->closeRing();
168
0
    }
169
0
    return coords;
170
0
}
171
172
std::ostream&
173
operator<< (std::ostream& os, const LinkedLine& ll)
174
0
{
175
0
    auto cs = ll.getCoordinates();
176
0
    os << WKTWriter::toLineString(*cs);
177
0
    return os;
178
0
}
179
180
181
182
} // namespace geos.simplify
183
} // namespace geos