Coverage Report

Created: 2025-03-15 06:58

/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.57k
{
33
    // Reset for new limit run
34
2.57k
    lastOutside = nullptr;
35
2.57k
    ptList.reset(nullptr);
36
2.57k
    sections.clear();
37
38
948k
    for (std::size_t i = 0; i < pts->size(); i++) {
39
946k
        const Coordinate* p = &(pts->getAt(i));
40
946k
        if (limitEnv->intersects(*p)) {
41
685k
            addPoint(p);
42
685k
        }
43
261k
        else {
44
261k
            addOutside(p);
45
261k
        }
46
946k
    }
47
    // finish last section, if any
48
2.57k
    finishSection();
49
2.57k
    return sections;
50
2.57k
}
51
52
/*private*/
53
void
54
LineLimiter::addPoint(const Coordinate* p)
55
835k
{
56
835k
    startSection();
57
835k
    ptList->add(*p, false);
58
835k
}
59
60
/*private*/
61
void
62
LineLimiter::addOutside(const Coordinate* p)
63
261k
{
64
261k
    bool segIntersects = isLastSegmentIntersecting(p);
65
261k
    if (!segIntersects) {
66
147k
        finishSection();
67
147k
    }
68
113k
    else {
69
113k
        if(lastOutside != nullptr) {
70
36.2k
            addPoint(lastOutside);
71
36.2k
        }
72
113k
        addPoint(p);
73
113k
    }
74
261k
    lastOutside = p;
75
261k
}
76
77
/*private*/
78
bool
79
LineLimiter::isLastSegmentIntersecting(const Coordinate* p)
80
261k
{
81
261k
    if (lastOutside == nullptr) {
82
        // last point must have been inside
83
79.5k
        if (isSectionOpen())
84
77.6k
            return true;
85
1.89k
        return false;
86
79.5k
    }
87
181k
    return limitEnv->intersects(*lastOutside, *p);
88
261k
}
89
90
/*private*/
91
bool
92
LineLimiter::isSectionOpen()
93
1.06M
{
94
1.06M
    return ptList != nullptr;
95
1.06M
}
96
97
/*private*/
98
void
99
LineLimiter::startSection()
100
835k
{
101
835k
    if (!isSectionOpen()) {
102
42.8k
        ptList = detail::make_unique<CoordinateSequence>();
103
42.8k
    }
104
105
835k
    if (lastOutside != nullptr) {
106
114k
        ptList->add(*lastOutside, false);
107
114k
    }
108
835k
    lastOutside = nullptr;
109
835k
}
110
111
/*private*/
112
void
113
LineLimiter::finishSection()
114
149k
{
115
149k
    if (!isSectionOpen())
116
106k
        return;
117
118
    // finish off this section
119
42.8k
    if (lastOutside != nullptr) {
120
41.8k
        ptList->add(*lastOutside, false);
121
41.8k
        lastOutside = nullptr;
122
41.8k
    }
123
124
    // remove repeated points from the section
125
42.8k
    assert(!ptList->hasRepeatedPoints());
126
    //ptList->erase(std::unique(ptList->begin(), ptList->end()), ptList->end());
127
128
42.8k
    sections.emplace_back(ptList.release());
129
42.8k
    ptList.reset(nullptr);
130
42.8k
}
131
132
133
134
135
} // namespace geos.operation.overlayng
136
} // namespace geos.operation
137
} // namespace geos