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  | 
				||
| (20 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});  | ||
var M = brd.create('point', [0,0], {name:'M'});  | var M = brd.create('point', [0,0], {name:'M'});  | ||
var c = brd.create('circle', [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 A = brd.create('glider', [1,0,c], {name:'A'});  | ||
var B = brd.create('glider', [0,1,c], {name:'B'});  | var B = brd.create('glider', [0,1,c], {name:'B'});  | ||
| Line 15: | 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 (Math.abs(by-ay)>JXG.Math.eps) {  |      if (Math.abs(by-ay)>JXG.Math.eps) {  | ||
| Line 23: | Line 26: | ||
};  | };  | ||
var P1 = brd.create('point', [  | var P1 = brd.create('point', [  | ||
             function(){ return   |              function(){ return A.X()-k(M,A,B)*(A.Y()-M.Y()); },  | ||
             function(){ return   |              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   |              function(){ return B.X()+k(M,A,B)*(B.Y()-M.Y()); },  | ||
             function(){ return   |              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});  | |||
</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:  | [[Category:Curves]]  | ||
[[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});