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