115 lines
3.4 KiB
Python
115 lines
3.4 KiB
Python
import cairocffi as cairo
|
|
import math
|
|
|
|
def draw_cylinder_at_xy(ctx: cairo.Context, x: int, y: int, cyl_width:int, cyl_height: int, top_ellipse_height: int, top_ellipse_color=(1,1,1)):
|
|
pat = cairo.LinearGradient(x, y, x + cyl_width, y)
|
|
pat.add_color_stop_rgb(0, 1, 1, 1) # White top
|
|
pat.add_color_stop_rgb(1, 0.2, 0.2, 1) # Blue bottom
|
|
|
|
# 1. Draw Bottom Ellipse (White)
|
|
ctx.set_line_width(1.0)
|
|
ctx.save()
|
|
ctx.translate(x + cyl_width / 2, y)
|
|
ctx.scale(1, top_ellipse_height / cyl_width ) # Ellipse scale
|
|
ctx.arc(0, 0, cyl_width / 2, 0, 2 * math.pi)
|
|
ctx.restore()
|
|
|
|
#ctx.set_source_rgb(1, 1, 1) # White
|
|
ctx.set_line_width(0.0)
|
|
ctx.set_source(pat)
|
|
ctx.fill_preserve()
|
|
#ctx.set_source_rgb(0, 0, 0)
|
|
#ctx.set_line_width(1)
|
|
ctx.stroke()
|
|
|
|
# 2. Draw the rectangle body
|
|
ctx.set_line_width(1.0)
|
|
ctx.rectangle(x, y, cyl_width, -cyl_height)
|
|
ctx.set_source(pat)
|
|
ctx.fill()
|
|
ctx.stroke()
|
|
|
|
# 3. Draw top Ellipse (White)
|
|
if True:
|
|
ctx.set_line_width(1.0)
|
|
ctx.save()
|
|
ctx.translate(x + cyl_width / 2, y-cyl_height)
|
|
ctx.scale(1, top_ellipse_height / (cyl_width / 2) * 0.5) # Ellipse scale
|
|
ctx.arc(0, 0, cyl_width / 2, 0, 2 * math.pi)
|
|
ctx.restore()
|
|
|
|
ctx.set_source_rgb(top_ellipse_color[0], top_ellipse_color[1], top_ellipse_color[2])
|
|
ctx.fill_preserve()
|
|
|
|
# Outline for better visibility
|
|
ctx.set_source_rgb(0, 0, 0)
|
|
ctx.set_line_width(1)
|
|
ctx.stroke()
|
|
|
|
|
|
def draw_cylinders(width, height, filename):
|
|
# Setup surface and context
|
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
|
|
ctx = cairo.Context(surface)
|
|
|
|
# White background
|
|
ctx.set_source_rgb(1, 1, 1)
|
|
ctx.paint()
|
|
|
|
# Cylinder dimensions
|
|
cyl_width = 80
|
|
cyl_height = 200
|
|
top_ellipse_height = 30
|
|
spacing = 50
|
|
|
|
# Starting position
|
|
start_x = 50
|
|
y = 50
|
|
|
|
for i in range(3):
|
|
x = start_x + i * (cyl_width + spacing)
|
|
|
|
# 1. Draw Side Gradient (Rect + Arc)
|
|
# Create a horizontal linear gradient: White (top) to Blue (bottom)
|
|
pat = cairo.LinearGradient(x, y, x+cyl_width, y)
|
|
pat.add_color_stop_rgb(0, 1, 1, 1) # White top
|
|
pat.add_color_stop_rgb(1, 0.2, 0.2, 1) # Blue bottom
|
|
|
|
# Draw the rectangle body
|
|
ctx.rectangle(x, y + top_ellipse_height / 2, cyl_width, cyl_height - top_ellipse_height / 2)
|
|
ctx.set_source(pat)
|
|
ctx.fill()
|
|
|
|
# 2. Draw Top Ellipse (White)
|
|
ctx.save()
|
|
ctx.translate(x + cyl_width / 2, y + top_ellipse_height / 2)
|
|
ctx.scale(1, top_ellipse_height / (cyl_width / 2) * 0.5) # Ellipse scale
|
|
ctx.arc(0, 0, cyl_width / 2, 0, 2 * math.pi)
|
|
ctx.restore()
|
|
|
|
ctx.set_source_rgb(1, 1, 1) # White
|
|
ctx.fill_preserve()
|
|
|
|
# Outline for better visibility
|
|
ctx.set_source_rgb(0, 0, 0)
|
|
ctx.set_line_width(1)
|
|
ctx.stroke()
|
|
|
|
# Save to PNG
|
|
surface.write_to_png(filename)
|
|
print(f"Saved {filename}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
surface = cairo.SVGSurface("cylinder.svg", 800, 800)
|
|
ctx = cairo.Context(surface)
|
|
ctx.set_source_rgb(0, 1, 0)
|
|
ctx.paint()
|
|
|
|
|
|
draw_cylinder_at_xy(ctx, 100,300, 50,150,10)
|
|
draw_cylinder_at_xy(ctx, 300,300, 60,110,10, top_ellipse_color=(0.9, 0.4, 0.7))
|
|
surface.write_to_png("cylinder.png")
|
|
print("Saved cylinder.png")
|
|
surface.finish()
|