From b1ff53da4da7533422425c764b17cd31e79d5d78 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Dec 20 2017 13:55:59 +0000 Subject: assistance: drawing --- diff --git a/mono/Assistance/ActivePoint.cs b/mono/Assistance/ActivePoint.cs index fbecc1f..b588f72 100644 --- a/mono/Assistance/ActivePoint.cs +++ b/mono/Assistance/ActivePoint.cs @@ -21,7 +21,7 @@ namespace Assistance { public static readonly Pen[] pens = new Pen[] { Pens.Gray, Pens.Blue }; public static readonly Brush[] brushes = new Brush[] { Brushes.LightGray, Brushes.LightBlue }; - public readonly Canvas canvas; + public readonly Workarea canvas; public readonly Assistant assistant; public readonly Type type; public Point position; diff --git a/mono/Assistance/Assistance.csproj b/mono/Assistance/Assistance.csproj index f398257..1519ced 100644 --- a/mono/Assistance/Assistance.csproj +++ b/mono/Assistance/Assistance.csproj @@ -38,8 +38,11 @@ - + + + + diff --git a/mono/Assistance/Assistant.cs b/mono/Assistance/Assistant.cs index c6abe90..bdc9581 100644 --- a/mono/Assistance/Assistant.cs +++ b/mono/Assistance/Assistant.cs @@ -10,10 +10,10 @@ namespace Assistance { public static readonly Pen pen = Pens.Gray; public static readonly Pen guidePen = Pens.LightGray; - public readonly Canvas canvas; + public readonly Workarea canvas; public readonly List points = new List(); - public Assistant(Canvas canvas) { + public Assistant(Workarea canvas) { this.canvas = canvas; canvas.assistants.Add(this); } @@ -51,6 +51,13 @@ namespace Assistance { public void drawGuidlines(Graphics g, Point target) { drawGuidlines(g, target, false); } + + public virtual double calcTrackWeight(Track track) { + return double.PositiveInfinity; + } + + public virtual Track modifyTrack(Track track) { + return new Track(); + } } } - diff --git a/mono/Assistance/Canvas.cs b/mono/Assistance/Canvas.cs index a211fb1..ca131fe 100644 --- a/mono/Assistance/Canvas.cs +++ b/mono/Assistance/Canvas.cs @@ -2,46 +2,56 @@ using System; using System.Drawing; using System.Drawing.Imaging; using System.Collections.Generic; -using System.Linq; namespace Assistance { public class Canvas { - public readonly List assistants = new List(); - public readonly List points = new List(); - - public ActivePoint ActivePoint = null; - - public ActivePoint findPoint(Point position) { - foreach(ActivePoint point in points.Reverse()) - if (point.isInside(position)) - return point; - return null; - } - - public void drawGuidlines(Graphics g, Point point) { - foreach(Assistant assistant in assistants) - assistant.drawGuidlines(g, point); - } - - public void drawAssistants(Graphics g) { - foreach(Assistant assistant in assistants) - assistant.draw(g); + public static readonly int initialSize = 100; + public static readonly double incrementScale = 1.2; + + private System.Drawing.Point offset = new System.Drawing.Point(-initialSize/2, -initialSize/2); + private Bitmap bitmap = new Bitmap(initialSize, initialSize); + + public void draw(Graphics g) { + g.DrawImageUnscaled(bitmap, offset); } - public void drawPoints(Graphics g, ActivePoint activePoint) { - foreach(ActivePoint point in points) - point.draw(g, activePoint == point ? ActivePoint.Mode.Active : ActivePoint.Mode.Common); + public void expand(Rectangle rect) { + System.Drawing.Point lt = offset; + System.Drawing.Point rb = lt + bitmap.Size; + System.Drawing.Rectangle recti = rect.toInt(); + + int incX = (int)Math.Ceiling(bitmap.Width*incrementScale); + int incY = (int)Math.Ceiling(bitmap.Height*incrementScale); + + if (recti.Left < lt.X) lt.X = recti.Left - incX; + if (recti.Top < lt.Y) lt.Y = recti.Top - incY; + if (recti.Right > rb.X) rb.X = recti.Right + incX; + if (recti.Bottom > rb.Y) rb.Y = recti.Bottom + incY; + + Size size = new Size(rb.X - lt.X, rb.Y - lt.Y); + if (lt != offset || size != bitmap.Size) { + Bitmap newBitmap = new Bitmap(size.Width, size.Height); + Graphics g = Graphics.FromImage(newBitmap); + g.DrawImageUnscaled(bitmap, new System.Drawing.Point(offset.X - lt.X, offset.Y - lt.Y)); + g.Flush(); + + offset = lt; + bitmap = newBitmap; + } } - public void draw(Graphics g, ActivePoint activePoint, Point guidlinesPoint) { - drawGuidlines(g, guidlinesPoint); - drawAssistants(g); - drawPoints(g, activePoint); + private Graphics getGraphics() { + Graphics g = Graphics.FromImage(bitmap); + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + g.TranslateTransform(-offset.X, -offset.Y); + return g; } - public void draw(Graphics g, ActivePoint activePoint) { - drawAssistants(g); - drawPoints(g, activePoint); + public void paintTrack(Track track) { + expand(track.getBounds()); + Graphics g = getGraphics(); + track.draw(g); + g.Flush(); } } } diff --git a/mono/Assistance/Grid.cs b/mono/Assistance/Grid.cs index 6bd02df..15159b7 100644 --- a/mono/Assistance/Grid.cs +++ b/mono/Assistance/Grid.cs @@ -4,16 +4,16 @@ namespace Assistance { public class Grid: Assistant { public ActivePoint center; - public Grid(Canvas canvas, Point center): base(canvas) { + public Grid(Workarea canvas, Point center): base(canvas) { this.center = new ActivePoint(this, ActivePoint.Type.CircleCross, center); } public override void draw(System.Drawing.Graphics g) { foreach(Assistant assistant in canvas.assistants) - foreach(Point p in assistant.getGridPoints(center.position, true)) + foreach(Point p in assistant.getGridPoints(center.position)) foreach(Assistant a in canvas.assistants) if (a != assistant) - a.drawGuidlines(g, p, true); + a.drawGuidlines(g, p); } } } diff --git a/mono/Assistance/MainWindow.cs b/mono/Assistance/MainWindow.cs index f1e294f..ea4f7e9 100644 --- a/mono/Assistance/MainWindow.cs +++ b/mono/Assistance/MainWindow.cs @@ -9,11 +9,13 @@ namespace Assistance { static public void Main() { Application.Run(new MainWindow()); } Bitmap bitmap = new Bitmap(1, 1); - Canvas canvas = new Canvas(); + Workarea workarea = new Workarea(); bool dragging = false; ActivePoint activePoint; Point offset; Point cursor; + + Track track = null; public MainWindow() { Paint += onPaint; @@ -33,80 +35,96 @@ namespace Assistance { g.Clear(Color.White); draw(g); g.Flush(); - e.Graphics.DrawImageUnscaled(bitmap, new Rectangle(0, 0, ClientSize.Width, ClientSize.Height)); + e.Graphics.DrawImageUnscaled(bitmap, 0, 0); } - public Point windowToCanvas(Point p) { + public Point windowToWorkarea(Point p) { return new Point(p.x - ClientSize.Width/2.0, p.y - ClientSize.Height/2.0); } - public Point canvasToWindow(Point p) { + public Point workareaToWindow(Point p) { return new Point(p.x + ClientSize.Width/2.0, p.y + ClientSize.Height/2.0); } private void beginDrag() { + endDragAndTrack(); dragging = true; offset = activePoint.position - cursor; activePoint.bringToFront(); } - private void endDrag() { + private void beginTrack() { + endDragAndTrack(); + track = new Track(); + } + + private void endDragAndTrack() { dragging = false; offset = new Point(); + + if (track != null) + workarea.paintTrack(track); + track = null; } public void onKeyDown(Object sender, KeyEventArgs e) { switch(e.KeyCode) { case Keys.D1: - new VanishingPoint(canvas, cursor); + new VanishingPoint(workarea, cursor); break; case Keys.D2: - new Grid(canvas, cursor); + new Grid(workarea, cursor); break; case Keys.Delete: if (activePoint != null) activePoint.assistant.remove(); - endDrag(); + endDragAndTrack(); break; } - endDrag(); + endDragAndTrack(); Invalidate(); } public void onMouseDown(Object sender, MouseEventArgs e) { - cursor = windowToCanvas(new Point(e.Location.X, e.Location.Y)); + cursor = windowToWorkarea(new Point(e.Location.X, e.Location.Y)); if (e.Button == MouseButtons.Left) { - activePoint = canvas.findPoint(cursor); - if (activePoint != null) + activePoint = workarea.findPoint(cursor); + if (activePoint != null) { beginDrag(); + } else { + beginTrack(); + track.points.Add(cursor); + } } Invalidate(); } public void onMouseUp(Object sender, MouseEventArgs e) { - cursor = windowToCanvas(new Point(e.X, e.Y)); + cursor = windowToWorkarea(new Point(e.X, e.Y)); if (e.Button == MouseButtons.Left) - endDrag(); - if (!dragging) - activePoint = canvas.findPoint(cursor); + endDragAndTrack(); + if (!dragging && track == null) + activePoint = workarea.findPoint(cursor); Invalidate(); } public void onMouseMove(Object sender, MouseEventArgs e) { - cursor = windowToCanvas(new Point(e.Location.X, e.Location.Y)); + cursor = windowToWorkarea(new Point(e.Location.X, e.Location.Y)); if (dragging) { activePoint.assistant.onMovePoint(activePoint, cursor + offset); + } else + if (track != null) { + track.points.Add(cursor); } else { - activePoint = canvas.findPoint(cursor); + activePoint = workarea.findPoint(cursor); } Invalidate(); } public void draw(Graphics g) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.TranslateTransform(0.5f*ClientSize.Width, 0.5f*ClientSize.Height); - canvas.draw(g, activePoint, cursor + offset); + g.TranslateTransform(ClientSize.Width/2, ClientSize.Height/2); + workarea.draw(g, activePoint, cursor + offset, track); } } } - diff --git a/mono/Assistance/VanishingPoint.cs b/mono/Assistance/VanishingPoint.cs index c14d254..5ec7473 100644 --- a/mono/Assistance/VanishingPoint.cs +++ b/mono/Assistance/VanishingPoint.cs @@ -9,7 +9,7 @@ namespace Assistance { public ActivePoint b1; public ActivePoint step; - public VanishingPoint(Canvas canvas, Point center): base(canvas) { + public VanishingPoint(Workarea canvas, Point center): base(canvas) { this.center = new ActivePoint(this, ActivePoint.Type.CircleCross, center); a0 = new ActivePoint(this, ActivePoint.Type.CircleFill, center + new Point(-100.0, 0.0)); a1 = new ActivePoint(this, ActivePoint.Type.Circle, center + new Point(-200.0, 0.0)); @@ -86,6 +86,8 @@ namespace Assistance { return new Point[0]; k = (step.position - center.position).len()/k; + //if (Math.Abs(k - 1.0) < 0.1) return new Point[0]; + Point[] points = new Point[truncate ? gridPointsCount + 1 : gridPointsCount*2 + 1]; Point a = target - center.position; Point b = a; @@ -115,6 +117,35 @@ namespace Assistance { g.DrawLine(guidePen, center.position.toFloat(), p.toFloat()); } } + + public override double calcTrackWeight(Track track) { + if (track.points.Count < 2) + return 0.0; + + Point point = track.points[0]; + Point d = (point - center.position).normalize(); + d = new Point(-d.y, d.x); + double weight = 0.0; + foreach(Point p in track.points) + weight += Math.Abs((p.x - point.x)*d.x + (p.y - point.y)*d.y); + weight /= track.points.Count; + + return weight; + } + + public override Track modifyTrack(Track track) { + Track t = new Track(); + if (track.points.Count < 1) + return t; + + Point point = track.points[0]; + Point d = (point - center.position).normalize(); + foreach(Point p in track.points) { + double l = (p.x - point.x)*d.x + (p.y - point.y)*d.y; + t.points.Add(l*d + point); + } + return t; + } } } diff --git a/mono/EllipseAntialiasing/MainWindow.cs b/mono/EllipseAntialiasing/MainWindow.cs index 5ef348c..78e9331 100644 --- a/mono/EllipseAntialiasing/MainWindow.cs +++ b/mono/EllipseAntialiasing/MainWindow.cs @@ -108,23 +108,30 @@ namespace Faraday { double dot = normalX*targetNormX + normalY*targetNormY; double aa = aaRadius/dot; + //double aaX = aa*targetNormX; + //double aaY = aa*targetNormY; + + double dotInv = + tangentL/(targetX*targetX*radiusY*radiusY + targetY*targetY*radiusX*radiusX); + double aaX = aaRadius*targetX*dotInv; + double aaY = aaRadius*targetY*dotInv; g.DrawLine( Pens.Red, - (float)(centerX + targetX - targetNormX*aa), - (float)(centerY + targetY - targetNormY*aa), - (float)(centerX + targetX + targetNormX*aa), - (float)(centerY + targetY + targetNormY*aa)); + (float)(centerX + targetX - aaX), + (float)(centerY + targetY - aaY), + (float)(centerX + targetX + aaX), + (float)(centerY + targetY + aaY)); g.FillEllipse( Brushes.Red, - (float)(centerX + targetX - targetNormX*aa - pointRadius), - (float)(centerY + targetY - targetNormY*aa - pointRadius), + (float)(centerX + targetX - aaX - pointRadius), + (float)(centerY + targetY - aaY - pointRadius), (float)(2.0*pointRadius), (float)(2.0*pointRadius)); g.FillEllipse( Brushes.Red, - (float)(centerX + targetX + targetNormX*aa - pointRadius), - (float)(centerY + targetY + targetNormY*aa - pointRadius), + (float)(centerX + targetX + aaX - pointRadius), + (float)(centerY + targetY + aaY - pointRadius), (float)(2.0*pointRadius), (float)(2.0*pointRadius)); }