"""Geometry Script recreation of the small pie chart from Shriinivas/piechart.blend.""" try: from tools.geometry_script_loader import load_repo_geometry_script except ModuleNotFoundError: import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[2])) from tools.geometry_script_loader import load_repo_geometry_script load_repo_geometry_script() from geometry_script import * # noqa: F403 - Geometry Script exposes node functions as DSL globals. TAU = 6.2831854820251465 @tree("VG Pie Segment") def vg_pie_segment( start: Float = TAU, value: Float = 0.5, total: Float = 0.5, shift: Float = 0.5, segment_material: Material = None, text_material: Material = None, ): fraction = math(operation=Math.Operation.DIVIDE, value=(value, total)) sweep = math(operation=Math.Operation.MULTIPLY, value=(fraction, TAU)) end = math(operation=Math.Operation.ADD, value=(start, sweep)) percentage = math(operation=Math.Operation.MULTIPLY, value=(fraction, 100.0)) percentage_string = value_to_string(data_type=ValueToString.DataType.FLOAT, value=percentage, decimals=2) label = join_strings(delimiter="", strings=[percentage_string, string(string="%")]) arc_curve = arc( mode=Arc.Mode.RADIUS, resolution=64, radius=1.0, start_angle=start, sweep_angle=sweep, connect_center=True, ) face = arc_curve.fill_curve() extruded_face = face.extrude_mesh(mode=ExtrudeMesh.Mode.FACES, offset_scale=-0.1) text_curve = string_to_curves(string=label, size=0.2, align_x="Center", align_y="Middle").curve_instances text_face = text_curve.fill_curve() text_mesh = text_face.extrude_mesh(mode=ExtrudeMesh.Mode.FACES, offset_scale=0.025).mesh face_center = attribute_statistic( data_type=AttributeStatistic.DataType.FLOAT_VECTOR, domain=AttributeStatistic.Domain.FACE, geometry=face, attribute=position(), ).mean positioned_text = text_mesh.set_position(offset=face_center).set_material(material=text_material) mid_angle = math(operation=Math.Operation.ADD, value=(start, math(operation=Math.Operation.DIVIDE, value=(sweep, 2.0)))) shift_vector = combine_xyz( x=math(operation=Math.Operation.MULTIPLY, value=(math(operation=Math.Operation.COSINE, value=mid_angle), shift)), y=math(operation=Math.Operation.MULTIPLY, value=(math(operation=Math.Operation.SINE, value=mid_angle), shift)), z=0.0, ) segment = extruded_face.mesh.set_material(material=segment_material) cap = face.set_material(material=segment_material) geometry = join_geometry(geometry=[positioned_text, segment, cap]).set_position(offset=shift_vector) return {"Curve": geometry, "End": end} @tree("VG Pie Chart") def vg_pie_chart( geometry: Geometry, a: Float = 0.5, a_shift: Float = 0.5, a_material: Material = None, b: Float = 0.5, b_shift: Float = 0.0, b_material: Material = None, c: Float = 0.5, c_shift: Float = 0.0, c_material: Material = None, text_material: Material = None, ): del geometry total = math(operation=Math.Operation.ADD, value=(math(operation=Math.Operation.ADD, value=(a, b)), c)) a_geometry, a_end = vg_pie_segment( start=0.0, value=a, total=total, shift=a_shift, segment_material=a_material, text_material=text_material, ) b_geometry, b_end = vg_pie_segment( start=a_end, value=b, total=total, shift=b_shift, segment_material=b_material, text_material=text_material, ) c_geometry, _c_end = vg_pie_segment( start=b_end, value=c, total=total, shift=c_shift, segment_material=c_material, text_material=text_material, ) return join_geometry(geometry=[a_geometry, b_geometry, c_geometry]) def _empty_geometry(): return mesh_line( mode=MeshLine.Mode.OFFSET, count_mode=MeshLine.CountMode.TOTAL, count=0, offset=(0.0, 0.0, 1.0), ) @tree("VG Extended Pie Segment") def vg_extended_pie_segment( radius: Float = 0.0, pie_height: Float = 0.0, text_height: Float = 0.0, text_size: Float = 0.0, text_material: Material = None, text_offset: Float = 0.0, pie_material: Material = None, include_percentage: Bool = True, value: Float = 0.0, total: Float = 0.0, start_angle: Float = 0.0, shift: Float = 0.0, text: String = "", ): fraction = math(operation=Math.Operation.DIVIDE, value=(value, total)) sweep = math(operation=Math.Operation.MULTIPLY, value=(fraction, TAU)) end_angle = math(operation=Math.Operation.ADD, value=(start_angle, sweep)) mid_angle = math(operation=Math.Operation.ADD, value=(start_angle, math(operation=Math.Operation.DIVIDE, value=(sweep, 2.0)))) percentage = value_to_string( data_type=ValueToString.DataType.FLOAT, value=math(operation=Math.Operation.MULTIPLY, value=(fraction, 100.0)), decimals=2, ) percentage_line = join_strings(delimiter="", strings=[string(string="%"), percentage]) label_with_percentage = join_strings(delimiter=special_characters().line_break, strings=[percentage_line, text]) label = switch(input_type=Switch.InputType.STRING, switch=include_percentage, false=text, true=label_with_percentage) shift_vector = combine_xyz( x=math(operation=Math.Operation.MULTIPLY, value=(shift, math(operation=Math.Operation.COSINE, value=mid_angle))), y=math(operation=Math.Operation.MULTIPLY, value=(shift, math(operation=Math.Operation.SINE, value=mid_angle))), z=0.0, ) label_radius = math(operation=Math.Operation.MULTIPLY, value=(text_offset, radius)) label_offset = vector_math( operation=VectorMath.Operation.ADD, vector=( shift_vector, combine_xyz( x=math(operation=Math.Operation.MULTIPLY, value=(label_radius, math(operation=Math.Operation.COSINE, value=mid_angle))), y=math(operation=Math.Operation.MULTIPLY, value=(label_radius, math(operation=Math.Operation.SINE, value=mid_angle))), z=0.0, ), ), ) text_curves = string_to_curves( string=label, size=text_size, align_x="Center", align_y="Middle", pivot_point="Bottom Left", ).curve_instances text_face = fill_curve(curve=text_curves, mode="Triangles", fill_rule="Even-Odd") placed_text = set_position(geometry=text_face.set_material(material=text_material), offset=label_offset) extruded_text = extrude_mesh( mode=ExtrudeMesh.Mode.FACES, mesh=placed_text, offset=combine_xyz(x=0.0, y=0.0, z=math(operation=Math.Operation.ADD, value=(text_height, pie_height))), offset_scale=1.0, individual=True, ).mesh.set_material(material=text_material) arc_curve = arc( mode=Arc.Mode.RADIUS, resolution=64, radius=radius, start_angle=start_angle, sweep_angle=sweep, connect_center=True, ) shifted_arc = transform_geometry(geometry=arc_curve, translation=shift_vector) pie_face = fill_curve(curve=shifted_arc, mode="Triangles", fill_rule="Even-Odd").set_material( material=pie_material ) extruded_pie = extrude_mesh( mode=ExtrudeMesh.Mode.FACES, mesh=pie_face, offset=combine_xyz(x=0.0, y=0.0, z=pie_height), offset_scale=1.0, individual=True, ).mesh.set_material(material=pie_material) return {"End Angle": end_angle, "Pie": join_geometry(geometry=[extruded_text, extruded_pie, placed_text, pie_face])} @tree("VG Extended Pie Chart") def vg_extended_pie_chart( title: String = "Extended Pie Chart", title_size: Float = 0.20000000298023224, title_material: Material = None, title_offset: Float = 0.18000000715255737, segment_count: Int = 10, radius: Float = 1.0, pie_height: Float = 0.10000000149011612, text_height: Float = 0.004999999888241291, text_size: Float = 0.07999999821186066, text_material: Material = None, text_offset: Float = 0.699999988079071, include_percentage: Bool = True, value_1: Float = 20.0, label_1: String = "Lorem", shift_1: Float = 0.20000000298023224, material_1: Material = None, value_2: Float = 30.0, label_2: String = "Ipsum", shift_2: Float = 0.0, material_2: Material = None, value_3: Float = 27.0, label_3: String = "Dolor", shift_3: Float = 0.0, material_3: Material = None, value_4: Float = 25.0, label_4: String = "Sit", shift_4: Float = 0.0, material_4: Material = None, value_5: Float = 55.0, label_5: String = "Amet", shift_5: Float = 0.0, material_5: Material = None, value_6: Float = 45.0, label_6: String = "Consectetur", shift_6: Float = 0.0, material_6: Material = None, value_7: Float = 25.0, label_7: String = "Adipiscing", shift_7: Float = 0.0, material_7: Material = None, value_8: Float = 35.0, label_8: String = "Elit", shift_8: Float = 0.0, material_8: Material = None, value_9: Float = 58.0, label_9: String = "Sed", shift_9: Float = 0.0, material_9: Material = None, value_10: Float = 32.0, label_10: String = "Do", shift_10: Float = 0.0, material_10: Material = None, ): values = [value_1, value_2, value_3, value_4, value_5, value_6, value_7, value_8, value_9, value_10] labels = [label_1, label_2, label_3, label_4, label_5, label_6, label_7, label_8, label_9, label_10] shifts = [shift_1, shift_2, shift_3, shift_4, shift_5, shift_6, shift_7, shift_8, shift_9, shift_10] materials = [ material_1, material_2, material_3, material_4, material_5, material_6, material_7, material_8, material_9, material_10, ] total = value_1 for index, segment_value in enumerate(values[1:], start=2): total = math( operation=Math.Operation.ADD, value=( total, switch( input_type=Switch.InputType.FLOAT, switch=math(operation=Math.Operation.GREATER_THAN, value=(segment_count, index - 1.0)), false=0.0, true=segment_value, ), ), ) empty = _empty_geometry() start_angle = 0.0 segments = [] for index, (segment_value, label, segment_shift, segment_material) in enumerate( zip(values, labels, shifts, materials), start=1, ): end_angle, segment_geometry = vg_extended_pie_segment( radius=radius, pie_height=pie_height, text_height=text_height, text_size=text_size, text_material=text_material, text_offset=text_offset, pie_material=segment_material, include_percentage=include_percentage, value=segment_value, total=total, start_angle=start_angle, shift=segment_shift, text=label, ) if index == 1: segments.append(segment_geometry) else: segments.append( switch( input_type=Switch.InputType.GEOMETRY, switch=math(operation=Math.Operation.GREATER_THAN, value=(segment_count, index - 1.0)), false=empty, true=segment_geometry, ) ) start_angle = end_angle title_curves = string_to_curves( string=title, size=title_size, align_x="Center", align_y="Middle", pivot_point="Bottom Left", ).curve_instances title_face = fill_curve(curve=title_curves, mode="Triangles", fill_rule="Even-Odd") title_position = combine_xyz( x=0.0, y=math( operation=Math.Operation.SUBTRACT, value=(math(operation=Math.Operation.MULTIPLY, value=(-1.0, math(operation=Math.Operation.ADD, value=(radius, title_size)))), title_offset), ), z=0.0, ) placed_title = transform_geometry(geometry=title_face, translation=title_position).set_material(material=title_material) extruded_title = extrude_mesh( mode=ExtrudeMesh.Mode.FACES, mesh=placed_title, offset=combine_xyz(x=0.0, y=0.0, z=text_height), offset_scale=1.0, individual=True, ).mesh.set_material(material=title_material) return {"Geometry": join_geometry(geometry=[*segments, placed_title, extruded_title])} def _finalize_groups(): import bpy groups = [] for name in ("VG Pie Segment", "VG Pie Chart", "VG Extended Pie Segment", "VG Extended Pie Chart"): group = bpy.data.node_groups.get(name) if not group: continue group.use_fake_user = True if hasattr(group, "interface"): for item in group.interface.items_tree: if item.item_type == "SOCKET" and item.in_out == "OUTPUT" and item.name == "Result": item.name = "Geometry" if item.item_type == "SOCKET" and item.in_out == "INPUT" and item.name in {"A", "B", "C"}: item.name = item.name.lower() groups.append(group) return groups _finalize_groups() if __name__ == "__main__": for group in _finalize_groups(): print( "VG_PIE_GROUP", group.name, len(group.nodes), len(group.links), sorted(set(node.bl_idname for node in group.nodes)), )