diff --git a/OSCADSharp/OSCADSharp/OSCADSharp.csproj b/OSCADSharp/OSCADSharp/OSCADSharp.csproj index edbee13..bcbbaf7 100644 --- a/OSCADSharp/OSCADSharp/OSCADSharp.csproj +++ b/OSCADSharp/OSCADSharp/OSCADSharp.csproj @@ -41,6 +41,7 @@ + diff --git a/OSCADSharp/OSCADSharp/Spatial/Matrix.cs b/OSCADSharp/OSCADSharp/Spatial/Matrix.cs new file mode 100644 index 0000000..9e22dd8 --- /dev/null +++ b/OSCADSharp/OSCADSharp/Spatial/Matrix.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OSCADSharp.Spatial +{ + /// + /// An n-dimensional Matrix for performing operations on doubles that + /// represent spatial positions + /// + 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 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 result = new List(); + 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; } } + + /// + /// Gets a transformation matrix for performing rotations on the X-Axis + /// (Assuming you are in a right-handed 3D world) + /// + /// Degrees of rotation + /// Transformation matrix to perform the rotation + 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); + } + + /// + /// Gets a transformation matrix for performing rotations on the Y-Axis + /// (Assuming you are in a right-handed 3D world) + /// + /// Degrees of rotation + /// Transformation matrix to perform the rotation + 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); + } + + /// + /// Gets a transformation matrix for performing rotations on the Z-Axis + /// (Assuming you are in a right-handed 3D world) + /// + /// Degrees of rotation + /// Transformation matrix to perform the rotation + 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); + } + + /// + /// Gets a point's position after rotations have been applied + /// + /// Point to rotate + /// + /// + /// + /// Point after rotation + 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 + } +} diff --git a/OSCADSharp/OSCADSharp/Vector3.cs b/OSCADSharp/OSCADSharp/Vector3.cs index 72a9ae1..22d1192 100644 --- a/OSCADSharp/OSCADSharp/Vector3.cs +++ b/OSCADSharp/OSCADSharp/Vector3.cs @@ -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());