Create an arc with a given thickness using PIL Imagedraw

I am trying to create a segmented arc using PIL and Imagedraw. The arc function allows me to easily draw an arc, but it's just a line. I need to be able to locate an arc of a given radius and thickness (ID-OD), but AI cannot find any type of thickness or width. Is there any way to do this? If not, is there another way to do this with PIL?

Excerpt:

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 
+6
source share
4 answers

The trick I found that can be pulled is to make a white circle inside the black circle. You can use the pieslice method to break it down as needed. The rendering is consistent, so you just need to get the correct ordering. The rigid part gets the correct positioning due to the use of Imagedraw bounding boxes as opposed to the center and radius coordinates. You must make sure that the centers of everything end up on top of each other.

THIS DECISION IS GOOD ONLY IN A LIMITED CASE, see comment.

0
source

PIL cannot draw wide arcs, but Aggdraw can and works well with PIL (by the same author).

+1
source

I created the following Mark- based arc replacement function:

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

Probably not a perfect pixel (or fast), but seems to be suitable for what I need. If you have a better version, comment in Gist.

 def arc(draw, bbox, start, end, fill, width=1, segments=100): """ Hack that looks similar to PIL 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
source

Simulate an arc using straight lines and put the coordinates of these segments in a list. Use draw.line with the width option to draw an arc.

0
source

Source: https://habr.com/ru/post/895091/


All Articles