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
108 Envelope getEnvelope() const;
109
111 double getLength() const;
112
117 int getOrientation() const {
118 if (!m_orientation_known) {
119 m_orientation = algorithm::Orientation::index(p0(), p1(), p2());
120 m_orientation_known = true;
121 }
122 return m_orientation;
123 }
124
126 double getRadius() const {
127 if (!m_radius_known) {
128 if (isCCW()) {
129 m_radius = getCenter().distance(p0());
130 } else {
131 m_radius = getCenter().distance(p2());
132 }
133 m_radius_known = true;
134 }
135
136 return m_radius;
137 }
138
140 double getSagitta() const {
141 CoordinateXY midpoint = algorithm::CircularArcs::getMidpoint(p0(), p2(), getCenter(), getRadius(), isCCW());
142 return algorithm::Distance::pointToSegment(midpoint, p0(), p2());
143 }
144
145 bool isCCW() const {
146 return getOrientation() == algorithm::Orientation::COUNTERCLOCKWISE;
147 }
148
150 bool isCircle() const {
151 return p0().equals(p2());
152 }
153
155 bool isLinear() const {
156 return !std::isfinite(getRadius());
157 }
158
160 double theta0() const {
161 return algorithm::CircularArcs::getAngle(p0(), getCenter());
162 }
163
165 double theta1() const {
166 return algorithm::CircularArcs::getAngle(p1(), getCenter());
167 }
168
170 double theta2() const {
171 return algorithm::CircularArcs::getAngle(p2(), getCenter());
172 }
174 bool containsAngle(double theta) const;
175
178 bool containsPoint(const CoordinateXY& q) const;
179
183 bool containsPointOnCircle(const CoordinateXY& q) const {
184 double theta = std::atan2(q.y - getCenter().y, q.x - getCenter().x);
185 return containsAngle(theta);
186 }
187
191 bool isUpwardAtPoint(const CoordinateXY& q) const;
192
193 CircularArc reverse() const;
194
195 // Split an arc at a specified point.
196 // The point is assumed to be on the arc.
197 //std::pair<CircularArc, CircularArc> splitAtPoint(const CoordinateXY& q) const;
198
199 bool equals(const CircularArc& other, double tol) const;
200
201 class Iterator {
202 public:
203 using iterator_category = std::forward_iterator_tag;
204 using difference_type = std::ptrdiff_t;
205 using value_type = geom::CoordinateXY;
206 using pointer = const geom::CoordinateXY*;
207 using reference = const geom::CoordinateXY&;
208
209 Iterator(const CircularArc& arc, int i) : m_arc(arc), m_i(i) {}
210
211 reference operator*() const {
212 return m_i == 0 ? m_arc.p0() : (m_i == 1 ? m_arc.p1() : m_arc.p2());
213 }
214
215 Iterator& operator++() {
216 m_i++;
217 return *this;
218 }
219
220 Iterator operator++(int) {
221 Iterator ret = *this;
222 m_i++;
223 return ret;
224 }
225
226 bool operator==(const Iterator& other) const {
227 return m_i == other.m_i;
228 }
229
230 bool operator!=(const Iterator& other) const {
231 return !(*this == other);
232 }
233
234 private:
235 const CircularArc& m_arc;
236 int m_i;
237
238 };
239
240 Iterator begin() const {
241 return Iterator(*this, 0);
242 }
243
244 Iterator end() const {
245 return Iterator(*this, 3);
246 }
247
248 template<typename T=CoordinateXY>
249 const T& p0() const {
250 return m_seq->getAt<T>(m_pos);
251 }
252
253 template<typename T=CoordinateXY>
254 const T& p1() const {
255 return m_seq->getAt<T>(m_pos + 1);
256 }
257
258 template<typename T=CoordinateXY>
259 const T& p2() const {
260 return m_seq->getAt<T>(m_pos + 2);
261 }
262
263 std::string toString() const;
264
265 template<typename F>
266 auto applyAt(std::size_t i, F&& f) const {
267 return m_seq->applyAt(m_pos + i, f);
268 }
269
270private:
271 const CoordinateSequence* m_seq;
272 std::size_t m_pos;
273
274 mutable CoordinateXY m_center;
275 mutable double m_radius;
276 mutable int m_orientation;
277 mutable bool m_center_known = false;
278 mutable bool m_radius_known = false;
279 mutable bool m_orientation_known = false;
280 bool m_own_coordinates;
281};
282
283}
284}
Definition CircularArc.h:29
bool containsPointOnCircle(const CoordinateXY &q) const
Definition CircularArc.h:183
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:150
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:117
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:140
bool isLinear() const
Returns whether this arc forms a straight line (p0, p1, and p2 are collinear)
Definition CircularArc.h:155
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:126
bool containsPoint(const CoordinateXY &q) const
double theta0() const
Return the angle of p0.
Definition CircularArc.h:160
double theta1() const
Return the angle of p1.
Definition CircularArc.h:165
double theta2() const
Return the angle of p2.
Definition CircularArc.h:170
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
Basic namespace for all GEOS functionalities.
Definition geos.h:38