dojox/gfx/arc.js

  • Provides:

    • dojox.gfx.arc
  • Requires:

    • dojox.gfx.matrix in common
  • twoPI

    • summary
  • pi48

    • summary
  • p2

    • type
      Object
    • summary
  • dojox.gfx.arc

    • type
      Object
    • summary
  • p2.x

    • summary
  • p2.y

    • summary
  • dojox.gfx.arc.unitArcAsBezier

    • summary
  • dojox.gfx.arc.curvePI4

    • summary
  • dojox.gfx.arc.arcAsBezier

    • type
      Function
    • parameters:
      • last: (typeof Object)
        a point-like object as a start of the arc
      • rx: (typeof Number)
        a horizontal radius for the virtual ellipse
      • ry: (typeof Number)
        a vertical radius for the virtual ellipse
      • xRotg: (typeof Number)
        a rotation of an x axis of the virtual ellipse in degrees
      • large: (typeof Boolean)
        which part of the ellipse will be used (the larger arc if true)
      • sweep: (typeof Boolean)
        direction of the arc (CW if true)
      • x: (typeof Number)
        the x coordinate of the end point of the arc
      • y: (typeof )
    • source: [view]
      dojo.provide("dojox.gfx.arc");


      dojo.require("dojox.gfx.matrix");


      (function(){
       var m = dojox.gfx.matrix,
        twoPI = 2 * Math.PI, pi4 = Math.PI / 4, pi8 = Math.PI / 8,
        pi48 = pi4 + pi8, curvePI4 = unitArcAsBezier(pi8);


       function unitArcAsBezier(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}
        };
       }


       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; // Array
    • 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.
    • returns
      Object|Array
  • dojox.gfx

    • type
      Object
    • summary
  • dojox

    • type
      Object
    • summary