summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 09ace14)
raw | patch | inline | side by side (parent: 09ace14)
author | ishmal <ishmal@users.sourceforge.net> | |
Sun, 23 Apr 2006 07:35:38 +0000 (07:35 +0000) | ||
committer | ishmal <ishmal@users.sourceforge.net> | |
Sun, 23 Apr 2006 07:35:38 +0000 (07:35 +0000) |
src/extension/internal/odf.cpp | patch | blob | history |
index edbc26c98d23741a189a9b1d5046ef92452ec4c5..da3a4068bb32e84769ba3b9475068dd2397973bf 100644 (file)
NR::Matrix getV();
/**
- * Return the three singular values along the diagonal
+ * Return the right singular vectors
+ * @return U x Vtransposed
+ */
+ NR::Matrix getUVt();
+
+ /**
+ * Return the s[0] value
*/
- void getSingularValues(double &s0, double &s1, double &s2);
+ double getS0();
+
+ /**
+ * Return the s[1] value
+ */
+ double getS1();
+
+ /**
+ * Return the s[2] value
+ */
+ double getS2();
/**
* Two norm
};
-static double hypot(double a, double b)
+static double svd_hypot(double a, double b)
{
double r;
// Compute 2-norm of k-th column without under/overflow.
s[k] = 0;
for (int i = k; i < m; i++) {
- s[k] = hypot(s[k],A[i][k]);
+ s[k] = svd_hypot(s[k],A[i][k]);
}
if (s[k] != 0.0) {
if (A[k][k] < 0.0) {
// Compute 2-norm without under/overflow.
e[k] = 0;
for (int i = k+1; i < n; i++) {
- e[k] = hypot(e[k],e[i]);
+ e[k] = svd_hypot(e[k],e[i]);
}
if (e[k] != 0.0) {
if (e[k+1] < 0.0) {
int pp = p-1;
int iter = 0;
- double eps = pow(2.0,-52.0);
- double tiny = pow(2.0,-966.0);
+ //double eps = pow(2.0,-52.0);
+ //double tiny = pow(2.0,-966.0);
+ //let's just calculate these now
+ //a double can be e ± 308.25, so this is safe
+ double eps = 2.22e-16;
+ double tiny = 1.6e-291;
while (p > 0) {
int k,kase;
double f = e[p-2];
e[p-2] = 0.0;
for (int j = p-2; j >= k; j--) {
- double t = hypot(s[j],f);
+ double t = svd_hypot(s[j],f);
double cs = s[j]/t;
double sn = f/t;
s[j] = t;
double f = e[k-1];
e[k-1] = 0.0;
for (int j = k; j < p; j++) {
- double t = hypot(s[j],f);
+ double t = svd_hypot(s[j],f);
double cs = s[j]/t;
double sn = f/t;
s[j] = t;
// Calculate the shift.
- double scale = 0.0;
- double d = fabs(s[p-1]);
- if (d>scale) scale=d;
- d = fabs(s[p-2]);
+ double scale = fabs(s[p-1]);
+ double d = fabs(s[p-2]);
if (d>scale) scale=d;
d = fabs(e[p-2]);
if (d>scale) scale=d;
// Chase zeros.
for (int j = k; j < p-1; j++) {
- double t = hypot(f,g);
+ double t = svd_hypot(f,g);
double cs = f/t;
double sn = g/t;
if (j != k) {
V[i][j] = t;
}
}
- t = hypot(f,g);
+ t = svd_hypot(f,g);
cs = f/t;
sn = g/t;
s[j] = t;
NR::Matrix SingularValueDecomposition::getU()
{
NR::Matrix mat(U[0][0], U[1][0], U[0][1],
- U[1][1], U[2][0], U[2][1]);
+ U[1][1], U[0][2], U[1][2]);
return mat;
}
NR::Matrix SingularValueDecomposition::getV()
{
NR::Matrix mat(V[0][0], V[1][0], V[0][1],
- V[1][1], V[2][0], V[2][1]);
+ V[1][1], V[0][2], V[1][2]);
return mat;
}
/**
- * Return the three singular values along the diagonal
+ * Return the right singular vectors
+ * @return U x Vtransposed
+ */
+
+NR::Matrix SingularValueDecomposition::getUVt()
+{
+ //instead of sum(row*column), sum(column, column)
+ double a = U[0][0] * V[0][0] + U[1][0] * V[1][0];
+ double b = U[0][0] * V[0][1] + U[1][0] * V[1][1];
+ double c = U[0][1] * V[0][0] + U[1][1] * V[1][0];
+ double d = U[0][1] * V[0][1] + U[1][1] * V[1][1];
+ double e = U[0][2] * V[0][0] + U[1][2] * V[1][0];
+ double f = U[0][2] * V[0][1] + U[1][2] * V[1][1];
+
+ NR::Matrix mat(a, b, c, d, e, f);
+ return mat;
+}
+
+/**
+ * Return the s[0] value
+ */
+double SingularValueDecomposition::getS0()
+{
+ return s[0];
+}
+
+/**
+ * Return the s[1] value
*/
-void SingularValueDecomposition::getSingularValues(
- double &s0, double &s1, double &s2)
+double SingularValueDecomposition::getS1()
{
- s0 = s[0];
- s1 = s[1];
- s2 = s[2];
+ return s[1];
+}
+
+/**
+ * Return the s[2] value
+ */
+double SingularValueDecomposition::getS2()
+{
+ return s[2];
}
/**
}
+/**
+ * An affine transformation Q may be decomposed via
+ * singular value decomposition into
+ *
+ * T = UDVt
+ * = (UDUt)UVt
+ * ('t' means transposed)
+ * where U and V are orthonormal matrices and D is a diagonal
+ * matrix. The decomposition may be interpreted as such:
+ * the image is firstly rotated by UVt. The image is then
+ * rotated by Ut, stretched in the coordinate directions
+ * by D then rotated back by U. The net effect is a slant operation in
+ * some tilt direction followed by an isotropic scale. If rot(x)
+ * is a matrix that rotates by x we can rewrite this as
+ * T = rot(-tau)( k 0, 0 1) rot(tau) rot(theta) S
+ * where S is a scaling matrix, k is a multiplying (contraction)
+ * factor related to slant, tau is the tilt direction and theta
+ * is the initial rotation angle.
+ */
+static void analyzeTransform(NR::Matrix &tf)
+{
+ SingularValueDecomposition svd(tf);
+ double scale1 = svd.getS0();
+ double rotate = svd.getS1();
+ double scale2 = svd.getS2();
+ NR::Matrix u = svd.getU();
+ NR::Matrix v = svd.getV();
+ NR::Matrix uvt = svd.getUVt();
+ g_message("s1:%f rot:%f s2:%f", scale1, rotate, scale2);
+ std::string us = formatTransform(u);
+ g_message("u:%s", us.c_str());
+ std::string vs = formatTransform(v);
+ g_message("v:%s", vs.c_str());
+ std::string uvts = formatTransform(uvt);
+ g_message("uvt:%s", uvts.c_str());
+}
+
+
+
/**
* Method descends into the repr tree, converting image and style info
NR::Matrix itemTransform = item->transform;
std::string itemTransformString = formatTransform(itemTransform);
-
- SingularValueDecomposition svd(itemTransform);
- double scale1, rotate, scale2;
- svd.getSingularValues(scale1, rotate, scale2);
- g_message("s1:%f rot:%f s2:%f", scale1, rotate, scale2);
+ g_message("trans:%s", itemTransformString.c_str());
+ analyzeTransform(itemTransform);
std::string href = getAttribute(node, "xlink:href");
std::map<std::string, std::string>::iterator iter = imageTable.find(href);
void
OdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *uri)
{
+ //g_message("native file:%s\n", uri);
+ documentUri = URI(uri);
+
ZipFile zf;
styleTable.clear();
styleLookupTable.clear();
imageTable.clear();
preprocess(zf, doc->rroot);
- g_message("native file:%s\n", uri);
- documentUri = URI(uri);
if (!writeManifest(zf))
{