GEOS 3.15.0dev
CircularArc.h
1/**********************************************************************
2 *
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
5 *
6 * Copyright (C) 2024-2025 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#pragma once
16
17#include <geos/export.h>
18#include <geos/geom/Coordinate.h>
19#include <geos/geom/LineSegment.h>
20#include <geos/geom/Quadrant.h>
21#include <geos/algorithm/CircularArcs.h>
22#include <geos/algorithm/Orientation.h>
23
24namespace geos {
25namespace geom {
26
29class GEOS_DLL CircularArc {
30public:
31
35
40 CircularArc(const CoordinateSequence&, std::size_t pos);
41 CircularArc(const CoordinateSequence&, std::size_t pos, const CoordinateXY& center, double radius, int orientation);
42
47 CircularArc(std::unique_ptr<CoordinateSequence>, std::size_t pos);
48 CircularArc(std::unique_ptr<CoordinateSequence>, std::size_t pos, const CoordinateXY& center, double radius, int orientation);
49
50 CircularArc(const CircularArc& other);
51
52 CircularArc(CircularArc&&) noexcept;
53
54 CircularArc& operator=(const CircularArc& other);
55 CircularArc& operator=(CircularArc&&) noexcept;
56
57 ~CircularArc();
58
62 template<typename CoordType>
63 static CircularArc create(const CoordType& p0, const CoordType& p1, const CoordType& p2)
64 {
65 auto seq = std::make_unique<CoordinateSequence>(3, CoordType::template has<Ordinate::Z>(), CoordType::template has<Ordinate::M>());
66 seq->setAt(p0, 0);
67 seq->setAt(p1, 1);
68 seq->setAt(p2, 2);
69
70 CircularArc ret(std::move(seq), 0);
71
72 return ret;
73 }
74
75 static CircularArc create(const CoordinateXY& p0, const CoordinateXY& p2, const CoordinateXY& center, double radius, int orientation);
76 static CircularArc create(const Coordinate& p0, const Coordinate& p2, const CoordinateXY& center, double radius, int orientation);
77 static CircularArc create(const CoordinateXYM& p0, const CoordinateXYM& p2, const CoordinateXY& center, double radius, int orientation);
78 static CircularArc create(const CoordinateXYZM& p0, const CoordinateXYZM& p2, const CoordinateXY& center, double radius, int orientation);
79
81 double getAngle() const;
82
84 double getArea() const;
85
87 const CoordinateXY& getCenter() const {
88 if (!m_center_known) {
89 if (isCCW()) {
90 m_center = algorithm::CircularArcs::getCenter(p0(), p1(), p2());
91 } else {
92 m_center = algorithm::CircularArcs::getCenter(p2(), p1(), p0());
93 }
94 m_center_known = true;
95 }
96
97 return m_center;
98 }
99
100 const CoordinateSequence* getCoordinateSequence() const {
101 return m_seq;
102 }
103
104 std::size_t getCoordinatePosition() const {
105 return m_pos;
106 }
107
111 CoordinateXY getDirectionPoint() const;
112
113 Envelope getEnvelope() const;
114
116 double getLength() const;
117
122 int getOrientation() const {
123 if (!m_orientation_known) {
124 m_orientation = algorithm::Orientation::index(p0(), p1(), p2());
125 m_orientation_known = true;
126 }
127 return m_orientation;
128 }
129
131 double getRadius() const {
132 if (!m_radius_known) {
133 if (isCCW()) {
134 m_radius = getCenter().distance(p0());
135 } else {
136 m_radius = getCenter().distance(p2());
137 }
138 m_radius_known = true;
139 }
140
141 return m_radius;
142 }
143
145 double getSagitta() const {
146 CoordinateXY midpoint = algorithm::CircularArcs::getMidpoint(p0(), p2(), getCenter(), getRadius(), isCCW());
147 return algorithm::Distance::pointToSegment(midpoint, p0(), p2());
148 }
149
150 bool isCCW() const {
151 return getOrientation() == algorithm::Orientation::COUNTERCLOCKWISE;
152 }
153
155 bool isCircle() const {
156 return p0().equals(p2());
157 }
158
160 bool isLinear() const {
161 return !std::isfinite(getRadius());
162 }
163
165 double theta0() const {
166 return algorithm::CircularArcs::getAngle(p0(), getCenter());
167 }
168
170 double theta1() const {
171 return algorithm::CircularArcs::getAngle(p1(), getCenter());
172 }
173
175 double theta2() const {
176 return algorithm::CircularArcs::getAngle(p2(), getCenter());
177 }
179 bool containsAngle(double theta) const;
180
183 bool containsPoint(const CoordinateXY& q) const;
184
188 bool containsPointOnCircle(const CoordinateXY& q) const {
189 double theta = std::atan2(q.y - getCenter().y, q.x - getCenter().x);
190 return containsAngle(theta);
191 }
192
196 bool isUpwardAtPoint(const CoordinateXY& q) const;
197
198 CircularArc reverse() const;
199
200 // Split an arc at a specified point.
201 // The point is assumed to be on the arc.
202 //std::pair<CircularArc, CircularArc> splitAtPoint(const CoordinateXY& q) const;
203
204 bool equals(const CircularArc& other, double tol) const;
205
206 class Iterator {
207 public:
208 using iterator_category = std::forward_iterator_tag;
209 using difference_type = std::ptrdiff_t;
210 using value_type = geom::CoordinateXY;
211 using pointer = const geom::CoordinateXY*;
212 using reference = const geom::CoordinateXY&;
213
214 Iterator(const CircularArc& arc, int i) : m_arc(arc), m_i(i) {}
215
216 reference operator*() const {
217 return m_i == 0 ? m_arc.p0() : (m_i == 1 ? m_arc.p1() : m_arc.p2());
218 }
219
220 Iterator& operator++() {
221 m_i++;
222 return *this;
223 }
224
225 Iterator operator++(int) {
226 Iterator ret = *this;
227 m_i++;
228 return ret;
229 }
230
231 bool operator==(const Iterator& other) const {
232 return m_i == other.m_i;
233 }
234
235 bool operator!=(const Iterator& other) const {
236 return !(*this == other);
237 }
238
239 private:
240 const CircularArc& m_arc;
241 int m_i;
242
243 };
244
245 Iterator begin() const {
246 return Iterator(*this, 0);
247 }
248
249 Iterator end() const {
250 return Iterator(*this, 3);
251 }
252
253 template<typename T=CoordinateXY>
254 const T& p0() const {
255 return m_seq->getAt<T>(m_pos);
256 }
257
258 template<typename T=CoordinateXY>
259 const T& p1() const {
260 return m_seq->getAt<T>(m_pos + 1);
261 }
262
263 template<typename T=CoordinateXY>
264 const T& p2() const {
265 return m_seq->getAt<T>(m_pos + 2);
266 }
267
268 std::string toString() const;
269
270 template<typename F>
271 auto applyAt(std::size_t i, F&& f) const {
272 return m_seq->applyAt(m_pos + i, f);
273 }
274
275private:
276 const CoordinateSequence* m_seq;
277 std::size_t m_pos;
278
279 mutable CoordinateXY m_center;
280 mutable double m_radius;
281 mutable int m_orientation;
282 mutable bool m_center_known = false;
283 mutable bool m_radius_known = false;
284 mutable bool m_orientation_known = false;
285 bool m_own_coordinates;
286};
287
288}
289}
Definition CircularArc.h:29
CoordinateXY getDirectionPoint() const
bool containsPointOnCircle(const CoordinateXY &q) const
Definition CircularArc.h:188
bool isUpwardAtPoint(const CoordinateXY &q) const
CircularArc(std::unique_ptr< CoordinateSequence >, std::size_t pos)
bool isCircle() const
Return whether this arc forms a complete circle.
Definition CircularArc.h:155
CircularArc(const CoordinateSequence &, std::size_t pos)
bool containsAngle(double theta) const
Check to see if a given angle lies on this arc.
int getOrientation() const
Definition CircularArc.h:122
const CoordinateXY & getCenter() const
Return the center point of the circle associated with this arc.
Definition CircularArc.h:87
double getSagitta() const
Return the distance from the centerpoint of the arc to the line segment formed by the end points of t...
Definition CircularArc.h:145
bool isLinear() const
Returns whether this arc forms a straight line (p0, p1, and p2 are collinear)
Definition CircularArc.h:160
double getAngle() const
Return the inner angle of the sector associated with this arc.
double getLength() const
Return the length of the arc.
double getArea() const
Return the area enclosed by the arc p0-p1-p2 and the line segment p2-p0.
double getRadius() const
Return the radius of the circle associated with this arc.
Definition CircularArc.h:131
bool containsPoint(const CoordinateXY &q) const
double theta0() const
Return the angle of p0.
Definition CircularArc.h:165
double theta1() const
Return the angle of p1.
Definition CircularArc.h:170
double theta2() const
Return the angle of p2.
Definition CircularArc.h:175
The internal representation of a list of coordinates inside a Geometry.
Definition CoordinateSequence.h:56
Coordinate is the lightweight class used to store coordinates.
Definition Coordinate.h:220
An Envelope defines a rectangulare region of the 2D coordinate plane.
Definition Envelope.h:59
Basic namespace for all GEOS functionalities.
Definition geos.h:38