Difference between revisions of "Circular arc approximation by cubic Bezier curve"
From JSXGraph Wiki
Jump to navigationJump to searchA WASSERMANN (talk | contribs) |
A WASSERMANN (talk | contribs) |
||
(17 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 (Math.abs(by-ay)>JXG.Math.eps) { | if (Math.abs(by-ay)>JXG.Math.eps) { | ||
Line 24: | 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]), | 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: | + | [[Category:Curves]] |
+ | [[Category:Interpolation]] |
Latest revision as of 22: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});