Code

update 2geom
[inkscape.git] / src / 2geom / elliptical-arc.h
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 "curve.h"
42 #include "angle.h"
43 #include "utils.h"
44 #include "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         }
63         
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     }
74           
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         }
94         
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     }
168     
169     
170     Rect boundsFast() const
171     {
172         return boundsExact();
173     }
174   
175     Rect boundsExact() const;
176     
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     }
182     
183     std::vector<double> roots(double v, Dim2 d) const;
184     
185     std::vector<double> 
186     allNearestPoints( Point const& p, double from = 0, double to = 1 ) const;
187     
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     }
196     
197     // TODO: native implementation of the following methods
198     int winding(Point p) const
199     {
200         return SBasisCurve(toSBasis()).winding(p);
201     }
202     
203     Curve *derivative() const;
204     
205     // TODO: native implementation of the following methods
206     Curve *transformed(Matrix const &m) const
207     {
208         return SBasisCurve(toSBasis()).transformed(m);
209     }
210     
211     std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const;
212     
213     D2<SBasis> toSBasis() const;
214     
215     bool containsAngle(Coord angle) const;
216     
217     double valueAtAngle(Coord t, Dim2 d) const;
218     
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     }
229     
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;
255     
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     }
276     
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;
287     
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 :