diff --git a/mono/Assistance/ActivePoint.cs b/mono/Assistance/ActivePoint.cs index 155edda..5fe461c 100644 --- a/mono/Assistance/ActivePoint.cs +++ b/mono/Assistance/ActivePoint.cs @@ -11,6 +11,16 @@ namespace Assistance { CircleCross, }; + public class Owner { + public readonly Workarea workarea; + public readonly List points = new List(); + + public Owner(Workarea workarea) { this.workarea = workarea; } + public virtual void onMovePoint(ActivePoint point, Point position) { point.position = position; } + public virtual void bringToFront() { } + public virtual void remove() { foreach(ActivePoint point in points) workarea.points.Remove(point); } + } + public static readonly double radius = 10.0; public static readonly double crossSize = 1.2*radius; public static readonly Pen pen = Pens.Gray; @@ -18,18 +28,18 @@ namespace Assistance { public static readonly Pen penActive = Pens.Blue; public static readonly Brush brushActive = Brushes.LightBlue; - public readonly Workarea canvas; - public readonly Assistant assistant; + public readonly Workarea workarea; + public readonly Owner owner; public readonly Type type; public Point position; - public ActivePoint(Assistant assistant, Type type, Point position = new Point()) { - this.canvas = assistant.canvas; - this.assistant = assistant; + public ActivePoint(Owner owner, Type type, Point position = new Point()) { + this.workarea = owner.workarea; + this.owner = owner; this.type = type; this.position = position; - canvas.points.Add(this); - assistant.points.Add(this); + workarea.points.Add(this); + owner.points.Add(this); } public bool isInside(Point p) { @@ -37,11 +47,11 @@ namespace Assistance { } public void bringToFront() { - assistant.bringToFront(); - assistant.points.Remove(this); - assistant.points.Add(this); - canvas.points.Remove(this); - canvas.points.Add(this); + owner.bringToFront(); + owner.points.Remove(this); + owner.points.Add(this); + workarea.points.Remove(this); + workarea.points.Add(this); } private Pen getPen(bool active) { diff --git a/mono/Assistance/Assistance.csproj b/mono/Assistance/Assistance.csproj index 67f810d..5abba85 100644 --- a/mono/Assistance/Assistance.csproj +++ b/mono/Assistance/Assistance.csproj @@ -34,7 +34,9 @@ - + + AssistantGrid.cs + @@ -46,6 +48,10 @@ + + Point.cs + + diff --git a/mono/Assistance/Assistant.cs b/mono/Assistance/Assistant.cs index 64148d7..15e1425 100644 --- a/mono/Assistance/Assistant.cs +++ b/mono/Assistance/Assistant.cs @@ -4,40 +4,31 @@ using System.Drawing.Imaging; using System.Collections.Generic; namespace Assistance { - public class Assistant { + public class Assistant: ActivePoint.Owner { public static readonly double maxLen = 1000.0; - public static readonly int gridPointsCount = 100; + //public static readonly int gridPointsCount = 100; public static readonly Pen pen = Pens.Gray; - public readonly Workarea canvas; - public readonly List points = new List(); - - public Assistant(Workarea canvas) { - this.canvas = canvas; - canvas.assistants.Add(this); - } - - public void remove() { - foreach(ActivePoint point in points) - canvas.points.Remove(point); - canvas.assistants.Remove(this); + public Assistant(Workarea workarea): base(workarea) { + workarea.assistants.Add(this); } - public void bringToFront() { - canvas.assistants.Remove(this); - canvas.assistants.Add(this); + public override void remove() { + base.remove(); + workarea.assistants.Remove(this); } - public double getMaxLen() { - double l = 0.0; - foreach(ActivePoint point in points) - l = Math.Max(l, point.position.len()); - return maxLen + l; + public override void bringToFront() { + workarea.assistants.Remove(this); + workarea.assistants.Add(this); } - public virtual void onMovePoint(ActivePoint point, Point position) { - point.position = position; - } + //public double getMaxLen() { + // double l = 0.0; + // foreach(ActivePoint point in points) + // l = Math.Max(l, point.position.len()); + // return maxLen + l; + //} public virtual void draw(Graphics g) { } diff --git a/mono/Assistance/AssistantVanishingPoint.cs b/mono/Assistance/AssistantVanishingPoint.cs index 7786dda..5524732 100644 --- a/mono/Assistance/AssistantVanishingPoint.cs +++ b/mono/Assistance/AssistantVanishingPoint.cs @@ -12,7 +12,7 @@ namespace Assistance { public ActivePoint b1; public ActivePoint step; - public AssistantVanishingPoint(Workarea canvas, Point center): base(canvas) { + public AssistantVanishingPoint(Workarea workarea, Point center): base(workarea) { 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)); diff --git a/mono/Assistance/MainWindow.cs b/mono/Assistance/MainWindow.cs index 570b559..9cd62e9 100644 --- a/mono/Assistance/MainWindow.cs +++ b/mono/Assistance/MainWindow.cs @@ -75,9 +75,12 @@ namespace Assistance { case Keys.D2: new AssistantGrid(workarea, cursor); break; + case Keys.Q: + new ModifierSnowflake(workarea, cursor); + break; case Keys.Delete: if (activePoint != null) - activePoint.assistant.remove(); + activePoint.owner.remove(); endDragAndTrack(); break; } @@ -111,7 +114,7 @@ namespace Assistance { public void onMouseMove(Object sender, MouseEventArgs e) { cursor = windowToWorkarea(new Point(e.Location.X, e.Location.Y)); if (dragging) { - activePoint.assistant.onMovePoint(activePoint, cursor + offset); + activePoint.owner.onMovePoint(activePoint, cursor + offset); } else if (track != null) { track.points.Add(cursor); diff --git a/mono/Assistance/Modifier.cs b/mono/Assistance/Modifier.cs new file mode 100644 index 0000000..1c314d4 --- /dev/null +++ b/mono/Assistance/Modifier.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Collections.Generic; + +namespace Assistance { + public class Modifier: ActivePoint.Owner { + public static readonly Pen pen = Pens.LightGray; + + public Modifier(Workarea workarea): base(workarea) { + workarea.modifiers.Add(this); + } + + public override void remove() { + base.remove(); + workarea.modifiers.Remove(this); + } + + public override void bringToFront() { + workarea.modifiers.Remove(this); + workarea.modifiers.Add(this); + } + + public virtual void draw(Graphics g) { } + + public virtual void getTransformFuncs(List transformFuncs) { } + + public List modify(List tracks) { + List outTracks = new List(); + List transformFuncs = new List(); + getTransformFuncs(transformFuncs); + foreach(Track track in tracks) + foreach(Geometry.TransformFunc transformFunc in transformFuncs) + outTracks.Add(track.createChild(transformFunc)); + return outTracks; + } + } +} diff --git a/mono/Assistance/ModifierSnowflake.cs b/mono/Assistance/ModifierSnowflake.cs new file mode 100644 index 0000000..4a69b23 --- /dev/null +++ b/mono/Assistance/ModifierSnowflake.cs @@ -0,0 +1,47 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Collections.Generic; + +namespace Assistance { + public class ModifierSnowflake: Modifier { + public static readonly int rays = 6; + + public ActivePoint center; + + public ModifierSnowflake(Workarea workarea, Point center): base(workarea) { + this.center = new ActivePoint(this, ActivePoint.Type.CircleCross, center); + } + + public override void draw(System.Drawing.Graphics g) { + for(int i = 0; i < rays/2; ++i) { + Point pp0 = center.position; + Point pp1 = center.position + new Point(100.0, 0.0).rotate( i*2.0*Math.PI/(double)rays ); + Geometry.truncateInfiniteLine(new Rectangle(g.VisibleClipBounds), ref pp0, ref pp1); + g.DrawLine(pen, pp0.toFloat(), pp1.toFloat()); + } + } + + public override void getTransformFuncs(List transformFuncs) { + Point p0 = center.position; + for(int i = 0; i < rays; ++i) { + double angle = i*2.0*Math.PI/(double)rays; + double s = Math.Sin(angle); + double c = Math.Cos(angle); + + transformFuncs.Add(delegate(Point p) { + double x = p.x - p0.x; + double y = p.y - p0.y; + return p0 + new Point(c*x - s*y, s*x + c*y); + }); + + transformFuncs.Add(delegate(Point p) { + double x = p.x - p0.x; + double y = p.y - p0.y; + return p0 + new Point(c*x + s*y, s*x - c*y); + }); + } + } + } +} + diff --git a/mono/Assistance/Point.cs b/mono/Assistance/Point.cs index 6a415c9..e931004 100644 --- a/mono/Assistance/Point.cs +++ b/mono/Assistance/Point.cs @@ -55,6 +55,12 @@ namespace Assistance { return l > Geometry.precision*Geometry.precision ? this/l : this; } + public Point rotate(double angle) { + double s = Math.Sin(angle); + double c = Math.Cos(angle); + return new Point(c*x - s*y, s*x + c*y); + } + public System.Drawing.PointF toFloat() { return new System.Drawing.PointF((float)x, (float)y); } diff --git a/mono/Assistance/Track.cs b/mono/Assistance/Track.cs index 47131f7..c8e1d7f 100644 --- a/mono/Assistance/Track.cs +++ b/mono/Assistance/Track.cs @@ -30,7 +30,7 @@ namespace Assistance { rebuild(precision); } - public Track createChild(Geometry.TransformFunc transformFunc, double precision){ + public Track createChild(Geometry.TransformFunc transformFunc){ return new Track(this, transformFunc); } @@ -46,14 +46,18 @@ namespace Assistance { bounds = bounds.expand(p); return bounds.inflate(Math.Max(pen.Width, penPreview.Width) + 2.0); } - + + public Point transform(Point p) { + return Geometry.transform(transformFuncs, p); + } + private void addSpline(Point p0, Point p1, Point t0, Point t1, Point tp0, Point tp1, double l0, double l1, double precisionSqr) { if ((tp1 - tp0).lenSqr() < precisionSqr) { points.Add(tp1); } else { double l = 0.5*(l0 + l1); Point p = Geometry.splinePoint(p0, p1, t0, t1, l); - Point tp = Geometry.transform(transformFuncs, p); + Point tp = transform(p); addSpline(p0, p1, t0, t1, tp0, tp, l0, l, precisionSqr); addSpline(p0, p1, t0, t1, tp, tp1, l, l1, precisionSqr); } diff --git a/mono/Assistance/Workarea.cs b/mono/Assistance/Workarea.cs index 970ee20..1b95df3 100644 --- a/mono/Assistance/Workarea.cs +++ b/mono/Assistance/Workarea.cs @@ -7,6 +7,7 @@ using System.Linq; namespace Assistance { public class Workarea { public readonly List assistants = new List(); + public readonly List modifiers = new List(); public readonly List points = new List(); public readonly Canvas canvas = new Canvas(); @@ -31,54 +32,75 @@ namespace Assistance { // guidelines and track List guidelines = new List(); if (track != null && track.points.Count > 0) { - getGuidelines(guidelines, track.points[0]); - Guideline guideline = Guideline.findBest(guidelines, track); - Track modifiedTrack = guideline == null - ? track.createChildAndBuild(Geometry.noTransform) - : track.createChildAndBuild(guideline.transformPoint); - - if (modifiedTrack.points.Count > 0) { - guidelines.Clear(); - getGuidelines(guidelines, modifiedTrack.points.Last()); - } - foreach(Guideline gl in guidelines) - gl.draw(g); + Guideline guideline; + Track modifiedTrack = modifyTrackByAssistant(track, out guideline); + + getGuidelines(guidelines, modifiedTrack.transform(track.points.Last())); + foreach(Guideline gl in guidelines) gl.draw(g); - if (guideline != null) { - track.draw(g, true); - guideline.draw(g, true); - } - modifiedTrack.draw(g); + track.draw(g, true); + if (guideline != null) guideline.draw(g, true); + + List modifiedTracks = modifyTrackByModifiers(modifiedTrack); + rebuildTracks(modifiedTracks); + foreach(Track t in modifiedTracks) + t.draw(g); } else { getGuidelines(guidelines, target); foreach(Guideline guideline in guidelines) guideline.draw(g); } + // modifiers + foreach(Modifier modifier in modifiers) + modifier.draw(g); + // assistants foreach(Assistant assistant in assistants) assistant.draw(g); - // assistant active points + // active points foreach(ActivePoint point in points) point.draw(g, activePoint == point); } - public Track modifyTrack(Track track) { + public Track modifyTrackByAssistant(Track track, out Guideline guideline) { + guideline = null; if (track.points.Count < 1) - return track; - + return track.createChild(Geometry.noTransform); + List guidelines = new List(); getGuidelines(guidelines, track.points[0]); - Guideline guideline = Guideline.findBest(guidelines, track); + guideline = Guideline.findBest(guidelines, track); if (guideline == null) - return track.createChildAndBuild(Geometry.noTransform); - - return track.createChildAndBuild(guideline.transformPoint); + return track.createChild(Geometry.noTransform); + return track.createChild(guideline.transformPoint); } + public List modifyTrackByModifiers(Track track) { + List tracks = new List() { track }; + foreach(Modifier modifier in modifiers) + tracks = modifier.modify(tracks); + return tracks; + } + + public void rebuildTracks(List tracks) { + foreach(Track track in tracks) + track.rebuild(); + } + + public List modifyTrack(Track track) { + Guideline guideline; + List tracks = modifyTrackByModifiers( + modifyTrackByAssistant(track, out guideline) ); + rebuildTracks(tracks); + return tracks; + } + public void paintTrack(Track track) { - canvas.paintTrack( modifyTrack(track) ); + List tracks = modifyTrack(track); + foreach(Track t in tracks) + canvas.paintTrack(t); } } }