summaryrefslogtreecommitdiffstats
path: root/src/2geom/transforms.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/2geom/transforms.cpp')
-rw-r--r--src/2geom/transforms.cpp199
1 files changed, 118 insertions, 81 deletions
diff --git a/src/2geom/transforms.cpp b/src/2geom/transforms.cpp
index 8182ce16d..3a1866c13 100644
--- a/src/2geom/transforms.cpp
+++ b/src/2geom/transforms.cpp
@@ -1,106 +1,143 @@
+/**
+ * @file
+ * @brief Affine transformation classes
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright ?-2009 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.
+ */
+
+#include <boost/concept_check.hpp>
+#include <2geom/point.h>
#include <2geom/transforms.h>
namespace Geom {
-Matrix operator*(Translate const &t, Scale const &s) {
- Matrix ret(s);
- ret[4] = t[X] * s[X];
- ret[5] = t[Y] * s[Y];
- return ret;
+// Point transformation methods.
+Point &Point::operator*=(Translate const &t)
+{
+ _pt[X] += t.vec[X];
+ _pt[Y] += t.vec[Y];
+ return *this;
}
-
-Matrix operator*(Translate const &t, Rotate const &r) {
- Matrix ret(r);
- ret.setTranslation(t.vec * ret);
- return ret;
+Point &Point::operator*=(Scale const &s)
+{
+ _pt[X] *= s.vec[X];
+ _pt[Y] *= s.vec[Y];
+ return *this;
}
-
-Matrix operator*(Scale const &s, Translate const &t) {
- return Matrix(s[0], 0,
- 0 , s[1],
- t[0], t[1]);
+Point &Point::operator*=(Rotate const &r)
+{
+ double x = _pt[X], y = _pt[Y];
+ _pt[X] = x * r.vec[X] - y * r.vec[Y];
+ _pt[Y] = y * r.vec[X] + x * r.vec[Y];
+ return *this;
}
-
-Matrix operator*(Scale const &s, Matrix const &m) {
- Matrix ret(m);
- ret[0] *= s[X];
- ret[1] *= s[X];
- ret[2] *= s[Y];
- ret[3] *= s[Y];
- return ret;
+Point &Point::operator*=(HShear const &h)
+{
+ _pt[X] += h.f * _pt[Y];
+ return *this;
}
-
-Matrix operator*(Matrix const &m, Translate const &t) {
- Matrix ret(m);
- ret[4] += t[X];
- ret[5] += t[Y];
- return ret;
+Point &Point::operator*=(VShear const &v)
+{
+ _pt[Y] += v.f * _pt[X];
+ return *this;
}
-Matrix operator*(Matrix const &m, Scale const &s) {
- Matrix ret(m);
- ret[0] *= s[X]; ret[1] *= s[Y];
- ret[2] *= s[X]; ret[3] *= s[Y];
- ret[4] *= s[X]; ret[5] *= s[Y];
- return ret;
-}
+// Affine multiplication methods.
-Matrix operator*(Matrix const &m, Rotate const &r) {
- // TODO: we just convert the Rotate to a matrix and use the existing operator*(); is there a better way?
- Matrix ret(m);
- ret *= (Matrix) r;
- return ret;
+/** @brief Combine this transformation with a translation. */
+Affine &Affine::operator*=(Translate const &t) {
+ _c[4] += t[X];
+ _c[5] += t[Y];
+ return *this;
}
-Translate pow(Translate const &t, int n) {
- return Translate(t[0]*n, t[1]*n);
+/** @brief Combine this transformation with scaling. */
+Affine &Affine::operator*=(Scale const &s) {
+ _c[0] *= s[X]; _c[1] *= s[Y];
+ _c[2] *= s[X]; _c[3] *= s[Y];
+ _c[4] *= s[X]; _c[5] *= s[Y];
+ return *this;
}
-Coord pow(Coord x, long n) // shamelessly lifted from WP
-{
- Coord result = 1;
- while ( n ) {
- if ( n & 1 ) {
- result = result * x;
- n = n-1;
- }
- x = x*x;
- n = n/2;
- }
- return result;
+/** @brief Combine this transformation a rotation. */
+Affine &Affine::operator*=(Rotate const &r) {
+ // TODO: we just convert the Rotate to an Affine and use the existing operator*=()
+ // is there a better way?
+ *this *= (Affine) r;
+ return *this;
}
-Scale pow(Scale const &s, int n) {
- return Scale(pow(s[0],n), pow(s[1],n));
+/** @brief Combine this transformation with horizontal shearing (skew). */
+Affine &Affine::operator*=(HShear const &h) {
+ _c[0] += h.f * _c[1];
+ _c[2] += h.f * _c[3];
+ _c[4] += h.f * _c[5];
+ return *this;
}
-Rotate pow(Rotate x, long n)
-{
- Rotate result(0,1); // identity
- while ( n ) {
- if ( n & 1 ) {
- result = result * x;
- n = n-1;
- }
- x = x*x;
- n = n/2;
- }
- return result;
+/** @brief Combine this transformation with vertical shearing (skew). */
+Affine &Affine::operator*=(VShear const &v) {
+ _c[1] += v.f * _c[0];
+ _c[3] += v.f * _c[2];
+ _c[5] += v.f * _c[4];
+ return *this;
}
-Matrix pow(Matrix x, long n)
+// 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()
{
- Matrix result;
- result.setIdentity();
- while ( n ) {
- if ( n & 1 ) {
- result = result * x;
- n = n-1;
- }
- x = x*x;
- n = n/2;
- }
- return result;
+#ifdef BOOST_CONCEPT_ASSERT
+ BOOST_CONCEPT_ASSERT((TransformConcept<Translate>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Scale>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Rotate>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<HShear>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<VShear>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Affine>)); // Affine is also a transform
+#endif
+
+ // check inter-transform multiplication
+ Affine m;
+ Translate t(Translate::identity());
+ Scale s(Scale::identity());
+ Rotate r(Rotate::identity());
+ HShear h(HShear::identity());
+ VShear v(VShear::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;
}
}