|
|
72b17c |
using System;
|
|
|
72b17c |
using System.Collections.Generic;
|
|
|
72b17c |
|
|
|
72b17c |
namespace Assistance {
|
|
|
72b17c |
public class ModifierSnowflake: Modifier {
|
|
|
589f9a |
public class Modifier: Track.Modifier {
|
|
|
589f9a |
Point center, px, py;
|
|
|
589f9a |
|
|
|
589f9a |
public Modifier(Track.Handler handler, Point center, double angle, bool flip):
|
|
|
589f9a |
base(handler)
|
|
|
589f9a |
{
|
|
|
589f9a |
this.center = center;
|
|
|
589f9a |
double s = Math.Sin(angle);
|
|
|
589f9a |
double c = Math.Cos(angle);
|
|
|
589f9a |
if (flip) { px = new Point(c, s); py = new Point(s,-c); }
|
|
|
589f9a |
else { px = new Point(c,-s); py = new Point(s, c); }
|
|
|
589f9a |
}
|
|
|
589f9a |
|
|
|
589f9a |
public InputManager.KeyPoint.Holder holder = null;
|
|
|
589f9a |
public List<guideline> guidelines = new List<guideline>();</guideline></guideline>
|
|
|
589f9a |
|
|
|
589f9a |
public override Track.WayPoint calcWayPoint(double originalIndex) {
|
|
|
589f9a |
Track.WayPoint p = original.calcWayPoint(originalIndex);
|
|
|
589f9a |
Point pp = p.point.position - center;
|
|
|
589f9a |
p.point.position = center + new Point(Point.dot(pp, px), Point.dot(pp, py));
|
|
|
589f9a |
p.tangent.position = new Point(Point.dot(p.tangent.position, px), Point.dot(p.tangent.position, py));
|
|
|
589f9a |
return p;
|
|
|
589f9a |
}
|
|
|
589f9a |
}
|
|
|
589f9a |
|
|
|
589f9a |
|
|
|
72b17c |
public ActivePoint center;
|
|
|
589f9a |
public int rays;
|
|
|
72b17c |
|
|
|
589f9a |
public ModifierSnowflake(Document document, Point center, int rays = 6): base(document) {
|
|
|
72b17c |
this.center = new ActivePoint(this, ActivePoint.Type.CircleCross, center);
|
|
|
589f9a |
this.rays = rays;
|
|
|
72b17c |
}
|
|
|
72b17c |
|
|
|
b82ef4 |
public override void draw(Cairo.Context context) {
|
|
|
72b17c |
for(int i = 0; i < rays/2; ++i) {
|
|
|
72b17c |
Point pp0 = center.position;
|
|
|
72b17c |
Point pp1 = center.position + new Point(100.0, 0.0).rotate( i*2.0*Math.PI/(double)rays );
|
|
|
b82ef4 |
Rectangle bounds = Drawing.Helper.getBounds(context);
|
|
|
b82ef4 |
Geometry.truncateInfiniteLine(bounds, ref pp0, ref pp1);
|
|
|
b82ef4 |
|
|
|
b82ef4 |
context.Save();
|
|
|
b82ef4 |
pen.apply(context);
|
|
|
b82ef4 |
context.MoveTo(pp0.x, pp0.y);
|
|
|
b82ef4 |
context.LineTo(pp1.x, pp1.y);
|
|
|
b82ef4 |
context.Stroke();
|
|
|
b82ef4 |
context.Restore();
|
|
|
72b17c |
}
|
|
|
72b17c |
}
|
|
|
589f9a |
|
|
|
589f9a |
public override void modify(Track track, InputManager.KeyPoint keyPoint, List<track> outTracks) {
|
|
|
589f9a |
if (track.handler == null) {
|
|
|
589f9a |
track.handler = new Track.Handler(this, track);
|
|
|
589f9a |
for(int i = 0; i < rays; ++i) {
|
|
|
589f9a |
double angle = i*2.0*Math.PI/(double)rays;
|
|
|
589f9a |
track.handler.tracks.Add(new Track( new Modifier(track.handler, center.position, angle, false) ));
|
|
|
589f9a |
track.handler.tracks.Add(new Track( new Modifier(track.handler, center.position, angle, true) ));
|
|
|
589f9a |
}
|
|
|
589f9a |
}
|
|
|
589f9a |
|
|
|
589f9a |
outTracks.AddRange(track.handler.tracks);
|
|
|
589f9a |
if (!track.isChanged)
|
|
|
589f9a |
return;
|
|
|
589f9a |
|
|
|
589f9a |
int start = track.points.Count - track.wayPointsAdded;
|
|
|
589f9a |
if (start < 0) start = 0;
|
|
|
589f9a |
foreach(Track subTrack in track.handler.tracks) {
|
|
|
589f9a |
// remove points
|
|
|
589f9a |
if (subTrack.points.Count < start) {
|
|
|
589f9a |
subTrack.points.RemoveRange(start, subTrack.points.Count - start);
|
|
|
589f9a |
subTrack.wayPointsRemoved += subTrack.points.Count - start;
|
|
|
589f9a |
}
|
|
|
72b17c |
|
|
|
589f9a |
// add points
|
|
|
589f9a |
Track.WayPoint p0 = track.getWayPoint(start - 1);
|
|
|
589f9a |
for(int i = start; i < track.points.Count; ++i)
|
|
|
589f9a |
subTrack.points.Add( subTrack.calcWayPoint(i) );
|
|
|
589f9a |
subTrack.wayPointsAdded += subTrack.points.Count - start;
|
|
|
72b17c |
}
|
|
|
72b17c |
}
|
|
|
72b17c |
}
|
|
|
72b17c |
}
|
|
|
72b17c |
|