1 /*
2 * Elliptical Arc - implementation of the svg elliptical arc path element
3 *
4 * Authors:
5 * MenTaLguY <mental@rydia.net>
6 * Marco Cecchetti <mrcekets at gmail.com>
7 *
8 * Copyright 2007-2008 authors
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it either under the terms of the GNU Lesser General Public
12 * License version 2.1 as published by the Free Software Foundation
13 * (the "LGPL") or, at your option, under the terms of the Mozilla
14 * Public License Version 1.1 (the "MPL"). If you do not alter this
15 * notice, a recipient may use your version of this file under either
16 * the MPL or the LGPL.
17 *
18 * You should have received a copy of the LGPL along with this library
19 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * You should have received a copy of the MPL along with this library
22 * in the file COPYING-MPL-1.1
23 *
24 * The contents of this file are subject to the Mozilla Public License
25 * Version 1.1 (the "License"); you may not use this file except in
26 * compliance with the License. You may obtain a copy of the License at
27 * http://www.mozilla.org/MPL/
28 *
29 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
30 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
31 * the specific language governing rights and limitations.
32 */
37 #ifndef _2GEOM_ELLIPTICAL_ARC_H_
38 #define _2GEOM_ELLIPTICAL_ARC_H_
41 #include <2geom/curve.h>
42 #include <2geom/angle.h>
43 #include <2geom/utils.h>
44 #include <2geom/sbasis-curve.h> // for non-native methods
46 #include <algorithm>
49 namespace Geom
50 {
52 class EllipticalArc : public Curve
53 {
54 public:
55 EllipticalArc()
56 : m_initial_point(Point(0,0)), m_final_point(Point(0,0)),
57 m_rx(0), m_ry(0), m_rot_angle(0),
58 m_large_arc(true), m_sweep(true)
59 {
60 m_start_angle = m_end_angle = 0;
61 m_center = Point(0,0);
62 }
64 EllipticalArc( Point _initial_point, double _rx, double _ry,
65 double _rot_angle, bool _large_arc, bool _sweep,
66 Point _final_point
67 )
68 : m_initial_point(_initial_point), m_final_point(_final_point),
69 m_rx(_rx), m_ry(_ry), m_rot_angle(_rot_angle),
70 m_large_arc(_large_arc), m_sweep(_sweep)
71 {
72 calculate_center_and_extreme_angles();
73 }
75 void set( Point _initial_point, double _rx, double _ry,
76 double _rot_angle, bool _large_arc, bool _sweep,
77 Point _final_point
78 )
79 {
80 m_initial_point = _initial_point;
81 m_final_point = _final_point;
82 m_rx = _rx;
83 m_ry = _ry;
84 m_rot_angle = _rot_angle;
85 m_large_arc = _large_arc;
86 m_sweep = _sweep;
87 calculate_center_and_extreme_angles();
88 }
90 Curve* duplicate() const
91 {
92 return new EllipticalArc(*this);
93 }
95 double center(unsigned int i) const
96 {
97 return m_center[i];
98 }
100 Point center() const
101 {
102 return m_center;
103 }
105 Point initialPoint() const
106 {
107 return m_initial_point;
108 }
110 Point finalPoint() const
111 {
112 return m_final_point;
113 }
115 double start_angle() const
116 {
117 return m_start_angle;
118 }
120 double end_angle() const
121 {
122 return m_end_angle;
123 }
125 double ray(unsigned int i) const
126 {
127 return (i == 0) ? m_rx : m_ry;
128 }
130 bool large_arc_flag() const
131 {
132 return m_large_arc;
133 }
135 bool sweep_flag() const
136 {
137 return m_sweep;
138 }
140 double rotation_angle() const
141 {
142 return m_rot_angle;
143 }
145 void setInitial( const Point _point)
146 {
147 m_initial_point = _point;
148 calculate_center_and_extreme_angles();
149 }
151 void setFinal( const Point _point)
152 {
153 m_final_point = _point;
154 calculate_center_and_extreme_angles();
155 }
157 void setExtremes( const Point& _initial_point, const Point& _final_point )
158 {
159 m_initial_point = _initial_point;
160 m_final_point = _final_point;
161 calculate_center_and_extreme_angles();
162 }
164 bool isDegenerate() const
165 {
166 return ( are_near(ray(X), 0) || are_near(ray(Y), 0) );
167 }
170 Rect boundsFast() const
171 {
172 return boundsExact();
173 }
175 Rect boundsExact() const;
177 // TODO: native implementation of the following methods
178 Rect boundsLocal(Interval i, unsigned int deg) const
179 {
180 return SBasisCurve(toSBasis()).boundsLocal(i, deg);
181 }
183 std::vector<double> roots(double v, Dim2 d) const;
185 std::vector<double>
186 allNearestPoints( Point const& p, double from = 0, double to = 1 ) const;
188 double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
189 {
190 if ( are_near(ray(X), ray(Y)) && are_near(center(), p) )
191 {
192 return from;
193 }
194 return allNearestPoints(p, from, to).front();
195 }
197 // TODO: native implementation of the following methods
198 int winding(Point p) const
199 {
200 return SBasisCurve(toSBasis()).winding(p);
201 }
203 Curve *derivative() const;
205 // TODO: native implementation of the following methods
206 Curve *transformed(Matrix const &m) const
207 {
208 return SBasisCurve(toSBasis()).transformed(m);
209 }
211 std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const;
213 D2<SBasis> toSBasis() const;
215 bool containsAngle(Coord angle) const;
217 double valueAtAngle(Coord t, Dim2 d) const;
219 Point pointAtAngle(Coord t) const
220 {
221 double sin_rot_angle = std::sin(rotation_angle());
222 double cos_rot_angle = std::cos(rotation_angle());
223 Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle,
224 -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle,
225 center(X), center(Y) );
226 Point p( std::cos(t), std::sin(t) );
227 return p * m;
228 }
230 double valueAt(Coord t, Dim2 d) const
231 {
232 Coord tt = map_to_02PI(t);
233 return valueAtAngle(tt, d);
234 }
236 Point pointAt(Coord t) const
237 {
238 Coord tt = map_to_02PI(t);
239 return pointAtAngle(tt);
240 }
242 std::pair<EllipticalArc, EllipticalArc>
243 subdivide(Coord t) const
244 {
245 EllipticalArc* arc1 = static_cast<EllipticalArc*>(portion(0, t));
246 EllipticalArc* arc2 = static_cast<EllipticalArc*>(portion(t, 1));
247 assert( arc1 != NULL && arc2 != NULL);
248 std::pair<EllipticalArc, EllipticalArc> arc_pair(*arc1, *arc2);
249 delete arc1;
250 delete arc2;
251 return arc_pair;
252 }
254 Curve* portion(double f, double t) const;
256 // the arc is the same but traversed in the opposite direction
257 Curve* reverse() const
258 {
259 EllipticalArc* rarc = new EllipticalArc( *this );
260 rarc->m_sweep = !m_sweep;
261 rarc->m_initial_point = m_final_point;
262 rarc->m_final_point = m_initial_point;
263 rarc->m_start_angle = m_end_angle;
264 rarc->m_end_angle = m_start_angle;
265 return rarc;
266 }
268 double sweep_angle() const
269 {
270 Coord d = end_angle() - start_angle();
271 if ( !sweep_flag() ) d = -d;
272 if ( d < 0 )
273 d += 2*M_PI;
274 return d;
275 }
277 private:
278 Coord map_to_02PI(Coord t) const;
279 Coord map_to_01(Coord angle) const;
280 void calculate_center_and_extreme_angles();
281 private:
282 Point m_initial_point, m_final_point;
283 double m_rx, m_ry, m_rot_angle;
284 bool m_large_arc, m_sweep;
285 double m_start_angle, m_end_angle;
286 Point m_center;
288 }; // end class EllipticalArc
291 } // end namespace Geom
293 #endif // _2GEOM_ELLIPTICAL_ARC_H_
298 /*
299 Local Variables:
300 mode:c++
301 c-file-style:"stroustrup"
302 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
303 indent-tabs-mode:nil
304 fill-column:99
305 End:
306 */
307 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :