Jade Dungeon

圆的方程

设圆心为点\((a,b)\)半径为\(r\)。

圆的标准方程表示为以下二元二次方程:

\[ (x - x_0)^2 + (y - y_0)^2 = r^2 \quad (r \gt 0) \]

圆的一般方程表示为以下二元二次方程:

\[ x^2 + y^2 + Dx + Ey + F = 0 \quad (D^2 + E^2 -4F \gt 0) \]

直线与圆的关系

设圆的半径为\(r\),圆心到直线的距离为\(d\):

  • \(d \gt r\):直线与圆「相离」。
  • \(d = r\):直线与圆「相切」。
  • \(d \lt r\):直线与圆「相交」。

另一个判断的方法:把圆方程与直线方程联立,消去一个\(x\)或是\(y\)转为一元二次方程:

  • 如果该一元二次方程的判式\(\gt 0\),则相交。
  • 如果该一元二次方程的判式\(= 0\),则相切。
  • 如果该一元二次方程的判式\(\lt 0\),则相离。

圆与圆的位置关系

两个圆\(C_0, C_1\)的半径分别是\(r_0, r_1\),两圆心间的距离为\(d\):

  • 相离:\(d \gt r_0 + r_1\),两个圆有4条公切线。
  • 外切:\(d = r_0 + r_1\),两个圆有3条公切线。
  • 相交:\(|r_0 - r_1| \lt d \lt r_0 + r_1\),两个圆有2条公切线。
  • 内切:\(d = |r_0 - r_1|\),两个圆有1条公切线。
  • 内含:\(0 \le d \lt r_0 - r_1\),两个圆有0条公切线。其中当\(d=0\)时,两个圆为同心圆。

圆系方程

同心圆系方程

圆心与指定点的所有的圆:

\[ (x - x_0)^2 + (y - y_0) = r^2 \]

其中:\(x_0, y_0\)为常量,\(r\)为参数。

过两圆交点的圆系方程

有两个圆\(C_1, C_2\):

\[ \begin{split} C_1: (x - x_1)^2 + (y - y_1)^2 &= r_1^2 \\ C_2: (x - x_2)^2 + (y - y_2)^2 &= r_2^2 \end{split} \]

过\(C_1, C_2\)交点的所有圆(不包括\(C_2\))的方程:

\[ (x - x_1)^2 + (y - y_1)^2 - r_1^2 + \lambda [(x - x_2)^2 + (y - y_2)^2 - r_2^2] = 0 \]

其中\(\lambda\)是参数,而且不为\(-1\)。因为当\(\lambda = -1\)表示的是过两交点的直线。

圆切线

1.极线方程(2020-1-4)

如果与圆锥曲线切于A,B两点的切线相交于P点,那么P点称为直线AB关于该曲线的极点,直线AB称为P点的极线。

一开始我看成了切线方程,现在看应该是求极线方程。

1.1 特殊情况

圆 \(C:x^2+y^2=r^2\), 圆外一点\(P(x_0,y_0)\), \(A\), \(B\)坐标分别为 \((x_1,y_1),(x_2,y_2)\)

切线 \(AP:{x_1}x+{y_1}y=r^{2}\), \(BP:{x_2}x+{y_2}y=r^{2}\)

将\(P\)点坐标代入, 得 \({x_1}{x_0}+{y_1}{y_0}=r^{2},{x_2}{x_0}+{y_2}{y_0}=r^{2}\)

A、B坐标满足 \({x_0}x+{y_0}y=r^2\)

此时, 极线方程为 \({x_0}x+{y_0}y=r^2\)

1.2 一般情况

圆 \(C:(x-a)^2+(y-b)^2=r^2\) , 圆外一点 \(P(x_0,y_0)\)

原点平移至圆心, \(x'=x-a\),\(y'=y-b\)

\(C:(x')^2+(y')^2=r^2\),\(P(x_0-a,y_0-b)\)

由上例可得, 极线方程 \((x_0-a)x'+(y_0-b)y'=r^2\)

即 \((x_0-a)(x-a)+(y_0-b)(y-b)=r^2\)

1.3 圆系方程解法

参考楼下dalao @风里 的解法

\(\odot O:(x-a)^2+(y-b)^2=r^2\)①

圆外一点 \(P(x_0,y_0)\), 两切点位于以OP为直径的圆上,

直径式: \((x-a)(x-x_0)+(y-b)(y-y_0)=0\) ②

①-②得,极线方程 \((x_0-a)(x-a)+(y_0-b)(y-b)=r^2\)

1.4 拓展

对于椭圆 \(C:\frac{x^2}{a^2}+\frac{y^2}{b^2}=1\) 和点 \(P(x_0,y_0)\) ,极线方程为 \(\frac{x_0x}{a^2}+\frac{y_0y}{b^2}=1\)

对于双曲线 \(C:\frac{x^2}{a^2}-\frac{y^2}{b^2}=1\) 和点 \(P(x_0,y_0)\) ,极线方程为 \(\frac{x_0x}{a^2}-\frac{y_0y}{b^2}=1\)

对于抛物线 \(C:y^2=2px\) 和点 \(P(x_0,y_0)\) ,极线方程为 \(y_0y=p(x+x_0)\)

2. 切线方程(2019-11-22)

2.1 圆外

若已知圆 \((x-x_0)^2+(y-y_0)^2=r^2\) , 圆外一点\(A(x_1,y_1)\) , 求点A切线方程

设直线的点法向式方程: \(a(x-x_1)+b(y-y_1)=0\)

由点到直线的距离公式得 \(r=\frac{|a(x_0-x_1)+b(y_0-y_1)|}{\sqrt{a^2+b^2}}\)

\(r^2(a^2+b^2)=[a(x_0-x_1)+b(y_0-y_1)]^2\)

令 \(\Delta x=x_1-x_0,\Delta y=y_1-y_0\),

\(a^2(\Delta x^2-r^2)+2 ab\Delta x\Delta y+b^2(\Delta y^2-r^2)=0\)

解上述方程,得到a与b的关系式,代入点法向式方程即可得到两个切线方程

2.2 圆上

切线方程怎么推导?

点 \(P(a,b)\)在圆 \(x^2+y^2=r^2\) 上, 那么有 \(a^2+b^2=r^2\)

切线的法向量取 \(\vec{OP}=(a,b)\)

可以用直线的点法向式方程: \(a(x-a)+b(y-b)=0\Leftrightarrow ax+by=a^2+b^2=r^2\)

用程序计算

切线

传统的做法是用圆的方程与切线的方程联立解,但这样用代码实现太繁, 用向量旋转更方便。

二维坐标下向量旋转后的坐标公式:

切线

思路是以点到圆心的向量旋转得到新的点到圆心和向量,然后乘以模长得到坐标:

切线

例子:


export type Point2D = { x: number, y: number };
export type Circle  = { location: Point2D, radius: number}

genVertex(location: Point2D, circle: Circle): Array<Point2D> {
	let p1 = {x: 0, y: 0};
	let p2 = {x: 0, y: 0};

	// 外部点到圆心的距离
	let dx = location.x - circle.location.x;
	let dy = location.y - circle.location.y;
	let distance = Math.sqrt(dx * dx + dy * dy);

	// 点在圆内无效
	if (distance < circle.radius || distance == circle.radius) {
		return [p1, p2];
	}

	// 点到切点的距离
	let length = Math.sqrt(distance * distance - circle.radius * circle.radius);

	let u = {x: 0, y: 0};
	// 点到圆心的单位向量
	u.x = (circle.location.x - location.x) / distance;
	u.y = (circle.location.y - location.y) / distance;
	// u.x = dx / distance;
	// u.y = dy / distance;
	// 切线与圆心的夹角
	let angle = Math.asin(circle.radius / distance);
	console.log(' Math.cos( angle) ' + Math.cos( angle));
	console.log(' Math.sin( angle) ' + Math.sin( angle));
	console.log(' Math.cos(-angle) ' + Math.cos(-angle));
	console.log(' Math.sin(-angle) ' + Math.sin(-angle));

	// 向两个方向旋转单位向量
	p1.x = u.x * Math.cos( angle) - u.y * Math.sin( angle);
	p1.y = u.x * Math.sin( angle) + u.y * Math.cos( angle);
	p2.x = u.x * Math.cos(-angle) - u.y * Math.sin(-angle);
	p2.y = u.x * Math.sin(-angle) + u.y * Math.cos(-angle);
	console.log(`p1: (${p1.x.toFixed(6)},${p1.y.toFixed(6)}),   p2: (${p2.x.toFixed(6)},${p2.y.toFixed(6)})`);
	// 得到新坐标
	p1.x = p1.x * length + location.x;
	p1.y = p1.y * length + location.y;
	p2.x = p2.x * length + location.x;
	p2.y = p2.y * length + location.y;
	console.log(`p1: (${p1.x.toFixed(6)},${p1.y.toFixed(6)}),   p2: (${p2.x.toFixed(6)},${p2.y.toFixed(6)})`);
	return [p1, p2];
}