]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojox/gfx/arc.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojox / gfx / arc.js
1 if(!dojo._hasResource["dojox.gfx.arc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojox.gfx.arc"] = true;
3 dojo.provide("dojox.gfx.arc");
4
5 dojo.require("dojox.gfx.matrix");
6
7 (function(){
8         var m = dojox.gfx.matrix,
9                 unitArcAsBezier = function(alpha){
10                         // summary: return a start point, 1st and 2nd control points, and an end point of
11                         //              a an arc, which is reflected on the x axis
12                         // alpha: Number: angle in radians, the arc will be 2 * angle size
13                         var cosa  = Math.cos(alpha), sina  = Math.sin(alpha),
14                                 p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};
15                         return {        // Object
16                                 s:  {x: cosa, y: -sina},
17                                 c1: {x: p2.x, y: -p2.y},
18                                 c2: p2,
19                                 e:  {x: cosa, y: sina}
20                         };
21                 },
22                 twoPI = 2 * Math.PI, pi4 = Math.PI / 4, pi8 = Math.PI / 8, 
23                 pi48 = pi4 + pi8, curvePI4 = unitArcAsBezier(pi8);
24
25         dojo.mixin(dojox.gfx.arc, {
26                 unitArcAsBezier: unitArcAsBezier,
27                 curvePI4: curvePI4,
28                 arcAsBezier: function(last, rx, ry, xRotg, large, sweep, x, y){
29                         // summary: calculates an arc as a series of Bezier curves
30                         //      given the last point and a standard set of SVG arc parameters,
31                         //      it returns an array of arrays of parameters to form a series of
32                         //      absolute Bezier curves.
33                         // last: Object: a point-like object as a start of the arc
34                         // rx: Number: a horizontal radius for the virtual ellipse
35                         // ry: Number: a vertical radius for the virtual ellipse
36                         // xRotg: Number: a rotation of an x axis of the virtual ellipse in degrees
37                         // large: Boolean: which part of the ellipse will be used (the larger arc if true)
38                         // sweep: Boolean: direction of the arc (CW if true)
39                         // x: Number: the x coordinate of the end point of the arc
40                         // y: Number: the y coordinate of the end point of the arc
41                         
42                         // calculate parameters
43                         large = Boolean(large);
44                         sweep = Boolean(sweep);
45                         var xRot = m._degToRad(xRotg),
46                                 rx2 = rx * rx, ry2 = ry * ry,
47                                 pa = m.multiplyPoint(
48                                         m.rotate(-xRot), 
49                                         {x: (last.x - x) / 2, y: (last.y - y) / 2}
50                                 ),
51                                 pax2 = pa.x * pa.x, pay2 = pa.y * pa.y,
52                                 c1 = Math.sqrt((rx2 * ry2 - rx2 * pay2 - ry2 * pax2) / (rx2 * pay2 + ry2 * pax2));
53                         if(isNaN(c1)){ c1 = 0; }
54                         var     ca = {
55                                         x:  c1 * rx * pa.y / ry,
56                                         y: -c1 * ry * pa.x / rx
57                                 };
58                         if(large == sweep){
59                                 ca = {x: -ca.x, y: -ca.y};
60                         }
61                         // the center
62                         var c = m.multiplyPoint(
63                                 [
64                                         m.translate(
65                                                 (last.x + x) / 2,
66                                                 (last.y + y) / 2
67                                         ),
68                                         m.rotate(xRot)
69                                 ], 
70                                 ca
71                         );
72                         // calculate the elliptic transformation
73                         var elliptic_transform = m.normalize([
74                                 m.translate(c.x, c.y),
75                                 m.rotate(xRot),
76                                 m.scale(rx, ry)
77                         ]);
78                         // start, end, and size of our arc
79                         var inversed = m.invert(elliptic_transform),
80                                 sp = m.multiplyPoint(inversed, last),
81                                 ep = m.multiplyPoint(inversed, x, y),
82                                 startAngle = Math.atan2(sp.y, sp.x),
83                                 endAngle   = Math.atan2(ep.y, ep.x),
84                                 theta = startAngle - endAngle;  // size of our arc in radians
85                         if(sweep){ theta = -theta; }
86                         if(theta < 0){
87                                 theta += twoPI;
88                         }else if(theta > twoPI){
89                                 theta -= twoPI;
90                         }
91                                                         
92                         // draw curve chunks
93                         var alpha = pi8, curve = curvePI4, step  = sweep ? alpha : -alpha,
94                                 result = [];
95                         for(var angle = theta; angle > 0; angle -= pi4){
96                                 if(angle < pi48){
97                                         alpha = angle / 2;
98                                         curve = unitArcAsBezier(alpha);
99                                         step  = sweep ? alpha : -alpha;
100                                         angle = 0;      // stop the loop
101                                 }
102                                 var c1, c2, e,
103                                         M = m.normalize([elliptic_transform, m.rotate(startAngle + step)]);
104                                 if(sweep){
105                                         c1 = m.multiplyPoint(M, curve.c1);
106                                         c2 = m.multiplyPoint(M, curve.c2);
107                                         e  = m.multiplyPoint(M, curve.e );
108                                 }else{
109                                         c1 = m.multiplyPoint(M, curve.c2);
110                                         c2 = m.multiplyPoint(M, curve.c1);
111                                         e  = m.multiplyPoint(M, curve.s );
112                                 }
113                                 // draw the curve
114                                 result.push([c1.x, c1.y, c2.x, c2.y, e.x, e.y]);
115                                 startAngle += 2 * step;
116                         }
117                         return result;  // Object
118                 }
119         });
120 })();
121
122 }