Coverage Report

Created: 2026-06-10 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/geom/CurvePolygon.cpp
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2024 ISciences, LLC
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/algorithm/Area.h>
16
#include <geos/geom/Curve.h>
17
#include <geos/geom/CurvePolygon.h>
18
#include <geos/geom/CoordinateSequence.h>
19
#include <geos/geom/GeometryFactory.h>
20
#include <geos/geom/LineString.h>
21
#include <geos/geom/MultiCurve.h>
22
#include <geos/geom/SimpleCurve.h>
23
#include <geos/util/UnsupportedOperationException.h>
24
25
namespace geos {
26
namespace geom {
27
28
    std::unique_ptr<CoordinateSequence>
29
    CurvePolygon::getCoordinates() const
30
0
    {
31
0
        auto coordinates = shell->getCoordinates();
32
0
        for (const auto& hole : holes) {
33
0
            if (auto simpleHole = dynamic_cast<const SimpleCurve*>(hole.get())) {
34
0
                coordinates->add(*simpleHole->getCoordinatesRO());
35
0
            } else {
36
0
                coordinates->add(*hole->getCoordinates());
37
0
            }
38
0
        }
39
0
        return coordinates;
40
0
    }
41
42
60
    std::string CurvePolygon::getGeometryType() const {
43
60
        return "CurvePolygon";
44
60
    }
45
46
2.14k
    GeometryTypeId CurvePolygon::getGeometryTypeId() const {
47
2.14k
        return GEOS_CURVEPOLYGON;
48
2.14k
    }
49
50
    static std::unique_ptr<Geometry>
51
    getRingForBoundary(const Geometry* ring)
52
0
    {
53
        // Convert LinearRing -> LineString
54
0
        if (ring->getGeometryTypeId() == GEOS_LINEARRING) {
55
0
            return ring->getFactory()->createLineString(*static_cast<const LineString*>(ring));
56
0
        }
57
0
        return ring->clone();
58
0
    }
59
60
    std::unique_ptr<Geometry>
61
0
    CurvePolygon::getBoundary() const {
62
63
0
        const GeometryFactory* gf = getFactory();
64
65
0
        if(isEmpty()) {
66
0
            return gf->createMultiCurve();
67
0
        }
68
69
0
        if(holes.empty()) {
70
0
            return getRingForBoundary(shell.get());
71
0
        }
72
73
0
        std::vector<std::unique_ptr<Geometry>> rings(holes.size() + 1);
74
75
0
        rings[0] = getRingForBoundary(shell.get());
76
0
        for(std::size_t i = 0; i < holes.size(); ++i) {
77
0
            rings[i + 1] = getRingForBoundary(holes[i].get());
78
0
        }
79
80
0
        return getFactory()->createMultiCurve(std::move(rings));
81
0
    }
82
83
    void
84
    CurvePolygon::normalize()
85
0
    {
86
0
        shell->normalize();
87
0
        for(auto& lr : holes) {
88
0
            lr->normalize();
89
0
            lr = lr->reverse();
90
0
        }
91
0
        std::sort(holes.begin(), holes.end(), [](const auto& a, const auto& b) {
92
0
            return a->compareTo(b.get()) > 0;
93
0
        });
94
0
    }
95
96
306
    double CurvePolygon::getArea() const {
97
306
        double sum = algorithm::Area::ofClosedCurve(*shell);
98
306
        for (const auto& hole : holes) {
99
119
            sum -= algorithm::Area::ofClosedCurve(*hole);
100
119
        }
101
306
        return sum;
102
306
    }
103
104
383
    bool CurvePolygon::hasCurvedComponents() const {
105
383
        if (shell->hasCurvedComponents()) {
106
1
            return true;
107
1
        }
108
382
        for (const auto& hole : holes) {
109
132
            if (hole->hasCurvedComponents()) {
110
0
                return true;
111
0
            }
112
132
        }
113
382
        return false;
114
382
    }
115
116
    Geometry*
117
24
    CurvePolygon::cloneImpl() const {
118
24
        return new CurvePolygon(*this);
119
24
    }
120
121
    Geometry*
122
0
    CurvePolygon::reverseImpl() const {
123
0
        std::unique_ptr<Curve> revShell(static_cast<Curve*>(shell->reverse().release()));
124
0
        std::vector<std::unique_ptr<Curve>> revHoles(holes.size());
125
0
        for (std::size_t i = 0; i < revHoles.size(); i++) {
126
0
            revHoles[i].reset(static_cast<Curve*>(holes[i]->reverse().release()));
127
0
        }
128
0
        return new CurvePolygon(std::move(revShell), std::move(revHoles), *getFactory());
129
0
    }
130
131
}
132
}