円と交わる直線の座標を求める関数を作ってみました。
直線の方程式オブジェクトには、
y軸に平行な場合yに値が格納され、
x軸に平行な場合xに値が格納され、
それ以外の場合はy=mx+nの形式でmとnの値が格納されます。
※ax+by+c=0と使い分けるためにy=mx+nを使用しています。
import math
# 円と交わる直線の座標を返却
def cli(line, x, y, r):
points = []
if "y" in line:
# y軸に平行な直線の場合
a = 0
b = 1
c = -(line["y"])
elif "x" in line:
# x軸に平行な直線の場合
a = 1
b = 0
c = -(line["x"])
else:
# y = mx + n
a = line["m"]
c = line["n"]
b = -(c / line["n"])
l = a ** 2 + b ** 2
k = a * x + b * y + c
d = l * r ** 2 - k ** 2
if d > 0:
# 2点交わる
ds = math.sqrt(d)
apl = a / l
bpl = b / l
xc = x - apl * k
yc = y - bpl * k
xd = bpl * ds
yd = apl * ds
point = {}
point["x"] = xc - xd
point["y"] = yc + yd
points.append(point)
point = {}
point["x"] = xc + xd
point["y"] = yc - yd
points.append(point)
elif d == 0:
# 1点交わる
point = {}
point["x"] = x - a * k / l
point["y"] = y - b * k / l
points.append(point)
return points
実際に動かしてみます。
x=2と(2, 2)半径4の円が交わる座標
# -*- coding: utf-8
import json
# x=2と(2, 2)半径4の円が交わる座標
print("x=2と(2, 2)半径4の円が交わる座標")
line = {"x": 2}
print(json.dumps(cli(line, 2, 2, 4), indent=4))
x=2と(2, 2)半径4の円が交わる座標
[
{
"x": 2.0,
"y": 6.0
},
{
"x": 2.0,
"y": -2.0
}
]
y=4と(2, 2)半径2の円が交わる座標
# -*- coding: utf-8
import json
# y=4と(2, 2)半径2の円が交わる座標
print("y=4と(2, 2)半径2の円が交わる座標")
line = {"y": 4}
print(json.dumps(cli(line, 2, 2, 2), indent=4))
y=4と(2, 2)半径2の円が交わる座標
[
{
"x": 2.0,
"y": 4.0
}
]
y=3x-2と(2, 3)半径1の円が交わる座標
# -*- coding: utf-8
import json
# y=3x-2と(2, 3)半径1の円が交わる座標
print("y=3x-2と(2, 3)半径1の円が交わる座標")
line = {"m": 3, "n": -2}
print(json.dumps(cli(line, 2, 3, 1), indent=4))
y=3x-2と(2, 3)半径1の円が交わる座標
[
{
"x": 2.0,
"y": 4.0
},
{
"x": 1.4,
"y": 2.2
}
]
y=3x-2と(5, 3)半径1の円が交わる座標(交わらない場合)
# -*- coding: utf-8
import json
# y=3x-2と(5, 3)半径1の円が交わる座標
print("y=3x-2と(5, 3)半径1の円が交わる座標")
line = {"m": 3, "n": -2}
print(json.dumps(cli(line, 5, 3, 1), indent=4))
y=3x-2と(5, 3)半径1の円が交わる座標
[]