How to draw a circle segment (pie) in Scene?
In my Scene project I need to draw a circle segment with a certain fill color. Unfortunately, ellipse() does not offer the possibility of a start and end angle.
I am still using the classic render loop.
Any idea on how to achieve this?
I don't have a complete answer, but I guess that Path.add_arc is what you are looking for.
Path.add_arc() is in UI, which is not useful for Scene as far as I know.
I think there has been some discussion before where you can use ImageContext.get_image() to make an image and then use that one in the (pre 2.0) Scene? Perhaps you have to save it to file in between.
Ohh. Actually this might be the way to use a PIL image with the old scene drawing: scene_drawing.load_pil_image()
Not the most straight forward bit of Code, but it works:
def draw(self): with ui.ImageContext(200, 200) as ctx: path = ui.Path() path.move_to(180, 100) path.add_arc(100, 100, 80, 0, radians(170)) path.line_width = 5 ui.set_color('blue') path.stroke() ui_image = ctx.get_image() pil_image = Image.open(io.BytesIO(ui_image.to_png())) scene_image = load_pil_image(pil_image) image(scene_image)
I have also been frustrated in the past by the lack of drawing functionality in
scene. It lacks simple functions like drawing a polygon from a list of points. I'd love for
sceneto have all the functionality of
I think that right now the way to do it is using a PathNode. The old way of doing explicit drawing is not very efficient.
Edit: I meant ShapeNode when I wrote PathNode...
You can either use a
ShapeNodeif you're using the new
sceneAPI, or the
triangle_stripfunction (also new in 2.0) if you're working in "legacy mode".
# coding: utf-8 import math, scene, ui def circle_segment_path(r, angle): '''Path for circle segment (i.e. 'pizza slice') of radius r and angle degrees''' path = ui.Path() path.move_to(0, 0) path.line_to(r, 0) path.add_arc(0, 0, r, 0, -math.radians(angle), False) path.line_to(0, 0) return path def circle_segment_shape(point, r, angle): '''Blue & red shape for circle segment of radius r and angle degrees at point''' return scene.ShapeNode(path=circle_segment_path(r, angle), fill_color='blue', stroke_color='red', position=point) class MyScene (scene.Scene): def setup(self): self.add_child(circle_segment_shape(self.size/2, 200, 45)) if __name__ == '__main__': scene.run(MyScene(), show_fps=True)```
Or if you want more 'pizza':
class MyScene (scene.Scene): def setup(self): for x in xrange(0, int(self.size.w)+50, 50): for y in xrange(0, int(self.size.h)+50, 50): self.add_child(circle_segment_shape((x, y), 50, 45))
I am trying to work out how to use triangle_strip, but I can't get it to work. For now all I want to do is draw a (solid) triangle.
If I try triangle_strip(((0,0),(10,0),(0,10))) I get a "Type error: expected sequence". Same if I close the sequence with a (0,0) tuple.
An example would be very helpful.
Thanks for all thoce nice examples with the new node objects. But for me the classical render loop is a must, because what am actuelly doing is prototyping an animation film that finally will be ported to Python on a Windows machine, most likely with PyGame or just plain PIL. Therefor the node objects are not an option to me, although I really like the concept.
The list of points in your example is not strictly a list, it is a tuple of tuples.
I haven't tried it myself, but does triangle_strip([(0,0),(10,0),(0,10)]) work?
No also the list of tuples as you suggest does not work. Alas.
Although the documentation states
scene_drawing.triangle_strip(points[, tex_coords, image_name]), it seems tex_coords are mandatory (and of equal length as points).
image_nameis optional. I don't fully comprehend the logic at this time.
scene_drawingcontains a call to
Super! I just added a list of tuples with random values and voilà it works!