我正在建造一个游戏,我需要为它创建一个地图。为了做到这一点,我必须使用两种椭圆:一种是使用2点找到的,一种是使用3点找到的(并通过它们)。我找到了一种方法来找到2分的方程,但现在我还没有找到一个方法来处理3分。所以我希望找到给出3点椭圆的方程。这就是我如何做到2分(这不是优雅,但它的工作做得很好):
import turtle
import sympy as sp
import random
SCREEN = turtle.Screen()
t = turtle.Turtle()
t.up()
t.ht()
t.speed(0)
tt = turtle.Turtle()
tt.up()
tt.ht()
tt.speed(0)
press = 1
def get_mouse_click_coor(x, y):
turtle.onscreenclick(None)
print(x, y)
draw(x,y)
def draw(mou_x,mou_y):
SCREEN.tracer(0)
global press
global x_press1, y_press1
if press%2 != 0:
t.goto(mou_x,mou_y)
x_press1, y_press1 = mou_x, mou_y
tt.color('blue')
tt.goto(mou_x,mou_y)
tt.dot(7)
if press%2 == 0:
if mou_x == x_press1 and mou_y == y_press1:
press = press - 1
else:
tt.color('red')
tt.goto(mou_x,mou_y)
tt.dot(7)
if mou_x > x_press1 and mou_y > y_press1:
turn = 1
if mou_x > x_press1 and mou_y < y_press1:
turn = 2
if mou_x < x_press1 and mou_y < y_press1:
turn = 3
if mou_x < x_press1 and mou_y > y_press1:
turn = 4
# if turn <= 2:
x0 = -mou_x+x_press1
if turn >= 3:
x0 = -x_press1+mou_x
y0 = mou_y - y_press1
for x in range(int(x0), 1, 1):
y = y0 - y0*sp.root(1.0-(float((x-x0)**2)/(x0**2)),2)
if turn >= 3:
x = -x
t.goto(x+mou_x, y+y_press1)
t.down()
t.up()
press = press + 1
SCREEN.tracer(1)
while True:
t.color('black')
turtle.onscreenclick(get_mouse_click_coor)
turtle.mainloop()
听起来很有趣!如果您的3个点击点位于同一象限中,则由这些点定义的三角形的一个角度必须是钝角。调用B和其他两个顶点A和C. x-y定向椭圆的一般方程中有4个参数。将A,B和C的x和y坐标代入椭圆方程将给出三个方程。你需要拿出第4个。您可以自由选择在游戏环境中有意义的第四点。这是一个SymPy代码片段,它根据A,B和C以及参数“f”将x值分配给椭圆的中心。
def e3(p1, p2, p3, f):
t = Triangle(p1, p2, p3)
a = t.angles
for p in a:
if a[p] > pi/2:
break
else:
return
while p != p2:
p1, p2, p3 = p2, p3, p1
pts = A, B, C = p1, p2, p3
# perpendicular line to AB passing through A
perp = Segment(A, B).perpendicular_line(A)
# intersection between that and the perpendicular to that
# which passes through C
m = perp.perpendicular_line(C).intersection(perp)[0]
delta = m - A
c = A + delta*f
x, y, h, r, y0 = symbols('x y h r y0', cls=Dummy)
eq = Ellipse((c.x, y0), h, r).equation(x, y)
s = solve([
eq.xreplace(dict(zip((x, y), p))) for p in pts], dict=True)[0]
return eq.subs(s) # for desmos graphing: str(eq.subs(s)).replace('**','^').replace('_','')+'=0'
f = .125,.25,.5,1,2的一些结果显示在desmos。
您可以看到他们都通过您提供的要点作为示例。红色圆圈提供了一个有趣的参考点。您可能想要选择一个f,因此椭圆的最终宽度是圆的直径的一小部分,它将通过这些点。
然而,椭圆经过的点不在每个椭圆的相同象限中。要满足该标准,您必须考虑“离轴”椭圆。使用here发布的任意椭圆方程可能也会有所帮助,以指导您在定义椭圆时选择要控制的变量。
为了使方程尽可能简单地求解和确定,如果该角度产生锐角,则可以使轴穿过第二个点击点,否则通过第1和第3点。这是代码证明:
def e3(A, B, C, n=7):
'''Return centered at the midpoint of A and C with the axis going through B if the angle at B is acute, else going through A and C.
'''
from sympy import Line
xc, yc = ctr = (A + C)/2
AC = A.distance(C)
smalls = True
if AC >= B.distance(A) and AC >= B.distance(C):
s = Line(A, C).slope
M2 = ctr.distance(A)**2
b = B
if abs(s) <= 1:
m2 = -M2*(s*(b.x - xc) - b.y + yc)**2/(
-M2*(s**2 + 1) + (s*(b.y - yc) + b.x - xc)**2)
else:
s = 1/s
m2 = M2*(s*(b.y - yc) - b.x + xc)**2/(
M2*(s**2 + 1) - (s*(b.x - xc) + b.y - yc)**2)
smalls = False
else:
s = Line(B, ctr).slope
M2 = ctr.distance(B)**2
p = A # or C
if abs(s) <= 1:
m2 = -M2*(s*(p.x - xc) - p.y + yc)**2/(
-M2*(s**2 + 1) + (s*(p.y - yc) + p.x - xc)**2)
else:
s = 1/s
m2 = M2*(s*(p.y - yc) - p.x + xc)**2/(
M2*(s**2 + 1) - (s*(p.x - xc) + p.y - yc)**2)
smalls = False
if smalls:
el = -1 + (-s*(x - xc) + y - yc)**2/(m2*(s**2 + 1)) + (
s*(y - yc) + x - xc)**2/(M2*(s**2 + 1))
else:
el = (M2*(s**2 + 1)*(-m2*(s**2 + 1) + (s*(y - yc) - x + xc)**2
) + m2*(s**2 + 1)*(s*(x - xc) + y - yc)**2)/(
M2*m2*(s**2 + 1)**2)
return el.expand().n(n=n)
from sympy import Point
a,b,c = Point(7/5, 12/5), Point(3/2, 5/2), Point(19/10, 3/2)
e3(a,b,c)
e3(b,c,a)
e3(c,a,b)
根据第二个单击点,您将获得1或3个省略号:
不确定我是否得到你的观点,因为它实际上是一个数学问题。对我来说,似乎你正在寻找类似于需要3个输入参数来绘制椭圆的函数。接下来是代码,其中width是长轴,高度是短轴。 xy是椭圆的中心点。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Ellipse
# These are 3 xy points
xpoints=(1.5,1.4,1.9)
ypoints=(2.5,2.4,1.5)
# calculate the center
mean_x=np.mean(xpoints)
mean_y=np.mean(ypoints)
# set the size of the ellipse
w=np.max(xpoints)+0.1
h=np.max(ypoints)+0.1
# buid the ellipse around it
ells = Ellipse((mean_x,mean_y), width=w, height=h,facecolor='None')
# plot it
fig = plt.figure(0)
ax = fig.add_subplot(111, aspect='equal')
ax.add_artist(ells)
ax.scatter(xpoints,ypoints, color='r')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
plt.show()