Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
I need help Using ui.Path.add_arc 👀
-
I am trying to draw a arc using add_arc to a ui.Path (). With the sample below I can draw a wedge, but I only want the arc drawn. I have tried many ways, I can't figure it out 😱
I would also like to be able to draw the arc in degrees instead of rads, some how I can't also get that working properly, I have tried math.degrees but that seems not to work for me.
Hi-fully its something simple I am doing wrongAny help appreciated
def draw_arc(rect): r = ui.Rect(*rect) s = ui.Path() s.move_to(r.center()[0], r.center()[1]) s.add_arc(r.center()[0], r.center()[1], r.width / 2,math.radians(0), math.radians(45)) s.eo_fill_rule = False s.close() ui.set_color('black') s.line_width = .3 s.stroke()
Edit
-
You need to move_to the initial point of the arc, not the center. That would be
r*sin(start), r*cos(end)
also, skip the close().
-
@JonB , thanks. I did try moving the start point, but not as you describe, now you mention not closing the path , that sort of makes sense, but not so intuitive. At least for me.
I guess people are educated up the wazoo these days. But It does seem to me that a thin API layer on top of the geometric functions could help us less educated 😁
But really thanks again. -
To @JonB
I think that for any point on the circle, x=r * cos(angle) and y=r * sin(angle) must refer to the same angle, this not cos(start) and sin(end) like you wrote. -
Guys, I am embarrassed to say, but I really can't work it out. I am so confused now, I just had to stop and ask. I thought I could figure it out after the advice. But my head is about to implode in on itself.
This is the latest crap, I have done. But I am so confused now about degrees, radiants, angles.....basically I am screwed.
If you could help me to get this function to work as expected, I would really appreciate it. Believe me, I have tried many things my self.
Thanks in advance 😳def draw_arc(rect): r = ui.Rect(*rect) s = ui.Path() radius = r.width / 2 start = 0 finish = 90 start = math.radians(start) finish = math.radians(finish) x = radius * math.cos(start) y = radius * math.sin(finish) s.move_to(x, y) s.add_arc(r.center()[0], r.center()[1], radius, start, finish) s.eo_fill_rule = False #s.close() ui.set_color('black') s.line_width = 1 s.stroke() #s.fill()
-
Almost correct, believe me, use the same angle for x,y:
x = r.center()[0]+radius * math.cos(start) y = r.center()[1]+radius * math.sin(start)
Try it and say if it's what you expect.
-
@cvp , thanks for your help. It's not quite. The pic below. The only thing I changed was To add your 2 lines and comment out the 2 other lines that were setting x and y.
In the pic can see I am a vertical line, which I don't want. I just want the arc -
Really, I don't know anything about ui.path but I really knows geometry...
Try without the stroke. What do you want to draw with this line of code? -
My two lines only compute the coordinates of the start point of the arc.
Then you move to it.
Then you draw the arc.
Then you "stroke" but I don't know this instruction. -
The code hereafter only draws an arc
import ui import math with ui.ImageContext(100, 100) as ctx: r = ui.Rect(0,0,100,100) s = ui.Path() radius = r.width / 2 start = 0 finish = 90 start = math.radians(start) finish = math.radians(finish) x = r.center()[0]+radius * math.cos(start) y = r.center()[1]+radius * math.sin(start) s.move_to(x, y) s.add_arc(r.center()[0], r.center()[1], radius, start, finish) s.eo_fill_rule = False #s.close() ui.set_color('black') s.line_width = 1 s.stroke() #s.fill() img = ctx.get_image() img.show()
-
@cvp , ok thanks. I am just trying to draw an arc around a circle as so many apps do in their interfaces. Also to animate that later. Once I can make the basic arc, I can do a lot from there.
If you are interested the below is a test bed to test the arc in. I probably should have done this first.
import ui, editor import math def draw_arc(rect): r = ui.Rect(*rect) s = ui.Path() radius = r.width / 2 start = 0 finish = 90 start = math.radians(start) finish = math.radians(finish) #x = radius * math.cos(start) #y = radius * math.sin(finish) x = r.center()[0]+radius * math.cos(start) y = r.center()[1]+radius s.move_to(x, y) s.add_arc(r.center()[0], r.center()[1], radius, start, finish) s.eo_fill_rule = False #s.close() ui.set_color('black') s.line_width = 1 s.stroke() #s.fill() class MyClass(ui.View): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def draw(self): r = ui.Rect(10, 10, 200, 200) s = ui.Path.oval(*r) ui.set_color('deeppink') s.fill() draw_arc(r.inset(10, 10)) if __name__ == '__main__': w, h = 600, 800 f = (0, 0, w, h) mc = MyClass(frame=f, bg_color='white') mc.present('sheet', animated=False)
-
Your y = line is truncated, you forgot +radius * math.sin(start)
y = r.center()[1]+radius * math.sin(start)
-
@cvp , yes thanks I just seen that. It works perfectly now. Sorry about that. I have just tried so many things, I almost get vertigo when looking at that small function.
Lol, now, I have to modify it to work with params start and finish using degrees. I will be able to get that now, I hope 😬
But again thanks for your help. I will post something for the degrees once I work it out in case someone else reading has a hard time like me -
Good luck
-
@cvp , thanks. I am sure you were smiling. For a few minutes I did go off on a stupid hunt then realised I just had to retard the start and finish by -90 to have degrees. I have just did it with a extra param as an offset. I guess not so clear. I think I will change that. But below, is the type of effect I was going after. A very std thing in apps. I have not put numbers etc there yet. But I have that already.
I realise this would normally run off a thread or of ui.delay etc... This was just a testimport ui, editor import math, time def draw_arc(rect, start, finish, offset = -90): r = ui.Rect(*rect) s = ui.Path() radius = r.width / 2 start = math.radians(start + offset) finish = math.radians(finish + offset ) x = r.center()[0]+radius * math.cos(start) y = r.center()[1]+radius * math.sin(start) s.move_to(x, y) s.add_arc(r.center()[0], r.center()[1], radius, start, finish) ui.set_color('white') s.line_width = 15 s.line_cap_style = ui.LINE_CAP_ROUND s.stroke() class MyClass(ui.View): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.deg = 0 def draw(self): r = ui.Rect(10, 10, 200, 200) s = ui.Path.oval(*r) ui.set_color('deeppink') s.fill() draw_arc(r.inset(20, 20), 0 , self.deg) if __name__ == '__main__': w, h = 600, 800 f = (0, 0, w, h) mc = MyClass(frame=f, bg_color='white') mc.present('sheet', animated=False) for i in range(0, 360): mc.deg = i mc.set_needs_display() time.sleep(.015)
-
Sincerely, I didn't smile. I know by experience that sometimes I can search during hours for an obvious solution, obvious only when found 😬 And I dare not ask for help (sorry for my poor English).
I like the effect of your code! -
@cvp , no problems. I meant it a nice way. I wanted to solve it myself. Like it was something major to solve 😬 I didn't realise it was that simple. Btw, your English is fine. I have no problems understanding you.
-
a (very) small improvement:
tot_time = 2 # total time in seconds for i in range(0, 360): mc.deg = i mc.set_needs_display() time.sleep(tot_time/360)
-
This post is deleted!