Coverage Report

Created: 2026-10-28 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/include/geos/algorithm/Centroid.h
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2013 Sandro Santilli <strk@kbt.io>
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
 * Last port: algorithm/Centroid.java r728 (JTS-0.13+)
16
 *
17
 **********************************************************************/
18
19
#pragma once
20
21
#include <geos/export.h>
22
#include <geos/geom/Coordinate.h> // for composition
23
#include <memory> // for std::unique_ptr
24
25
// Forward declarations
26
namespace geos {
27
namespace geom {
28
class Geometry;
29
class Polygon;
30
class CoordinateSequence;
31
}
32
}
33
34
35
namespace geos {
36
namespace algorithm { // geos::algorithm
37
38
/** \brief
39
 * Computes the centroid of a [Geometry](@ref geom::Geometry) of any dimension.
40
 *
41
 * If the geometry is nomimally of higher dimension, but contains only
42
 * components having a lower effective dimension (i.e. zero length or area),
43
 * the centroid will be computed appropriately.
44
 *
45
 * ### Algorithm #
46
 *
47
 * - **Dimension = 2** - Based on the usual algorithm for calculating
48
 *     the centroid as a weighted sum of the centroids
49
 *     of a decomposition of the area into (possibly overlapping) triangles.
50
 *     The algorithm has been extended to handle holes and multi-polygons.
51
 *     See http://www.faqs.org/faqs/graphics/algorithms-faq/
52
 *     for further details of the basic approach.
53
 * - **Dimension = 1** - Computes the average of the midpoints
54
 *     of all line segments weighted by the segment length.
55
 * - **Dimension = 0** - Compute the average coordinate over all points.
56
 *
57
 * If the input geometries are empty, a `null` Coordinate is returned.
58
 *
59
 */
60
class GEOS_DLL Centroid {
61
62
public:
63
64
    /** \brief
65
     * Computes the centroid point of a geometry.
66
     *
67
     * @param geom the geometry to use
68
     * @param cent will be set to the centroid point, if any
69
     *
70
     * @return `true` if a centroid could be computed,
71
     *         `false` otherwise (empty geom)
72
     */
73
    static bool getCentroid(const geom::Geometry& geom, geom::CoordinateXY& cent);
74
75
    /** \brief
76
     * Creates a new instance for computing the centroid of a geometry
77
     */
78
    Centroid(const geom::Geometry& geom)
79
        :
80
26.4k
        areasum2(0.0),
81
26.4k
        totalLength(0.0),
82
26.4k
        ptCount(0)
83
26.4k
    {
84
26.4k
        add(geom);
85
26.4k
    }
86
87
    /** \brief
88
     * Gets the computed centroid.
89
     *
90
     * @param cent will be set to the centroid point, if any
91
     *
92
     * @return `true` if a centroid could be computed,
93
     *         `false` otherwise (empty geom)
94
     */
95
    bool getCentroid(geom::CoordinateXY& cent) const;
96
97
private:
98
99
    std::unique_ptr<geom::CoordinateXY> areaBasePt;
100
    geom::CoordinateXY triangleCent3;
101
    geom::CoordinateXY cg3;
102
    geom::CoordinateXY lineCentSum;
103
    geom::CoordinateXY ptCentSum;
104
    double areasum2;
105
    double totalLength;
106
    int ptCount;
107
108
    /**
109
     * Adds a Geometry to the centroid total.
110
     *
111
     * @param geom the geometry to add
112
     */
113
    void add(const geom::Geometry& geom);
114
115
    void setAreaBasePoint(const geom::CoordinateXY& basePt);
116
117
    void add(const geom::Polygon& poly);
118
119
    void addShell(const geom::CoordinateSequence& pts);
120
121
    void addHole(const geom::CoordinateSequence& pts);
122
123
    void addTriangle(const geom::CoordinateXY& p0, const geom::CoordinateXY& p1, const geom::CoordinateXY& p2,
124
                     bool isPositiveArea);
125
126
    /**
127
     * Computes three times the centroid of the triangle p1-p2-p3.
128
     * The factor of 3 is
129
     * left in to permit division to be avoided until later.
130
     */
131
    static void centroid3(const geom::CoordinateXY& p1, const geom::CoordinateXY& p2, const geom::CoordinateXY& p3,
132
                          geom::CoordinateXY& c);
133
134
    /**
135
     * Returns twice the signed area of the triangle p1-p2-p3.
136
     * The area is positive if the triangle is oriented CCW, and negative if CW.
137
     */
138
    static double area2(const geom::CoordinateXY& p1, const geom::CoordinateXY& p2, const geom::CoordinateXY& p3);
139
140
    /**
141
     * Adds the line segments defined by an array of coordinates
142
     * to the linear centroid accumulators.
143
     *
144
     * @param pts an array of {@link Coordinate}s
145
     */
146
    void addLineSegments(const geom::CoordinateSequence& pts);
147
148
    /**
149
     * Adds a point to the point centroid accumulator.
150
     * @param pt a {@link Coordinate}
151
     */
152
    void addPoint(const geom::CoordinateXY& pt);
153
};
154
155
} // namespace geos::algorithm
156
} // namespace geos
157