Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from tkinter import *
- from tkinter import ttk
- from tkinter.messagebox import *
- import math
- def draw(event):
- global f_lst, r_lst
- a = f_lst.get(0, END)
- b = r_lst.get(0, END)
- print(a, b)
- return
- if a is None or b is None:
- showerror('Ошибка', 'Введите точки в формате х,у')
- return
- cnv.delete('all')
- cir1, cir2, inter, l1, l2 = calc(a, b)
- if cir1 is None:
- showwarning('Упс', "Окружностей не найдено!")
- else:
- cnv.create_oval((cir1[0][0] - cir1[1]) * scale + dx, (cir1[0][1] + cir1[1]) * scale + dy,
- (cir1[0][0] + cir1[1]) * scale + dx, (cir1[0][1] - cir1[1]) * scale + dy, fill='#FFF0F5')
- cnv.create_oval((cir2[0][0] - cir2[1]) * scale + dx, (cir2[0][1] + cir2[1]) * scale + dy,
- (cir2[0][0] + cir2[1]) * scale + dx, (cir2[0][1] - cir2[1]) * scale + dy, fill='#E6E6FA')
- cnv.create_oval((cir1[0][0] - 0.2) * scale + dx, (cir1[0][1] - 0.2) * scale + dy, (cir1[0][0] + 0.2) * scale + dx,
- (cir1[0][1] + 0.2) * scale + dy, fil='#DB7093')
- cnv.create_oval((cir2[0][0] - 0.2) * scale + dx, (cir2[0][1] - 0.2) * scale + dy,
- (cir2[0][0] + 0.2) * scale + dx,
- (cir2[0][1] + 0.2) * scale + dy, fil='#9370DB')
- cnv.create_oval((inter[0] - 0.2) * scale + dx, (inter[1] - 0.2) * scale + dy, (inter[0] + 0.2) * scale + dx,
- (inter[1] + 0.2) * scale + dy, fill="black")
- cnv.create_line(l1[0][0] * scale + dx, l1[0][1] * scale + dy, l1[1][0] * scale + dx, l1[1][1] * scale + dy,
- width=1, fill="black")
- cnv.create_line(l2[0][0] * scale + dx, l2[0][1] * scale + dy, l2[1][0] * scale + dx, l2[1][1] * scale + dy,
- width=1, fill="black")
- for i in range(len(a)):
- cnv.create_oval((a[i][0] - 0.2) * scale + dx, (a[i][1] - 0.2) * scale + dy, (a[i][0] + 0.2) * scale + dx,
- (a[i][1] + 0.2) * scale + dy, fill="green")
- for i in range(len(b)):
- cnv.create_oval((b[i][0] - 0.2) * scale + dx, (b[i][1] - 0.2) * scale + dy, (b[i][0] + 0.2) * scale + dx,
- (b[i][1] + 0.2) * scale + dy, fill="red")
- tx.delete('1.0', END)
- tx.insert(1.0, "Окружности найдены. \n "
- "Окружность 1: ее радиус {0:.2f}, координаты центра ({1:.2f}, {2:.2f}) \n"
- "Окружность 2: ее радиус {3:.2f}, координаты центра ({4:.2f}, {5:.2f}) \n"
- "Точка пересечения касательных {6:.2f}".format(cir1[1], cir1[0][0], cir1[0][1], cir2[1], cir2[0][0],
- cir2[0][1], inter[0], inter[1]))
- def redraw_max(event):
- global scale, cnv
- scale += 1
- cnv.delete('all')
- draw(event)
- def redraw_min(event):
- global scale, cnv
- scale -= 1
- cnv.delete('all')
- draw(event)
- def to_right(event):
- global dx, cnv
- dx += 10
- cnv.delete('all')
- draw(event)
- def to_left(event):
- global dx, cnv
- dx -= 10
- cnv.delete('all')
- draw(event)
- def to_top(event):
- global dy, cnv
- dy -= 10
- cnv.delete('all')
- draw(event)
- def to_bottom(event):
- global dy, cnv
- dy += 10
- cnv.delete('all')
- draw(event)
- def str_to_float(a):
- if a == '':
- return None
- a = a.split(' ')
- for i in range(len(a)):
- try:
- a[i] = float(a[i])
- except ValueError:
- showwarning('Упс', "Уберите лишние пробелы или добавьте еще одну координату!")
- return None
- return a
- def distance_between_points(xy1, xy2):
- x_1 = xy1[0]
- x_2 = xy2[0]
- y_1 = xy1[1]
- y_2 = xy2[1]
- dis = math.sqrt((x_2 - x_1) ** 2 + (y_2 - y_1) ** 2)
- return dis
- def calc(a, b):
- min_squere = None
- circle1 = None
- circle2 = None
- line1 = None
- line2 = None
- inter_points = None
- for i in range(len(a) - 2): # первая связка-точка
- for j in range(i + 1, len(a) - 1): # вторая связка-точка
- for k in range(j + 1, len(a)): # третья связка-точка
- res = find_cir(a[i], a[j], a[k])
- # print(a[i], a[j], a[k], centre_a, rad_a)
- if res is None:
- continue
- else:
- centre_a = res[0]
- rad_a = res[1]
- for l in range(len(b) - 2): # первая связка-точка
- for m in range(l + 1, len(b) - 1): # вторая связка-точка
- for n in range(m + 1, len(b)): # третья связка-точка
- res = find_cir(b[l], b[m], b[n])
- # print(b[i], b[j], b[k], centre_b, rad_b)
- if res is None:
- continue
- else:
- centre_b = res[0]
- rad_b = res[1]
- look_dis = distance_between_points(centre_b, centre_a)
- if look_dis <= rad_a + rad_b:
- continue
- k = rad_a / rad_b # коэфициент подобия
- xm = (centre_a[0] + centre_b[0] * k) / (1 + k) # точка пересечения касательных
- ym = (centre_a[1] + centre_b[1] * k) / (1 + k)
- r = math.sqrt(distance_between_points([xm, ym], centre_a) ** 2 - rad_a ** 2)
- d = math.sqrt(math.pow(abs(centre_a[0] - xm), 2) + math.pow(abs(centre_a[1] - ym), 2)) # расстояние между центрами окружностей
- if d >= r + rad_a:
- continue
- aa = (r**2 - rad_a**2 + d**2) / (2*d) # расстояние от r до точки пересечения линии, соединяющей точки пересечения
- h = math.sqrt(math.pow(r, 2) - math.pow(aa ,2)) # //расстояние от точки пересеч окружностей до линииб соед т пересеч
- x0 = xm + aa * (centre_a[0] - xm) / d # точка пересеч линии соединения и линии центров
- y0 = ym + aa * (centre_a[1] - ym) / d
- up_a = [x0 + h * (centre_a[1] - ym) / d,
- y0 - h * (centre_a[0] - xm) / d]
- down_a = [x0 - h * (centre_a[1] - ym) / d,
- y0 + h * (centre_a[0] - xm) / d]
- #print(up_a, '\n', down_a, '\n')
- # _________________________________________________________________
- r = math.sqrt(distance_between_points([xm, ym], centre_b) ** 2 - rad_b ** 2)
- d = math.sqrt(math.pow(abs(centre_b[0] - xm), 2) + math.pow(abs(centre_b[1] - ym), 2)) # расстояние между центрами окружностей
- if d >= r + rad_b:
- continue
- aa = (r ** 2 - rad_b ** 2 + d ** 2) / (2 * d) # расстояние от r до точки пересечения линии, соединяющей точки пересечения
- h = math.sqrt(math.pow(r, 2) - math.pow(aa, 2)) # //расстояние от точки пересеч окружностей до линииб соед т пересеч
- x0 = xm + aa * (centre_b[0] - xm) / d # точка пересеч линии соединения и линии центров
- y0 = ym + aa * (centre_b[1] - ym) / d
- up_b = [x0 + h * (centre_b[1] - ym) / d,
- y0 - h * (centre_b[0] - xm) / d]
- down_b = [x0 - h * (centre_b[1] - ym) / d,
- y0 + h * (centre_b[0] - xm) / d]
- #print(up_b, '\n', down_b, '\n')
- d1 = distance_between_points(up_a, down_a)
- d2 = distance_between_points([xm, ym], centre_a)
- squere1 = (d1 * d2) / 2
- d1 = distance_between_points(up_b, down_b)
- d2 = distance_between_points([xm, ym], centre_b)
- squere2 = (d1 * d2) / 2
- if min_squere is None or abs(squere1 - squere2) < min_squere:
- min_squere = abs(squere1 - squere2)
- circle1 = [centre_a, rad_a]
- circle2 = [centre_b, rad_b]
- line1 = [up_a, up_b]
- line2 = [down_b, down_a]
- inter_points = [xm, ym]
- return circle1, circle2, inter_points, line1, line2
- def find_cir(p1, p2, p3): # поиск окружности по трем точкам
- x1, y1 = p1[0], p1[1]
- x2, y2 = p2[0], p2[1]
- x3, y3 = p3[0], p3[1]
- if x1 == x2 == x3: # три точки лежат на одной прямой
- return None
- if x2 == x1: # случай, когда одна хорда вертикальная, ее коэф = int
- x2, x3 = x3, x2
- y2, y3 = y3, y2
- elif x2 == x3:
- x1, x2 = x2, x1
- y1, y2 = y2, y1
- ma = (y2 - y1) / (x2 - x1) # наклонный коэф 1-ой хорды
- mb = (y3 - y2) / (x3 - x2) # накл коэф 2-ой хорды
- if ma != mb: # прямые совпадают
- x_centre = (ma * mb * (y1 - y3) + mb * (x1 + x2) - ma * (x2 + x3)) / (2 * (mb - ma))
- if ma == 0:
- y_centre = (-1 / mb) * (x_centre - (x2 + x3) / 2) + ((y2 + y3) / 2)
- else:
- y_centre = (-1 / ma) * (x_centre - (x1 + x2) / 2) + ((y1 + y2) / 2)
- radius = distance_between_points([x_centre, y_centre], [x1, y1])
- return [[x_centre, y_centre], radius]
- else:
- return None
- def get_line(p1, p2):
- x1, y1 = p1[0], p1[1]
- x2, y2 = p2[0], p2[1]
- try:
- k = (y1 - y2) / (x1 - x2)
- except ZeroDivisionError:
- return None
- b = y2 - k * x2
- return [k, b]
- def is_tangent(x0, y0, rad, k, v):
- c = x0 ** 2 + v ** 2 - 2 * y0 * v + y0 ** 2 - rad ** 2
- a = k ** 2 + 1
- b = -2 * x0 - 2 * y0 * k + 2 * k * v
- D = b ** 2 - 4 * a * c
- if D != 0:
- return False
- else:
- return True
- def intersection(k1, b1, k2, b2):
- try:
- x = (b2 - b1) / (k1 - k2)
- except ZeroDivisionError:
- return None
- y = k1 * x + b1
- return [x, y]
- def k_comb(n, k):
- assert n > k, "Check values in k_comb!"
- return int(math.factorial(n) / (math.factorial(k) * math.factorial(n - k)))
- def quit_win(event):
- global root, widgets
- root.destroy()
- widgets.destroy()
- navigation.destroy()
- def insert_lst_f(event):
- global f_lst, ent_f
- p = ent_f.get()
- p = str_to_float(p)
- if p is None:
- return
- if len(p) > 2 or len(p) < 2:
- showwarning('Упс', "У точки должно быть всего две координаты!")
- return
- f_lst.insert(END, str(p))
- ent_f.delete(0, END)
- def insert_lst_s(event):
- global r_lst, ent_s
- p = ent_s.get()
- p = str_to_float(p)
- if p is None:
- return
- if len(p) > 2:
- showwarning('Упс', "У точки должно быть всего две координаты!")
- return
- r_lst.insert(END, str(p))
- ent_s.delete(0, END)
- def del_point(event):
- global f_lst, r_lst
- print(f_lst.get(ACTIVE))
- print(r_lst.get(ACTIVE))
- root = Tk()
- root.title("Поле точек")
- widgets = Tk()
- widgets.title("Инструменты")
- navigation = Tk()
- navigation.title("Навигация")
- root.geometry('700x600')
- widgets.wm_geometry("+%d+%d" % (100, 100))
- root.wm_geometry("+%d+%d" % (500, 50))
- navigation.wm_geometry("+%d+%d" % (100, 350))
- r = Tk()
- scale = 9
- dx = 10
- dy = 10
- scale_p = ttk.Button(navigation)
- scale_p['text'] = "Увеличить"
- scale_m = ttk.Button(navigation)
- scale_m['text'] = 'Уменьшить'
- right = ttk.Button(navigation)
- right['text'] = '〉'
- left = ttk.Button(navigation)
- left['text'] = '〈'
- bottom = ttk.Button(navigation)
- bottom['text'] = '﹀'
- top = ttk.Button(navigation)
- top['text'] = '︿'
- scrollbar1 = Scrollbar(r)
- scrollbar2 = Scrollbar(r)
- f_lst = Listbox(r, selectmode=SINGLE, height=10, yscrollcommand=scrollbar1.set)
- r_lst = Listbox(r, selectmode=SINGLE, height=10, yscrollcommand=scrollbar2.set)
- scrollbar1.config(command=f_lst.yview)
- scrollbar2.config(command=r_lst.yview)
- lab_f = Label(r, text="Красное можество точек", font="Times 12")
- lab_s = Label(r, text="Зеленое можество точек", font="Times 12")
- xy_f = Label(r, text='Введите красную точку ', font="Times 12")
- xy_s = Label(r, text='Введите зеленую точку ', font="Times 12")
- ent_f = Entry(r, width=50, bd=3)
- ent_s = Entry(r, width=50, bd=3)
- but_change = ttk.Button(r)
- but_change['text'] = 'Изменить'
- but_del = ttk.Button(r)
- but_del['text'] = 'Удалить'
- but_answ = ttk.Button(r)
- but_answ["text"] = "Отобразить ответ"
- but_exit = ttk.Button(r)
- but_exit['text'] = 'Выход'
- ent_f.bind('<Return>', insert_lst_f)
- ent_s.bind('<Return>', insert_lst_s)
- but_del.bind('<Button-1>', del_point)
- ent1 = Entry(widgets, width=50, bd=3)
- ent2 = Entry(widgets, width=50, bd=3)
- tx = Text(root, width=700, height=4, font='Times 12')
- ent1.insert(0, '4,6 10,12.34 23.9,12 2,1 6.2,4 4,1')
- ent2.insert(0, '23.5,14 8.1,5.1 4,9 23,34 3,4')
- lab1 = Label(widgets, text="Первое можество точек:", font="Times 12", highlightcolor='red')
- lab2 = Label(widgets, text="Второе можество точек:", font="Times 12", highlightcolor='green')
- cnv = Canvas(root, height=600, width=700, bg='white')
- but_answ.bind("<Button-1>", draw)
- scale_p.bind('<Button-1>', redraw_max)
- scale_m.bind('<Button-1>', redraw_min)
- right.bind('<Button-1>', to_right)
- left.bind('<Button-1>', to_left)
- top.bind('<Button-1>', to_top)
- bottom.bind('<Button-1>', to_bottom)
- but_exit.bind('<Button-1>', quit_win)
- f_lst.grid(row=1, column=0, padx=10)
- r_lst.grid(row=1, column=1, padx=10)
- lab_f.grid(row=0, column=0, padx=5)
- lab_s.grid(row=0, column=1, padx=5)
- xy_f.grid(row=2, column=0, pady=5)
- ent_f.grid(row=2, column=1, pady=5)
- xy_s.grid(row=3, column=0, pady=5)
- ent_s.grid(row=3, column=1, pady=5)
- but_change.grid(row=4, column=0, padx=10, pady=5)
- but_del.grid(row=5, column=0, padx=10, pady=5)
- but_answ.grid(row=4, column=1, padx=10, pady=5)
- but_exit.grid(row=5, column=1, padx=10, pady=5)
- lab1.pack()
- ent1.pack()
- ent1.focus_set()
- lab2.pack()
- tx.pack()
- ent2.pack()
- cnv.pack()
- scale_p.grid(row=0, column=0, padx=20)
- scale_m.grid(row=1, column=0, padx=20, pady=5)
- right.grid(row=0, column=1, padx=20)
- left.grid(row=1, column=1, padx=20, pady=5)
- top.grid(row=0, column=2, padx=20)
- bottom.grid(row=1, column=2, padx=20, pady=5)
- r.mainloop()
- root.mainloop()
- widgets.mainloop()
- navigation.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement