/src/geos/include/geos/algorithm/MinimumDiameter.h
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2023 Paul Ramsey <pramsey@cleverelephant.ca> |
7 | | * Copyright (C) 2005-2006 Refractions Research Inc. |
8 | | * Copyright (C) 2001-2002 Vivid Solutions Inc. |
9 | | * |
10 | | * This is free software; you can redistribute and/or modify it under |
11 | | * the terms of the GNU Lesser General Public Licence as published |
12 | | * by the Free Software Foundation. |
13 | | * See the COPYING file for more information. |
14 | | * |
15 | | **********************************************************************/ |
16 | | |
17 | | #pragma once |
18 | | |
19 | | #include <geos/geom/Coordinate.h> |
20 | | #include <geos/geom/LineSegment.h> |
21 | | |
22 | | #include <memory> |
23 | | #include <geos/export.h> |
24 | | |
25 | | // Forward declarations |
26 | | namespace geos { |
27 | | namespace geom { |
28 | | class GeometryFactory; |
29 | | class Geometry; |
30 | | class LineString; |
31 | | class CoordinateSequence; |
32 | | } |
33 | | } |
34 | | |
35 | | |
36 | | namespace geos { |
37 | | namespace algorithm { // geos::algorithm |
38 | | |
39 | | /** \brief |
40 | | * Computes the minimum diameter of a geom::Geometry |
41 | | * |
42 | | * The minimum diameter is defined to be the width of the smallest band that |
43 | | * contains the geometry, where a band is a strip of the plane defined |
44 | | * by two parallel lines. This can be thought of as the smallest hole |
45 | | * that the geometry can be moved through, with a single rotation. |
46 | | * |
47 | | * The first step in the algorithm is computing the convex hull of the Geometry. |
48 | | * If the input Geometry is known to be convex, a hint can be supplied to |
49 | | * avoid this computation. |
50 | | * |
51 | | * This class can also be used to compute a line segment representing |
52 | | * the minimum diameter, the supporting line segment of the minimum diameter, |
53 | | * and a minimum-width rectangle of the input geometry. |
54 | | * This rectangle will have width equal to the minimum diameter, and have |
55 | | * one side parallel to the supporting segment. |
56 | | * |
57 | | * In degenerate cases the rectangle may be a LineString or a Point. |
58 | | * (Note that this may not be the enclosing rectangle with minimum area; |
59 | | * use MinimumAreaRectangle to compute this.) |
60 | | * |
61 | | * @see ConvexHull |
62 | | * @see MinimumAreaRectangle |
63 | | */ |
64 | | class GEOS_DLL MinimumDiameter { |
65 | | private: |
66 | | const geom::Geometry* inputGeom; |
67 | | bool isConvex; |
68 | | |
69 | | std::unique_ptr<geom::CoordinateSequence> convexHullPts; |
70 | | |
71 | | geom::LineSegment minBaseSeg; |
72 | | geom::Coordinate minWidthPt; |
73 | | std::size_t minPtIndex; |
74 | | double minWidth; |
75 | | void computeMinimumDiameter(); |
76 | | void computeWidthConvex(const geom::Geometry* geom); |
77 | | |
78 | | /** |
79 | | * Compute the width information for a ring of Coordinate. |
80 | | * Leaves the width information in the instance variables. |
81 | | * |
82 | | * @param pts |
83 | | * @return |
84 | | */ |
85 | | void computeConvexRingMinDiameter(const geom::CoordinateSequence* pts); |
86 | | |
87 | | unsigned int findMaxPerpDistance(const geom::CoordinateSequence* pts, |
88 | | const geom::LineSegment* seg, unsigned int startIndex); |
89 | | |
90 | | static unsigned int getNextIndex(const geom::CoordinateSequence* pts, |
91 | | unsigned int index); |
92 | | |
93 | | static double computeC(double a, double b, const geom::Coordinate& p); |
94 | | |
95 | | static geom::LineSegment computeSegmentForLine(double a, double b, double c); |
96 | | |
97 | | static std::unique_ptr<geom::Geometry> computeMaximumLine( |
98 | | const geom::CoordinateSequence* pts, |
99 | | const geom::GeometryFactory* factory); |
100 | | |
101 | | public: |
102 | 0 | ~MinimumDiameter() = default; |
103 | | |
104 | | /** \brief |
105 | | * Compute a minimum diameter for a given [Geometry](@ref geom::Geometry). |
106 | | * |
107 | | * @param newInputGeom a Geometry |
108 | | */ |
109 | | MinimumDiameter(const geom::Geometry* newInputGeom); |
110 | | |
111 | | /** \brief |
112 | | * Compute a minimum diameter for a given Geometry, |
113 | | * with a hint if the Geometry is convex |
114 | | * (e.g. a convex Polygon or LinearRing, |
115 | | * or a two-point LineString, or a Point). |
116 | | * |
117 | | * @param newInputGeom a Geometry which is convex |
118 | | * @param newIsConvex `true` if the input geometry is convex |
119 | | */ |
120 | | MinimumDiameter(const geom::Geometry* newInputGeom, |
121 | | const bool newIsConvex); |
122 | | |
123 | | /** \brief |
124 | | * Gets the length of the minimum diameter of the input Geometry. |
125 | | * |
126 | | * @return the length of the minimum diameter |
127 | | */ |
128 | | double getLength(); |
129 | | |
130 | | /** \brief |
131 | | * Gets the geom::Coordinate forming one end of the minimum diameter. |
132 | | * |
133 | | * @return a coordinate forming one end of the minimum diameter |
134 | | */ |
135 | | const geom::Coordinate& getWidthCoordinate(); |
136 | | |
137 | | /** \brief |
138 | | * Gets the segment forming the base of the minimum diameter. |
139 | | * |
140 | | * @return the segment forming the base of the minimum diameter |
141 | | */ |
142 | | std::unique_ptr<geom::LineString> getSupportingSegment(); |
143 | | |
144 | | /** \brief |
145 | | * Gets a LineString which is a minimum diameter. |
146 | | * |
147 | | * @return a LineString which is a minimum diameter |
148 | | */ |
149 | | std::unique_ptr<geom::LineString> getDiameter(); |
150 | | |
151 | | /** \brief |
152 | | * Gets the rectangular Polygon which encloses the input geometry |
153 | | * and is based on the minimum diameter supporting segment. |
154 | | * |
155 | | * The rectangle has width equal to the minimum diameter, and a longer |
156 | | * length. If the convex hill of the input is degenerate (a line or point) |
157 | | * a LineString or Point is returned. |
158 | | * This is not necessarily the rectangle with minimum area. |
159 | | * Use MinimumAreaRectangle to compute this. |
160 | | * |
161 | | * @return the the minimum-width rectangle enclosing the geometry |
162 | | * @see MinimumAreaRectangle |
163 | | */ |
164 | | std::unique_ptr<geom::Geometry> getMinimumRectangle(); |
165 | | |
166 | | /** \brief |
167 | | * Gets the minimum rectangle enclosing a geometry. |
168 | | * |
169 | | * @param geom the geometry |
170 | | * @return a rectangle enclosing the input (or a line or point if degenerate) |
171 | | * @see MinimumAreaRectangle |
172 | | */ |
173 | | static std::unique_ptr<geom::Geometry> getMinimumRectangle(geom::Geometry* geom); |
174 | | |
175 | | /** \brief |
176 | | * Gets the length of the minimum diameter enclosing a geometry. |
177 | | * @param geom the geometry |
178 | | * @return the length of the minimum diameter of the geometry |
179 | | */ |
180 | | static std::unique_ptr<geom::Geometry> getMinimumDiameter(geom::Geometry* geom); |
181 | | |
182 | | }; |
183 | | |
184 | | } // namespace geos::algorithm |
185 | | } // namespace geos |