using netDxf; using netDxf.Tables; using Svg; using Svg.Transforms; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; using FontStyle = System.Drawing.FontStyle; using Vector2 = System.Numerics.Vector2; using Vector3 = System.Numerics.Vector3; using Vector4 = System.Numerics.Vector4; namespace InABox.Dxf; internal class TransformData { public DxfData Data { get; set; } private Stack MatrixStack = new(); public Matrix4x4 Transform { get; private set; } = Matrix4x4.Identity; public void PushTransform() { MatrixStack.Push(Transform); } protected virtual void UpdateTransform() { } protected Matrix ProjectMatrix(Matrix4x4 matrix) { var elMatrix = new Matrix3x2(); elMatrix.M11 = (float)matrix.M11; elMatrix.M12 = (float)matrix.M12; elMatrix.M21 = (float)matrix.M21; elMatrix.M22 = (float)matrix.M22; elMatrix.M31 = (float)matrix.M41; elMatrix.M32 = (float)matrix.M42; var newMatrix = new Matrix(); newMatrix.MatrixElements = elMatrix; return newMatrix; } public void PopTransform() { Transform = MatrixStack.Pop(); UpdateTransform(); } public static Matrix4x4 ArbitraryAxisMatrix(Vector3 zAxis) { if (zAxis.Equals(Vector3.UnitZ)) { return Matrix4x4.Identity; } var unitY = Vector3.UnitY; var unitZ = Vector3.UnitZ; var v = ((!(Math.Abs(zAxis.X) < 1.0 / 64.0) || !(Math.Abs(zAxis.Y) < 1.0 / 64.0)) ? Vector3.Cross(unitZ, zAxis) : Vector3.Cross(unitY, zAxis)); v = Vector3.Normalize(v); var vector = Vector3.Cross(zAxis, v); vector = Vector3.Normalize(vector); return new Matrix4x4(v.X, vector.X, zAxis.X, 0, v.Y, vector.Y, zAxis.Y, 0, v.Z, vector.Z, zAxis.Z, 0, 0, 0, 0, 1); } public void ArbitraryAxis(netDxf.Vector3 zAxis) { Transform = ArbitraryAxisMatrix(new((float)zAxis.X, (float)zAxis.Y, (float)zAxis.Z)) * Transform; UpdateTransform(); } public void ArbitraryAxis(Vector3 zAxis) { Transform = ArbitraryAxisMatrix(zAxis) * Transform; UpdateTransform(); } public void Translate(float x, float y) { Transform = Transform.Translate(x, y, 0); UpdateTransform(); } public void Translate(PointF point) { Transform = Transform.Translate(point.X, point.Y, 0); UpdateTransform(); } public void Rotate(float angle) { Transform = Transform.Rotate(0, 0, 1, angle); UpdateTransform(); } public void Scale(float scale) { Scale(scale, scale); } public void Scale(float scaleX, float scaleY) { Transform = Transform.Scale(scaleX, scaleY, 1); UpdateTransform(); } public float ConvertThickness(float thickness) { return thickness == 0 ? 1f / ScaleFactor() : thickness; } public PointF TransformPoint(float x, float y) { var nVec = Vector4.Transform(new Vector4(x, y, 0, 1), Transform); return new(nVec.X, nVec.Y); } public PointF TransformPoint(PointF vec) { var nVec = Vector4.Transform(new Vector4(vec.X, vec.Y, 0, 1), Transform); return new(nVec.X, nVec.Y); } public PointF TransformPoint(netDxf.Vector2 vec) { var nVec = Vector4.Transform(new Vector4((float)vec.X, (float)vec.Y, 0, 1), Transform); return new(nVec.X, nVec.Y); } public PointF TransformPoint(netDxf.Vector3 vec) { var nVec = Vector4.Transform(new Vector4((float)vec.X, (float)vec.Y, (float)vec.Z, 1), Transform); return new(nVec.X, nVec.Y); } public PointF TransformVec(PointF vec) { var nVec = Vector4.Transform(new Vector4(vec.X, vec.Y, 0, 0), Transform); return new(nVec.X, nVec.Y); } public Vector2 TransformVec(Vector2 vec) { var nVec = Vector4.Transform(new Vector4(vec.X, vec.Y, 0, 0), Transform); return new(nVec.X, nVec.Y); } public float ScaleFactor() { return (TransformVec(new Vector2(1, 0))).Length(); } public static PointF ConvertPoint(netDxf.Vector2 vec) { return new PointF((float)vec.X, (float)vec.Y); } public static PointF ConvertPoint(netDxf.Vector3 vec) { return new PointF((float)vec.X, (float)vec.Y); } } internal class DrawData : TransformData { public IGraphics Graphics { get; set; } protected override void UpdateTransform() { base.UpdateTransform(); Graphics.SetTransform(ProjectMatrix(Transform)); } } public interface IGraphics { void SetTransform(Matrix transform); void DrawLine(Color color, float thickness, params PointF[] points); void FillPolygon(Color color, params PointF[] points); /// /// Set the current font to be the default font at the given . /// /// Size of the new font. void SetFont(float fontSize, FontStyle fontStyle = FontStyle.Regular); void SetFont(string fontName, float fontSize, FontStyle fontStyle = FontStyle.Regular); void DrawText(string text, Color color, PointF position); void Clear(Color color); } public class GdiGraphics : IGraphics { public Graphics Graphics { get; set; } private Font Font { get; set; } public GdiGraphics(Graphics graphics) { Graphics = graphics; } public void DrawLine(Color color, float thickness, params PointF[] points) { if(points.Length == 2) { Graphics.DrawLine(new Pen(color, thickness), points[0], points[1]); } else { Graphics.DrawLines(new Pen(color, thickness), points); } } public void DrawText(string text, Color color, PointF position) { Graphics.DrawString(text, Font, new SolidBrush(color), position, StringFormat.GenericTypographic); } public void FillPolygon(Color color, params PointF[] points) { Graphics.FillPolygon(new SolidBrush(color), points); } public void SetFont(string fontName, float fontSize, FontStyle fontStyle) { var fontFamily = new FontFamily(fontName); var font = new Font(fontFamily, fontSize, fontStyle); Font = font; } public void SetFont(float fontSize, FontStyle fontStyle) { var fontFamily = SystemFonts.DefaultFont.FontFamily; var font = new Font(fontFamily, fontSize, fontStyle); Font = font; } public void SetTransform(Matrix transform) { Graphics.Transform = transform; } public void Clear(Color color) { Graphics.Clear(color); } } public class SvgGraphics : IGraphics { public SvgDocument Document { get; set; } private SvgMatrix _transform; private SvgGroup _group; public SvgGraphics(SvgDocument document) { Document = document; _group = new SvgGroup(); } public void SetTransform(Matrix transform) { _transform = new(transform.Elements.ToList()); } public void DrawLine(Color color, float thickness, params PointF[] points) { if(points.Length == 2) { Document.Children.Add(new SvgLine { StartX = points[0].X, StartY = points[0].Y, EndX = points[1].X, EndY = points[1].Y, Transforms = new() { _transform }, Stroke = new SvgColourServer(color), StrokeWidth = thickness }); } else { var line = new SvgPolyline { Transforms = new() { _transform }, Stroke = new SvgColourServer(color), StrokeWidth = thickness }; foreach(var point in points) { line.Points.Add(point.X); line.Points.Add(point.Y); } Document.Children.Add(line); } } public void FillPolygon(Color color, params PointF[] points) { } public void SetFont(float fontSize, FontStyle fontStyle = FontStyle.Regular) { } public void SetFont(string fontName, float fontSize, FontStyle fontStyle = FontStyle.Regular) { } public void DrawText(string text, Color color, PointF position) { } public void Clear(Color color) { } }