2016-04-30 2 views
1

Моя проблема очень проста: у меня есть два овала, в центрах которых (x0, y0) и (x1, y1). Если бы я хотел нарисовать линию между ними, я бы просто сделал create_line (x0, y0, x1, y1).Нарисуйте дугу между двумя точками на холсте tkinter

Но я хочу нарисовать дугу между ними. Я борюсь с математикой здесь. Вот ситуация:

  • У меня есть эти два центра: они должны быть частью эллипса
  • Существует бесконечное число эллипсов, проходящих через эти две точки, но с Tkinter, мы можем сделать только горизонтальные эллипсы. (? Правая)

мне нужно:

  • в верхнем левом и нижнем правом координаты прямоугольника, который содержит эллипс
  • начальный угол и степень дуги

Я также думаю, что, возможно, рисование дуги - это неправильный путь? Я мог бы сделать что-то эквивалентное с линией, для которой указываю много точек на этой дуге (даже если она не будет актуальной дуга)

Редактировать ответить Blindman:

С Tkinter, вы можете определить такую ​​дугу: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/create_oval.html Мы не определяем эллипс как таковой, а только координаты верхнего и нижнего правого углов прямоугольника, содержащего эллипс.

Как два овала связаны друг с другом: они этого не делают. У вас просто два овала в случайной позиции на холсте, и вам нужна дуга между ними. Я хочу, чтобы дуга соединяла два центра этих овалов.

Наконец, вот идея о том, что я хочу, в случае, если две овальной формы имеют одинаковые у координаты:

ellipse

То, что я хочу именно этого, для любой позиции.

И код Tkinter:

import tkinter as tk 

class SampleApp(tk.Tk): 

    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 

     self.canvas = tk.Canvas(width=400, height=400) 
     self.canvas.pack(fill="both", expand=True) 

     self._create_token((100, 100), "white") 
     self._create_token((200, 100), "pink") 

     self.canvas.create_arc(100, 100 + 10, 200, 100 - 10, extent=180, style=tk.ARC) 

    def _create_token(self, coord, color): 
     '''Create a token at the given coordinate in the given color''' 
     (x,y) = coord 
     self.canvas.create_oval(x-5, y-5, x+5, y+5, 
           outline=color, fill=color, tags="token") 

if __name__ == "__main__": 
    app = SampleApp() 
    app.mainloop() 
+1

я начал, чтобы посмотреть в раствор, но слишком много неизвестных. Я никогда не использовал python, поэтому я не знаю, какой тип эллипса/овала они используют. Также нет никаких указаний о том, как два овала связаны друг с другом и где вы хотите, чтобы линия/кривая/дуга/соединение соединялись между собой, существует слишком много возможностей для ответа. Не могли бы вы представить эскиз проблемы и дать подробную информацию о том, что вы используете для определения эллипсов. – Blindman67

+0

Я обновил сообщение, надеюсь, что теперь он станет понятнее – user5049567

+0

Когда начальная и конечная точки дуги имеют одинаковые координаты x (или y), тогда вы можете использовать прямоугольник, где начальная и конечная точки являются серединами противоположных сторон прямоугольника, а arc имеет протяженность = 180. Как и в вашем примере кода. Когда начальная и конечная точки дуги имеют разные координаты x и y, вы можете использовать прямоугольник, где начальная и конечная точки являются серединами соседних сторон прямоугольника, а arc имеет длину 90. –

ответ

2

Существует start варианта для создания дуги, которые определяют, где начать рисование в придании угла. Используя это и некоторые математические вы можете использовать create_arc -метод, чтобы нарисовать дугу при любом положении:

import Tkinter as tk 


class SampleApp(tk.Tk): 

    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 

     self.canvas = tk.Canvas(width=400, height=400) 
     self.canvas.pack(fill="both", expand=True) 

     self._create_token((100, 100), "white") 
     self._create_token((200, 300), "pink") 
     self._create_arc((100,100), (200, 300)) 

    def _create_token(self, coord, color): 
     '''Create a token at the given coordinate in the given color''' 
     (x,y) = coord 
     self.canvas.create_oval(x-5, y-5, x+5, y+5, 
           outline=color, fill=color, tags="token") 

    def _create_arc(self, p0, p1): 
     extend_x = (self._distance(p0,p1) -(p1[0]-p0[0]))/2 # extend x boundary 
     extend_y = (self._distance(p0,p1) -(p1[1]-p0[1]))/2 # extend y boundary 
     startAngle = math.atan2(p0[0] - p1[0], p0[1] - p1[1]) *180/math.pi # calculate starting angle 
     self.canvas.create_arc(p0[0]-extend_x, p0[1]-extend_y , 
           p1[0]+extend_x, p1[1]+extend_y, 
           extent=180, start=90+startAngle, style=tk.ARC) 

     '''use this rectangle for visualisation''' 
     #self.canvas.create_rectangle(p0[0]-extend_x, p0[1]-extend_y, 
     #        p1[0]+extend_x, p1[1]+extend_y)  

    def _distance(self, p0, p1): 
     '''calculate distance between 2 points''' 
     return sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2) 

if __name__ == "__main__": 
    app = SampleApp() 
    app.mainloop() 
+0

Есть ли простой способ адаптировать это, чтобы получить другой угол? Например, дуга, которая была бы очень близка к линии трассировки? Как я вижу, когда угол слишком мал, углы прямоугольника, используемые для определения эллипса, точно являются центрами двух овалов. – user5049567

+0

На самом деле, я думаю, я могу просто взять точку на деление пополам линии между двумя овалами, а затем вычислить углы этого нового круга. – user5049567

1

На самом деле, я отвечу на свой вопрос, так как я нашел лучший способ сделать это. Ответ VRage в порядке, но его трудно адаптировать, если вы хотите, чтобы дуга была ближе к линии между двумя точками. Правильный способ сделать это - использовать линию с третьей точкой на перпендикулярном биссектрисе сегмента в сочетании с «гладкой» опцией.

Вот пример именно то, что я хотел:

import tkinter as tk 
import math 

class SampleApp(tk.Tk): 

    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 

     self.canvas = tk.Canvas(width=400, height=400) 
     self.canvas.pack(fill="both", expand=True) 

    def _create_token(self, coord, color): 
     '''Create a token at the given coordinate in the given color''' 
     (x,y) = coord 
     self.canvas.create_oval(x-5, y-5, x+5, y+5, 
           outline=color, fill=color, tags="token") 

    def create(self, xA, yA, xB, yB, d=10): 
     self._create_token((xA, yA), "white") 
     self._create_token((xB, yB), "pink") 

     t = math.atan2(yB - yA, xB - xA) 
     xC = (xA + xB)/2 + d * math.sin(t) 
     yC = (yA + yB)/2 - d * math.cos(t) 
     xD = (xA + xB)/2 - d * math.sin(t) 
     yD = (yA + yB)/2 + d * math.cos(t) 

     self.canvas.create_line((xA, yA), (xC, yC), (xB, yB), smooth=True) 
     self.canvas.create_line((xA, yA), (xD, yD), (xB, yB), smooth=True, fill="red") 

    if __name__ == "__main__": 
     app = SampleApp() 
     app.create(100, 100, 300, 250) 
     app.mainloop()