Circular arc approximation by cubic Bezier curve: Difference between revisions
From JSXGraph Wiki
| A WASSERMANN (talk | contribs) No edit summary | A WASSERMANN (talk | contribs) No edit summary | ||
| (9 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
| Approximating a circular by a single Bezier curve only is sufficiently exakt if the arc is less or equal than a quarter circle. | |||
| <jsxgraph width="600" height="600"> | <jsxgraph width="600" height="600"> | ||
| var brd = JXG.JSXGraph.initBoard('jxgbox',{axis:false,boundingbox:[-2,2,2,-2],keepaspectratio:true}); | var brd = JXG.JSXGraph.initBoard('jxgbox',{axis:false,boundingbox:[-2,2,2,-2],keepaspectratio:true}); | ||
| Line 16: | Line 17: | ||
|      r = M.Dist(A); |      r = M.Dist(A); | ||
|      d = Math.sqrt((ax+bx)*(ax+bx) + (ay+by)*(ay+by)); |      d = Math.sqrt((ax+bx)*(ax+bx) + (ay+by)*(ay+by)); | ||
|     if (JXG.Math.Geometry.rad(A,M,B)>Math.PI) { d *= -1; } | |||
|      if ( |      if (Math.abs(by-ay)>JXG.Math.eps) { | ||
|          return (ax+bx)*(r/d-0.5)*8.0/3.0/(by-ay); |          return (ax+bx)*(r/d-0.5)*8.0/3.0/(by-ay); | ||
|      } else { |      } else { | ||
| Line 26: | Line 28: | ||
|              function(){ return A.X()-k(M,A,B)*(A.Y()-M.Y()); }, |              function(){ return A.X()-k(M,A,B)*(A.Y()-M.Y()); }, | ||
|              function(){ return A.Y()+k(M,A,B)*(A.X()-M.X()); } |              function(){ return A.Y()+k(M,A,B)*(A.X()-M.X()); } | ||
| ], {}); | ], {color:'blue'}); | ||
| var P2 = brd.create('point', [ | var P2 = brd.create('point', [ | ||
|              function(){ return B.X()+k(M,A,B)*(B.Y()-M.Y()); }, |              function(){ return B.X()+k(M,A,B)*(B.Y()-M.Y()); }, | ||
|              function(){ return B.Y()-k(M,A,B)*(B.X()-M.X()); } |              function(){ return B.Y()-k(M,A,B)*(B.X()-M.X()); } | ||
| ], {}); | ], {color:'blue'}); | ||
| var b = brd.create('curve', JXG.Math.Numerics.bezier([A,P1,P2,B]),   | var b = brd.create('curve', JXG.Math.Numerics.bezier([A,P1,P2,B]),   | ||
|                 {strokecolor:'black', strokeOpacity:1, strokeWidth:3});   |                 {strokecolor:'black', strokeOpacity:1, strokeWidth:3});   | ||
| var l1 = brd.create('segment', [A,P1], {dash:2}); | |||
| var l2 = brd.create('segment', [B,P2], {dash:2}); | |||
| </jsxgraph> | </jsxgraph> | ||
| ===The underlying JavaScript code=== | ===The underlying JavaScript code=== | ||
| <source lang="javascript"> | |||
| var brd = JXG.JSXGraph.initBoard('jxgbox',{axis:false,boundingbox:[-2,2,2,-2],keepaspectratio:true}); | |||
| var M = brd.create('point', [0,0], {name:'M'}); | |||
| var C = brd.create('point', [0,-1], {name:'D'}); | |||
| var c = brd.create('circle', [M,C], {strokeWidth:1}); | |||
| var A = brd.create('glider', [1,0,c], {name:'A'}); | |||
| var B = brd.create('glider', [0,1,c], {name:'B'}); | |||
| var k = function(M, A, B) { | |||
|     var ax = A.X()-M.X(), | |||
|         ay = A.Y()-M.Y(), | |||
|         bx = B.X()-M.X(), | |||
|         by = B.Y()-M.Y(), | |||
|         d, r; | |||
|     r = M.Dist(A); | |||
|     d = Math.sqrt((ax+bx)*(ax+bx) + (ay+by)*(ay+by)); | |||
|     if (JXG.Math.Geometry.rad(A,M,B)>Math.PI) { d *= -1; } | |||
|     if (Math.abs(by-ay)>JXG.Math.eps) { | |||
|         return (ax+bx)*(r/d-0.5)*8.0/3.0/(by-ay); | |||
|     } else { | |||
|         return (ay+by)*(r/d-0.5)*8.0/3.0/(ax-bx); | |||
|     } | |||
| }; | |||
| var P1 = brd.create('point', [ | |||
|             function(){ return A.X()-k(M,A,B)*(A.Y()-M.Y()); }, | |||
|             function(){ return A.Y()+k(M,A,B)*(A.X()-M.X()); } | |||
| ], {color:'blue'}); | |||
| var P2 = brd.create('point', [ | |||
|             function(){ return B.X()+k(M,A,B)*(B.Y()-M.Y()); }, | |||
|             function(){ return B.Y()-k(M,A,B)*(B.X()-M.X()); } | |||
| ], {color:'blue'}); | |||
| var b = brd.create('curve', JXG.Math.Numerics.bezier([A,P1,P2,B]),  | |||
|                {strokecolor:'black', strokeOpacity:1, strokeWidth:3});  | |||
| var l1 = brd.create('segment', [A,P1], {dash:2}); | |||
| var l2 = brd.create('segment', [B,P2], {dash:2}); | |||
| </source> | |||
| [[Category:Examples]] | [[Category:Examples]] | ||
| [[Category:Curves]] | [[Category:Curves]] | ||
| [[Category:Interpolation]] | [[Category:Interpolation]] | ||
Latest revision as of 20:31, 1 July 2012
Approximating a circular by a single Bezier curve only is sufficiently exakt if the arc is less or equal than a quarter circle.
The underlying JavaScript code
var brd = JXG.JSXGraph.initBoard('jxgbox',{axis:false,boundingbox:[-2,2,2,-2],keepaspectratio:true});
var M = brd.create('point', [0,0], {name:'M'});
var C = brd.create('point', [0,-1], {name:'D'});
var c = brd.create('circle', [M,C], {strokeWidth:1});
var A = brd.create('glider', [1,0,c], {name:'A'});
var B = brd.create('glider', [0,1,c], {name:'B'});
var k = function(M, A, B) {
    var ax = A.X()-M.X(),
        ay = A.Y()-M.Y(),
        bx = B.X()-M.X(),
        by = B.Y()-M.Y(),
        d, r;
    r = M.Dist(A);
    d = Math.sqrt((ax+bx)*(ax+bx) + (ay+by)*(ay+by));
    if (JXG.Math.Geometry.rad(A,M,B)>Math.PI) { d *= -1; }
    if (Math.abs(by-ay)>JXG.Math.eps) {
        return (ax+bx)*(r/d-0.5)*8.0/3.0/(by-ay);
    } else {
        return (ay+by)*(r/d-0.5)*8.0/3.0/(ax-bx);
    }
};
var P1 = brd.create('point', [
            function(){ return A.X()-k(M,A,B)*(A.Y()-M.Y()); },
            function(){ return A.Y()+k(M,A,B)*(A.X()-M.X()); }
], {color:'blue'});
var P2 = brd.create('point', [
            function(){ return B.X()+k(M,A,B)*(B.Y()-M.Y()); },
            function(){ return B.Y()-k(M,A,B)*(B.X()-M.X()); }
], {color:'blue'});
var b = brd.create('curve', JXG.Math.Numerics.bezier([A,P1,P2,B]), 
               {strokecolor:'black', strokeOpacity:1, strokeWidth:3}); 
var l1 = brd.create('segment', [A,P1], {dash:2});
var l2 = brd.create('segment', [B,P2], {dash:2});
