Создание дуги с заданной толщиной, используя Imagedraw PIL - PullRequest
7 голосов
/ 16 августа 2011

Я пытаюсь создать сегментированную дугу, используя PIL и Imagedraw.Функция дуги позволяет мне легко нарисовать дугу, но это всего лишь линия.Мне нужно иметь возможность разместить дугу заданного радиуса и толщины (от ID до OD), но AI не может найти какой-либо тип толщины или ширины.Есть ли способ сделать это?Если нет, есть ли другой способ сделать это с помощью PIL?

Фрагмент:

import Image
import ImageDraw

conv = 0.1
ID = 15
OD = 20
image = Image.new('1',(int(ceil(OD/conv))+2,int(ceil(OD/conv))+1), 1)
draw = ImageDraw.Draw(image)
diam = OD-ID
box=(1, 1, int(ceil(diam/conv)), int(ceil(diam/conv))) #create bounding box
draw.arc(box, 0, 90, 0) #draw circle in black

Ответы [ 4 ]

2 голосов
/ 28 февраля 2014

Я создал следующую функцию замены дуги на основе предложения Mark :

https://gist.github.com/skion/9259926

Вероятно, не идеальный пиксель (и не быстрый), но, кажется, подходит близко к тому, для чего он мне нужен. Если у вас есть лучшая версия, пожалуйста, оставьте комментарий в Gist.

def arc(draw, bbox, start, end, fill, width=1, segments=100):
    """
    Hack that looks similar to PIL's draw.arc(), but can specify a line width.
    """
    # radians
    start *= math.pi / 180
    end *= math.pi / 180

    # angle step
    da = (end - start) / segments

    # shift end points with half a segment angle
    start -= da / 2
    end -= da / 2

    # ellips radii
    rx = (bbox[2] - bbox[0]) / 2
    ry = (bbox[3] - bbox[1]) / 2

    # box centre
    cx = bbox[0] + rx
    cy = bbox[1] + ry

    # segment length
    l = (rx+ry) * da / 2.0

    for i in range(segments):

        # angle centre
        a = start + (i+0.5) * da

        # x,y centre
        x = cx + math.cos(a) * rx
        y = cy + math.sin(a) * ry

        # derivatives
        dx = -math.sin(a) * rx / (rx+ry)
        dy = math.cos(a) * ry / (rx+ry)

        draw.line([(x-dx*l,y-dy*l), (x+dx*l, y+dy*l)], fill=fill, width=width)
1 голос
/ 16 августа 2011

PIL не может рисовать широкие дуги, но Aggdraw может и хорошо работает с PIL (тот же автор).

0 голосов
/ 17 августа 2011

Уловка, которую я нашел, которую можно вытащить, это сделать белый круг внутри черного круга.Вы можете использовать метод pieslice, чтобы разбить его по мере необходимости.Рендеринг является последовательным, поэтому вы просто должны получить правильный порядок.Трудная часть получает правильное позиционирование благодаря использованию Imagedraw ограничивающих рамок, а не координат центра и радиуса.Вы должны убедиться, что центры всего оказываются точно друг на друге.

НАСТОЯЩЕЕ РЕШЕНИЕ ХОРОШО ТОЛЬКО В ОГРАНИЧЕННОМ СЛУЧАЕ, см. Комментарий.

0 голосов
/ 16 августа 2011

Имитируйте дугу, используя отрезки прямых линий, и поместите координаты этих отрезков в список.Используйте draw.line с опцией width, чтобы нарисовать дугу.

...