diff --git a/mono/Assistance/Document.cs b/mono/Assistance/Document.cs index ef232d0..8af4cbc 100644 --- a/mono/Assistance/Document.cs +++ b/mono/Assistance/Document.cs @@ -10,9 +10,8 @@ namespace Assistance { public readonly List points = new List(); public readonly Canvas canvas = new Canvas(); - public Document(Workarea workarea) { - this.workarea = workarea; - } + public Document(Workarea workarea) + { this.workarea = workarea; } } } diff --git a/mono/Assistance/Guideline.cs b/mono/Assistance/Guideline.cs index 923ac19..19d822b 100644 --- a/mono/Assistance/Guideline.cs +++ b/mono/Assistance/Guideline.cs @@ -9,9 +9,7 @@ namespace Assistance { public static readonly double snapLenght = 20.0; public static readonly double snapScale = 1.0; - public virtual Point transformPoint(Point p) { - return p; - } + public virtual Track.WayPoint transformPoint(Track.WayPoint point) { } public virtual void draw(Cairo.Context context, bool active) { } diff --git a/mono/Assistance/InputManager.cs b/mono/Assistance/InputManager.cs index 99b0acf..b66d7b5 100644 --- a/mono/Assistance/InputManager.cs +++ b/mono/Assistance/InputManager.cs @@ -15,17 +15,36 @@ namespace Assistance { public class KeyPoint { public class Holder: IDisposable { public readonly KeyPoint keyPoint; - private bool disposed = false; + private bool holded = false; + public Holder(KeyPoint keyPoint) - { this.keyPoint = keyPoint; ++keyPoint.refCount; } + { this.keyPoint = keyPoint; reuse(); } + + public bool available + { get { return keyPoint.available; } } + public bool isHolded + { get { return holded; } } + public bool reuse() { + if (!holded) ++keyPoint.refCount; + holded = true; + return keyPoint.available; + } + public void release() { + if (holded) --keyPoint.refCount; + holded = false; + } + public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) - { if (!disposed) --keyPoint.refCount; disposed = true; } + { release(); } ~Holder() { Dispose(false); } } + private int refCount = 0; + public bool available = true; + public Holder hold() { return new Holder(this); } public bool isFree @@ -80,6 +99,7 @@ namespace Assistance { track.wayPointsRemoved = 0; track.wayPointsAdded = track.points.Count - index - 1; } + for(int i = level; i < keyPoints.Count; ++i) keyPoints[i].available = false; keyPoints.RemoveRange(level, keyPoints.Count - level); } @@ -87,7 +107,7 @@ namespace Assistance { if (count <= 0) return; - level = keyPoints.Count - count; + int level = keyPoints.Count - count; if (level >= keyPointsSent || tool.paintApply(keyPointsSent - level)) { // apply foreach(Track track in subTracks) @@ -104,6 +124,7 @@ namespace Assistance { } } + for(int i = level; i < keyPoints.Count; ++i) keyPoints[i].available = false; keyPoints.RemoveRange(level, keyPoints.Count - level); if (level < keyPointsSent) keyPointsSent = level; diff --git a/mono/Assistance/InputModifierAssistants.cs b/mono/Assistance/InputModifierAssistants.cs new file mode 100644 index 0000000..f745001 --- /dev/null +++ b/mono/Assistance/InputModifierAssistants.cs @@ -0,0 +1,98 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; + +namespace Assistance { + public class InputModifierAssistants: InputModifierTangents { + public readonly Workarea workarea; + public readonly bool interpolate; + + public InputModifierAssistants(Workarea workarea, bool interpolate = false, double precision = 1.0): + base(precision) + { + this.workarea = workarea; + this.interpolate = interpolate; + } + + public class Modifier: Track.Modifier { + public Modifier(Track.Handler handler): + base(handler) { } + + public InputManager.KeyPoint.Holder holder = null; + public List guidelines = new List(); + + public override Track.WayPoint calcWayPoint(double originalIndex) { + Track.WayPoint p = original.calcWayPoint(originalIndex); + return guidelines.Count > 0 ? guidelines[0].transformPoint(p) : p; + } + } + + public override List modify(Track track, InputManager.KeyPoint keyPoint, List outTracks) { + Track subTrack; + Modifier modifier; + + if (track.handler == null) { + if (track.points.Count == 0) + return; + + Track.Handler handler = new Track.Handler(this, track); + modifier = new Track.Modifier(track.handler); + workarea.getGuidelines(modifier.guidelines, track.points[0].point.position); + if (interpolate && modifier.guidelines.Count == 0) + { base.modify(track, keyPoint, outTracks); return; } + + track.handler = handler; + subTrack = new Track(modifier); + track.handler.tracks.Add(subTrack); + + if (modifier.guidelines.Count > 1) { + modifier.holder = keyPoint.hold(); + outTracks.Add(subTrack); + return; + } + } + + subTrack = track.handler.tracks[0]; + if (subTrack.modifier is InputModifierTangents.Modifier) + { base.modify(track, keyPoint, outTracks); return; } + + modifier = (Modifier)subTrack.modifier; + outTracks.Add(subTrack); + + if (!track.isChanged) + return; + + // remove points + int start = track.points.Count - track.wayPointsAdded; + if (start < 0) start = 0; + if (subTrack.points.Count < start) { + subTrack.points.RemoveRange(start, subTrack.points.Count - start); + subTrack.wayPointsRemoved += subTrack.points.Count - start; + } + + bool trackIsLong = track.points.Count > 0 && track.getLast().length > 2.0*Guideline.snapLenght; + if (!trackIsLong && modifier.holder != null && !modifier.holder.isHolded && modifier.holder.available) + modifier.holder.reuse(); + + // select guideline + if (modifier.holder != null && modifier.holder.isHolded) { + Guideline guideline = Guideline.findBest(modifier.guidelines, track); + if (guideline != modifier.guidelines[0]) { + modifier.guidelines[ modifier.guidelines.IndexOf(guideline) ] = modifier.guidelines[0]; + modifier.guidelines[0] = guideline; + start = 0; + subTrack.wayPointsRemoved += subTrack.points.Count; + subTrack.points.Clear; + } + if (trackIsLong) + modifier.holder.release(); + } + + // add points + for(int i = start; i < track.points.Count; ++i) + subTrack.points.Add(modifier.calcWayPoint(i)); + subTrack.wayPointsAdded = subTrack.points.Count - start; + } + } +} + diff --git a/mono/Assistance/InputModifierInterpolation.cs b/mono/Assistance/InputModifierInterpolation.cs index f526038..f9b9545 100644 --- a/mono/Assistance/InputModifierInterpolation.cs +++ b/mono/Assistance/InputModifierInterpolation.cs @@ -6,9 +6,9 @@ namespace Assistance { public readonly double precision; public readonly double precisionSqr; - public InputModifierInterpolation(double precision = 0.0) { - this.precision = precision; - this.precisionSqr = precision*precision; + public InputModifierInterpolation(double precision = 1.0) { + this.precision = Math.Max(precision, Geometry.precision); + this.precisionSqr = this.precision*this.precision; } public void addSegment(Track track, Track.WayPoint p0, Track.WayPoint p1) { @@ -37,7 +37,7 @@ namespace Assistance { if (start < 0) start = 0; int subStart = subTrack.floorIndex(subTrack.indexByOriginalIndex(start)); if (subTrack.points.Count < subStart) { - subTrack.points.RemoveRange(start, subTrack.points.Count - subStart); + subTrack.points.RemoveRange(subStart, subTrack.points.Count - subStart); subTrack.wayPointsRemoved += subTrack.points.Count - subStart; } diff --git a/mono/Assistance/InputModifierTangents.cs b/mono/Assistance/InputModifierTangents.cs index dba5aaf..66c177e 100644 --- a/mono/Assistance/InputModifierTangents.cs +++ b/mono/Assistance/InputModifierTangents.cs @@ -85,7 +85,10 @@ namespace Assistance { subTrack.wayPointsAdded += index - start; // release previous key point - if (modifier.holder) modifier.holder.Dispose(); + if (modifier.holder) { + modifier.holder.Dispose(); + modifier.holder = null; + } if (track.isFinished) { // finish diff --git a/mono/Assistance/Modifier.cs b/mono/Assistance/Modifier.cs index 5337b5c..72630d0 100644 --- a/mono/Assistance/Modifier.cs +++ b/mono/Assistance/Modifier.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using Assistance.Drawing; namespace Assistance { - public class Modifier: ActivePoint.Owner { + public class Modifier: ActivePoint.Owner, InputModifier { public static readonly Pen pen = new Pen("Light Gray"); public Modifier(Document document): base(document) { @@ -20,18 +20,10 @@ namespace Assistance { document.modifiers.Add(this); } - public virtual void draw(Cairo.Context context) { } + public virtual void activate() { } + public virtual List modify(List tracks) { return tracks; } + public virtual void deactivate() { } - 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; - } + public virtual void draw(Cairo.Context context) { } } }