summaryrefslogtreecommitdiffstats
path: root/src/2geom/elliptical-arc.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/2geom/elliptical-arc.h')
-rw-r--r--src/2geom/elliptical-arc.h92
1 files changed, 51 insertions, 41 deletions
diff --git a/src/2geom/elliptical-arc.h b/src/2geom/elliptical-arc.h
index 342b8c8c9..83909370e 100644
--- a/src/2geom/elliptical-arc.h
+++ b/src/2geom/elliptical-arc.h
@@ -38,10 +38,11 @@
#define LIB2GEOM_SEEN_ELLIPTICAL_ARC_H
#include <algorithm>
+#include <2geom/affine.h>
#include <2geom/angle.h>
#include <2geom/bezier-curve.h>
#include <2geom/curve.h>
-#include <2geom/affine.h>
+#include <2geom/ellipse.h>
#include <2geom/sbasis-curve.h> // for non-native methods
#include <2geom/utils.h>
@@ -56,21 +57,30 @@ public:
: AngleInterval(0, 0, true)
, _initial_point(0,0)
, _final_point(0,0)
- , _rays(0,0)
- , _center(0,0)
- , _rot_angle(0)
, _large_arc(true)
{}
/** @brief Create a new elliptical arc.
* @param ip Initial point of the arc
- * @param rx First ray of the ellipse
- * @param ry Second ray of the ellipse
+ * @param r Rays of the ellipse as a point
* @param rot Angle of rotation of the X axis of the ellipse in radians
* @param large If true, the large arc is chosen (always >= 180 degrees), otherwise
* the smaller arc is chosen
* @param sweep If true, the clockwise arc is chosen, otherwise the counter-clockwise
* arc is chosen
* @param fp Final point of the arc */
+ EllipticalArc( Point const &ip, Point const &r,
+ Coord rot_angle, bool large_arc, bool sweep,
+ Point const &fp
+ )
+ : AngleInterval(0,0,sweep)
+ , _initial_point(ip)
+ , _final_point(fp)
+ , _ellipse(0, 0, r[X], r[Y], rot_angle)
+ , _large_arc(large_arc)
+ {
+ _updateCenterAndAngles();
+ }
+
EllipticalArc( Point const &ip, Coord rx, Coord ry,
Coord rot_angle, bool large_arc, bool sweep,
Point const &fp
@@ -78,11 +88,10 @@ public:
: AngleInterval(0,0,sweep)
, _initial_point(ip)
, _final_point(fp)
- , _rays(rx, ry)
- , _rot_angle(rot_angle)
+ , _ellipse(0, 0, rx, ry, rot_angle)
, _large_arc(large_arc)
{
- _updateCenterAndAngles(false);
+ _updateCenterAndAngles();
}
// methods new to EllipticalArc go here
@@ -98,15 +107,15 @@ public:
/** @brief Get the defining ellipse's rotation
* @return Angle between the +X ray of the ellipse and the +X axis */
Angle rotationAngle() const {
- return _rot_angle;
+ return _ellipse.rotationAngle();
}
/** @brief Get one of the ellipse's rays
* @param d Dimension to retrieve
* @return The selected ray of the ellipse */
- Coord ray(Dim2 d) const { return _rays[d]; }
+ Coord ray(Dim2 d) const { return _ellipse.ray(d); }
/** @brief Get both rays as a point
* @return Point with X equal to the X ray and Y to Y ray */
- Point rays() const { return _rays; }
+ Point rays() const { return _ellipse.rays(); }
/** @brief Whether the arc is larger than half an ellipse.
* @return True if the arc is larger than \f$\pi\f$, false otherwise */
bool largeArc() const { return _large_arc; }
@@ -125,12 +134,11 @@ public:
{
_initial_point = ip;
_final_point = fp;
- _rays[X] = rx;
- _rays[Y] = ry;
- _rot_angle = Angle(rot_angle);
+ _ellipse.setRays(rx, ry);
+ _ellipse.setRotationAngle(rot_angle);
_large_arc = large_arc;
_sweep = sweep;
- _updateCenterAndAngles(isSVGCompliant());
+ _updateCenterAndAngles();
}
/** @brief Change the initial and final point in one operation.
* This method exists because modifying any of the endpoints causes rather costly
@@ -140,21 +148,16 @@ public:
void setEndpoints(Point const &ip, Point const &fp) {
_initial_point = ip;
_final_point = fp;
- _updateCenterAndAngles(isSVGCompliant());
+ _updateCenterAndAngles();
}
/// @}
/// @name Access computed parameters of the arc
/// @{
- Coord center(Dim2 d) const { return _center[d]; }
+ Coord center(Dim2 d) const { return _ellipse.center(d); }
/** @brief Get the arc's center
* @return The arc's center, situated on the intersection of the ellipse's rays */
- Point center() const { return _center; }
- /** @brief Get the extent of the arc
- * @return The angle between the initial and final point, in arc's angular coordinates */
- Coord sweepAngle() const {
- return extent();
- }
+ Point center() const { return _ellipse.center(); }
/// @}
/// @name Angular evaluation
@@ -177,14 +180,13 @@ public:
* This function returns the transform that maps the unit circle to the arc's ellipse.
* @return Transform from unit circle to the arc's ellipse */
Affine unitCircleTransform() const;
+ Affine inverseUnitCircleTransform() const;
/// @}
- /** @brief Check whether the arc adheres to SVG 1.1 implementation guidelines */
- virtual bool isSVGCompliant() const { return false; }
-
- /// Check whether both rays are nonzero
+ /** @brief Check whether both rays are nonzero.
+ * If they are not, the arc is represented as a line segment instead. */
bool isChord() const {
- return _rays[0] == 0 || _rays[Y] == 0;
+ return ray(X) == 0 || ray(Y) == 0;
}
std::pair<EllipticalArc, EllipticalArc> subdivide(Coord t) const {
@@ -203,15 +205,16 @@ public:
virtual Curve* duplicate() const { return new EllipticalArc(*this); }
virtual void setInitial(Point const &p) {
_initial_point = p;
- _updateCenterAndAngles(isSVGCompliant());
+ _updateCenterAndAngles();
}
virtual void setFinal(Point const &p) {
_final_point = p;
- _updateCenterAndAngles(isSVGCompliant());
+ _updateCenterAndAngles();
}
virtual bool isDegenerate() const {
return _initial_point == _final_point;
}
+ virtual bool isLineSegment() const { return isChord(); }
virtual Rect boundsFast() const {
return boundsExact();
}
@@ -230,13 +233,14 @@ public:
}
return allNearestTimes(p, from, to).front();
}
+ virtual std::vector<CurveIntersection> intersect(Curve const &other, Coord eps=EPSILON) const;
virtual int degreesOfFreedom() const { return 7; }
virtual Curve *derivative() const;
virtual void transform(Affine const &m);
virtual Curve &operator*=(Translate const &m) {
- _initial_point += m.vector();
- _final_point += m.vector();
- _center += m.vector();
+ _initial_point *= m;
+ _final_point *= m;
+ _ellipse *= m;
return *this;
}
@@ -248,28 +252,34 @@ public:
virtual D2<SBasis> toSBasis() const;
virtual double valueAt(Coord t, Dim2 d) const {
- return valueAtAngle(angleAt(t), d);
- }
- virtual Point pointAt(Coord t) const {
- return pointAtAngle(angleAt(t));
+ if (isChord()) return chord().valueAt(t, d);
+ return valueAtAngle(angleAt(t), d);
}
+ virtual Point pointAt(Coord t) const;
virtual Curve* portion(double f, double t) const;
virtual Curve* reverse() const;
virtual bool operator==(Curve const &c) const;
virtual void feed(PathSink &sink, bool moveto_initial) const;
protected:
- void _updateCenterAndAngles(bool svg);
+ void _updateCenterAndAngles();
+ void _filterIntersections(std::vector<ShapeIntersection> &xs, bool is_first) const;
Point _initial_point, _final_point;
- Point _rays, _center;
- Angle _rot_angle;
+ Ellipse _ellipse;
bool _large_arc;
private:
Coord map_to_01(Coord angle) const;
}; // end class EllipticalArc
+
+// implemented in elliptical-arc-from-sbasis.cpp
+bool arc_from_sbasis(EllipticalArc &ea, D2<SBasis> const &in,
+ double tolerance = EPSILON, unsigned num_samples = 20);
+
+std::ostream &operator<<(std::ostream &out, EllipticalArc const &ea);
+
} // end namespace Geom
#endif // LIB2GEOM_SEEN_ELLIPTICAL_ARC_H