Forgot password?
 Register account
View 182|Reply 3

[几何] 椭圆弧 起终点+半径⇔中心+起终角 互相转换

[Copy link]

3159

Threads

7941

Posts

610K

Credits

Credits
63770
QQ

Show all posts

hbghlyj Posted 2023-3-7 00:01 |Read mode
Last edited by hbghlyj 2023-3-7 22:28 calculate the start and end angles of an SVG path arc command
implementation note
椭圆上的任意点$(x,y)$可以表示为:
\[\begin{pmatrix}x\\y\end{pmatrix}=\begin{pmatrix}\cos\varphi&-\sin\varphi\\\sin\varphi&\cos\varphi\end{pmatrix}\pmatrix{r_x\\&r_y}\begin{pmatrix}\cos\theta\\\sin\theta\end{pmatrix}+\begin{pmatrix}c_x\\c_y\end{pmatrix}\]$(c_x,c_y)$为椭圆中心, $r_x,r_y$为椭圆半轴长, $\varphi$为椭圆轴的倾角, $\theta$为参数.
椭圆弧的起点$(x_1,y_1)$和终点$(x_2,y_2)$用$\theta_1$和$\theta_2=\theta_1+\Delta\theta$表示为:
\begin{gather*}
\begin{pmatrix}x_1\\y_1\end{pmatrix}=\begin{pmatrix}\cos\varphi&-\sin\varphi\\\sin\varphi&\cos\varphi\end{pmatrix}\pmatrix{r_x\\&r_y}\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix}+\begin{pmatrix}c_x\\c_y\end{pmatrix}\\
\begin{pmatrix}x_2\\y_2\end{pmatrix}=\begin{pmatrix}\cos\varphi&-\sin\varphi\\\sin\varphi&\cos\varphi\end{pmatrix}\pmatrix{r_x\\&r_y}\begin{pmatrix}\cos\theta_2\\\sin\theta_2\end{pmatrix}+\begin{pmatrix}c_x\\c_y\end{pmatrix}
\end{gather*}
因为$\theta_{1,2}\in(-\pi,\pi]$, 定义$\Delta\theta=\theta_1-\theta_2$, 则 $-2\pi<\Delta\theta\le2\pi$.
large arc flag $f_A$定义为
\[f_A=\begin{cases}1&\text{if }\left|\Delta\theta\right|>\pi\\\text{0}&\text{if }\left|\Delta\theta\right|\leq\pi\end{cases}\]
sweep flag $f_S$定义为
\[f_S=\begin{cases}1&\text{if }\Delta\theta>0\\\text{0}&\text{if }\Delta\theta<0\end{cases}\]
给定
\[
x_1, y_1, x_2, y_2, f_A, f_S, r_x, r_y, φ
\]
如何求
\[
c_x, c_y, θ_1, \Delta θ
\]
svg2tikz.py有下面的代码
  1. # The calc_arc function is based on the calc_arc function in the
  2. # paths_svg2obj.py script bundled with Blender 3D
  3. # Copyright (c) jm soler juillet/novembre 2004-april 2007,
  4. def calc_arc(cp: Point, r_i: Point, ang, fa, fs, pos: Point):
  5.     """
  6.     Calc arc paths
  7.     """
  8.     ang = math.radians(ang)
  9.     r = Point(abs(r_i.x), abs(r_i.y))
  10.     pos.x = abs((cos(ang) * (cp.x - pos.x) + sin(ang) * (cp.y - pos.y)) * 0.5) ** 2.0
  11.     pos.y = abs((cos(ang) * (cp.y - pos.y) - sin(ang) * (cp.x - pos.x)) * 0.5) ** 2.0
  12.     rp = Point(
  13.         pos.x / (r.x**2.0) if abs(r.x) > 0.0 else 0.0,
  14.         pos.y / (r.y**2.0) if abs(r.y) > 0.0 else 0.0,
  15.     )
  16.     p_l = rp.x + rp.y
  17.     if p_l > 1.0:
  18.         p_l = p_l**0.5
  19.         r.x *= p_l
  20.         r.y *= p_l
  21.     car = Point(
  22.         cos(ang) / r.x if abs(r.x) > 0.0 else 0.0,
  23.         cos(ang) / r.y if abs(r.y) > 0.0 else 0.0,
  24.     )
  25.     sar = Point(
  26.         sin(ang) / r.x if abs(r.x) > 0.0 else 0.0,
  27.         sin(ang) / r.y if abs(r.y) > 0.0 else 0.0,
  28.     )
  29.     p0 = Point(car.x * cp.x + sar.x * cp.y, (-sar.y) * cp.x + car.y * cp.y)
  30.     p1 = Point(car.x * pos.x + sar.x * pos.y, (-sar.y) * pos.x + car.y * pos.y)
  31.     hyp = (p1.x - p0.x) ** 2 + (p1.y - p0.y) ** 2
  32.     if abs(hyp) > 0.0:
  33.         s_q = 1.0 / hyp - 0.25
  34.     else:
  35.         s_q = -0.25
  36.     s_q = max(0.0, s_q)
  37.     s_f = s_q**0.5
  38.     if fs == fa:
  39.         s_f *= -1
  40.     c = Point(
  41.         0.5 * (p0.x + p1.x) - s_f * (p1.y - p0.y),
  42.         0.5 * (p0.y + p1.y) + s_f * (p1.x - p0.x),
  43.     )
  44.     ang_0 = atan2(p0.y - c.y, p0.x - c.x)
  45.     ang_1 = atan2(p1.y - c.y, p1.x - c.x)
  46.     ang_arc = ang_1 - ang_0
  47.     if ang_arc < 0.0 and fs == 1:
  48.         ang_arc += 2.0 * mpi
  49.     elif ang_arc > 0.0 and fs == 0:
  50.         ang_arc -= 2.0 * mpi
  51.     ang0 = math.degrees(ang_0)
  52.     ang1 = math.degrees(ang_1)
  53.     if ang_arc > 0:
  54.         if ang_0 < ang_1:
  55.             pass
  56.         else:
  57.             ang0 -= 360
  58.     else:
  59.         if ang_0 < ang_1:
  60.             ang1 -= 360
  61.     return ang0, ang1, r
Copy the Code

3159

Threads

7941

Posts

610K

Credits

Credits
63770
QQ

Show all posts

 Author| hbghlyj Posted 2023-3-8 04:43
作差
\[\begin{pmatrix}\cos\theta_2\\\sin\theta_2\end{pmatrix}-\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix}=\pmatrix{r_x\\&r_y}^{-1}\begin{pmatrix}\cos\varphi&\sin\varphi\\-\sin\varphi&\cos\varphi\end{pmatrix}\begin{pmatrix}x_2-x_1\\y_2-y_1\end{pmatrix}\]
把右边(已知的)记为$\pmatrix{x_0\\y_0}$. 已知两单位向量之差, 应该可以求出它们
把$\theta_2$写成$\theta_1+\Delta\theta$
\[\left[\begin{pmatrix}\cos\Delta\theta&-\sin\Delta\theta\\\sin\Delta\theta&\cos\Delta\theta\end{pmatrix}-I\right]\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix}=\begin{pmatrix}x_0\\y_0\end{pmatrix}\]
即\[\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix}=\frac12\pmatrix{
-1 & \cot \frac{\Delta \theta }{2} \\
-\cot \frac{\Delta \theta }{2} & -1 \\
}\begin{pmatrix}x_0\\y_0\end{pmatrix}\]
因为左边为单位向量,
\[1=\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix}^T\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix}=\frac14\begin{pmatrix}x_0\\y_0\end{pmatrix}^T\pmatrix{
\csc ^2\frac{\Delta \theta }{2} & 0 \\
0 & \csc ^2\frac{\Delta \theta }{2} \\}\begin{pmatrix}x_0\\y_0\end{pmatrix}\]即$$\sin\frac{\Delta \theta }{2}=\pm\frac12\sqrt{x_0^2+y_0^2}$$


算完才发现

显然有$\sin\frac{\Delta \theta }{2}=\pm\frac12|AB|$

3159

Threads

7941

Posts

610K

Credits

Credits
63770
QQ

Show all posts

 Author| hbghlyj Posted 2023-3-8 05:11
当$f_S=1$时$\sin\frac{\Delta \theta }{2}>0$; 当$f_S=0$时$\sin\frac{\Delta \theta }{2}<0$. 因此
\[\sin\frac{\Delta \theta }{2}=(f_S-\frac12)\sqrt{x_0^2+y_0^2}\]
因为要代入\[\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix}=\frac12\pmatrix{
-1 & \cot \frac{\Delta \theta }{2} \\
-\cot \frac{\Delta \theta }{2} & -1 \\
}\begin{pmatrix}x_0\\y_0\end{pmatrix}\]所以需要求出$ \cos\frac{\Delta \theta }{2}$. 当$f_A=1$时$\cos\frac{\Delta \theta }{2}<0$; 当$f_A=0$时$\cos\frac{\Delta \theta }2>0$. 因此
\[\cos\frac{\Delta \theta }{2}=(1-2f_A)\sqrt{1-\sin^2\frac{\Delta \theta }{2}}\]

3159

Threads

7941

Posts

610K

Credits

Credits
63770
QQ

Show all posts

 Author| hbghlyj Posted 2023-3-8 05:31
B.2.4. Conversion from endpoint to center parameterization (eq. 5.2)
\[\begin{pmatrix}c_x'\\c_y'\end{pmatrix}=\pm\sqrt{\frac{r_x^2r_y^2-r_x^2\left(y_1'\right)^2-r_y^2\left(x_1'\right)^2}{r_x^2\left(y_1'\right)^2+r_y^2\left(x_1'\right)^2}}\begin{pmatrix}\frac{r_xy_1'}{r_y}\\-\frac{r_yx_1'}{r_x}\end{pmatrix}\]和\[\begin{pmatrix}c_x\\c_y\end{pmatrix}=\begin{pmatrix}\cos\varphi&-\sin\varphi\\\sin\varphi&\cos\varphi\end{pmatrix}⋅\begin{pmatrix}c_x'\\c_y'\end{pmatrix}+\begin{pmatrix}\frac{x_1+x_2}2\\\frac{y_1+y_2}2\end{pmatrix}\]
是怎么得到的

Mobile version|Discuz Math Forum

2025-5-31 11:01 GMT+8

Powered by Discuz!

× Quick Reply To Top Edit