Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Math 如何通过两点和半径大小计算椭圆中心_Math_Geometry_Svg_Vml_Ellipse - Fatal编程技术网

Math 如何通过两点和半径大小计算椭圆中心

Math 如何通过两点和半径大小计算椭圆中心,math,geometry,svg,vml,ellipse,Math,Geometry,Svg,Vml,Ellipse,在为基于自己的VML格式的Internet Explorer开发SVG实现时,我遇到了一个将SVG椭圆弧转换为VML椭圆弧的问题 在VML中,圆弧由以下公式给出:椭圆上两点的两个角度和半径的长度, 在SVG中,圆弧由以下公式给出:椭圆上两点的两对坐标和椭圆边界框的大小 所以,问题是:如何表达椭圆上两点对两对坐标的夹角。 一个中间问题可能是:如何通过椭圆曲线上一对点的坐标找到椭圆的中心 更新:让我们有一个先决条件,即椭圆通常放置(其半径平行于线性坐标系轴),因此不应用旋转 更新:此问题与svg:e

在为基于自己的VML格式的Internet Explorer开发SVG实现时,我遇到了一个将SVG椭圆弧转换为VML椭圆弧的问题

在VML中,圆弧由以下公式给出:椭圆上两点的两个角度和半径的长度, 在SVG中,圆弧由以下公式给出:椭圆上两点的两对坐标和椭圆边界框的大小

所以,问题是:如何表达椭圆上两点对两对坐标的夹角。 一个中间问题可能是:如何通过椭圆曲线上一对点的坐标找到椭圆的中心

更新:让我们有一个先决条件,即椭圆通常放置(其半径平行于线性坐标系轴),因此不应用旋转


更新:此问题与svg:eliple元素无关,而是与svg:path元素()中的“a”椭圆弧命令有关。

椭圆不能仅由两点定义。甚至一个圆(一个特殊的椭圆)也是由三个点定义的

即使有三个点,也会有无限的椭圆通过这三个点(想想:旋转)


请注意,边界框表示椭圆的中心,并且很可能假定其长轴和短轴平行于x、y(或y、x)轴。

中间问题相当简单。。。你没有。从边界框计算出椭圆的中心(即,只要椭圆在框中居中,框的中心就是椭圆的中心)

对于你的第一个问题,我会看一下椭圆方程的极性形式,它可以在上找到。你也需要算出椭圆的偏心率


或者,您可以强制边界框中的值。。。计算出一个点是否位于椭圆上并与角度匹配,然后迭代边界框中的每个点。

因此解决方案如下:

椭圆的参数化公式:

x = x0 + a * cos(t) y = y0 + b * sin(t) x=x0+a*cos(t) y=y0+b*sin(t) 让我们把两点的已知坐标放到这里:

x1 = x0 + a * cos(t1) x2 = x0 + a * cos(t2) y1 = y0 + b * sin(t1) y2 = y0 + b * sin(t2) x1=x0+a*cos(t1) x2=x0+a*cos(t2) y1=y0+b*sin(t1) y2=y0+b*sin(t2) 现在我们有一个方程组,有4个变量:椭圆中心(x0/y0)和两个角度t1,t2

让我们减去方程式,以去除中心坐标:

x1 - x2 = a * (cos(t1) - cos(t2)) y1 - y2 = b * (sin(t1) - sin(t2)) x1-x2=a*(cos(t1)-cos(t2)) y1-y2=b*(sin(t1)-sin(t2)) 这可以重写(使用乘积和公式)为:

(x1-x2)/(2*a)=sin((t1+t2)/2)*sin((t1-t2)/2) (y2-y1)/(2*b)=cos((t1+t2)/2)*sin((t1-t2)/2) 让我们替换一些等式:

r1: (x1 - x2) / (2 * a) r2: (y2 - y1) / (2 * b) a1: (t1 + t2) / 2 a2: (t1 - t2) / 2 r1:(x1-x2)/(2*a) r2:(y2-y1)/(2*b) a1:(t1+t2)/2 a2:(t1-t2)/2 然后我们得到简单的方程组:

r1 = sin(a1) * sin(a2) r2 = cos(a1) * sin(a2) r1=sin(a1)*sin(a2) r2=cos(a1)*sin(a2) 将第一个方程式除以第二个方程式得出:

a1 = arctan(r1/r2) a1=arctan(r1/r2) 将该结果与第一个方程式相加,得出:

a2 = arcsin(r2 / cos(arctan(r1/r2))) a2=arcsin(r2/cos(arctan(r1/r2))) 或者,简单(使用触发器和反向触发器函数的组合):

a2=弧心(r2/(1/sqrt(1+(r1/r2)^2))) 或者更简单:

a2 = arcsin(sqrt(r1^2 + r2^2)) a2=弧心(sqrt(r1^2+r2^2))
现在,最初的四个方程组可以用easy求解,所有角度以及eclipse中心坐标都可以找到。

您发布的椭圆曲线弧链接包括一个

在那里,你可以找到的方程

下面是我对这些等式的JavaScript实现,取自,用于执行矩阵和向量计算

// Calculate the centre of the ellipse
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
var x1 = 150;  // Starting x-point of the arc
var y1 = 150;  // Starting y-point of the arc
var x2 = 400;  // End x-point of the arc
var y2 = 300;  // End y-point of the arc
var fA = 1;    // Large arc flag
var fS = 1;    // Sweep flag
var rx = 100;  // Horizontal radius of ellipse
var ry =  50;  // Vertical radius of ellipse
var phi = 0;   // Angle between co-ord system and ellipse x-axes

var Cx, Cy;

// Step 1: Compute (x1′, y1′)
var M = $M([
               [ Math.cos(phi), Math.sin(phi)],
               [-Math.sin(phi), Math.cos(phi)]
            ]);
var V = $V( [ (x1-x2)/2, (y1-y2)/2 ] );
var P = M.multiply(V);

var x1p = P.e(1);  // x1 prime
var y1p = P.e(2);  // y1 prime


// Ensure radii are large enough
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
// Step (a): Ensure radii are non-zero
// Step (b): Ensure radii are positive
rx = Math.abs(rx);
ry = Math.abs(ry);
// Step (c): Ensure radii are large enough
var lambda = ( (x1p * x1p) / (rx * rx) ) + ( (y1p * y1p) / (ry * ry) );
if(lambda > 1)
{
    rx = Math.sqrt(lambda) * rx;
    ry = Math.sqrt(lambda) * ry;
}


// Step 2: Compute (cx′, cy′)
var sign = (fA == fS)? -1 : 1;
// Bit of a hack, as presumably rounding errors were making his negative inside the square root!
if((( (rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p) ) / ( (rx*rx*y1p*y1p) + (ry*ry*x1p*x1p) )) < 1e-7)
    var co = 0;
else
    var co = sign * Math.sqrt( ( (rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p) ) / ( (rx*rx*y1p*y1p) + (ry*ry*x1p*x1p) ) );
var V = $V( [rx*y1p/ry, -ry*x1p/rx] );
var Cp = V.multiply(co);

// Step 3: Compute (cx, cy) from (cx′, cy′)
var M = $M([
               [ Math.cos(phi), -Math.sin(phi)],
               [ Math.sin(phi),  Math.cos(phi)]
            ]);
var V = $V( [ (x1+x2)/2, (y1+y2)/2 ] );
var C = M.multiply(Cp).add(V);

Cx = C.e(1);
Cy = C.e(2);
//计算椭圆的中心
//基于http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
变量x1=150;//弧的起始x点
变量y1=150;//弧的起始y点
变量x2=400;//弧的终点x点
变量y2=300;//圆弧的结束y点
var fA=1;//大弧旗
var fS=1;//横扫旗
var rx=100;//椭圆水平半径
变量ry=50;//椭圆垂直半径
var phi=0;//坐标系与椭圆x轴之间的角度
var-Cx,Cy;
//步骤1:计算(x1′,y1′)
var M=$M([
[Math.cos(phi),Math.sin(phi)],
[-Math.sin(phi),Math.cos(phi)]
]);
var V=$V([(x1-x2)/2,(y1-y2)/2]);
var P=M乘以(V);
var x1p=P.e(1);//x1素数
变量y1p=P.e(2);//y1素数
//确保半径足够大
//基于http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
//步骤(a):确保半径不为零
//步骤(b):确保半径为正
rx=数学绝对值(rx);
ry=Math.abs(ry);
//步骤(c):确保半径足够大
varλ=((x1p*x1p)/(rx*rx))+((y1p*y1p)/(ry*ry));
如果(λ>1)
{
rx=数学平方比(λ)*rx;
ry=数学sqrt(λ)*ry;
}
//步骤2:计算(cx′,cy′)
变量符号=(fA==fS)-1 : 1;
//有点奇怪,大概是舍入误差在平方根内造成了负数!
如果(((rx*rx*ry*rx*y1p*y1p)-(rx*rx*x1p*x1p))/((rx*rx*y1p*y1p)+(ry*ry*x1p*x1p))<1e-7)
var-co=0;
其他的
var co=符号*数学sqrt(((rx*rx*ry*rx*y1p*y1p)-(rx*rx*y1p*y1p)-(ry*ry*x1p*x1p))/((rx*rx*y1p*y1p)+(ry*ry*x1p*x1p));
var V=$V([rx*y1p/ry,-ry*x1p/rx]);
var Cp=V.乘以(co);
//步骤3:从(cx′,cy′)计算(cx,cy)
var M=$M([
[Math.cos(phi),-Math.sin(phi)],
[数学sin(phi),数学cos(phi)]
]);
var V=$V([(x1+x2)/2,(y1+y2)/2]);
var C=M.乘(Cp).加(V);
Cx=C.e(1);
Cy=C.e(2);

基于Rikki答案的TypeScript实现

默认DOMMatrix和DOMPoint用于计算(在最新的Chrome v.80中测试),而不是外部库

椭圆中心(
x1:数字,
y1:数字,
rx:号码,
李:号码,
轮换表:号码,
fa:号码,
财政司司长:数字,
x2:数字,
a2 = arcsin(sqrt(r1^2 + r2^2))
// Calculate the centre of the ellipse
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
var x1 = 150;  // Starting x-point of the arc
var y1 = 150;  // Starting y-point of the arc
var x2 = 400;  // End x-point of the arc
var y2 = 300;  // End y-point of the arc
var fA = 1;    // Large arc flag
var fS = 1;    // Sweep flag
var rx = 100;  // Horizontal radius of ellipse
var ry =  50;  // Vertical radius of ellipse
var phi = 0;   // Angle between co-ord system and ellipse x-axes

var Cx, Cy;

// Step 1: Compute (x1′, y1′)
var M = $M([
               [ Math.cos(phi), Math.sin(phi)],
               [-Math.sin(phi), Math.cos(phi)]
            ]);
var V = $V( [ (x1-x2)/2, (y1-y2)/2 ] );
var P = M.multiply(V);

var x1p = P.e(1);  // x1 prime
var y1p = P.e(2);  // y1 prime


// Ensure radii are large enough
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
// Step (a): Ensure radii are non-zero
// Step (b): Ensure radii are positive
rx = Math.abs(rx);
ry = Math.abs(ry);
// Step (c): Ensure radii are large enough
var lambda = ( (x1p * x1p) / (rx * rx) ) + ( (y1p * y1p) / (ry * ry) );
if(lambda > 1)
{
    rx = Math.sqrt(lambda) * rx;
    ry = Math.sqrt(lambda) * ry;
}


// Step 2: Compute (cx′, cy′)
var sign = (fA == fS)? -1 : 1;
// Bit of a hack, as presumably rounding errors were making his negative inside the square root!
if((( (rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p) ) / ( (rx*rx*y1p*y1p) + (ry*ry*x1p*x1p) )) < 1e-7)
    var co = 0;
else
    var co = sign * Math.sqrt( ( (rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p) ) / ( (rx*rx*y1p*y1p) + (ry*ry*x1p*x1p) ) );
var V = $V( [rx*y1p/ry, -ry*x1p/rx] );
var Cp = V.multiply(co);

// Step 3: Compute (cx, cy) from (cx′, cy′)
var M = $M([
               [ Math.cos(phi), -Math.sin(phi)],
               [ Math.sin(phi),  Math.cos(phi)]
            ]);
var V = $V( [ (x1+x2)/2, (y1+y2)/2 ] );
var C = M.multiply(Cp).add(V);

Cx = C.e(1);
Cy = C.e(2);