/// <summary> /// Perform all Transformation from the list /// </summary> /// <returns>The resulting matrix after all the transform</returns> public double[] ApplyTransforms() { // double[] matrix = new double[] { 1f, 0f, 0f, 1f, 0f, 0f }; Matrix2D matrix = new Matrix2D(); foreach (DrawingTransform transform in _transformList) { switch (transform.TransformType) { case TranformType.Translate: matrix.T1 += transform.Data[0]; matrix.T2 += transform.Data[1]; // matrix[4] += transform.Data[0]; // matrix[5] += transform.Data[1]; break; case TranformType.Scale: matrix.X1 *= transform.Data[0]; matrix.Y1 *= transform.Data[0]; matrix.T1 *= transform.Data[0]; matrix.X2 *= transform.Data[1]; matrix.Y2 *= transform.Data[1]; matrix.T2 *= transform.Data[1]; // matrix[0] *= transform.Data[0]; // matrix[1] *= transform.Data[0]; // matrix[4] *= transform.Data[1]; // matrix[2] *= transform.Data[1]; // matrix[3] *= transform.Data[1]; // matrix[5] *= transform.Data[0]; break; case TranformType.Rotate: double angle = transform.Data[0]; double sin = Math.Sin(angle); double cos = Math.Cos(angle); Matrix2D temp = (Matrix2D)matrix.Clone(); matrix.X1 = temp.X1 * cos + temp.X2 * sin; matrix.X2 = temp.Y1 * cos + temp.Y2 * sin; matrix.T1 = temp.T1 * cos + temp.T2 * sin; matrix.Y1 = -temp.X1 * sin + temp.X2 * cos; matrix.Y2 = -temp.Y1 * sin + temp.Y2 * cos; matrix.T2 = -temp.T1 * sin + temp.T2 * cos; // double[] temp = (double[])matrix.Clone(); // // matrix[0] = temp[0] * cos - temp[2] * sin; // matrix[1] = temp[1] * cos - temp[3] * sin; // matrix[4] = temp[4] * cos - temp[5] * sin; // matrix[2] = temp[0] * sin + temp[2] * cos; // matrix[3] = temp[1] * sin + temp[3] * cos; // matrix[5] = temp[4] * sin + temp[5] * cos; break; default: throw new Exception("Unsupported transform type passed in"); } } Matrix = matrix; return(matrix); }
/// <summary> /// Apply the transform using the supplied matrix /// </summary> /// <param name="matrix">the matrix to be applied (format if x1,y1,x2,y2,t1,t2)</param> public void Transform(Matrix2D matrix) { if (_imageSource == null) { throw new RenderingVerificationException("ImageSource not Assigned, cannot transform a unknow image"); } if (matrix == null) { throw new ArgumentException("Invalid argument passed in, must be a valid instance (not set to null) of Matrix2D or an array of double of length " + Matrix2D.Length); } if (matrix.IsInvertible == false) { throw new Matrix2DException("Matrix passed in is not inversible, cannot transform using this matrix (matrix passed in : )" + matrix.ToString()); } if (matrix.IsIdentity) { _imageTransformed = (IImageAdapter)_imageSource.Clone(); return; } // Create the IImageAdapter to return int width = _imageSource.Width; int height = _imageSource.Height; if (_resizeToFitOutputImage) { double x = 0.0; double y = 0.0; Point topLeft = new Point((int)(x + Math.Sign(x) * 0.5), (int)(y + Math.Sign(y) * 0.5)); x = matrix.X1 * width; y = matrix.X2 * width; Point topRight = new Point((int)(x + Math.Sign(x) * 0.5), (int)(y + Math.Sign(y) * 0.5)); x = matrix.X1 * width + matrix.Y1 * height; y = matrix.X2 * width + matrix.Y2 * height; Point bottomRight = new Point((int)(x + Math.Sign(x) * 0.5), (int)(y + Math.Sign(y) * 0.5)); x = matrix.Y1 * height; y = matrix.Y2 * height; Point bottomLeft = new Point((int)(x + Math.Sign(x) * 0.5), (int)(y + Math.Sign(y) * 0.5)); width = (int)Math.Max(Math.Abs(bottomRight.X - topLeft.X), Math.Abs(topRight.X - bottomLeft.X)); height = (int)Math.Max(Math.Abs(bottomRight.Y - topLeft.Y), Math.Abs(topRight.Y - bottomLeft.Y)); } _imageTransformed = new ImageAdapter(width, height, _unassignedColor); // Scale down imnage if needed (average pixels) // double horizontalScaling = double.NaN; if (matrix.X1 != 0) { horizontalScaling = Math.Sqrt(Math.Abs(matrix.Determinant * matrix.Y2 / matrix.X1)); } else { horizontalScaling = Math.Sqrt(Math.Abs(matrix.Determinant * matrix.Y1 / matrix.X2)); } double verticalScaling = Math.Sqrt(matrix.Determinant / horizontalScaling); IImageAdapter scaledImage = BilinearInterpolator.ScaleDown(horizontalScaling, verticalScaling, _imageSource); // Interpolate image (if scaling up and/or rotation applied to image) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { double ix = 0.0; double iy = 0.0; ConvertCoordinates(matrix, x, y, out ix, out iy); _imageTransformed[x, y] = _interpolationMethod(ix, iy, scaledImage, _unassignedColor); } } }
static Matrix2D() { Identity = new Matrix2D(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); }
/// <summary> /// Divide a matrix by another one /// NOT IMPLEMENTED YET, contact the avalon tool team if you need this feature /// </summary> /// <param name="matrix1">The original matrix</param> /// <param name="matrix2">The matrix to divide by</param> /// <returns>The resulting matrix</returns> public static Matrix2D operator /(Matrix2D matrix1, Matrix2D matrix2) { Matrix2D retVal = new Matrix2D(); throw new NotImplementedException("Not implemented, contact the Avalon tool team if you need this feature"); }
/// <summary> /// Create an copy of a Matrix2D class /// </summary> /// <param name="matrix2D">The Matrix2D to copy</param> public Matrix2D(Matrix2D matrix2D) : this() { _matrix = (double[])matrix2D._matrix.Clone(); }