Как я могу нарисовать текст под любым углом выше и параллельно линии? - PullRequest
0 голосов
/ 23 апреля 2020

Я хочу разместить текст в центре над строкой (управляется переменной distance). Для этого есть метод drawLineDescription(). Этот метод берет начальную и конечную точки линий, а затем вычисляет центральную точку x, y. Я уже работал с angle, чтобы убедиться, что текст размещен правильно. К сожалению, я не могу понять, как разместить текст вертикально над линией под каждым углом, т.е. в зависимости от поворота переменные x, y должны иметь возможность перемещаться. Как я могу дополнить это?

def drawLineDescription(canvas, startX, startY, endX, endY, distance):
        lengthX = endX - startX
        lengthY = endY - startY
        x = int(startX+((lengthX)/2))
        y = int(startY+((lengthY)/2))

        angle = math.degrees(math.atan2(lengthY, lengthX)*-1)
        angle = round(angle)
        if angle < -90 or angle > 90:
           angle += 180

        canvas.create_text(x, y, angle=angle, font=("Arial", 12), text="exampleText")

В конце это должно выглядеть следующим образом (пример нескольких строк с текстом - строки никогда не пересекают их текст): Пример результата

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

Вы можете нарисовать повернутый текст на tkinter, если используете tcl > 8.6 со следующими инструкциями: canvas_item = tk.create_text и canvas.itemconfig(canvas_item, angle=rotation_angle)

Чтобы достичь того, что вы хотите, вам нужно немного геометрия, особенно координаты отрезка, его средняя точка, вектор смещения, перпендикулярный отрезку, и угол отрезка.

Я инкапсулировал арифметику c, необходимую для вычисления правильной геометрии c элементы в классе point, а в c классе Vector. Эти классы не являются пуленепробиваемыми, но они дают вам отправную точку для базовой геометрии c.

Я добавил пример линии, определяемой двумя точками, с текстом, размещенным по мере необходимости и повернутым в соответствии направление отрезка.

enter image description here

import math
import tkinter as tk


class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other: 'Vector'):
        return Vector(other.x + self.x, other.y + self.y)

    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)

    def __iter__(self):
        yield self.x
        yield self.y

    def __str__(self):
        return f'{self.__class__.__name__}({self.x}, {self.y})'


class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Point(other.x + self.x, other.y + self.y)

    def __sub__(self, other):
        return Vector(other.x - self.x, other.y - self.y)

    def scale(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

    def normal(self):
        norm = self.norm()
        return Vector(self.x / norm, self.y / norm)

    def norm(self):
        return math.hypot(self.x, self.y)

    def perp(self):
        x, y = self.normal()
        return Vector(y, -x)

    def angle(self):
        return math.atan2(-self.y, self.x) * (180 / math.pi)

    def __iter__(self):
        yield self.x
        yield self.y

    def __str__(self):
        return f'{self.__class__.__name__}({self.x}, {self.y})'


if __name__ == '__main__':

    root = tk.Tk()
    canvas = tk.Canvas(root, width=500, height=500)

    p0, p1 = Point(100, 40), Point(200, 300)
    segment = p1 - p0
    mid_point = segment.scale(0.5) + p0
    # canvas.create_oval(*(mid_point - Vector(2, 2)), *(Vector(2, 2) + mid_point))

    line = canvas.create_line(*p0, *p1)
    offset = segment.perp().scale(20)
    # canvas.create_line(*mid_point, *(mid_point+offset))

    txt = canvas.create_text(*(offset + mid_point), text='example')
    canvas.itemconfig(txt, angle=segment.angle())

    canvas.pack()
    root.mainloop()
1 голос
/ 23 апреля 2020

enter image description here

lengthX = endX - startX
lengthY = endY - startY
fullLength = math.sqrt(lengthX**2 + lengthY**2)
#unit direction vector
ux = lengthX / fullLength
uy = lengthY / fullLength
#unit normal
if ux < 0:
    nx, ny = -uy, ux
else:
    nx, ny = uy, -ux
#text center point (D at the picture)
cx = x + nx * distance
cy = y + ny * distance

#if you need start of text (S at the picture)
sx = x + nx * distance - ux * halfwidth
sy = y + ny * distance - uy * halfwidth
...