incorporate cylinders with gradient into main class
This commit is contained in:
parent
d1cb78a742
commit
dfe2d16d6c
@ -1,6 +1,51 @@
|
|||||||
import cairocffi as cairo
|
import cairocffi as cairo
|
||||||
import math
|
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):
|
def draw_cylinders(width, height, filename):
|
||||||
# Setup surface and context
|
# Setup surface and context
|
||||||
@ -25,7 +70,7 @@ def draw_cylinders(width, height, filename):
|
|||||||
x = start_x + i * (cyl_width + spacing)
|
x = start_x + i * (cyl_width + spacing)
|
||||||
|
|
||||||
# 1. Draw Side Gradient (Rect + Arc)
|
# 1. Draw Side Gradient (Rect + Arc)
|
||||||
# Create a vertical linear gradient: White (top) to Blue (bottom)
|
# Create a horizontal linear gradient: White (top) to Blue (bottom)
|
||||||
pat = cairo.LinearGradient(x, y, x+cyl_width, y)
|
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(0, 1, 1, 1) # White top
|
||||||
pat.add_color_stop_rgb(1, 0.2, 0.2, 1) # Blue bottom
|
pat.add_color_stop_rgb(1, 0.2, 0.2, 1) # Blue bottom
|
||||||
@ -56,4 +101,14 @@ def draw_cylinders(width, height, filename):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
draw_cylinders(450, 300, "cylinders.png")
|
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()
|
||||||
|
|||||||
@ -12,6 +12,9 @@ import pandas as pd
|
|||||||
import cairocffi as cairo
|
import cairocffi as cairo
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
from cylinder_drawing_example import draw_cylinder_at_xy
|
||||||
|
|
||||||
|
|
||||||
class Topology:
|
class Topology:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
country=None,
|
country=None,
|
||||||
@ -162,22 +165,55 @@ class Topology:
|
|||||||
values[r, c] = np.mean(this_array[this_array != 0])
|
values[r, c] = np.mean(this_array[this_array != 0])
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
def draw_cylinder_at_xy(self, 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 create_cylinder_svg_file(self, rotation=None,file_index=None):
|
def create_cylinder_svg_file(self, rotation=None,file_index=None):
|
||||||
|
|
||||||
# subfunction to draw an array, options are line y/n, fill y/n, line and fill color
|
# subfunction to draw an array, options are line y/n, fill y/n, line and fill color
|
||||||
def svg_draw_cylinder(svg_context: cairo.Context, x1,y1,x2,y2,gradient=None):
|
|
||||||
circlew = self.linemap_xscale / 3
|
|
||||||
halfcirclew = circlew / 2
|
|
||||||
svg_context.set_source_rgb(1, 1, 1)
|
|
||||||
svg_context.arc(x1,y1,circlew,0,2*math.pi)
|
|
||||||
svg_context.stroke()
|
|
||||||
|
|
||||||
svg_context.arc(x2,y2,circlew, 0,2*math.pi)
|
|
||||||
svg_context.stroke()
|
|
||||||
|
|
||||||
svg_context.move_to(x1-1,y1-1)
|
|
||||||
svg_context.rectangle(x1-1,y1-1,x1+1,y2+1)
|
|
||||||
svg_context.stroke()
|
|
||||||
# if no refetch, check if file exists
|
# if no refetch, check if file exists
|
||||||
if os.path.exists(self.elevation_filename):
|
if os.path.exists(self.elevation_filename):
|
||||||
print("Elevation file exists")
|
print("Elevation file exists")
|
||||||
@ -220,7 +256,7 @@ class Topology:
|
|||||||
# Projects (x,y,z) -> (x+z/2, y+z/2)
|
# Projects (x,y,z) -> (x+z/2, y+z/2)
|
||||||
# max height should be no more than 3 times the distance between rows, this could be a setting
|
# max height should be no more than 3 times the distance between rows, this could be a setting
|
||||||
def project(x, y, z):
|
def project(x, y, z):
|
||||||
return (x * self.linemap_xscale, y * self.linemap_yscale - (z if z > 0 else (-1.5 * self.linemap_yscale)))
|
return (x * self.linemap_xscale, y * self.linemap_yscale )
|
||||||
# return (offset[0] + x * scale + z * 2, offset[1] + y * scale + z * 2)
|
# return (offset[0] + x * scale + z * 2, offset[1] + y * scale + z * 2)
|
||||||
|
|
||||||
rows, cols = values.shape
|
rows, cols = values.shape
|
||||||
@ -229,13 +265,6 @@ class Topology:
|
|||||||
# Normalize data for visualization height (0-100) -- max is no more than three row heights
|
# Normalize data for visualization height (0-100) -- max is no more than three row heights
|
||||||
norm_data = (values / max_val) * self.linemap_xscale * 3
|
norm_data = (values / max_val) * self.linemap_xscale * 3
|
||||||
|
|
||||||
# Draw Lines along rows
|
|
||||||
cr.set_source_rgb(0, 0, 0) # Black lines
|
|
||||||
cr.set_line_width(self.linemap_width)
|
|
||||||
cr.set_line_cap(cairo.LINE_CAP_ROUND)
|
|
||||||
cr.set_line_join(cairo.LINE_JOIN_ROUND)
|
|
||||||
x = 0
|
|
||||||
y = 0
|
|
||||||
|
|
||||||
if True:
|
if True:
|
||||||
for r in range(rows):
|
for r in range(rows):
|
||||||
@ -243,9 +272,7 @@ class Topology:
|
|||||||
for c in range(cols):
|
for c in range(cols):
|
||||||
z = norm_data[r,c]
|
z = norm_data[r,c]
|
||||||
x,y = project(c, r, z) # now need to make array of x,y vals and pass to drawing func
|
x,y = project(c, r, z) # now need to make array of x,y vals and pass to drawing func
|
||||||
draw_list.append((x,y))
|
draw_cylinder_at_xy(cr,x,y,self.linemap_xscale,z,self.linemap_yscale/2)
|
||||||
svg_draw_cylinder(cr,x,y,x,y-z)
|
|
||||||
print("***" + str(draw_list))
|
|
||||||
#svg_draw_list(cr, draw_list, line_color="Black", fill_shape=True)
|
#svg_draw_list(cr, draw_list, line_color="Black", fill_shape=True)
|
||||||
|
|
||||||
|
|
||||||
@ -376,9 +403,9 @@ def main():
|
|||||||
print(topology.get_boundingbox())
|
print(topology.get_boundingbox())
|
||||||
#topology.create_svg_file()
|
#topology.create_svg_file()
|
||||||
topology.create_cylinder_svg_file()
|
topology.create_cylinder_svg_file()
|
||||||
#for r in range(4*360):
|
for r in range(4*360):
|
||||||
#print("Rotating by [{}] degrees".format(r/4.0))
|
print("Rotating by [{}] degrees".format(r/4.0))
|
||||||
#topology.create_svg_file(rotation=(r / 4.0), file_index=r)
|
topology.create_cylinder_svg_file(rotation=(r / 4.0), file_index=r)
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user