/// <summary> /// Push skew (shear) transformation to matrix. The skewing origin is assumed at (0, 0) /// </summary> /// <param name="angleX">X-axis skew angle (in degree)</param> /// <param name="angleY">Y-axis skew angle (in degree)</param> public void Skew(double angleX, double angleY) { //if (currentTransform == null) PushMatrix(); if (currentTransform == null) currentTransform = new Matrix3x3(); currentTransform.SkewRelative(angleX, angleY); transformRequired = true; }
/// <summary> /// Push skew (shear) transformation to matrix /// </summary> /// <param name="angleX">X-axis skew angle (in degree)</param> /// <param name="angleY">Y-axis skew angle (in degree)</param> /// <param name="centerX">X-coordinate of skewing origin</param> /// <param name="centerY">Y-coordinate of skewing origin</param> public void Skew(double angleX, double angleY, double centerX, double centerY) { if (currentTransform == null) currentTransform = new Matrix3x3(); //if (currentTransform == null) PushMatrix(); //currentTransform.Translate(-centerX, -centerY); //currentTransform.Skew(angleX, angleY); //currentTransform.Translate(centerX, centerY); currentTransform.SkewRelative(angleX, angleY, centerY, centerY); transformRequired = true; }
/// <summary> /// Push scale transformation to matrix. The scaling origin is assumed at (0, 0) /// </summary> /// <param name="scaleX">The horizontal factor to scale by</param> /// <param name="scaleY">The vertical factor to scale by</param> public void Scale(double scaleX, double scaleY) { //if (currentTransform == null) PushMatrix(); if (currentTransform == null) currentTransform = new Matrix3x3(); currentTransform.ScaleRelative(scaleX, scaleY); transformRequired = true; }
/// <summary> /// Push scale transformation to matrix. /// </summary> /// <param name="scaleX">The horizontal factor to scale by</param> /// <param name="scaleY">The vertical factor to scale by</param> /// <param name="centerX">X-coordinate of scaling origin</param> /// <param name="centerY">Y-coordinate of scaling origin</param> public void Scale(double scaleX, double scaleY, double centerX, double centerY) { if (currentTransform == null) currentTransform = new Matrix3x3(); //if (currentTransform == null) PushMatrix(); //currentTransform.Translate(centerX, centerY); //currentTransform.Translate(-centerX, -centerY); //currentTransform.Scale(scaleX, scaleY); //currentTransform.Translate(centerX, centerY); currentTransform.ScaleRelative(scaleX, scaleY, centerX, centerY); transformRequired = true; }
/// <summary> /// Push translate transformation to matrix /// </summary> /// <param name="x">horizontal coordinate value to transform by</param> /// <param name="y">vertical coordinate value to transform by</param> public void Translate(double x, double y) { //if (currentTransform == null) PushMatrix(); //currentTransform.Translate(x, y); if (currentTransform == null) currentTransform = new Matrix3x3(); currentTransform.TranslateRelative(x, y); transformRequired = true; }
/// <summary> /// Push rotate transformation to matrix /// </summary> /// <param name="angle">The angle (in degree) to rotate by</param> /// <param name="centerX">X-coordinate of rotation origin</param> /// <param name="centerY">Y-coordinate of rotation origin</param> public void Rotate(double angle, double centerX, double centerY) { //if (currentTransform == null) PushMatrix(); if (currentTransform == null) currentTransform = new Matrix3x3(); currentTransform.RotateRelative(angle, centerX, centerY); transformRequired = true; }
/// <summary> /// Create a new transformation matrix and make it active /// </summary> public void PushMatrix() { if (currentTransform == null) { currentTransform = new Matrix3x3(); } else { //store current transform to stack if (matrixStack == null) matrixStack = new Matrix3x3Stack(); matrixStack.Push(currentTransform); //create a new matrix currentTransform = currentTransform.Clone(); } transformRequired = true; }
/// <summary> /// Remove the currently active transformation matrix, make the previous one in matrix stack active /// </summary> public void PopMatrix() { if (matrixStack != null) { if (matrixStack.Count > 0) { Matrix3x3 prev = matrixStack.Pop(); currentTransform = prev; transformRequired = true; } else { currentTransform = null; transformRequired = false; } } }
/// <summary> /// Apply current transformation for (centerX, centerY) then skew at center point /// </summary> /// <param name="xSkewAngle">x skew angle (in degree)</param> /// <param name="ySkewAngle">y skew angle (in degree)</param> /// <param name="centerX">center point x coordinate</param> /// <param name="centerY">center point y coordinate</param> public void SkewPrepend(double xSkewAngle, double ySkewAngle, double centerX, double centerY) { if ((xSkewAngle != 0) || (ySkewAngle != 0)) { Matrix3x3 matrix = new Matrix3x3(); matrix.Translate(-centerX, -centerY); matrix.Skew(xSkewAngle, ySkewAngle); matrix.Translate(centerX, centerY); // then prepend multiply this.PrependSelfMultiply(matrix.Sx, matrix.Sy, matrix.Shx, matrix.Shy, matrix.Tx, matrix.Ty); //PrependSelfMultiply(1.0, 1.0, // Math.Tan(xSkewAngle * DegreeToRadianFactor), // Math.Tan(ySkewAngle * DegreeToRadianFactor), // centerX, centerY); isChanged = true; SimpleScaleAndTranslateOnly = false; ScaleAndTransformOnly = false; } }
/// <summary> /// Restore the state of this drawer /// </summary> public void Load(object state) { if (state is DrawerState) { DrawerState ds = (DrawerState)state; currentTransform = ds.CurrentTransform; matrixStack = ds.MatrixStack; transformRequired = currentTransform != null; } else Cross.Drawing.IncompatibleTypeException.Publish(state, typeof(DrawerState)); }
/// <summary> /// Calculate just in time property /// </summary> void CalculateJustInTime() { // when there are changed mIsTransformed = ((Sx != 1.0 || Sy != 1 || Shx != 0.0 || Shy != 0.0 || Tx != 0 || Ty != 0)); if (CanInvert()) { //mInvertedMatrix = CloneInverted(); mInvertedMatrix = Clone(); mInvertedMatrix.Invert(); } else { mInvertedMatrix = null; } // turn of the flag isChanged = false; }
/// <summary> /// New matrix from other /// Create a new instance with information from the provided source matrix /// </summary> /// <param name="matrix">The source matrix to copy values from</param> public Matrix3x3(Matrix3x3 source) { Sx = source.Sx; Shy = source.Shy; Shx = source.Shx; Sy = source.Sy; Tx = source.Tx; Ty = source.Ty; //IsTransformed = matrix.IsTransformed; ScaleXFactor = source.ScaleXFactor; ScaleYFactor = source.ScaleYFactor; SimpleScaleAndTranslateOnly = source.SimpleScaleAndTranslateOnly; ScaleAndTransformOnly = source.ScaleAndTransformOnly; isChanged = true; }
/// <summary> /// Product maxtrix from two matrix /// </summary> /// <param name="source">source matrix</param> /// <param name="dest">dest matrix</param> /// <returns></returns> public static Matrix3x3 operator *(Matrix3x3 source, Matrix3x3 dest) { Matrix3x3 result = new Matrix3x3(source); result.Multiply(dest); return result; }
/// <summary> /// Multiply current matrix to another one /// </summary> /// <param name="matrix">input matrix</param> public void Multiply(Matrix3x3 matrix) { t0 = Sx * matrix.Sx + Shy * matrix.Shx; t2 = Shx * matrix.Sx + Sy * matrix.Shx; t4 = Tx * matrix.Sx + Ty * matrix.Shx + matrix.Tx; t1 = Sx * matrix.Shy + Shy * matrix.Sy; t3 = Shx * matrix.Shy + Sy * matrix.Sy; t5 = Tx * matrix.Shy + Ty * matrix.Sy + matrix.Ty; Sx = t0; Shx = t2; Tx = t4; Shy = t1; Sy = t3; Ty = t5; ScaleXFactor *= matrix.ScaleXFactor; ScaleYFactor *= matrix.ScaleYFactor; //ScaleAndTranslateOnly true when in both matrix is true SimpleScaleAndTranslateOnly = SimpleScaleAndTranslateOnly && (matrix.SimpleScaleAndTranslateOnly); ScaleAndTransformOnly = ScaleAndTransformOnly && (matrix.ScaleAndTransformOnly); isChanged = true; }
/// <summary> /// Add a path to current path by transforming data from source path /// NOTES: Currently this method does not support Arc commands from source path /// </summary> /// <param name="path">The source path to copy from</param> public void AddPath(DrawingPath path, Matrix3x3 matrix) { // using array .copy only ReserveSpace(path.CommandCount, path.CoordinateCount); // change private fields currentFirstCommandIndex = CommandCount + path.currentFirstCommandIndex; currentFirstCoordinateIndex = CoordinateCount + path.currentFirstCoordinateIndex; currentFirstX = path.currentFirstX; currentFirstY = path.currentFirstY; // copy command Array.Copy(path.Commands, 0, Commands, CommandCount, path.CommandCount); CommandCount += path.CommandCount; // copy coordinates //Array.Copy(path.Coordinates, 0, Coordinates, CoordinateCount, path.CoordinateCount); //CoordinateCount += path.CoordinateCount; double sx = matrix.Sx; double sy = matrix.Sy; double shx = matrix.Shx; double shy = matrix.Shy; double tx = matrix.Tx; double ty = matrix.Ty; //double tmp = x; //x = tmp * Sx + y * Shx + Tx; //y = tmp * Shy + y * Sy + Ty; double[] pathCoodinates = path.Coordinates; for (int cooridnateIndex = 0; cooridnateIndex < path.CoordinateCount; cooridnateIndex += 2) { Coordinates[CoordinateCount++] = pathCoodinates[cooridnateIndex] * sx + pathCoodinates[cooridnateIndex + 1] * shx + tx; Coordinates[CoordinateCount++] = pathCoodinates[cooridnateIndex] * shy + pathCoodinates[cooridnateIndex + 1] * sy + ty; } }