123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- if (!dojo._hasResource["dojox.gfx.arc"]) { // _hasResource checks added by
- // build. Do not use _hasResource
- // directly in your code.
- dojo._hasResource["dojox.gfx.arc"] = true;
- dojo.provide("dojox.gfx.arc");
- dojo.require("dojox.gfx.matrix");
- (function() {
- var m = dojox.gfx.matrix, unitArcAsBezier = function(alpha) {
- // summary: return a start point, 1st and 2nd control points, and an
- // end point of
- // a an arc, which is reflected on the x axis
- // alpha: Number: angle in radians, the arc will be 2 * angle size
- var cosa = Math.cos(alpha), sina = Math.sin(alpha), p2 = {
- x : cosa + (4 / 3) * (1 - cosa),
- y : sina - (4 / 3) * cosa * (1 - cosa) / sina
- };
- return { // Object
- s : {
- x : cosa,
- y : -sina
- },
- c1 : {
- x : p2.x,
- y : -p2.y
- },
- c2 : p2,
- e : {
- x : cosa,
- y : sina
- }
- };
- }, twoPI = 2 * Math.PI, pi4 = Math.PI / 4, pi8 = Math.PI / 8, pi48 = pi4
- + pi8, curvePI4 = unitArcAsBezier(pi8);
- dojo.mixin(dojox.gfx.arc, {
- unitArcAsBezier : unitArcAsBezier,
- curvePI4 : curvePI4,
- arcAsBezier : function(last, rx, ry, xRotg, large, sweep, x, y) {
- // summary: calculates an arc as a series of Bezier curves
- // given the last point and a standard set of SVG arc
- // parameters,
- // it returns an array of arrays of parameters to form a series
- // of
- // absolute Bezier curves.
- // last: Object: a point-like object as a start of the arc
- // rx: Number: a horizontal radius for the virtual ellipse
- // ry: Number: a vertical radius for the virtual ellipse
- // xRotg: Number: a rotation of an x axis of the virtual ellipse
- // in degrees
- // large: Boolean: which part of the ellipse will be used (the
- // larger arc if true)
- // sweep: Boolean: direction of the arc (CW if true)
- // x: Number: the x coordinate of the end point of the arc
- // y: Number: the y coordinate of the end point of the arc
- // calculate parameters
- large = Boolean(large);
- sweep = Boolean(sweep);
- var xRot = m._degToRad(xRotg), rx2 = rx * rx, ry2 = ry * ry, pa = m
- .multiplyPoint(m.rotate(-xRot), {
- x : (last.x - x) / 2,
- y : (last.y - y) / 2
- }), pax2 = pa.x * pa.x, pay2 = pa.y * pa.y, c1 = Math
- .sqrt((rx2 * ry2 - rx2 * pay2 - ry2 * pax2)
- / (rx2 * pay2 + ry2 * pax2));
- if (isNaN(c1)) {
- c1 = 0;
- }
- var ca = {
- x : c1 * rx * pa.y / ry,
- y : -c1 * ry * pa.x / rx
- };
- if (large == sweep) {
- ca = {
- x : -ca.x,
- y : -ca.y
- };
- }
- // the center
- var c = m.multiplyPoint(
- [m.translate((last.x + x) / 2, (last.y + y) / 2),
- m.rotate(xRot)], ca);
- // calculate the elliptic transformation
- var elliptic_transform = m.normalize([m.translate(c.x, c.y),
- m.rotate(xRot), m.scale(rx, ry)]);
- // start, end, and size of our arc
- var inversed = m.invert(elliptic_transform), sp = m
- .multiplyPoint(inversed, last), ep = m.multiplyPoint(
- inversed, x, y), startAngle = Math.atan2(sp.y, sp.x), endAngle = Math
- .atan2(ep.y, ep.x), theta = startAngle - endAngle; // size
- // of
- // our
- // arc
- // in
- // radians
- if (sweep) {
- theta = -theta;
- }
- if (theta < 0) {
- theta += twoPI;
- } else if (theta > twoPI) {
- theta -= twoPI;
- }
- // draw curve chunks
- var alpha = pi8, curve = curvePI4, step = sweep
- ? alpha
- : -alpha, result = [];
- for (var angle = theta; angle > 0; angle -= pi4) {
- if (angle < pi48) {
- alpha = angle / 2;
- curve = unitArcAsBezier(alpha);
- step = sweep ? alpha : -alpha;
- angle = 0; // stop the loop
- }
- var c1, c2, e, M = m.normalize([elliptic_transform,
- m.rotate(startAngle + step)]);
- if (sweep) {
- c1 = m.multiplyPoint(M, curve.c1);
- c2 = m.multiplyPoint(M, curve.c2);
- e = m.multiplyPoint(M, curve.e);
- } else {
- c1 = m.multiplyPoint(M, curve.c2);
- c2 = m.multiplyPoint(M, curve.c1);
- e = m.multiplyPoint(M, curve.s);
- }
- // draw the curve
- result.push([c1.x, c1.y, c2.x, c2.y, e.x, e.y]);
- startAngle += 2 * step;
- }
- return result; // Object
- }
- });
- })();
- }
|