procedure crazyLine(const ctx: TAgg2D; fromX, fromY, toX, toY: double; sloppiness: double = 0.5);
const
DEBUG: boolean = false;
var
// The idea is to draw a curve, setting two control points at random
// close to each side of the line. The longer the line, the sloppier it's drawn.
control1x, control1y: double;
control2x, control2y: double;
length: double;
offset: double;
t1X, t1Y, t2X, t2Y: double;
r: double;
begin
// Crazyline. By Steve Hanov, 2008
// Released to the public domain.
ctx.ResetPath;
ctx.NoFill;
ctx.LineColor(0, 0, 0);
// calculate the length of the line.
length := sqrt( (toX-fromX)*(toX-fromX) + (toY-fromY)*(toY-fromY));
// This offset determines how sloppy the line is drawn. It depends on the
// length, but maxes out at 20.
offset := length / 10 * sloppiness;
if (offset > 20) then
offset := 20;
// Overshoot the destination a little, as one might if drawing with a pen.
toX := toX + sloppiness * random * offset/4;
toY := toY + sloppiness * random * offset / 4;
// t1 and t2 are coordinates of a line shifted under or to the right of
// our original.
t1X := fromX + offset;
t1Y := fromY + offset;
t2X := toX + offset;
t2Y := toY + offset;
// create a control point at random along our shifted line.
r := random;
control1X := t1X + r * (t2X-t1X);
control1Y := t1Y + r * (t2Y-t1Y);
// now make t1 and t2 the coordinates of our line shifted above
// and to the left of the original.
t1X := fromX - offset;
t2X := toX - offset;
t1Y := fromY - offset;
t2Y := toY - offset;
// create a second control point at random along the shifted line.
r := random;
control2X := t1X + r * (t2X-t1X);
control2Y := t1Y + r * (t2Y-t1Y);
// draw the line!
ctx.MoveTo(fromX, fromY);
ctx.CubicCurveTo(control1X, control1Y, control2X, control2Y, toX, toY);
ctx.DrawPath;
if DEBUG then
begin
ctx.ResetPath;
ctx.NoFill;
// red - control point 1
ctx.LineColor($FF, 0, 0);
ctx.Ellipse(control1X, control1Y, 3, 3);
ctx.LineColor($E6, $E6, $EF, 150);
ctx.Line(fromX, fromY, control1X, control1Y);
// green - control point 2
ctx.LineColor(0, $FF, 0);
ctx.Ellipse(control2X, control2Y, 3, 3);
ctx.LineColor($E6, $E6, $EF, 150);
ctx.Line(toX, toY, control2X, control2Y);
end;
end;