Skip to content

Instantly share code, notes, and snippets.

@timo22345
Created March 2, 2014 20:03
Show Gist options
  • Save timo22345/9312925 to your computer and use it in GitHub Desktop.
Save timo22345/9312925 to your computer and use it in GitHub Desktop.
Raphael's a2c function with cacher
function cacher(f, scope, postprocessor)
{
function newf()
{
var arg = Array.prototype.slice.call(arguments, 0),
args = arg.join("\u2400"),
cache = newf.cache = newf.cache ||
{}, count = newf.count = newf.count || [];
if (cache.hasOwnProperty(args))
{
for (var i = 0, ii = count.length; i < ii; i++)
if (count[i] === args)
{
count.push(count.splice(i, 1)[0]);
}
return postprocessor ? postprocessor(cache[args]) : cache[args];
}
count.length >= 1E3 && delete cache[count.shift()];
count.push(args);
cache[args] = f.apply(scope, arg);
return postprocessor ? postprocessor(cache[args]) : cache[args];
}
return newf;
}
var a2c = cacher(function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive)
{
var _120 = PI * 120 / 180,
rad = PI / 180 * (+angle || 0),
res = [],
xy,
rotate = cacher(function (x, y, rad)
{
var X = x * Math.cos(rad) - y * Math.sin(rad),
Y = x * Math.sin(rad) + y * Math.cos(rad);
return {
x: X,
y: Y
};
});
if (!recursive)
{
xy = rotate(x1, y1, -rad);
x1 = xy.x;
y1 = xy.y;
xy = rotate(x2, y2, -rad);
x2 = xy.x;
y2 = xy.y;
var cos = Math.cos(PI / 180 * angle),
sin = Math.sin(PI / 180 * angle),
x = (x1 - x2) / 2,
y = (y1 - y2) / 2;
var h = x * x / (rx * rx) + y * y / (ry * ry);
if (h > 1)
{
h = Math.sqrt(h);
rx = h * rx;
ry = h * ry;
}
var rx2 = rx * rx,
ry2 = ry * ry,
k = (large_arc_flag == sweep_flag ? -1 : 1) * Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
cx = k * rx * y / ry + (x1 + x2) / 2,
cy = k * -ry * x / rx + (y1 + y2) / 2,
f1 = Math.asin(((y1 - cy) / ry).toFixed(9)),
f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
f1 = x1 < cx ? PI - f1 : f1;
f2 = x2 < cx ? PI - f2 : f2;
f1 < 0 && (f1 = PI * 2 + f1);
f2 < 0 && (f2 = PI * 2 + f2);
if (sweep_flag && f1 > f2)
{
f1 = f1 - PI * 2;
}
if (!sweep_flag && f2 > f1)
{
f2 = f2 - PI * 2;
}
}
else
{
f1 = recursive[0];
f2 = recursive[1];
cx = recursive[2];
cy = recursive[3];
}
var df = f2 - f1;
if (Math.abs(df) > _120)
{
var f2old = f2,
x2old = x2,
y2old = y2;
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
x2 = cx + rx * Math.cos(f2);
y2 = cy + ry * Math.sin(f2);
res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy])
}
df = f2 - f1;
var c1 = Math.cos(f1),
s1 = Math.sin(f1),
c2 = Math.cos(f2),
s2 = Math.sin(f2),
t = Math.tan(df / 4),
hx = 4 / 3 * rx * t,
hy = 4 / 3 * ry * t,
m1 = [x1, y1],
m2 = [x1 + hx * s1, y1 - hy * c1],
m3 = [x2 + hx * s2, y2 - hy * c2],
m4 = [x2, y2];
m2[0] = 2 * m1[0] - m2[0];
m2[1] = 2 * m1[1] - m2[1];
if (recursive) return [m2, m3, m4].concat(res);
else
{
res = [m2, m3, m4].concat(res).join().split(",");
var newres = [];
for (var i = 0, ii = res.length; i < ii; i++)
newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x
return newres
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment