/// <summary> /// Creates a skew matrix for the given point and angle. /// </summary> /// <param name="origin">The origin point to rotate around</param> /// <param name="degreesX">The x-angle in degrees.</param> /// <param name="degreesY">The y-angle in degrees.</param> /// <returns>The rotation <see cref="Matrix3x2"/></returns> public static Matrix3x2 CreateSkew(Point origin, float degreesX, float degreesY) { float radiansX = ImageMaths.DegreesToRadians(degreesX); float radiansY = ImageMaths.DegreesToRadians(degreesY); return(Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(origin.X, origin.Y))); }
public static Matrix3x2 CreateSkew(float degreesX, float degreesY, PointF centerPoint) { float radiansX = MathF.DegreeToRadian(degreesX); float radiansY = MathF.DegreeToRadian(degreesY); return(Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(centerPoint.X, centerPoint.Y))); }
public void Matrix3x2CreateSkewIdentityTest() { Matrix3x2 expected = Matrix3x2.Identity; Matrix3x2 actual = Matrix3x2.CreateSkew(0, 0); Assert.AreEqual(expected, actual, "Matrix3x2.CreateSkew did not return the expected value."); }
public void AppendSkewDegrees_WithSkewCenter( int width, int height, float degreesX, float degreesY, float cx, float cy, float x, float y) { var size = new Size(width, height); TBuilder builder = this.CreateBuilder(); var centerPoint = new Vector2(cx, cy); this.AppendSkewDegrees(builder, degreesX, degreesY, centerPoint); var matrix = Matrix3x2.CreateSkew(GeometryUtilities.DegreeToRadian(degreesX), GeometryUtilities.DegreeToRadian(degreesY), centerPoint); var position = new Vector2(x, y); var expected = Vector2.Transform(position, matrix); Vector2 actual = this.Execute(builder, new Rectangle(Point.Empty, size), position); Assert.Equal(actual, expected, Comparer); }
public void Matrix3x2CreateSkewIdentityTest() { Matrix3x2 expected = Matrix3x2.Identity; Matrix3x2 actual = Matrix3x2.CreateSkew(0, 0); Assert.Equal(expected, actual); }
public void CreatePDF(Stream stream) { const string baseTxt = "Text drawn at (0,36) in a 4\"x2\" box"; var doc = new GcPdfDocument(); var page = doc.NewPage(); var g = page.Graphics; var box = new RectangleF(0, 36, 72 * 4, 72 * 2); // #1: DrawBox($"Box 1: {baseTxt}, no transformations.", g, box); // var translate0 = Matrix3x2.CreateTranslation(72 * 1, 72 * 4); var scale0 = Matrix3x2.CreateScale(0.5f); // Transforms are applied in order from last to first. // #2: g.Transform = scale0 * translate0; DrawBox($"Box 2: {baseTxt}, translated by (1\",4\") and scaled by 0.5.", g, box); // #3: g.Transform = translate0 * scale0; DrawBox($"Box 3: {baseTxt}, scaled by 0.5 and translated by (1\",4\").", g, box); // var translate1 = Matrix3x2.CreateTranslation(72 * 3, 72 * 5); var scale1 = Matrix3x2.CreateScale(0.7f); var rotate0 = Matrix3x2.CreateRotation((float)(-70 * Math.PI) / 180f); // 70 degrees CCW // #4: g.Transform = rotate0 * translate1 * scale1; DrawBox($"Box 4: {baseTxt}, scaled by 0.7, translated by (3\",5\"), and rotated 70 degrees counterclockwise.", g, box); // #5: g.Transform = Matrix3x2.CreateTranslation(36, 72) * g.Transform; DrawBox($"Box 5: {baseTxt}, applied current transform (Box 4), and translated by (1/2\",1\").", g, box); // #6: g.Transform = // rotate0 * Matrix3x2.CreateSkew((float)(-45 * Math.PI) / 180f, (float)(20 * Math.PI) / 180f) * Matrix3x2.CreateTranslation(72 * 3, 72 * 7); DrawBox($"Box 6: {baseTxt}, translated by (3\",7\"), and skewed -45 degrees on axis X and 20 degrees on axis Y.", g, box); // #7: g.Transform = Matrix3x2.CreateRotation((float)Math.PI) * Matrix3x2.CreateTranslation(page.Size.Width - 72, page.Size.Height - 72); DrawBox($"Box 7: {baseTxt}, translated by (7.5\",10\"), and rotated by 180 degrees.", g, box); // We can remove any transformations on a graphics like so: g.Transform = Matrix3x2.Identity; // Done: doc.Save(stream); }
internal static Matrix3x2 GetMatrix(double centerX, double centerY, double angleXDegree, double angleYDegree) { var angleX = (float)MathEx.ToRadians(angleXDegree); var angleY = (float)MathEx.ToRadians(angleYDegree); var centerPoint = new Vector2((float)centerX, (float)centerY); return(Matrix3x2.CreateSkew(angleX, angleY, centerPoint)); }
internal override Matrix3x2 ToNativeTransform(Size size) { var centerPoint = new Vector2( (float)(Origin.X * size.Width + CenterX), (float)(Origin.Y * size.Height + CenterY)); return(Matrix3x2.CreateSkew((float)MathEx.ToRadians(AngleX), (float)MathEx.ToRadians(AngleY), centerPoint)); }
private void UpdateDefaultDrawingAttributes() { if (_inkPresenter != null) { InkDrawingAttributes drawingAttributes = _inkPresenter.CopyDefaultDrawingAttributes(); drawingAttributes.IgnorePressure = true; switch (drawingColor.SelectedValue.ToString()) { case "Red": drawingAttributes.Color = Colors.Red; break; case "Green": drawingAttributes.Color = Colors.Green; break; case "Blue": drawingAttributes.Color = Colors.Blue; break; } drawingAttributes.Size = new Size(drawingSize.Value, drawingSize.Value); drawingAttributes.DrawAsHighlighter = drawingDrawAsHighlighter.IsChecked.Value; drawingAttributes.FitToCurve = drawingFitToCurve.IsChecked.Value; drawingAttributes.PenTip = drawingPenTip.IsOn ? PenTipShape.Circle : PenTipShape.Rectangle; if (drawingPenTipTransform.IsChecked == true) { drawingAttributes.PenTipTransform = Matrix3x2.CreateSkew(4, 4); } else { drawingAttributes.PenTipTransform = Matrix3x2.Identity; } _inkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes); if (chkErasing.IsChecked == true) { _inkPresenter.InputProcessingConfiguration.Mode = InkInputProcessingMode.Erasing; } else { _inkPresenter.InputProcessingConfiguration.Mode = InkInputProcessingMode.Inking; } _inkPresenter.IsInputEnabled = chkIsInputEnabled.IsChecked.Value; } }
public void DrawPolygon_Transformed <TPixel>(TestImageProvider <TPixel> provider) where TPixel : unmanaged, IPixel <TPixel> { PointF[] simplePath = { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; provider.RunValidatingProcessorTest( c => c.SetDrawingTransform(Matrix3x2.CreateSkew(GeometryUtilities.DegreeToRadian(-15), 0, new Vector2(200, 200))) .DrawPolygon(Color.White, 2.5f, simplePath)); }
public void Transform_Point_Should_Return_Correct_Value_For_Skewed_Matrix() { var expected = Vector2.Transform( new Vector2(1, 1), Matrix3x2.CreateSkew(30, 20)); var matrix = Matrix.CreateSkew(30, 20); var point = new Point(1, 1); var actual = matrix.Transform(point); AssertCoordinatesEqualWithReducedPrecision(expected, actual); }
/// <summary> /// Skew /// </summary> /// <param name="value"> The destination value.</param> /// <param name="indicatorMode"> The indicator mode </param> /// <returns> The produced matrix. </returns> public Matrix3x2 TransformSkew(float value, IndicatorMode indicatorMode = IndicatorMode.LeftTop) { Vector2 horizontal = this.Horizontal; float horizontalHalf = horizontal.Length() / 2; Vector2 footPoint = FanKit.Math.FootPoint(this.Center, this.LeftBottom, this.RightBottom); float verticalHalf = Vector2.Distance(this.Center, footPoint); float radians = Transformer.GetRadians(horizontal) / 180.0f * FanKit.Math.Pi; float skew = -value / 180.0f * FanKit.Math.Pi; //Vector2 Vector2 postion; Vector2 center; switch (indicatorMode) { case IndicatorMode.LeftTop: case IndicatorMode.Top: case IndicatorMode.RightTop: postion = new Vector2(-horizontalHalf, 0); center = this.CenterTop; break; case IndicatorMode.LeftBottom: case IndicatorMode.Bottom: case IndicatorMode.RightBottom: postion = new Vector2(-horizontalHalf, -verticalHalf * 2); center = this.CenterBottom; break; default: postion = new Vector2(-horizontalHalf, -verticalHalf); center = this.Center; break; } //Matrix Matrix3x2 skewMatrix = Matrix3x2.CreateSkew(skew, 0) * Matrix3x2.CreateRotation(radians) * Matrix3x2.CreateTranslation(center); Transformer zeroTransformer = new Transformer(horizontalHalf * 2, verticalHalf * 2, postion); Transformer transformer = Transformer.Multiplies(zeroTransformer, skewMatrix); return(Transformer.FindHomography(transformer, this)); }
public void Matrix3x2CreateSkewCenterTest() { float skewX = 1, skewY = 2; Vector2 center = new Vector2(23, 42); Matrix3x2 skewAroundZero = Matrix3x2.CreateSkew(skewX, skewY, Vector2.Zero); Matrix3x2 skewAroundZeroExpected = Matrix3x2.CreateSkew(skewX, skewY); Assert.True(MathHelper.Equal(skewAroundZero, skewAroundZeroExpected)); Matrix3x2 skewAroundCenter = Matrix3x2.CreateSkew(skewX, skewY, center); Matrix3x2 skewAroundCenterExpected = Matrix3x2.CreateTranslation(-center) * Matrix3x2.CreateSkew(skewX, skewY) * Matrix3x2.CreateTranslation(center); Assert.True(MathHelper.Equal(skewAroundCenter, skewAroundCenterExpected)); }
public void Matrix3x2CreateSkewXYTest() { Matrix3x2 expected = new Matrix3x2(1, -0.414213562373095f, 1, 1, 0, 0); Matrix3x2 actual = Matrix3x2.CreateSkew(MathHelper.Pi / 4, -MathHelper.Pi / 8); Assert.True(MathHelper.Equal(expected, actual)); Vector2 result = Vector2.Transform(new Vector2(0, 0), actual); Assert.True(MathHelper.Equal(new Vector2(0, 0), result)); result = Vector2.Transform(new Vector2(1, 0), actual); Assert.True(MathHelper.Equal(new Vector2(1, -0.414213562373095f), result)); result = Vector2.Transform(new Vector2(0, 1), actual); Assert.True(MathHelper.Equal(new Vector2(1, 1), result)); result = Vector2.Transform(new Vector2(1, 1), actual); Assert.True(MathHelper.Equal(new Vector2(2, 0.585786437626905f), result)); }
public void Matrix3x2CreateSkewYTest() { Matrix3x2 expected = new Matrix3x2(1, -0.414213562373095f, 0, 1, 0, 0); Matrix3x2 actual = Matrix3x2.CreateSkew(0, -MathHelper.Pi / 8); Assert.True(MathHelper.Equal(expected, actual)); expected = new Matrix3x2(1, 0.414213562373095f, 0, 1, 0, 0); actual = Matrix3x2.CreateSkew(0, MathHelper.Pi / 8); Assert.True(MathHelper.Equal(expected, actual)); Vector2 result = Vector2.Transform(new Vector2(0, 0), actual); Assert.True(MathHelper.Equal(new Vector2(0, 0), result)); result = Vector2.Transform(new Vector2(1, 0), actual); Assert.True(MathHelper.Equal(new Vector2(1, 0.414213568f), result)); result = Vector2.Transform(new Vector2(-1, 0), actual); Assert.True(MathHelper.Equal(new Vector2(-1, -0.414213568f), result)); result = Vector2.Transform(new Vector2(10, 3), actual); Assert.True(MathHelper.Equal(new Vector2(10, 7.14213568f), result)); }
public void Matrix3x2CreateSkewXTest() { Matrix3x2 expected = new Matrix3x2(1, 0, -0.414213562373095, 1, 0, 0); Matrix3x2 actual = Matrix3x2.CreateSkew(-MathHelper.Pi / 8, 0); Assert.True(MathHelper.Equal(expected, actual)); expected = new Matrix3x2(1, 0, 0.414213562373095, 1, 0, 0); actual = Matrix3x2.CreateSkew(MathHelper.Pi / 8, 0); Assert.True(MathHelper.Equal(expected, actual)); Vector2 result = Vector2.Transform(new Vector2(0, 0), actual); Assert.True(MathHelper.Equal(new Vector2(0, 0), result)); result = Vector2.Transform(new Vector2(0, 1), actual); Assert.True(MathHelper.Equal(new Vector2(0.414213568, 1), result)); result = Vector2.Transform(new Vector2(0, -1), actual); Assert.True(MathHelper.Equal(new Vector2(-0.414213568, -1), result)); result = Vector2.Transform(new Vector2(3, 10), actual); Assert.True(MathHelper.Equal(new Vector2(7.14213568, 10), result)); }
public Matrix3x2 CreateSkewFromScalarXYWithCenterBenchmark() => Matrix3x2.CreateSkew(1.0f, 2.0f, Vector2.Zero);
public Matrix3x2 CreateSkewFromScalarXYBenchmark() => Matrix3x2.CreateSkew(1.0f, 2.0f);
/// <summary> /// Gets the matrix. /// </summary> /// <param name="image">The image.</param> /// <param name="targetLocation">The target location.</param> /// <returns>The matrix used for the transformation</returns> protected override Matrix3x2 GetMatrix(Image image, Rectangle targetLocation) { return(Matrix3x2.CreateSkew(XAngle, YAngle, targetLocation.Center)); }
/// <summary> /// Appends a skew matrix using the given angles in radians at the given origin. /// </summary> /// <param name="radiansX">The X angle, in radians.</param> /// <param name="radiansY">The Y angle, in radians.</param> /// <param name="origin">The skew origin point.</param> /// <returns>The <see cref="AffineTransformBuilder"/>.</returns> public AffineTransformBuilder AppendSkewRadians(float radiansX, float radiansY, Vector2 origin) => this.AppendMatrix(Matrix3x2.CreateSkew(radiansX, radiansY, origin));
/// <summary> /// Creates a skew matrix from the given angles in radians and a center point. /// </summary> /// <param name="degreesX">The X angle, in degrees.</param> /// <param name="degreesY">The Y angle, in degrees.</param> /// <param name="centerPoint">The center point.</param> /// <returns>A skew matrix.</returns> public static Matrix3x2 CreateSkewDegrees(float degreesX, float degreesY, PointF centerPoint) => Matrix3x2.CreateSkew(MathF.ToRadians(degreesX), MathF.ToRadians(degreesY), centerPoint);
/// <summary> /// Creates a skew matrix from the given angles in degrees and a center point. /// </summary> /// <param name="degreesX">The X angle, in degrees.</param> /// <param name="degreesY">The Y angle, in degrees.</param> /// <param name="centerPoint">The center point.</param> /// <returns>A skew matrix.</returns> public static Matrix3x2 CreateSkewDegrees(float degreesX, float degreesY, PointF centerPoint) => Matrix3x2.CreateSkew(GeometryUtilities.DegreeToRadian(degreesX), GeometryUtilities.DegreeToRadian(degreesY), centerPoint);
private BuiltInExpressionFfi() { _registry = new DelegateExpressionFfi { { "Abs", (float f) => Math.Abs(f) }, { "Abs", (Vector2 v) => Vector2.Abs(v) }, { "Abs", (Vector3 v) => Vector3.Abs(v) }, { "Abs", (Vector4 v) => Vector4.Abs(v) }, { "ACos", (float f) => (float)Math.Acos(f) }, { "ASin", (float f) => (float)Math.Asin(f) }, { "ATan", (float f) => (float)Math.Atan(f) }, { "Ceil", (float f) => (float)Math.Ceiling(f) }, { "Clamp", (float a1, float a2, float a3) => MathUtilities.Clamp(a1, a2, a3) }, { "Clamp", (Vector2 a1, Vector2 a2, Vector2 a3) => Vector2.Clamp(a1, a2, a3) }, { "Clamp", (Vector3 a1, Vector3 a2, Vector3 a3) => Vector3.Clamp(a1, a2, a3) }, { "Clamp", (Vector4 a1, Vector4 a2, Vector4 a3) => Vector4.Clamp(a1, a2, a3) }, { "Concatenate", (Quaternion a1, Quaternion a2) => Quaternion.Concatenate(a1, a2) }, { "Cos", (float a) => (float)Math.Cos(a) }, /* * TODO: * ColorHsl(Float h, Float s, Float l) * ColorLerpHSL(Color colorTo, CompositionColorcolorFrom, Float progress) */ { "ColorLerp", (Avalonia.Media.Color to, Avalonia.Media.Color from, float progress) => ColorInterpolator.LerpRGB(to, from, progress) }, { "ColorLerpRGB", (Avalonia.Media.Color to, Avalonia.Media.Color from, float progress) => ColorInterpolator.LerpRGB(to, from, progress) }, { "ColorRGB", (float a, float r, float g, float b) => Avalonia.Media.Color.FromArgb( (byte)MathUtilities.Clamp(a, 0, 255), (byte)MathUtilities.Clamp(r, 0, 255), (byte)MathUtilities.Clamp(g, 0, 255), (byte)MathUtilities.Clamp(b, 0, 255) ) }, { "Distance", (Vector2 a1, Vector2 a2) => Vector2.Distance(a1, a2) }, { "Distance", (Vector3 a1, Vector3 a2) => Vector3.Distance(a1, a2) }, { "Distance", (Vector4 a1, Vector4 a2) => Vector4.Distance(a1, a2) }, { "DistanceSquared", (Vector2 a1, Vector2 a2) => Vector2.DistanceSquared(a1, a2) }, { "DistanceSquared", (Vector3 a1, Vector3 a2) => Vector3.DistanceSquared(a1, a2) }, { "DistanceSquared", (Vector4 a1, Vector4 a2) => Vector4.DistanceSquared(a1, a2) }, { "Floor", (float v) => (float)Math.Floor(v) }, { "Inverse", (Matrix3x2 v) => Inverse(v) }, { "Inverse", (Matrix4x4 v) => Inverse(v) }, { "Length", (Vector2 a1) => a1.Length() }, { "Length", (Vector3 a1) => a1.Length() }, { "Length", (Vector4 a1) => a1.Length() }, { "Length", (Quaternion a1) => a1.Length() }, { "LengthSquared", (Vector2 a1) => a1.LengthSquared() }, { "LengthSquared", (Vector3 a1) => a1.LengthSquared() }, { "LengthSquared", (Vector4 a1) => a1.LengthSquared() }, { "LengthSquared", (Quaternion a1) => a1.LengthSquared() }, { "Lerp", (float a1, float a2, float a3) => Lerp(a1, a2, a3) }, { "Lerp", (Vector2 a1, Vector2 a2, float a3) => Vector2.Lerp(a1, a2, a3) }, { "Lerp", (Vector3 a1, Vector3 a2, float a3) => Vector3.Lerp(a1, a2, a3) }, { "Lerp", (Vector4 a1, Vector4 a2, float a3) => Vector4.Lerp(a1, a2, a3) }, { "Ln", (float f) => (float)Math.Log(f) }, { "Log10", (float f) => (float)Math.Log10(f) }, { "Matrix3x2.CreateFromScale", (Vector2 v) => Matrix3x2.CreateScale(v) }, { "Matrix3x2.CreateFromTranslation", (Vector2 v) => Matrix3x2.CreateTranslation(v) }, { "Matrix3x2.CreateRotation", (float v) => Matrix3x2.CreateRotation(v) }, { "Matrix3x2.CreateScale", (Vector2 v) => Matrix3x2.CreateScale(v) }, { "Matrix3x2.CreateSkew", (float a1, float a2, Vector2 a3) => Matrix3x2.CreateSkew(a1, a2, a3) }, { "Matrix3x2.CreateTranslation", (Vector2 v) => Matrix3x2.CreateScale(v) }, { "Matrix3x2", (float m11, float m12, float m21, float m22, float m31, float m32) => new Matrix3x2(m11, m12, m21, m22, m31, m32) }, { "Matrix4x4.CreateFromAxisAngle", (Vector3 v, float angle) => Matrix4x4.CreateFromAxisAngle(v, angle) }, { "Matrix4x4.CreateFromScale", (Vector3 v) => Matrix4x4.CreateScale(v) }, { "Matrix4x4.CreateFromTranslation", (Vector3 v) => Matrix4x4.CreateTranslation(v) }, { "Matrix4x4.CreateScale", (Vector3 v) => Matrix4x4.CreateScale(v) }, { "Matrix4x4.CreateTranslation", (Vector3 v) => Matrix4x4.CreateScale(v) }, { "Matrix4x4", (Matrix3x2 m) => new Matrix4x4(m) }, { "Matrix4x4", (float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) => new Matrix4x4( m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44) }, { "Max", (float a1, float a2) => Math.Max(a1, a2) }, { "Max", (Vector2 a1, Vector2 a2) => Vector2.Max(a1, a2) }, { "Max", (Vector3 a1, Vector3 a2) => Vector3.Max(a1, a2) }, { "Max", (Vector4 a1, Vector4 a2) => Vector4.Max(a1, a2) }, { "Min", (float a1, float a2) => Math.Min(a1, a2) }, { "Min", (Vector2 a1, Vector2 a2) => Vector2.Min(a1, a2) }, { "Min", (Vector3 a1, Vector3 a2) => Vector3.Min(a1, a2) }, { "Min", (Vector4 a1, Vector4 a2) => Vector4.Min(a1, a2) }, { "Mod", (float a, float b) => a % b }, { "Normalize", (Quaternion a) => Quaternion.Normalize(a) }, { "Normalize", (Vector2 a) => Vector2.Normalize(a) }, { "Normalize", (Vector3 a) => Vector3.Normalize(a) }, { "Normalize", (Vector4 a) => Vector4.Normalize(a) }, { "Pow", (float a, float b) => (float)Math.Pow(a, b) }, { "Quaternion.CreateFromAxisAngle", (Vector3 a, float b) => Quaternion.CreateFromAxisAngle(a, b) }, { "Quaternion", (float a, float b, float c, float d) => new Quaternion(a, b, c, d) }, { "Round", (float a) => (float)Math.Round(a) }, { "Scale", (Matrix3x2 a, float b) => a * b }, { "Scale", (Matrix4x4 a, float b) => a * b }, { "Scale", (Vector2 a, float b) => a * b }, { "Scale", (Vector3 a, float b) => a * b }, { "Scale", (Vector4 a, float b) => a * b }, { "Sin", (float a) => (float)Math.Sin(a) }, { "SmoothStep", (float a1, float a2, float a3) => SmoothStep(a1, a2, a3) }, { "SmoothStep", (Vector2 a1, Vector2 a2, Vector2 a3) => SmoothStep(a1, a2, a3) }, { "SmoothStep", (Vector3 a1, Vector3 a2, Vector3 a3) => SmoothStep(a1, a2, a3) }, { "SmoothStep", (Vector4 a1, Vector4 a2, Vector4 a3) => SmoothStep(a1, a2, a3) }, // I have no idea how to do a spherical interpolation for a scalar value, so we are doing a linear one { "Slerp", (float a1, float a2, float a3) => Lerp(a1, a2, a3) }, { "Slerp", (Quaternion a1, Quaternion a2, float a3) => Quaternion.Slerp(a1, a2, a3) }, { "Sqrt", (float a) => (float)Math.Sqrt(a) }, { "Square", (float a) => a * a }, { "Tan", (float a) => (float)Math.Tan(a) }, { "ToRadians", (float a) => (float)(a * Math.PI / 180) }, { "ToDegrees", (float a) => (float)(a * 180d / Math.PI) }, { "Transform", (Vector2 a, Matrix3x2 b) => Vector2.Transform(a, b) }, { "Transform", (Vector3 a, Matrix4x4 b) => Vector3.Transform(a, b) }, { "Vector2", (float a, float b) => new Vector2(a, b) }, { "Vector3", (float a, float b, float c) => new Vector3(a, b, c) }, { "Vector3", (Vector2 v2, float z) => new Vector3(v2, z) }, { "Vector4", (float a, float b, float c, float d) => new Vector4(a, b, c, d) }, { "Vector4", (Vector2 v2, float z, float w) => new Vector4(v2, z, w) }, { "Vector4", (Vector3 v3, float w) => new Vector4(v3, w) }, }; }
internal override Matrix3x2 ToNativeTransform(Size size) { var centerPoint = new Vector2((float)CenterX, (float)CenterY); return(Matrix3x2.CreateSkew((float)MathEx.ToRadians(AngleX), (float)MathEx.ToRadians(AngleY), centerPoint)); }
/// <summary> /// Creates a skew matrix from the given angles in degrees. /// </summary> /// <param name="degreesX">The X angle, in degrees.</param> /// <param name="degreesY">The Y angle, in degrees.</param> /// <returns>A skew matrix.</returns> public static Matrix3x2 CreateSkewDegrees(float degreesX, float degreesY) => Matrix3x2.CreateSkew(MathFExtensions.DegreeToRadian(degreesX), MathFExtensions.DegreeToRadian(degreesY));
/// <summary> /// Creates a skew matrix from the given angles in radians. /// </summary> /// <param name="degreesX">The X angle, in degrees.</param> /// <param name="degreesY">The Y angle, in degrees.</param> /// <returns>A skew matrix.</returns> public static Matrix3x2 CreateSkewDegrees(float degreesX, float degreesY) => Matrix3x2.CreateSkew(MathF.ToRadians(degreesX), MathF.ToRadians(degreesY));
/// <summary> /// Appends a skew matrix using the given angles in radians at the given origin. /// </summary> /// <param name="radiansX">The X angle, in radians.</param> /// <param name="radiansY">The Y angle, in radians.</param> /// <param name="origin">The skew origin point.</param> /// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns> public ProjectiveTransformBuilder AppendSkewRadians(float radiansX, float radiansY, Vector2 origin) => this.AppendMatrix(new Matrix4x4(Matrix3x2.CreateSkew(radiansX, radiansY, origin)));
/// <summary> /// Creates a skew matrix from the given angles in radians and a center point. /// </summary> /// <param name="radiansX">The X angle, in radians.</param> /// <param name="radiansY">The Y angle, in radians.</param> /// <param name="centerPoint">The center point.</param> /// <returns>A skew matrix.</returns> public static Matrix3x2 CreateSkew(float radiansX, float radiansY, PointF centerPoint) => Matrix3x2.CreateSkew(radiansX, radiansY, centerPoint);
// Main entry point. public void CreatePDF(Stream stream) { var doc = new GcPdfDocument(); var page = doc.Pages.Add(); var g = page.Graphics; // Document header: g.DrawString("Shapes", new TextFormat() { Font = StandardFonts.TimesBold, FontSize = 14, Underline = true, }, new RectangleF(PointF.Empty, new SizeF(page.Size.Width, 44)), TextAlignment.Center, ParagraphAlignment.Far); // Pen used to draw shapes: var pen = new Pen(Color.Orange, 1); pen.LineJoin = PenLineJoin.Round; int fill = 100; // Surfaces fill alpha // Set up the helper layout grid: var grid = new { Cols = 3, Rows = 5, MarginX = 72, MarginY = 36, Radius = 36, StepX = (page.Size.Width - 144) / 3, StepY = (page.Size.Height - 72) / 5, }; // Insertion point of the next figure's center: PointF startIp = new PointF(grid.MarginX + grid.StepX / 2, grid.MarginY + grid.StepY / 2 + 10); PointF ip = startIp; // Debug code to show the layout grid: /* * var ipp = ip; * for (int i = 0; i < grid.Cols; ++i) * { * ipp.Y = ip.Y; * for (int j = 0; j < grid.Rows; ++j) * { * g.DrawRectangle(new RectangleF(ipp.X - grid.Radius, ipp.Y - grid.Radius, grid.Radius * 2, grid.Radius * 2), Color.LightGreen, 0.5f); * ipp.Y += grid.StepY; * } * ipp.X += grid.StepX; * } */ // Circle: g.DrawEllipse(new RectangleF(ip.X - grid.Radius, ip.Y - grid.Radius, grid.Radius * 2, grid.Radius * 2), pen); DrawCaption(g, ip, grid.Radius, "Circle"); ip.X += grid.StepX; // Ellipse: g.DrawEllipse(new RectangleF(ip.X - grid.Radius * 1.4f, ip.Y - grid.Radius / 2, grid.Radius * 2 * 1.4f, grid.Radius), pen); DrawCaption(g, ip, grid.Radius, "Ellipse"); ip.X += grid.StepX; // Cylinder: float radX = grid.Radius / 1.4f; float radY = grid.Radius / 6; float height = grid.Radius * 1.8f; g.DrawEllipse(new RectangleF(ip.X - radX, ip.Y - height / 2, radX * 2, radY * 2), pen); g.FillEllipse(new RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), Color.FromArgb(fill, pen.Color)); g.DrawEllipse(new RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), pen); g.DrawLine(new PointF(ip.X - radX, ip.Y - height / 2 + radY), new PointF(ip.X - radX, ip.Y + height / 2 - radY), pen); g.DrawLine(new PointF(ip.X + radX, ip.Y - height / 2 + radY), new PointF(ip.X + radX, ip.Y + height / 2 - radY), pen); DrawCaption(g, ip, grid.Radius, "Cylinder"); ip.X = startIp.X; ip.Y += grid.StepY; pen.Color = Color.Indigo; // Square: DrawPolygon(g, ip, grid.Radius, 4, (float)-Math.PI / 4, pen, "Square"); ip.X += grid.StepX; // Rectangle: float rectQx = 1.4f; float rectQy = 0.6f; var rect = new RectangleF(ip.X - grid.Radius * rectQx, ip.Y - grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy); g.DrawRectangle(rect, pen); DrawCaption(g, ip, grid.Radius, "Rectangle"); ip.X += grid.StepX; // Cube: float cubex = 6; var cubePtsFar = DrawPolygon(g, new PointF(ip.X - cubex, ip.Y - cubex), grid.Radius, 4, (float)-Math.PI / 4, pen); var cubePtsNear = DrawPolygon(g, new PointF(ip.X + cubex, ip.Y + cubex), grid.Radius, 4, (float)-Math.PI / 4, pen); g.DrawLine(cubePtsFar[0], cubePtsNear[0], pen); g.DrawLine(cubePtsFar[1], cubePtsNear[1], pen); g.DrawLine(cubePtsFar[2], cubePtsNear[2], pen); g.DrawLine(cubePtsFar[3], cubePtsNear[3], pen); g.FillPolygon(new PointF[] { cubePtsFar[1], cubePtsFar[2], cubePtsNear[2], cubePtsNear[1], }, Color.FromArgb(fill, pen.Color)); DrawCaption(g, ip, grid.Radius, "Cube"); ip.X = startIp.X; ip.Y += grid.StepY; pen.Color = Color.DarkGreen; // Pentagon: DrawPolygon(g, ip, grid.Radius, 5, (float)-Math.PI / 2, pen, "Pentagon"); ip.X += grid.StepX; // Hexagon: // For sample sake, we apply a transform to make the hexagon wider and shorter: g.Transform = Matrix3x2.CreateScale(1.4f, 0.8f) * Matrix3x2.CreateTranslation(ip.X, ip.Y); DrawPolygon(g, PointF.Empty, grid.Radius, 6, 0, pen, null); g.Transform = Matrix3x2.Identity; DrawCaption(g, ip, grid.Radius, "Hexagon"); ip.X += grid.StepX; // Octagon: DrawPolygon(g, ip, grid.Radius, 8, (float)-Math.PI / 8, pen, "Octagon"); ip.X = startIp.X; ip.Y += grid.StepY; pen.Color = Color.DarkRed; // Triangle: DrawPolygon(g, ip, grid.Radius, 3, (float)-Math.PI / 2, pen, "Triangle"); ip.X += grid.StepX; // Filled pentagram: var pts = DrawPolygon(g, ip, grid.Radius, 5, (float)-Math.PI / 2, pen, "Pentagram"); pts = new PointF[] { pts[0], pts[2], pts[4], pts[1], pts[3], }; g.FillPolygon(pts, Color.FromArgb(fill, pen.Color)); g.DrawPolygon(pts, pen); ip.X += grid.StepX; // Set up a simple kind of oblique projection to draw a pyramid: var angle = Math.PI / 6; float s = (float)Math.Sin(angle); float c = (float)Math.Cos(angle); Func <float, float, float, PointF> project = (x_, y_, z_) => new PointF(x_ - c * y_ * 0.5f, -(z_ - s * y_ * 0.5f)); Func <Vector3, PointF> p3d = v_ => project(v_.X, v_.Y, v_.Z); float hedge = grid.Radius; // 1/2 edge // Debug - draw the 3 axis: /* * g.DrawLine(project(0, 0, 0), project(100, 0, 0), Color.Red); * g.DrawLine(project(0, 0, 0), project(0, 100, 0), Color.Green); * g.DrawLine(project(0, 0, 0), project(0, 0, 100), Color.Blue); */ // 3d points forming a square pyramid: var pts3d = new Vector3[] { new Vector3(-hedge, -hedge, 0), new Vector3(hedge, -hedge, 0), new Vector3(hedge, hedge, 0), new Vector3(-hedge, hedge, 0), new Vector3(0, 0, hedge * 2), }; // Project the points to draw the pyramid: pts = pts3d.Select(v_ => p3d(v_)).ToArray(); g.Transform = Matrix3x2.CreateTranslation(ip.X, ip.Y + hedge * 0.7f); // Visible edges: g.DrawPolygon(new PointF[] { pts[4], pts[1], pts[2], pts[3], pts[4], pts[2] }, pen); // Invisible edges: pen.Width /= 2; pen.Color = Color.FromArgb(fill, pen.Color); g.DrawLine(pts[0], pts[4], pen); g.DrawLine(pts[0], pts[1], pen); g.DrawLine(pts[0], pts[3], pen); g.FillPolygon(pts.Take(4).ToArray(), pen.Color); // g.Transform = Matrix3x2.Identity; DrawCaption(g, ip, grid.Radius, "Pyramid"); ip.X = startIp.X; ip.Y += grid.StepY; pen.Width *= 2; pen.Color = Color.Green; // Cone: float baseh = grid.Radius * 0.3f; pts = DrawPolygon(g, ip, grid.Radius, 3, (float)-Math.PI / 2, null, "Cone"); g.DrawLines(new PointF[] { pts[2], pts[0], pts[1] }, pen); rect = new RectangleF(pts[2].X, pts[2].Y - baseh / 2, pts[1].X - pts[2].X, baseh); g.FillEllipse(rect, Color.FromArgb(fill, pen.Color)); g.DrawEllipse(rect, pen); ip.X += grid.StepX; // Parallelogram (use graphics.Transform on a rectangle): rect = new RectangleF(-grid.Radius * rectQx, -grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy); g.Transform = Matrix3x2.CreateSkew((float)Math.PI / 6, 0) * Matrix3x2.CreateTranslation(ip.X, ip.Y); g.DrawRectangle(rect, pen); g.Transform = Matrix3x2.Identity; DrawCaption(g, ip, grid.Radius, "Parallelogram"); ip.X += grid.StepX; // Trapezoid (use DrawPolygon to just get the points of the square): float dx = 10; pts = DrawPolygon(g, ip, grid.Radius, 4, (float)-Math.PI / 4, null, "Trapezoid"); pts[0].X -= dx; pts[1].X += dx; pts[2].X -= dx; pts[3].X += dx; g.DrawPolygon(pts, pen); // Done: doc.Save(stream); }
/// <summary> /// Creates a skew matrix from the given angles in degrees. /// </summary> /// <param name="degreesX">The X angle, in degrees.</param> /// <param name="degreesY">The Y angle, in degrees.</param> /// <returns>A skew matrix.</returns> public static Matrix3x2 CreateSkewDegrees(float degreesX, float degreesY) => Matrix3x2.CreateSkew(GeometryUtilities.DegreeToRadian(degreesX), GeometryUtilities.DegreeToRadian(degreesY));