Created
May 30, 2020 12:50
-
-
Save michiel/55c4b2752393390bedf4a2ddede7f755 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import svgwrite | |
import math | |
import json | |
class Pyramid: | |
def __init__(self, data, filename, height=500): | |
self.data = data | |
self.filename = filename | |
self.height = height | |
self.width = 2 * height | |
self.drawing = svgwrite.Drawing(filename, height=self.height, width=self.width) | |
def draw_polygon(self, points, color="#00ffff"): | |
shape = svgwrite.shapes.Polygon( | |
points, | |
stroke=svgwrite.rgb(0, 0, 0, '%'), | |
stroke_width=1, | |
stroke_opacity=100, | |
fill=color, | |
fill_opacity=100) | |
self.drawing.add(shape) | |
def add_text(self, txt, coord, fontsize=30): | |
g = self.drawing.g( | |
style="font-size:%s;font-family:DejaVu Sans;text-align:center" % fontsize | |
) | |
g.add(self.drawing.text(txt, insert=coord)) | |
self.drawing.add(g) | |
def draw_pyramid(self, colour="#ff0000"): | |
midpoint = self.width / 2 | |
points=[ | |
(midpoint, 0), | |
(self.width, self.height), | |
(0, self.height), | |
] | |
shape = svgwrite.shapes.Polygon( | |
points, | |
stroke=svgwrite.rgb(0, 0, 0, '%'), | |
stroke_width=1, | |
stroke_opacity=100, | |
fill=colour, | |
fill_opacity=100) | |
self.drawing.add(shape) | |
def volume_at(self, base, height): | |
squareside = (base - height) | |
if (squareside > 0): | |
rectangle = (squareside * 2) * height | |
else: | |
rectangle = 0 | |
remainder = height * height | |
# print("(total: %s) - volume at %s, %s = %s" % ( (HEIGHT*WIDTH) / 2, base, height, rectangle + remainder)) | |
return rectangle + remainder | |
def calculate_heights(self, arr): | |
volume = (self.height * self.width) / 2 | |
total = sum(arr) | |
unit = volume / total | |
volumes = [(unit * x) for x in arr] | |
print("volume %s, total %s, unit %s, volumes : %s" % (volume, total, unit, volumes)) | |
heights = [] | |
base = self.height | |
height = 1 | |
for v in volumes: | |
running = True | |
while running: | |
if (self.volume_at(base, height) >= v): | |
heights.append([base, height]) | |
base -= height | |
height = 1 | |
running = False | |
elif (height > self.height): | |
heights.append([base, height]) | |
base -= height | |
height = 1 | |
running = False | |
else: | |
height +=1 | |
return heights | |
def points_for(self, coor): | |
base = coor[0] | |
height = coor[1] | |
midpoint = self.width/2 | |
bottom = base | |
top = (base - height) | |
return [ | |
(midpoint, base), | |
((midpoint - bottom), base), | |
((midpoint - top), (base - height)), | |
((midpoint + top), (base - height)), | |
((midpoint + bottom), base) | |
]; | |
def add_segments(self): | |
coords = self.calculate_heights([item["number"] for item in data["items"]]) | |
for idx, coord in enumerate(coords): | |
item = self.data["items"][idx] | |
self.draw_polygon( | |
self.points_for(coord), | |
color=item["color"], | |
) | |
label = item["label"] | |
labelshift = (len(label) / 2) * 15 | |
self.add_text( | |
txt=item["label"], | |
coord=( | |
(self.width / 2) - labelshift, | |
coord[0] - (coord[1]/2) + 12) | |
) | |
num = "%s" % item["number"] | |
numshift = (len(num) / 2) * 15 | |
self.add_text( | |
txt=num, | |
coord=( | |
(self.width / 2) - numshift, | |
coord[0] - (coord[1]/2) + 36), | |
fontsize=16 | |
) | |
def save(self): | |
self.drawing.save() | |
with open('sample.json', 'r') as json_file: | |
data = json.load(json_file) | |
pyramid = Pyramid(data, 'sample.svg', 600) | |
pyramid.add_segments() | |
pyramid.save() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment