/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 | | |