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 |
||
(24 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 A = brd. | var c = brd.create('circle', [M,C], {strokeWidth:1}); | ||
var B = brd. | 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: | [[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});