summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/2geom/2geom.h75
-rw-r--r--src/2geom/affine.h4
-rw-r--r--src/2geom/coord.h6
-rw-r--r--src/2geom/forward.h1
-rw-r--r--src/2geom/generic-interval.h4
-rw-r--r--src/2geom/generic-rect.h44
-rw-r--r--src/2geom/int-point.h5
-rw-r--r--src/2geom/int-rect.h1
-rw-r--r--src/2geom/interval.h15
-rw-r--r--src/2geom/path-intersection.cpp6
-rw-r--r--src/2geom/point.cpp4
-rw-r--r--src/2geom/point.h15
-rw-r--r--src/2geom/rect.h30
-rw-r--r--src/2geom/solve-bezier-parametric.cpp12
-rw-r--r--src/2geom/solver.h4
-rw-r--r--src/2geom/transforms.cpp41
-rw-r--r--src/2geom/transforms.h85
17 files changed, 258 insertions, 94 deletions
diff --git a/src/2geom/2geom.h b/src/2geom/2geom.h
new file mode 100644
index 000000000..000f3423d
--- /dev/null
+++ b/src/2geom/2geom.h
@@ -0,0 +1,75 @@
+/**
+ * \file
+ * \brief Include everything
+ *//*
+ * Authors:
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright 2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_LIB2GEOM_2GEOM_H
+#define SEEN_LIB2GEOM_2GEOM_H
+
+#include <2geom/forward.h>
+
+// primitives
+#include <2geom/coord.h>
+#include <2geom/point.h>
+#include <2geom/interval.h>
+#include <2geom/rect.h>
+#include <2geom/angle.h>
+#include <2geom/ray.h>
+#include <2geom/line.h>
+#include <2geom/affine.h>
+#include <2geom/transforms.h>
+
+// curves and paths
+#include <2geom/curves.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+
+// fragments
+#include <2geom/d2.h>
+#include <2geom/linear.h>
+#include <2geom/bezier.h>
+#include <2geom/sbasis.h>
+
+// others
+#include <2geom/math-utils.h>
+#include <2geom/utils.h>
+
+#endif // SEEN_LIB2GEOM_HEADER_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/2geom/affine.h b/src/2geom/affine.h
index b07fba0f7..d7a7a0692 100644
--- a/src/2geom/affine.h
+++ b/src/2geom/affine.h
@@ -65,7 +65,8 @@ class Affine
, MultipliableNoncommutative< Affine, Rotate
, MultipliableNoncommutative< Affine, HShear
, MultipliableNoncommutative< Affine, VShear
- > > > > > > >
+ , MultipliableNoncommutative< Affine, Zoom
+ > > > > > > > >
{
Coord _c[6];
public:
@@ -113,6 +114,7 @@ public:
Affine &operator*=(Rotate const &r);
Affine &operator*=(HShear const &h);
Affine &operator*=(VShear const &v);
+ Affine &operator*=(Zoom const &);
/// @}
bool operator==(Affine const &o) const {
diff --git a/src/2geom/coord.h b/src/2geom/coord.h
index c7bbcdcd4..f7bf2c5d0 100644
--- a/src/2geom/coord.h
+++ b/src/2geom/coord.h
@@ -69,9 +69,6 @@ struct CoordTraits<IntCoord> {
typedef OptIntInterval OptIntervalType;
typedef IntRect RectType;
typedef OptIntRect OptRectType;
- inline static bool contains(IntCoord low, IntCoord high, IntCoord testlow, IntCoord testhigh) {
- return low <= testlow && testhigh < high;
- }
};
template<>
@@ -81,9 +78,6 @@ struct CoordTraits<Coord> {
typedef OptInterval OptIntervalType;
typedef Rect RectType;
typedef OptRect OptRectType;
- inline static bool contains(Coord low, Coord high, Coord testlow, Coord testhigh) {
- return low <= testlow && testhigh <= high;
- }
};
} // end namespace Geom
diff --git a/src/2geom/forward.h b/src/2geom/forward.h
index b1cad6f1f..0dbd9fa94 100644
--- a/src/2geom/forward.h
+++ b/src/2geom/forward.h
@@ -97,6 +97,7 @@ class Rotate;
class Scale;
class HShear;
class VShear;
+class Zoom;
// templates
template <typename> class D2;
diff --git a/src/2geom/generic-interval.h b/src/2geom/generic-interval.h
index d719c16c8..a32e97d4b 100644
--- a/src/2geom/generic-interval.h
+++ b/src/2geom/generic-interval.h
@@ -106,11 +106,11 @@ public:
/// @{
/** @brief Check whether the interval includes this number. */
bool contains(C val) const {
- return CoordTraits<C>::contains(min(), max(), val, val);
+ return min() <= val && val <= max();
}
/** @brief Check whether the interval includes the given interval. */
bool contains(Self const &val) const {
- return CoordTraits<C>::contains(min(), max(), val.min(), val.max());
+ return min() <= val.min() && val.max() <= max();
}
/** @brief Check whether the intervals have any common elements. */
bool intersects(Self const &val) const {
diff --git a/src/2geom/generic-rect.h b/src/2geom/generic-rect.h
index d60c4bb0f..2db30dfa9 100644
--- a/src/2geom/generic-rect.h
+++ b/src/2geom/generic-rect.h
@@ -40,6 +40,7 @@
#ifndef LIB2GEOM_SEEN_GENERIC_RECT_H
#define LIB2GEOM_SEEN_GENERIC_RECT_H
+#include <limits>
#include <boost/optional.hpp>
namespace Geom {
@@ -53,10 +54,10 @@ class GenericOptRect;
*/
template <typename C>
class GenericRect
- : boost::additive< GenericRect<C>, typename CoordTraits<C>::PointType
- , boost::equality_comparable< GenericRect<C>
- , boost::orable< GenericRect<C>
- , boost::orable< GenericRect<C>, typename CoordTraits<C>::OptRectType
+ : boost::additive< typename CoordTraits<C>::RectType, typename CoordTraits<C>::PointType
+ , boost::equality_comparable< typename CoordTraits<C>::RectType
+ , boost::orable< typename CoordTraits<C>::RectType
+ , boost::orable< typename CoordTraits<C>::RectType, typename CoordTraits<C>::OptRectType
> > > >
{
typedef typename CoordTraits<C>::IntervalType CInterval;
@@ -93,30 +94,37 @@ public:
* @param end End of the range
* @return Rectangle that contains all points from [start, end). */
template <typename InputIterator>
- static GenericRect<C> from_range(InputIterator start, InputIterator end) {
+ static CRect from_range(InputIterator start, InputIterator end) {
assert(start != end);
CPoint p1 = *start++;
- GenericRect<C> result(p1, p1);
+ CRect result(p1, p1);
for (; start != end; ++start) {
result.expandTo(*start);
}
return result;
}
/** @brief Create a rectangle from a C-style array of points it should contain. */
- static GenericRect<C> from_array(CPoint const *c, unsigned n) {
- GenericRect<C> result = GenericRect<C>::from_range(c, c+n);
+ static CRect from_array(CPoint const *c, unsigned n) {
+ CRect result = GenericRect<C>::from_range(c, c+n);
return result;
}
/** @brief Create rectangle from origin and dimensions. */
- static GenericRect<C> from_xywh(C x, C y, C w, C h) {
+ static CRect from_xywh(C x, C y, C w, C h) {
CPoint xy(x, y);
CPoint wh(w, h);
- GenericRect<C> result(xy, xy + wh);
+ CRect result(xy, xy + wh);
return result;
}
/** @brief Create rectangle from origin and dimensions. */
- static GenericRect<C> from_xywh(CPoint const &xy, CPoint const &wh) {
- GenericRect<C> result(xy, xy + wh);
+ static CRect from_xywh(CPoint const &xy, CPoint const &wh) {
+ CRect result(xy, xy + wh);
+ return result;
+ }
+ /// Create infinite rectangle.
+ static CRect infinite() {
+ CPoint p0(std::numeric_limits<C>::min(), std::numeric_limits<C>::min());
+ CPoint p1(std::numeric_limits<C>::max(), std::numeric_limits<C>::max());
+ CRect result(p0, p1);
return result;
}
/// @}
@@ -155,6 +163,8 @@ public:
C width() const { return f[X].extent(); }
/** @brief Get the vertical extent of the rectangle. */
C height() const { return f[Y].extent(); }
+ /** @brief Get the ratio of width to height of the rectangle. */
+ Coord aspectRatio() const { return Coord(width()) / Coord(height()); }
/** @brief Get rectangle's width and height as a point.
* @return Point with X coordinate corresponding to the width and the Y coordinate
@@ -215,7 +225,7 @@ public:
f[X].expandTo(p[X]); f[Y].expandTo(p[Y]);
}
/** @brief Enlarge the rectangle to contain the given rectangle. */
- void unionWith(GenericRect<C> const &b) {
+ void unionWith(CRect const &b) {
f[X].unionWith(b[X]); f[Y].unionWith(b[Y]);
}
/** @brief Enlarge the rectangle to contain the given rectangle.
@@ -255,7 +265,7 @@ public:
return *this;
}
/** @brief Union two rectangles. */
- GenericRect<C> &operator|=(GenericRect<C> const &o) {
+ GenericRect<C> &operator|=(CRect const &o) {
unionWith(o);
return *this;
}
@@ -275,9 +285,9 @@ public:
template <typename C>
class GenericOptRect
: public boost::optional<typename CoordTraits<C>::RectType>
- , boost::orable< GenericOptRect<C>
- , boost::andable< GenericOptRect<C>
- , boost::andable< GenericOptRect<C>, typename CoordTraits<C>::RectType
+ , boost::orable< typename CoordTraits<C>::OptRectType
+ , boost::andable< typename CoordTraits<C>::OptRectType
+ , boost::andable< typename CoordTraits<C>::OptRectType, typename CoordTraits<C>::RectType
> > >
{
typedef typename CoordTraits<C>::IntervalType CInterval;
diff --git a/src/2geom/int-point.h b/src/2geom/int-point.h
index cf2fe720f..1a16ecb7a 100644
--- a/src/2geom/int-point.h
+++ b/src/2geom/int-point.h
@@ -83,6 +83,11 @@ public:
}
IntCoord operator[](Dim2 d) const { return _pt[d]; }
IntCoord &operator[](Dim2 d) { return _pt[d]; }
+
+ IntCoord x() const throw() { return _pt[X]; }
+ IntCoord &x() throw() { return _pt[X]; }
+ IntCoord y() const throw() { return _pt[Y]; }
+ IntCoord &y() throw() { return _pt[Y]; }
/// @}
/// @name Vector-like arithmetic operations
diff --git a/src/2geom/int-rect.h b/src/2geom/int-rect.h
index a143b3ac5..567d42da5 100644
--- a/src/2geom/int-rect.h
+++ b/src/2geom/int-rect.h
@@ -32,7 +32,6 @@
#define LIB2GEOM_SEEN_INT_RECT_H
#include <2geom/coord.h>
-#include <2geom/int-point.h>
#include <2geom/int-interval.h>
#include <2geom/generic-rect.h>
diff --git a/src/2geom/interval.h b/src/2geom/interval.h
index ee6d674d2..e95da4811 100644
--- a/src/2geom/interval.h
+++ b/src/2geom/interval.h
@@ -64,7 +64,7 @@ typedef GenericOptInterval<Coord> OptInterval;
class Interval
: public GenericInterval<Coord>
, boost::multipliable< Interval
- , boost::multipliable< Interval, Coord
+ , boost::multiplicative< Interval, Coord
> >
{
typedef GenericInterval<Coord> Base;
@@ -180,7 +180,20 @@ public:
/// @}
};
+// functions required for Python bindings
+inline Interval unify(Interval const &a, Interval const &b)
+{
+ Interval r = a | b;
+ return r;
+}
+inline OptInterval intersect(Interval const &a, Interval const &b)
+{
+ OptInterval r = a & b;
+ return r;
}
+
+} // end namespace Geom
+
#endif //SEEN_INTERVAL_H
/*
diff --git a/src/2geom/path-intersection.cpp b/src/2geom/path-intersection.cpp
index 7aa662abb..c38776304 100644
--- a/src/2geom/path-intersection.cpp
+++ b/src/2geom/path-intersection.cpp
@@ -226,8 +226,8 @@ intersect_polish_f (const gsl_vector * x, void *params,
#endif
static void
-intersect_polish_root (Curve const &A, double &s,
- Curve const &B, double &t) {
+intersect_polish_root (Curve const &A, double &s, Curve const &B, double &t)
+{
std::vector<Point> as, bs;
as = A.pointAndDerivatives(s, 2);
bs = B.pointAndDerivatives(t, 2);
@@ -271,6 +271,8 @@ intersect_polish_root (Curve const &A, double &s,
}
#ifdef HAVE_GSL
+ int status;
+ size_t iter = 0;
if(0) { // the GSL version is more accurate, but taints this with GPL
const size_t n = 2;
struct rparams p = {A, B};
diff --git a/src/2geom/point.cpp b/src/2geom/point.cpp
index cafc0fdba..3ad9dd1fd 100644
--- a/src/2geom/point.cpp
+++ b/src/2geom/point.cpp
@@ -49,8 +49,8 @@ namespace Geom {
* from the origin (point at 0,0) to the stored coordinates,
* and has methods implementing several vector operations (like length()).
*
- * @par Operator note
- * @par
+ * @section OpNotePoint Operator note
+ *
* Most operators are provided by Boost operator helpers, so they are not visible in this class.
* If @a p, @a q, @a r denote points, @a s a floating-point scalar, and @a m a transformation matrix,
* then the following operations are available:
diff --git a/src/2geom/point.h b/src/2geom/point.h
index 69da8a4ae..0eb771874 100644
--- a/src/2geom/point.h
+++ b/src/2geom/point.h
@@ -58,7 +58,8 @@ class Point
, MultipliableNoncommutative< Point, Scale
, MultipliableNoncommutative< Point, HShear
, MultipliableNoncommutative< Point, VShear
- > > > > > > > > > // this uses chaining so it looks weird, but works
+ , MultipliableNoncommutative< Point, Zoom
+ > > > > > > > > > > // this uses chaining so it looks weird, but works
{
Coord _pt[2];
public:
@@ -111,6 +112,11 @@ public:
Coord operator[](Dim2 d) const throw() { return _pt[d]; }
Coord &operator[](Dim2 d) throw() { return _pt[d]; }
+
+ Coord x() const throw() { return _pt[X]; }
+ Coord &x() throw() { return _pt[X]; }
+ Coord y() const throw() { return _pt[Y]; }
+ Coord &y() throw() { return _pt[Y]; }
/// @}
/// @name Vector operations
@@ -172,12 +178,7 @@ public:
Point &operator*=(Rotate const &r);
Point &operator*=(HShear const &s);
Point &operator*=(VShear const &s);
- /** @brief Transform the point by the inverse of the specified matrix. */
- template <typename T>
- Point &operator/=(T const &m) {
- *this *= m.inverse();
- return *this;
- }
+ Point &operator*=(Zoom const &z);
/// @}
/// @name Conversion to integer points
diff --git a/src/2geom/rect.h b/src/2geom/rect.h
index e9f6cbeb7..f7d331523 100644
--- a/src/2geom/rect.h
+++ b/src/2geom/rect.h
@@ -73,31 +73,7 @@ public:
Rect(Point const &a, Point const &b) : Base(a,b) {}
Rect(Coord x0, Coord y0, Coord x1, Coord y1) : Base(x0, y0, x1, y1) {}
Rect(Base const &b) : Base(b) {}
- /** @brief Create a rectangle from a range of points.
- * The resulting rectangle will contain all ponts from the range.
- * The return type of iterators must be convertible to Point.
- * The range must not be empty. For possibly empty ranges, see OptRect.
- * @param start Beginning of the range
- * @param end End of the range
- * @return Rectangle that contains all points from [start, end). */
- template <typename InputIterator>
- static Rect from_range(InputIterator start, InputIterator end) {
- Rect result = Base::from_range(start, end);
- return result;
- }
- /** @brief Create a rectangle from a C-style array of points it should contain. */
- static Rect from_array(Point const *c, unsigned n) {
- Rect result = Rect::from_range(c, c+n);
- return result;
- }
- static Rect from_xywh(Coord x, Coord y, Coord w, Coord h) {
- Rect result = Base::from_xywh(x, y, w, h);
- return result;
- }
- static Rect from_xywh(Point const &o, Point const &dim) {
- Rect result = Base::from_xywh(o, dim);
- return result;
- }
+ Rect(IntRect const &ir) : Base(ir.min(), ir.max()) {}
/// @}
/// @name Inspect dimensions.
@@ -114,6 +90,10 @@ public:
bool interiorIntersects(Rect const &r) const {
return f[X].interiorIntersects(r[X]) && f[Y].interiorIntersects(r[Y]);
}
+ /** @brief Check whether the interior includes the given point. */
+ bool interiorContains(Point const &p) const {
+ return f[X].interiorContains(p[X]) && f[Y].interiorContains(p[Y]);
+ }
/** @brief Check whether the interior includes all points in the given rectangle.
* Interior of the rectangle is the entire rectangle without its borders. */
bool interiorContains(Rect const &r) const {
diff --git a/src/2geom/solve-bezier-parametric.cpp b/src/2geom/solve-bezier-parametric.cpp
index 437f073a3..76cf65e17 100644
--- a/src/2geom/solve-bezier-parametric.cpp
+++ b/src/2geom/solve-bezier-parametric.cpp
@@ -68,13 +68,13 @@ find_parametric_bezier_roots(Geom::Point const *w, /* The control points */
break;
}
- // Otherwise, solve recursively after subdividing control polygon
- std::vector<Geom::Point> Left(degree + 1); // New left and right
- std::vector<Geom::Point> Right(degree + 1); // control polygons
- Bezier(w, degree, 0.5, &Left[0], &Right[0]);
+ /* Otherwise, solve recursively after subdividing control polygon */
+ Geom::Point Left[degree+1], /* New left and right */
+ Right[degree+1]; /* control polygons */
+ Bezier(w, degree, 0.5, Left, Right);
total_subs ++;
- find_parametric_bezier_roots(&Left[0], degree, solutions, depth + 1);
- find_parametric_bezier_roots(&Right[0], degree, solutions, depth + 1);
+ find_parametric_bezier_roots(Left, degree, solutions, depth+1);
+ find_parametric_bezier_roots(Right, degree, solutions, depth+1);
}
diff --git a/src/2geom/solver.h b/src/2geom/solver.h
index 5e77f13dc..793939b2a 100644
--- a/src/2geom/solver.h
+++ b/src/2geom/solver.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Finding roots of Bernstein-Bezier polynomials
+ *//*
* Authors:
* ? <?@?.?>
*
diff --git a/src/2geom/transforms.cpp b/src/2geom/transforms.cpp
index 2658719c4..b8355cadc 100644
--- a/src/2geom/transforms.cpp
+++ b/src/2geom/transforms.cpp
@@ -35,9 +35,21 @@
#include <boost/concept_check.hpp>
#include <2geom/point.h>
#include <2geom/transforms.h>
+#include <2geom/rect.h>
namespace Geom {
+/** @brief Zoom between rectangles.
+ * Given two rectangles, compute a zoom that maps one to the other.
+ * Rectangles are assumed to have the same aspect ratio. */
+Zoom Zoom::map_rect(Rect const &old_r, Rect const &new_r)
+{
+ Zoom ret;
+ ret._scale = new_r.width() / old_r.width();
+ ret._trans = new_r.min() - old_r.min();
+ return ret;
+}
+
// Point transformation methods.
Point &Point::operator*=(Translate const &t)
{
@@ -68,6 +80,14 @@ Point &Point::operator*=(VShear const &v)
_pt[Y] += v.f * _pt[Y];
return *this;
}
+Point &Point::operator*=(Zoom const &z)
+{
+ _pt[X] += z._trans[X];
+ _pt[Y] += z._trans[Y];
+ _pt[X] *= z._scale;
+ _pt[Y] *= z._scale;
+ return *this;
+}
// Affine multiplication methods.
@@ -110,6 +130,14 @@ Affine &Affine::operator*=(VShear const &v) {
return *this;
}
+Affine &Affine::operator*=(Zoom const &z) {
+ _c[0] *= z._scale; _c[1] *= z._scale;
+ _c[2] *= z._scale; _c[3] *= z._scale;
+ _c[4] += z._trans[X]; _c[5] += z._trans[Y];
+ _c[4] *= z._scale; _c[5] *= z._scale;
+ return *this;
+}
+
// this checks whether the requirements of TransformConcept are satisfied for all transforms.
// if you add a new transform type, include it here!
void check_transforms()
@@ -120,6 +148,7 @@ void check_transforms()
BOOST_CONCEPT_ASSERT((TransformConcept<Rotate>));
BOOST_CONCEPT_ASSERT((TransformConcept<HShear>));
BOOST_CONCEPT_ASSERT((TransformConcept<VShear>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Zoom>));
BOOST_CONCEPT_ASSERT((TransformConcept<Affine>)); // Affine is also a transform
#endif
@@ -130,14 +159,16 @@ void check_transforms()
Rotate r(Rotate::identity());
HShear h(HShear::identity());
VShear v(VShear::identity());
+ Zoom z(Zoom::identity());
// notice that the first column is always the same and enumerates all transform types,
// while the second one changes to each transform type in turn.
- m = t * t; m = t * s; m = t * r; m = t * h; m = t * v;
- m = s * t; m = s * s; m = s * r; m = s * h; m = s * v;
- m = r * t; m = r * s; m = r * r; m = r * h; m = r * v;
- m = h * t; m = h * s; m = h * r; m = h * h; m = h * v;
- m = v * t; m = v * s; m = v * r; m = v * h; m = v * v;
+ m = t * t; m = t * s; m = t * r; m = t * h; m = t * v; m = t * z;
+ m = s * t; m = s * s; m = s * r; m = s * h; m = s * v; m = s * z;
+ m = r * t; m = r * s; m = r * r; m = r * h; m = r * v; m = r * z;
+ m = h * t; m = h * s; m = h * r; m = h * h; m = h * v; m = h * z;
+ m = v * t; m = v * s; m = v * r; m = v * h; m = v * v; m = v * z;
+ m = z * t; m = z * s; m = z * r; m = z * h; m = z * v; m = z * z;
}
}
diff --git a/src/2geom/transforms.h b/src/2geom/transforms.h
index 9623bed26..5627e8b6f 100644
--- a/src/2geom/transforms.h
+++ b/src/2geom/transforms.h
@@ -106,13 +106,14 @@ T pow(T const &t, int n) {
class Translate
: public TransformOperations< Translate >
{
- Translate() : vec(0, 0) {}
Point vec;
public:
- /** @brief Construct a translation from its vector. */
- explicit Translate(Point const &p) : vec(p) {}
- /** @brief Construct a translation from its coordinates. */
- explicit Translate(Coord x, Coord y) : vec(x, y) {}
+ /// Create a translation that doesn't do anything.
+ Translate() : vec(0, 0) {}
+ /// Construct a translation from its vector.
+ Translate(Point const &p) : vec(p) {}
+ /// Construct a translation from its coordinates.
+ Translate(Coord x, Coord y) : vec(x, y) {}
operator Affine() const { Affine ret(1, 0, 0, 1, vec[X], vec[Y]); return ret; }
Coord operator[](Dim2 dim) const { return vec[dim]; }
@@ -120,9 +121,10 @@ public:
Translate &operator*=(Translate const &o) { vec += o.vec; return *this; }
bool operator==(Translate const &o) const { return vec == o.vec; }
- /** @brief Get the inverse translation. */
+ Point vector() const { return vec; }
+ /// Get the inverse translation.
Translate inverse() const { return Translate(-vec); }
- /** @brief Get a translation that doesn't do anything. */
+ /// Get a translation that doesn't do anything.
static Translate identity() { Translate ret; return ret; }
friend class Point;
@@ -136,10 +138,14 @@ class Scale
: public TransformOperations< Scale >
{
Point vec;
- Scale() : vec(1, 1) {}
public:
+ /// Create a scaling that doesn't do anything.
+ Scale() : vec(1, 1) {}
+ /// Create a scaling from two scaling factors given as coordinates of a point.
explicit Scale(Point const &p) : vec(p) {}
+ /// Create a scaling from two scaling factors.
Scale(Coord x, Coord y) : vec(x, y) {}
+ /// Create an uniform scaling from a single scaling factor.
explicit Scale(Coord s) : vec(s, s) {}
inline operator Affine() const { Affine ret(vec[X], 0, 0, vec[Y], 0, 0); return ret; }
@@ -150,6 +156,8 @@ public:
Coord &operator[](unsigned d) { return vec[d]; }
Scale &operator*=(Scale const &b) { vec[X] *= b[X]; vec[Y] *= b[Y]; return *this; }
bool operator==(Scale const &o) const { return vec == o.vec; }
+
+ Point vector() const { return vec; }
Scale inverse() const { return Scale(1./vec[0], 1./vec[1]); }
static Scale identity() { Scale ret; return ret; }
@@ -162,15 +170,16 @@ public:
class Rotate
: public TransformOperations< Rotate >
{
- Rotate() : vec(1, 0) {}
- Point vec;
+ Point vec; ///< @todo Convert to storing the angle, as it's more space-efficient.
public:
+ /// Construct a zero-degree rotation.
+ Rotate() : vec(1, 0) {}
/** @brief Construct a rotation from its angle in radians.
* Positive arguments correspond to counter-clockwise rotations (if Y grows upwards). */
explicit Rotate(Coord theta) : vec(Point::polar(theta)) {}
- /** @brief Construct a rotation from its characteristic vector. */
+ /// Construct a rotation from its characteristic vector.
explicit Rotate(Point const &p) : vec(unit_vector(p)) {}
- /** @brief Construct a rotation from the coordinates of its characteristic vector. */
+ /// Construct a rotation from the coordinates of its characteristic vector.
explicit Rotate(Coord x, Coord y) { Rotate(Point(x, y)); }
operator Affine() const { Affine ret(vec[X], vec[Y], -vec[Y], vec[X], 0, 0); return ret; }
@@ -186,10 +195,10 @@ public:
r.vec = Point(vec[X], -vec[Y]);
return r;
}
- /** @brief Get a 0-degree rotation. */
+ /// @brief Get a zero-degree rotation.
static Rotate identity() { Rotate ret; return ret; }
/** @brief Construct a rotation from its angle in degrees.
- * Positive arguments correspond to counter-clockwise rotations (if Y grows upwards). */
+ * Positive arguments correspond to clockwise rotations if Y grows downwards. */
static Rotate from_degrees(Coord deg) {
Coord rad = (deg / 180.0) * M_PI;
return Rotate(rad);
@@ -213,8 +222,8 @@ public:
void setFactor(Coord nf) { f = nf; }
S &operator*=(S const &s) { f += s.f; return static_cast<S &>(*this); }
bool operator==(S const &s) const { return f == s.f; }
- S inverse() const { return S(-f); }
- static S identity() { return S(0); }
+ S inverse() const { S ret(-f); return ret; }
+ static S identity() { S ret(0); return ret; }
friend class Point;
friend class Affine;
@@ -244,6 +253,48 @@ public:
operator Affine() const { Affine ret(1, f, 0, 1, 0, 0); return ret; }
};
+/** @brief Combination of a translation and uniform scale.
+ * The translation part is applied first, then the result is scaled from the new origin.
+ * This way when the class is used to accumulate a zoom transform, trans always points
+ * to the new origin in original coordinates.
+ * @ingroup Transform */
+class Zoom
+ : public TransformOperations< Zoom >
+{
+ Coord _scale;
+ Point _trans;
+ Zoom() : _scale(1), _trans() {}
+public:
+ /// Construct a zoom from a scaling factor.
+ explicit Zoom(Coord s) : _scale(s), _trans() {}
+ /// Construct a zoom from a translation.
+ explicit Zoom(Translate const &t) : _scale(1), _trans(t.vector()) {}
+ /// Construct a zoom from a scaling factor and a translation.
+ Zoom(Coord s, Translate const &t) : _scale(s), _trans(t.vector()) {}
+
+ operator Affine() const {
+ Affine ret(_scale, 0, 0, _scale, _trans[X] * _scale, _trans[Y] * _scale);
+ return ret;
+ }
+ Zoom &operator*=(Zoom const &z) {
+ _trans += z._trans / _scale;
+ _scale *= z._scale;
+ return *this;
+ }
+ bool operator==(Zoom const &z) const { return _scale == z._scale && _trans == z._trans; }
+
+ Coord scale() const { return _scale; }
+ void setScale(Coord s) { _scale = s; }
+ Point translation() const { return _trans; }
+ void setTranslation(Point const &p) { _trans = p; }
+ Zoom inverse() const { Zoom ret(1/_scale, Translate(-_trans*_scale)); return ret; }
+ static Zoom identity() { Zoom ret(1.0); return ret; }
+ static Zoom map_rect(Rect const &old_r, Rect const &new_r);
+
+ friend class Point;
+ friend class Affine;
+};
+
/** @brief Specialization of exponentiation for Scale.
* @relates Scale */
template<>
@@ -259,7 +310,7 @@ inline Translate pow(Translate const &t, int n) {
return ret;
}
-//TODO: matrix to trans/scale/rotate
+//TODO: decomposition of Affine into some finite combination of the above classes
} // end namespace Geom