GCC Code Coverage Report


Directory: ./
File: include/2geom/ellipse.h
Date: 2024-03-18 17:01:34
Exec Total Coverage
Lines: 21 43 48.8%
Functions: 14 19 73.7%
Branches: 2 6 33.3%

Line Branch Exec Source
1 /** @file
2 * @brief Ellipse shape
3 *//*
4 * Authors:
5 * Marco Cecchetti <mrcekets at gmail.com>
6 * Krzysztof KosiƄski <tweenk.pl@gmail.com>
7 *
8 * Copyright 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 */
33
34
35 #ifndef LIB2GEOM_SEEN_ELLIPSE_H
36 #define LIB2GEOM_SEEN_ELLIPSE_H
37
38 #include <vector>
39 #include <2geom/angle.h>
40 #include <2geom/bezier-curve.h>
41 #include <2geom/exception.h>
42 #include <2geom/forward.h>
43 #include <2geom/line.h>
44 #include <2geom/transforms.h>
45
46 namespace Geom {
47
48 class EllipticalArc;
49 class Circle;
50
51 /** @brief Set of points with a constant sum of distances from two foci.
52 *
53 * An ellipse can be specified in several ways. Internally, 2Geom uses
54 * the SVG style representation: center, rays and angle between the +X ray
55 * and the +X axis. Another popular way is to use an implicit equation,
56 * which is as follows:
57 * \f$Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0\f$
58 *
59 * @ingroup Shapes */
60 class Ellipse
61 : boost::multipliable< Ellipse, Translate
62 , boost::multipliable< Ellipse, Scale
63 , boost::multipliable< Ellipse, Rotate
64 , boost::multipliable< Ellipse, Zoom
65 , boost::multipliable< Ellipse, Affine
66 , boost::equality_comparable< Ellipse
67 > > > > > >
68 {
69 Point _center;
70 Point _rays;
71 Angle _angle;
72 public:
73 2 Ellipse() {}
74 Ellipse(Point const &c, Point const &r, Coord angle)
75 : _center(c)
76 , _rays(r)
77 , _angle(angle)
78 {}
79 7 Ellipse(Coord cx, Coord cy, Coord rx, Coord ry, Coord angle)
80 7 : _center(cx, cy)
81 7 , _rays(rx, ry)
82 7 , _angle(angle)
83 7 {}
84 Ellipse(double A, double B, double C, double D, double E, double F) {
85 setCoefficients(A, B, C, D, E, F);
86 }
87 /// Construct ellipse from a circle.
88 Ellipse(Geom::Circle const &c);
89
90 /// Set center, rays and angle.
91 void set(Point const &c, Point const &r, Coord angle) {
92 _center = c;
93 _rays = r;
94 _angle = angle;
95 }
96 /// Set center, rays and angle as constituent values.
97 void set(Coord cx, Coord cy, Coord rx, Coord ry, Coord a) {
98 _center[X] = cx;
99 _center[Y] = cy;
100 _rays[X] = rx;
101 _rays[Y] = ry;
102 _angle = a;
103 }
104 /// Set an ellipse by solving its implicit equation.
105 void setCoefficients(double A, double B, double C, double D, double E, double F);
106 /// Set the center.
107 11589 void setCenter(Point const &p) { _center = p; }
108 /// Set the center by coordinates.
109 42 void setCenter(Coord cx, Coord cy) { _center[X] = cx; _center[Y] = cy; }
110 /// Set both rays of the ellipse.
111 52 void setRays(Point const &p) { _rays = p; }
112 /// Set both rays of the ellipse as coordinates.
113 11601 void setRays(Coord x, Coord y) { _rays[X] = x; _rays[Y] = y; }
114 /// Set one of the rays of the ellipse.
115 void setRay(Coord r, Dim2 d) { _rays[d] = r; }
116 /// Set the angle the X ray makes with the +X axis.
117 1226 void setRotationAngle(Angle a) { _angle = a; }
118
119 135468 Point center() const { return _center; }
120 212968 Coord center(Dim2 d) const { return _center[d]; }
121 /// Get both rays as a point.
122 10413 Point rays() const { return _rays; }
123 /// Get one ray of the ellipse.
124 1810477 Coord ray(Dim2 d) const { return _rays[d]; }
125 /// Get the angle the X ray makes with the +X axis.
126 20702 Angle rotationAngle() const { return _angle; }
127 /// Get the point corresponding to the +X ray of the ellipse.
128 Point initialPoint() const;
129 /// Get the point corresponding to the +X ray of the ellipse.
130 Point finalPoint() const { return initialPoint(); }
131
132 /** @brief Create an ellipse passing through the specified points
133 * At least five points have to be specified. */
134 void fit(std::vector<Point> const& points);
135
136 /** @brief Create an elliptical arc from a section of the ellipse.
137 * This is mainly useful to determine the flags of the new arc.
138 * The passed points should lie on the ellipse, otherwise the results
139 * will be undefined.
140 * @param ip Initial point of the arc
141 * @param inner Point in the middle of the arc, used to pick one of two possibilities
142 * @param fp Final point of the arc
143 * @return Newly allocated arc, delete when no longer used */
144 EllipticalArc *arc(Point const &ip, Point const &inner, Point const &fp);
145
146 /** @brief Return an ellipse with less degrees of freedom.
147 * The canonical form always has the angle less than \f$\frac{\pi}{2}\f$,
148 * and zero if the rays are equal (i.e. the ellipse is a circle). */
149 Ellipse canonicalForm() const;
150 void makeCanonical();
151
152 /** @brief Compute the transform that maps the unit circle to this ellipse.
153 * Each ellipse can be interpreted as a translated, scaled and rotate unit circle.
154 * This function returns the transform that maps the unit circle to this ellipse.
155 * @return Transform from unit circle to the ellipse */
156 Affine unitCircleTransform() const;
157 /** @brief Compute the transform that maps this ellipse to the unit circle.
158 * This may be a little more precise and/or faster than simply using
159 * unitCircleTransform().inverse(). An exception will be thrown for
160 * degenerate ellipses. */
161 Affine inverseUnitCircleTransform() const;
162
163
2/2
✓ Branch 2 taken 30000 times.
✓ Branch 3 taken 10000 times.
40000 LineSegment majorAxis() const { return ray(X) >= ray(Y) ? axis(X) : axis(Y); }
164 LineSegment minorAxis() const { return ray(X) < ray(Y) ? axis(X) : axis(Y); }
165 LineSegment semimajorAxis(int sign = 1) const {
166 return ray(X) >= ray(Y) ? semiaxis(X, sign) : semiaxis(Y, sign);
167 }
168 LineSegment semiminorAxis(int sign = 1) const {
169 return ray(X) < ray(Y) ? semiaxis(X, sign) : semiaxis(Y, sign);
170 }
171 LineSegment axis(Dim2 d) const;
172 LineSegment semiaxis(Dim2 d, int sign = 1) const;
173
174 /// Get the tight-fitting bounding box of the ellipse.
175 Rect boundsExact() const;
176
177 /** @brief Get a fast to compute bounding box which contains the ellipse.
178 *
179 * The returned rectangle engulfs the ellipse but it may not be the smallest
180 * axis-aligned rectangle with this property.
181 */
182 Rect boundsFast() const;
183
184 /// Get the coefficients of the ellipse's implicit equation.
185 std::vector<double> coefficients() const;
186 void coefficients(Coord &A, Coord &B, Coord &C, Coord &D, Coord &E, Coord &F) const;
187
188 /** @brief Evaluate a point on the ellipse.
189 * The parameter range is \f$[0, 2\pi)\f$; larger and smaller values
190 * wrap around. */
191 Point pointAt(Coord t) const;
192 /// Evaluate a single coordinate of a point on the ellipse.
193 Coord valueAt(Coord t, Dim2 d) const;
194
195 /** @brief Find the time value of a point on an ellipse.
196 * If the point is not on the ellipse, the returned time value will correspond
197 * to an intersection with a ray from the origin passing through the point
198 * with the ellipse. Note that this is NOT the nearest point on the ellipse. */
199 Coord timeAt(Point const &p) const;
200
201 /// Get the value of the derivative at time t normalized to unit length.
202 Point unitTangentAt(Coord t) const;
203
204 /// Check whether the ellipse contains the given point.
205 bool contains(Point const &p) const;
206
207 /// Compute intersections with an infinite line.
208 std::vector<ShapeIntersection> intersect(Line const &line) const;
209 /// Compute intersections with a line segment.
210 std::vector<ShapeIntersection> intersect(LineSegment const &seg) const;
211 /// Compute intersections with another ellipse.
212 std::vector<ShapeIntersection> intersect(Ellipse const &other) const;
213 /// Compute intersections with a 2D Bezier polynomial.
214 std::vector<ShapeIntersection> intersect(D2<Bezier> const &other) const;
215
216 Ellipse &operator*=(Translate const &t) {
217 _center *= t;
218 return *this;
219 }
220 4 Ellipse &operator*=(Scale const &s) {
221 4 _center *= s;
222 4 _rays *= s;
223 4 return *this;
224 }
225 Ellipse &operator*=(Zoom const &z) {
226 _center *= z;
227 _rays *= z.scale();
228 return *this;
229 }
230 Ellipse &operator*=(Rotate const &r);
231 Ellipse &operator*=(Affine const &m);
232
233 /// Compare ellipses for exact equality.
234 bool operator==(Ellipse const &other) const;
235 };
236
237 /** @brief Test whether two ellipses are approximately the same.
238 * This will check whether no point on ellipse a is further away from
239 * the corresponding point on ellipse b than precision.
240 * @relates Ellipse */
241 bool are_near(Ellipse const &a, Ellipse const &b, Coord precision = EPSILON);
242
243 /** @brief Outputs ellipse data, useful for debugging.
244 * @relates Ellipse */
245 std::ostream &operator<<(std::ostream &out, Ellipse const &e);
246
247 } // end namespace Geom
248
249 #endif // LIB2GEOM_SEEN_ELLIPSE_H
250
251 /*
252 Local Variables:
253 mode:c++
254 c-file-style:"stroustrup"
255 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
256 indent-tabs-mode:nil
257 fill-column:99
258 End:
259 */
260 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
261