svg里面绘制椭圆弧的参数是这样的:x1 y1 x2 y2 fA fS rx ry φ
分别代表的含义是:
(x1 y1)圆弧路径起点
(x2 y2)圆弧路径终点
fA 标记是否大弧段
fS 标记是否顺时针绘制
rx 椭圆弧的X半轴长度
ry 椭圆弧的Y半轴长度
φ 椭圆弧X轴方向的旋转角度
我需要的计算是,根据上述参数,计算出:
椭圆弧的中心点(cx,cy)
起始弧度 θ1
终点弧度与起点弧度的差 Δθ
网址:
http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
英文原文:
F.6.5 Conversion from endpoint to center parameterization
Given the following variables:
x1 y1 x2 y2 fA fS rx ry φ
the task is to find:
cx cy θ1 Δθ
The equations simplify after a translation which places the origin at the midpoint of the line joining (x1, y1) to (x2, y2), followed by a rotation to line up the coordinate axes with the axes of the ellipse. All transformed coordinates will be written with primes. They are computed as intermediate values on the way toward finding the required center parameterization variables. This procedure consists of the following steps:
Step 1: Compute (x1′, y1′)
Equation F.6.5.1 (F.6.5.1)
Step 2: Compute (cx′, cy′)
Equation F.6.5.2 (F.6.5.2)
where the + sign is chosen if fA ≠ fS, and the − sign is chosen if fA = fS.
Step 3: Compute (cx, cy) from (cx′, cy′)
Equation F.6.5.3 (F.6.5.3)
Step 4: Compute θ1 and Δθ
In general, the angle between two vectors (ux, uy) and (vx, vy) can be computed as
Equation F.6.5.4 (F.6.5.4)
where the ± sign appearing here is the sign of ux vy − uy vx.
This angle function can be used to express θ1 and Δθ as follows:
Equation F.6.5.5 (F.6.5.5)
Equation F.6.5.6 (F.6.5.6)
where θ1 is fixed in the range −360° < Δθ < 360° such that:
if fS = 0, then Δθ < 0,
else if fS = 1, then Δθ > 0.
In other words, if fS = 0 and the right side of (F.6.5.6) is greater than 0, then subtract 360°, whereas if fS = 1 and the right side of (F.6.5.6) is less than 0, then add 360°. In all other cases leave it as is.
4 个解决方案
#1
楼主,既然你教会我一个公式,我就帮你写一个代码,不过这份代码未经调试,需要你自己验证一下。
/**
svg里面绘制椭圆弧的参数是这样的:x1 y1 x2 y2 fA fS rx ry φ
分别代表的含义是:
(x1 y1)圆弧路径起点
(x2 y2)圆弧路径终点
fA 标记是否大弧段
fS 标记是否顺时针绘制
rx 椭圆弧的X半轴长度
ry 椭圆弧的Y半轴长度
φ 椭圆弧X轴方向的旋转角度
http://topic.csdn.net/u/20120511/17/d278e925-75f0-4325-8926-b812f2d95b23.html?85757
http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
*/
#include <stdio.h>
#include <math.h>
double radian( double ux, double uy, double vx, double vy ) {
double dot = ux * vx + uy * vy;
double mod = sqrt( ( ux * ux + uy * uy ) * ( vx * vx + vy * vy ) );
double rad = acos( dot / mod );
if( ux * vy - uy * vx < 0.0 ) rad = -rad;
return rad;
}
int conversion_from_endpoint_to_center_parameterization(
double x1, double y1, double x2, double y2,
bool fA, bool fS,
double rx, double ry, double phi,
double &cx, double &cy, double &theta1, double &delta_theta ) {
if( rx == 0.0 || ry == 0.0 ) return -1; // 不是椭圆
double s_phi = sin( phi );
double c_phi = cos( phi );
double hd_x = ( x1 - x2 ) / 2.0; // half diff of x
double hd_y = ( y1 - y2 ) / 2.0; // half diff of y
double hs_x = ( x1 + x2 ) / 2.0; // half sum of x
double hs_y = ( y1 + y2 ) / 2.0; // half sum of y
// F6.5.1
double x1_ = c_phi * hd_x + s_phi * hd_y;
double y1_ = c_phi * hd_y - s_phi * hd_x;
double rxry = rx * ry;
double rxy1_ = rx * y1_;
double ryx1_ = ry * x1_;
double sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square
double coe = sqrt( ( rxry * rxry - sum_of_sq ) / sum_of_sq );
if( fA == fS ) coe = -coe;
// F6.5.2
double cx_ = coe * rxy1_ / ry;
double cy_ = -coe * ryx1_ / rx;
// F6.5.3
cx = c_phi * cx_ - s_phi * cy_ + hs_x;
cy = s_phi * cx_ + c_phi * cy_ + hs_y;
double xcr1 = ( x1_ - cx_ ) / rx;
double xcr2 = ( x1_ + cx_ ) / rx;
double ycr1 = ( y1_ - cy_ ) / ry;
double ycr2 = ( y1_ + cy_ ) / ry;
// F6.5.5
theta1 = radian( 1.0, 0.0, xcr1, ycr1 );
// F6.5.6
delta_theta = radian( xcr1, ycr1, -xcr2, -ycr2 );
double PIx2 = M_PI * 2.0;
while( delta_theta > PIx2 ) delta_theta -= PIx2;
while( delta_theta < 0.0 ) delta_theta += PIx2;
if( fS == false ) delta_theta -= PIx2;
return 0;
}
#2
头文件那里需要加一句,否则编译器不认得M_PI
#define _USE_MATH_DEFINES
#include <math.h>
#3
谢谢gogdizzy,我按你的试试去
#4
gogdizzy的代码,验证可行,结帖给分。
#1
楼主,既然你教会我一个公式,我就帮你写一个代码,不过这份代码未经调试,需要你自己验证一下。
/**
svg里面绘制椭圆弧的参数是这样的:x1 y1 x2 y2 fA fS rx ry φ
分别代表的含义是:
(x1 y1)圆弧路径起点
(x2 y2)圆弧路径终点
fA 标记是否大弧段
fS 标记是否顺时针绘制
rx 椭圆弧的X半轴长度
ry 椭圆弧的Y半轴长度
φ 椭圆弧X轴方向的旋转角度
http://topic.csdn.net/u/20120511/17/d278e925-75f0-4325-8926-b812f2d95b23.html?85757
http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
*/
#include <stdio.h>
#include <math.h>
double radian( double ux, double uy, double vx, double vy ) {
double dot = ux * vx + uy * vy;
double mod = sqrt( ( ux * ux + uy * uy ) * ( vx * vx + vy * vy ) );
double rad = acos( dot / mod );
if( ux * vy - uy * vx < 0.0 ) rad = -rad;
return rad;
}
int conversion_from_endpoint_to_center_parameterization(
double x1, double y1, double x2, double y2,
bool fA, bool fS,
double rx, double ry, double phi,
double &cx, double &cy, double &theta1, double &delta_theta ) {
if( rx == 0.0 || ry == 0.0 ) return -1; // 不是椭圆
double s_phi = sin( phi );
double c_phi = cos( phi );
double hd_x = ( x1 - x2 ) / 2.0; // half diff of x
double hd_y = ( y1 - y2 ) / 2.0; // half diff of y
double hs_x = ( x1 + x2 ) / 2.0; // half sum of x
double hs_y = ( y1 + y2 ) / 2.0; // half sum of y
// F6.5.1
double x1_ = c_phi * hd_x + s_phi * hd_y;
double y1_ = c_phi * hd_y - s_phi * hd_x;
double rxry = rx * ry;
double rxy1_ = rx * y1_;
double ryx1_ = ry * x1_;
double sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square
double coe = sqrt( ( rxry * rxry - sum_of_sq ) / sum_of_sq );
if( fA == fS ) coe = -coe;
// F6.5.2
double cx_ = coe * rxy1_ / ry;
double cy_ = -coe * ryx1_ / rx;
// F6.5.3
cx = c_phi * cx_ - s_phi * cy_ + hs_x;
cy = s_phi * cx_ + c_phi * cy_ + hs_y;
double xcr1 = ( x1_ - cx_ ) / rx;
double xcr2 = ( x1_ + cx_ ) / rx;
double ycr1 = ( y1_ - cy_ ) / ry;
double ycr2 = ( y1_ + cy_ ) / ry;
// F6.5.5
theta1 = radian( 1.0, 0.0, xcr1, ycr1 );
// F6.5.6
delta_theta = radian( xcr1, ycr1, -xcr2, -ycr2 );
double PIx2 = M_PI * 2.0;
while( delta_theta > PIx2 ) delta_theta -= PIx2;
while( delta_theta < 0.0 ) delta_theta += PIx2;
if( fS == false ) delta_theta -= PIx2;
return 0;
}
#2
头文件那里需要加一句,否则编译器不认得M_PI
#define _USE_MATH_DEFINES
#include <math.h>
#3
谢谢gogdizzy,我按你的试试去
#4
gogdizzy的代码,验证可行,结帖给分。