私は個人的なプロジェクトとして小さなグラフ書き込みプログラムを書いています。2つの2次元座標系間の座標変換
各点はWPFのキャンバスに描画されることになっているが、私は、グラフの座標系、例からポイントを翻訳悩み抱えている:x = 600 to 0
y = 400 to 0
:キャンバスに、x = -8 to 4
y=-4 to 4
のシステムの一例をコーディネート。
私はhereの方法を使用して、変換方程式を事前計算しています。
しかし、私は乗算の結果に問題がありますv=M^-1*u
。 私の予想結果は次のとおりです。
[0.2 ]
[0.0 ]
[-8.0]
[4.0 ]
しかし、私は取得しています結果は次のとおりです。
[4.0 ]
[-4.0 ]
[0.01 ]
[-0.006]
私は私の変換行列が正しいことを確認していると私は手で計算を行うときに私は期待される結果を得る。
変換式計算する方法:
private void CalculateTransformationFunctions()
{
// Define the transformation matrix
var transformationMatrix = new Matrix4x4
{
M11 = _destArea.XMin,
M12 = _destArea.YMin,
M13 = 1,
M14 = 0,
M21 = -_destArea.YMin,
M22 = _destArea.XMin,
M23 = 0,
M24 = 1,
M31 = _destArea.XMax,
M32 = _destArea.YMax,
M33 = 1,
M34 = 0,
M41 = -_destArea.YMax,
M42 = _destArea.XMax,
M43 = 0,
M44 = 1
};
// Define the source vector
var srcVector = new Vector4
{
X = _srcArea.XMin,
Y = _srcArea.YMax,
Z = _srcArea.XMax,
W = _srcArea.YMin
};
// Invert the transformationmatrix before the multiplication
Matrix4x4 invertedTransformationMatrix;
if(!Matrix4x4.Invert(transformationMatrix,out invertedTransformationMatrix))
throw new Exception();
// Returns the wrong value
var transformResult = Vector4.Transform(srcVector, invertedTransformationMatrix);
float a = transformResult.X,
b = transformResult.Y,
c = transformResult.Z,
d = transformResult.W;
_xTransformationFunction = (x, y) => (a*x + b*y - b*d - a*c)/(a*a + b*b);
_yTransformationFunction = (x, y) => (b*x - a*y - b*c + a*d)/(a*a + b*b);
}
その親クラスのコンストラクタで呼ばれています。
私の質問:
私はVector4.Transform()
がここで何を勘違いだろうか?または私は完全に盲目であり、何かが非常に明白でないか?クラスの
完全なソース:
using System;
using System.Numerics;
using System.Windows;
using System.Windows.Media;
using Grapher.Control.Grapher;
namespace Grapher.GraphingMath
{
public class Translator
{
private GraphingArea _srcArea;
private GraphingArea _destArea;
public GraphingArea SourceArea
{
get
{
return _srcArea;
}
set
{
_srcArea = value;
CalculateTransformationFunctions();
}
}
public GraphingArea DestinationArea
{
get { return _destArea; }
set
{
_destArea = value;
CalculateTransformationFunctions();
}
}
private Func<double, double, double> _xTransformationFunction;
private Func<double, double, double> _yTransformationFunction;
public Translator(GraphingArea sourceArea, GraphingArea destArea)
{
_destArea = destArea;
_srcArea = sourceArea;
CalculateTransformationFunctions();
}
public Point TranslatePoint(Point point)
{
var x = point.X;
var y = point.Y;
return new Point
{
X = _xTransformationFunction(x, y),
Y = _yTransformationFunction(x, y)
};
}
/*
x1 y1 1 0
-y1 x1 0 1
M= x2 y2 1 0
-y2 x2 0 1
x1,y1 = dest_min
x2,y2 = dest_max
*/
private void CalculateTransformationFunctions()
{
// Define the transformation matrix
var transformationMatrix = new Matrix4x4
{
M11 = _destArea.XMin,
M12 = _destArea.YMin,
M13 = 1,
M14 = 0,
M21 = -_destArea.YMin,
M22 = _destArea.XMin,
M23 = 0,
M24 = 1,
M31 = _destArea.XMax,
M32 = _destArea.YMax,
M33 = 1,
M34 = 0,
M41 = -_destArea.YMax,
M42 = _destArea.XMax,
M43 = 0,
M44 = 1
};
// Define the source vector
var srcVector = new Vector4
{
X = _srcArea.XMin,
Y = _srcArea.YMax,
Z = _srcArea.XMax,
W = _srcArea.YMin
};
// Invert the transformationmatrix before the multiplication
Matrix4x4 invertedTransformationMatrix;
if(!Matrix4x4.Invert(transformationMatrix,out invertedTransformationMatrix))
throw new Exception();
// Returns the wrong value
var transformResult = Vector4.Transform(srcVector, invertedTransformationMatrix);
float a = transformResult.X,
b = transformResult.Y,
c = transformResult.Z,
d = transformResult.W;
_xTransformationFunction = (x, y) => (a*x + b*y - b*d - a*c)/(a*a + b*b);
_yTransformationFunction = (x, y) => (b*x - a*y - b*c + a*d)/(a*a + b*b);
}
}
}
やグラフエリアの構造体のために:私のメインの方法では
using System;
namespace Grapher.Control.Grapher
{
public struct GraphingArea
{
public float XMin { get; set; }
public float YMin { get; set; }
public float XMax { get; set; }
public float YMax { get; set; }
public float Width => Math.Abs(XMax - XMin);
public float Height => Math.Abs(YMax - YMin);
}
}
私はこのような翻訳クラスを呼び出す:
Point testPoint = new Point {X = 0, Y = 0};
var srcArea = new GraphingArea
{
XMax = 4,
XMin = -8,
YMax = 4,
YMin = -4
};
var destArea = new GraphingArea
{
XMax = 600,
XMin = 0,
YMax = 400,
YMin = 0
};
var translator = new Translator(srcArea, destArea);
var translatedPoint = translator.TranslatePoint(testPoint);
編集
私自身の行列乗法を書いてしまった。これが役立つ場合、私は知らないが、私は私のプロジェクトの一つに、これらの線に沿って何かを行う
using System.Numerics;
namespace Grapher.GraphingMath.MatrixAndVectorMath
{
public static class Matrix4x4Multiply
{
public static Vector4 Vector4Multiply(Matrix4x4 matrix, Vector4 vector)
{
var mat = new float[4, 4]
{
{matrix.M11, matrix.M12, matrix.M13, matrix.M14},
{matrix.M21, matrix.M22, matrix.M23, matrix.M24},
{matrix.M31, matrix.M32, matrix.M33, matrix.M34},
{matrix.M41, matrix.M42, matrix.M43, matrix.M44}
}; // We'll just wrap the matrix in a float so we can index it.
var vec = new float[4] {vector.X, vector.Y, vector.Z, vector.W}; // And the same with the vector
var result = new float[4] {0, 0, 0, 0};
for (var row = 0; row < mat.GetLength(0); row++)
{
for (var col = 0; col < mat.GetLength(1); col++)
{
result[row] += mat[row, col]*vec[col];
}
}
return new Vector4
{
X = result[0],
Y = result[1],
Z = result[2],
W = result[3]
};
}
}
}
私はこの方法を早く見つけ出し、それを最初に使いました。私がこれまでに何もしたことがないので、ほとんどのマトリックスは、いくつかのグラフィック操作を学ぶ方法として使用されています。タイトルの質問に答えてこの答えを受け入れる – Clanrat