Coverage Report

Created: 2025-09-27 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/operation/overlayng/LineLimiter.cpp
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2020 Paul Ramsey <pramsey@cleverelephant.ca>
7
 *
8
 * This is free software; you can redistribute and/or modify it under
9
 * the terms of the GNU Lesser General Public Licence as published
10
 * by the Free Software Foundation.
11
 * See the COPYING file for more information.
12
 *
13
 **********************************************************************/
14
15
#include <geos/operation/overlayng/LineLimiter.h>
16
#include <geos/geom/CoordinateSequence.h>
17
#include <geos/geom/Envelope.h>
18
#include <geos/geom/Coordinate.h>
19
#include <geos/util.h>
20
21
#include <algorithm>
22
23
using geos::geom::CoordinateSequence;
24
25
namespace geos {      // geos
26
namespace operation { // geos.operation
27
namespace overlayng { // geos.operation.overlayng
28
29
/*public*/
30
std::vector<std::unique_ptr<CoordinateSequence>>&
31
LineLimiter::limit(const CoordinateSequence *pts)
32
2.00k
{
33
    // Reset for new limit run
34
2.00k
    lastOutside = nullptr;
35
2.00k
    ptList.reset(nullptr);
36
2.00k
    sections.clear();
37
38
535k
    for (std::size_t i = 0; i < pts->size(); i++) {
39
533k
        const Coordinate* p = &(pts->getAt(i));
40
533k
        if (limitEnv->intersects(*p)) {
41
369k
            addPoint(p);
42
369k
        }
43
164k
        else {
44
164k
            addOutside(p);
45
164k
        }
46
533k
    }
47
    // finish last section, if any
48
2.00k
    finishSection();
49
2.00k
    return sections;
50
2.00k
}
51
52
/*private*/
53
void
54
LineLimiter::addPoint(const Coordinate* p)
55
463k
{
56
463k
    startSection();
57
463k
    ptList->add(*p, false);
58
463k
}
59
60
/*private*/
61
void
62
LineLimiter::addOutside(const Coordinate* p)
63
164k
{
64
164k
    bool segIntersects = isLastSegmentIntersecting(p);
65
164k
    if (!segIntersects) {
66
95.3k
        finishSection();
67
95.3k
    }
68
68.6k
    else {
69
68.6k
        if(lastOutside != nullptr) {
70
24.9k
            addPoint(lastOutside);
71
24.9k
        }
72
68.6k
        addPoint(p);
73
68.6k
    }
74
164k
    lastOutside = p;
75
164k
}
76
77
/*private*/
78
bool
79
LineLimiter::isLastSegmentIntersecting(const Coordinate* p)
80
164k
{
81
164k
    if (lastOutside == nullptr) {
82
        // last point must have been inside
83
44.9k
        if (isSectionOpen())
84
43.7k
            return true;
85
1.15k
        return false;
86
44.9k
    }
87
119k
    return limitEnv->intersects(*lastOutside, *p);
88
164k
}
89
90
/*private*/
91
bool
92
LineLimiter::isSectionOpen()
93
605k
{
94
605k
    return ptList != nullptr;
95
605k
}
96
97
/*private*/
98
void
99
LineLimiter::startSection()
100
463k
{
101
463k
    if (!isSectionOpen()) {
102
26.1k
        ptList = detail::make_unique<CoordinateSequence>();
103
26.1k
    }
104
105
463k
    if (lastOutside != nullptr) {
106
68.9k
        ptList->add(*lastOutside, false);
107
68.9k
    }
108
463k
    lastOutside = nullptr;
109
463k
}
110
111
/*private*/
112
void
113
LineLimiter::finishSection()
114
97.3k
{
115
97.3k
    if (!isSectionOpen())
116
71.1k
        return;
117
118
    // finish off this section
119
26.1k
    if (lastOutside != nullptr) {
120
25.1k
        ptList->add(*lastOutside, false);
121
25.1k
        lastOutside = nullptr;
122
25.1k
    }
123
124
    // remove repeated points from the section
125
26.1k
    assert(!ptList->hasRepeatedPoints());
126
    //ptList->erase(std::unique(ptList->begin(), ptList->end()), ptList->end());
127
128
26.1k
    sections.emplace_back(ptList.release());
129
26.1k
    ptList.reset(nullptr);
130
26.1k
}
131
132
133
134
135
} // namespace geos.operation.overlayng
136
} // namespace geos.operation
137
} // namespace geos