2016-03-30 22 views
1

私は個人的なプロジェクトとして小さなグラフ書き込みプログラムを書いています。2つの2次元座標系間の座標変換

各点はWPFのキャンバスに描画されることになっているが、私は、グラフの座標系、例からポイントを翻訳悩み抱えている:x = 600 to 0y = 400 to 0:キャンバスに、x = -8 to 4y=-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] 
      }; 
     } 
    } 
} 

答えて

0

:私は興味がある人のために、ここでVector4.Transform()が何をするのか...

コードを、誤解されなければなりません。私は行列を使用しませんが、それはあなたが探しているものではないかもしれません。グラフの座標範囲とコンテナ(キャンバス)の幅と高さを保存するだけです。これ

public static System.Windows.Point ConvertToScreen(this System.Windows.Point point, CartesianExtents2D extents, double containerWidth, double containerHeight) 
{ 
    var x = (point.X - extents.XMinimum) * containerWidth/(extents.XMaximum - extents.XMinimum); 
    var y = (extents.YMaximum - point.Y) * containerHeight/(extents.YMaximum - extents.YMinimum); 
    return new System.Windows.Point(x, y); 

}

public static System.Windows.Point ConvertToReal(this System.Windows.Point point, CartesianExtents2D extents, double containerWidth, double containerHeight,) 
{ 
    var x = extents.XMinimum + (point.X * (extents.XMaximum - extents.XMinimum))/containerWidth; 
    var y = extents.YMaximum - (point.Y * (extents.YMaximum - extents.YMinimum))/containerHeight; 
    return new System.Windows.Point(x, y); 
} 

コール:私は、2つの拡張機能を提供

Point p = new Point(); 
p.ConvertToReal(...); 

私はCartesianExtents2Dの内容は明白である願って - Xのためだけの最小値と最大値をとy

+0

私はこの方法を早く見つけ出し、それを最初に使いました。私がこれまでに何もしたことがないので、ほとんどのマトリックスは、いくつかのグラフィック操作を学ぶ方法として使用されています。タイトルの質問に答えてこの答えを受け入れる – Clanrat