Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
transf_mat_3x4.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * 3x4 transformation matrix to map points from projective 3-space into the projective plane
4 *
5 * Authors:
6 * Maximilian Albert <Anhalter42@gmx.de>
7 *
8 * Copyright (C) 2007 Authors
9 *
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
13#include "transf_mat_3x4.h"
14#include <2geom/affine.h>
15#include "svg/stringstream.h"
16#include "syseq.h"
17
18namespace Proj {
19
21 for (unsigned int i = 0; i < 3; ++i) {
22 for (unsigned int j = 0; j < 4; ++j) {
23 tmat[i][j] = (i == j ? 1 : 0); // or should we initialize all values with 0? does it matter at all?
24 }
25 }
26}
27
29 for (unsigned int i = 0; i < 3; ++i) {
30 tmat[i][0] = vp_x[i];
31 tmat[i][1] = vp_y[i];
32 tmat[i][2] = vp_z[i];
33 tmat[i][3] = origin[i];
34 }
35}
36
38 for (unsigned int i = 0; i < 3; ++i) {
39 for (unsigned int j = 0; j < 4; ++j) {
40 tmat[i][j] = rhs.tmat[i][j];
41 }
42 }
43}
44
45Pt2
47 return Proj::Pt2 (tmat[0][axis], tmat[1][axis], tmat[2][axis]);
48}
49
50Pt2
51TransfMat3x4::image (Pt3 const &point) {
52 double x = tmat[0][0] * point[0] + tmat[0][1] * point[1] + tmat[0][2] * point[2] + tmat[0][3] * point[3];
53 double y = tmat[1][0] * point[0] + tmat[1][1] * point[1] + tmat[1][2] * point[2] + tmat[1][3] * point[3];
54 double w = tmat[2][0] * point[0] + tmat[2][1] * point[1] + tmat[2][2] * point[2] + tmat[2][3] * point[3];
55
56 return Pt2 (x, y, w);
57}
58
59Pt3
60TransfMat3x4::preimage (Geom::Point const &pt, double coord, Proj::Axis axis) {
61 const double init_val = std::numeric_limits<double>::quiet_NaN();
62 double x[4] = { init_val, init_val, init_val, init_val };
63 double v[3] = { pt[Geom::X], pt[Geom::Y], 1.0 };
64 int index = (int) axis;
65
66 SysEq::SolutionKind sol = SysEq::gaussjord_solve<3,4>(tmat, x, v, index, coord, true);
67
68 if (sol != SysEq::unique) {
69 if (sol == SysEq::no_solution) {
70 g_warning ("No solution. Please investigate.");
71 } else {
72 g_warning ("Infinitely many solutions. Please investigate.");
73 }
74 }
75 return Pt3(x[0], x[1], x[2], x[3]);
76}
77
78void
80 // FIXME: Do we need to adapt the coordinates in any way or can we just use them as they are?
81 for (int i = 0; i < 3; ++i) {
82 tmat[i][axis] = pt[i];
83 }
84}
85
86void
88 g_return_if_fail (axis != Proj::W);
89 if (has_finite_image(axis)) {
90 Geom::Point dir (column(axis).affine());
91 Geom::Point origin (column(Proj::W).affine());
92 dir -= origin;
93 set_column (axis, Proj::Pt2(dir[Geom::X], dir[Geom::Y], 0));
94 } else {
95 Proj::Pt2 dir (column(axis));
96 Proj::Pt2 origin (column(Proj::W).affine());
97 dir = dir + origin;
98 dir[2] = 1.0;
99 set_column (axis, dir);
100 }
101}
102
103gchar *
106 os << tmat[0][axis] << " : "
107 << tmat[1][axis] << " : "
108 << tmat[2][axis];
109 return g_strdup(os.str().c_str());
110}
111
112/* Check for equality (with a small tolerance epsilon) */
113bool
115{
116 // Should we allow a certain tolerance or "normalize" the matrices first?
117 for (int i = 0; i < 3; ++i) {
118 Proj::Pt2 pt1 = column(Proj::axes[i]);
119 Proj::Pt2 pt2 = rhs.column(Proj::axes[i]);
120 if (pt1 != pt2) {
121 return false;
122 }
123 }
124 return true;
125}
126
127/* Multiply a projective matrix by an affine matrix (by only multiplying the 'affine part' of the
128 * projective matrix) */
131 TransfMat3x4 ret;
132
133 for (int j = 0; j < 4; ++j) {
134 ret.tmat[0][j] = A[0]*tmat[0][j] + A[2]*tmat[1][j] + A[4]*tmat[2][j];
135 ret.tmat[1][j] = A[1]*tmat[0][j] + A[3]*tmat[1][j] + A[5]*tmat[2][j];
136 ret.tmat[2][j] = tmat[2][j];
137 }
138
139 return ret;
140}
141
142// FIXME: Shouldn't rather operator* call operator*= for efficiency? (Because in operator*=
143// there is in principle no need to create a temporary object, which happens in the assignment)
146 *this = *this * A;
147 return *this;
148}
149
150void
151TransfMat3x4::copy_tmat(double rhs[3][4]) {
152 for (int i = 0; i < 3; ++i) {
153 for (int j = 0; j < 4; ++j) {
154 rhs[i][j] = tmat[i][j];
155 }
156 }
157}
158
159void
161 g_print ("Transformation matrix:\n");
162 for (const auto & i : tmat) {
163 g_print (" ");
164 for (double j : i) {
165 g_print ("%8.2f ", j);
166 }
167 g_print ("\n");
168 }
169}
170
171void
173 Proj::Pt2 new_col(column(axis));
174 new_col.normalize();
175 set_image_pt(axis, new_col);
176}
177
178
179} // namespace Proj
180
181/*
182 Local Variables:
183 mode:c++
184 c-file-style:"stroustrup"
185 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
186 indent-tabs-mode:nil
187 fill-column:99
188 End:
189*/
190// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Point origin
Definition aa.cpp:227
3x3 affine transformation matrix.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Two-dimensional point that doubles as a vector.
Definition point.h:66
std::string str() const
void normalize()
Definition proj_pt.cpp:42
Pt2 column(Proj::Axis axis) const
void toggle_finite(Proj::Axis axis)
TransfMat3x4 & operator*=(Geom::Affine const &A)
Pt3 preimage(Geom::Point const &pt, double coord=0, Axis=Z)
void normalize_column(Proj::Axis axis)
void set_image_pt(Proj::Axis axis, Proj::Pt2 const &pt)
bool operator==(const TransfMat3x4 &rhs) const
Pt2 image(Pt3 const &point)
bool has_finite_image(Proj::Axis axis)
void copy_tmat(double rhs[3][4])
void set_column(Proj::Axis axis, Proj::Pt2 pt)
TransfMat3x4 operator*(Geom::Affine const &A) const
char * pt_to_str(Proj::Axis axis)
const double w
Definition conic-4.cpp:19
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Generic auxiliary routines for 3D axes.
Axis axes[4]
SolutionKind
Definition syseq.h:24
@ unique
Definition syseq.h:25
@ no_solution
Definition syseq.h:27
TODO: insert short description here.
int index