Added Matrix.cs, matrix multiply method, Vector to matrix factory method

This commit is contained in:
Mike Smith 2016-02-14 22:53:04 -08:00
parent 5a61dd2199
commit 3711b6ef6b
3 changed files with 173 additions and 1 deletions

View File

@ -41,6 +41,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Sizes.cs" />
<Compile Include="Spatial\Matrix.cs" />
<Compile Include="Transforms\HulledObject.cs" />
<Compile Include="Transforms\IMimicer.cs" />
<Compile Include="Transforms\LinearExtrudedObject.cs" />

View File

@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OSCADSharp.Spatial
{
/// <summary>
/// An n-dimensional Matrix for performing operations on doubles that
/// represent spatial positions
/// </summary>
internal class Matrix
{
#region Fields/Properties
private double[] values;
internal int ColumnCount { get; private set; }
internal int RowCount { get; private set; }
internal double[] GetValues()
{
return this.values;
}
#endregion
#region Constructors
internal Matrix(double[] values, int numRows, int numColumns)
{
this.values = values;
this.RowCount = numRows;
this.ColumnCount = numColumns;
}
internal Matrix(List<double> values, int numColumns)
{
this.values = values.ToArray();
this.ColumnCount = numColumns;
this.RowCount = values.Count / numColumns;
}
#endregion
#region Public API
internal Matrix Multiply(Matrix other)
{
double[] otherValues = other.GetValues();
List<double> result = new List<double>();
int currentRowInResult = 0;
//Iterate over each row in this matrix
for (int row = 0; row < this.RowCount; row++)
{
//And iterate over each column in the other matrix
for (int column = 0; column < other.ColumnCount; column++)
{
// Multiply item in the current row on the left, by each item in column right
// and add it to the result in the corresponding row/column
for (int leftMatrixColumn = 0; leftMatrixColumn < this.ColumnCount; leftMatrixColumn++)
{
result[currentRowInResult * other.ColumnCount + column] +=
this.values[row * this.ColumnCount + leftMatrixColumn] *
otherValues[leftMatrixColumn * other.ColumnCount + column];
}
}
currentRowInResult++;
}
return new Matrix(result, other.ColumnCount);
}
#endregion
#region Static Transformation Matrices
private static readonly double piOver180 = Math.PI / 180;
private static double toRadians(double degrees)
{
return piOver180 * degrees;
}
private static readonly Matrix identity = new Matrix(new double[] {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
}, 4, 4);
internal static Matrix Identity { get { return identity; } }
/// <summary>
/// Gets a transformation matrix for performing rotations on the X-Axis
/// (Assuming you are in a right-handed 3D world)
/// </summary>
/// <param name="angle">Degrees of rotation</param>
/// <returns>Transformation matrix to perform the rotation</returns>
internal static Matrix XRotation(double angle)
{
double radAngle = toRadians(angle);
double[] rotationArr = new double[] {
1 , 0, 0, 0,
0, Math.Cos(radAngle), Math.Sin(radAngle), 0,
0, -Math.Sin(radAngle), Math.Cos(radAngle), 0,
0, 0, 0, 1
};
return new Matrix(rotationArr, 4, 4);
}
/// <summary>
/// Gets a transformation matrix for performing rotations on the Y-Axis
/// (Assuming you are in a right-handed 3D world)
/// </summary>
/// <param name="angle">Degrees of rotation</param>
/// <returns>Transformation matrix to perform the rotation</returns>
internal static Matrix YRotation(double angle)
{
double radAngle = toRadians(angle);
double[] rotationArr = new double[] {
Math.Cos(radAngle), 0, -Math.Sin(radAngle), 0,
0, 1, 0, 0,
Math.Sin(radAngle), 0, Math.Cos(radAngle), 0,
0, 0, 0, 1
};
return new Matrix(rotationArr, 4, 4);
}
/// <summary>
/// Gets a transformation matrix for performing rotations on the Z-Axis
/// (Assuming you are in a right-handed 3D world)
/// </summary>
/// <param name="angle">Degrees of rotation</param>
/// <returns>Transformation matrix to perform the rotation</returns>
internal static Matrix ZRotation(double angle)
{
double radAngle = toRadians(angle);
double[] rotationArr = new double[] {
Math.Cos(radAngle), Math.Sin(radAngle), 0, 0,
-Math.Sin(radAngle), Math.Cos(radAngle), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
return new Matrix(rotationArr, 4, 4);
}
/// <summary>
/// Gets a point's position after rotations have been applied
/// </summary>
/// <param name="point">Point to rotate</param>
/// <param name="xAngle"></param>
/// <param name="yAngle"></param>
/// <param name="zAngle"></param>
/// <returns>Point after rotation</returns>
internal static Vector3 GetRotatedPoint(Vector3 point, double xAngle, double yAngle, double zAngle)
{
Matrix transformation = XRotation(xAngle)
.Multiply(YRotation(yAngle))
.Multiply(ZRotation(zAngle));
double[] result = transformation.Multiply(point.ToMatrix()).GetValues();
return new Vector3(result[0], result[1], result[2]);
}
#endregion
}
}

View File

@ -1,4 +1,5 @@
using System;
using OSCADSharp.Spatial;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -57,6 +58,12 @@ namespace OSCADSharp
}
#endregion
internal Matrix ToMatrix()
{
double[] coords = { this.X, this.Y, this.Z, 0 };
return new Matrix(coords, 4, 1);
}
public override string ToString()
{
return String.Format("[X: {0}, Y: {1}, Z: {2}]", this.X.ToString(), this.Y.ToString(), this.Z.ToString());