Circular arc approximation by cubic Bezier curve: Difference between revisions

From JSXGraph Wiki
(Created page with "<jsxgraph width="600" height="600"> var brd = JXG.JSXGraph.initBoard('jxgbox',{axis:false,boundingbox:[-2,2,2,-2],keepaspectratio:true}); var M = brd.create('point', [0,0], {nam...")
 
No edit summary
 
(26 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,1]);
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});
 
</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:Geometry]]
[[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});