Files
braille_translator/model_gen/keyboard_3d.py
2024-06-11 08:02:41 +01:00

550 lines
30 KiB
Python

# -*- coding: utf-8 -*-
"""
@author: Edward Middleton-Smith
"""
# import argument_validation as av
from colour_theme_braille_character import Colour_Theme_Character_Braille, BaseStyle
from openscad_objects import ModelOpenSCAD # get_openscad_colours
# from translate_msg_2_braille import Character_Braille
from character_braille import Character_Braille
from translation_braille import Translation_Braille, Enum_Braille_Proficiency_Level
from utils_system import render_openscad, make_openscad, exec_oscmd
import openpyscad as ops # Union, Difference
import numpy as np
from typing import Optional, List
from prettytable import PrettyTable
from enum import Enum
from pydantic import BaseModel, Field, ValidationError, validate_arguments, validator
# from color import Color
from builtins import staticmethod
import os
import string
from abc import ABC, abstractmethod
import inspect
"""
class EnumBaseStyleMeta(type(Enum), type(BaseStyle)):
pass
"""
class Enum_Visibility_Character_Braille(Enum): # BaseStyle, metaclass=EnumBaseStyleMeta):
EMBOSSED = -1
HIDDEN = 0
VISIBLE = 1
def minimum():
return min([e.value for e in Enum_Visibility_Character_Braille])
def maximum():
return max([e.value for e in Enum_Visibility_Character_Braille])
def get_text_filename(self):
return '_0' if (self == Enum_Visibility_Character_Braille.HIDDEN) else '__' if (self == Enum_Visibility_Character_Braille.EMBOSSED) else '_1'
class Style_Character_Braille(BaseModel, BaseStyle):
show_braille: Enum_Visibility_Character_Braille # = Enum_Visibility_Character_Braille.VISIBLE
show_letter: Enum_Visibility_Character_Braille # = Enum_Visibility_Character_Braille.VISIBLE
show_number: Enum_Visibility_Character_Braille # = Enum_Visibility_Character_Braille.VISIBLE
"""
def __new__(cls, braille, letter, number):
_m = 'style.__new__'
av.val_type(braille, "<enum 'elem_visibility'>", 'braille', _m)
av.val_type(braille, "<enum 'elem_visibility'>", 'braille', _m)
av.val_type(braille, "<enum 'elem_visibility'>", 'braille', _m)
return super(style, cls).__new__(cls)
def __init__(self, braille, letter, number):
self.braille = braille
self.letter = letter
self.number = number
"""
def get_text_filename(self):
return f"{self.show_braille.get_text_filename()}{self.show_letter.get_text_filename()}{self.show_number.get_text_filename()}"
@staticmethod
def get_default():
return Style_Character_Braille(show_braille=Enum_Visibility_Character_Braille.VISIBLE, show_letter=Enum_Visibility_Character_Braille.VISIBLE, show_number=Enum_Visibility_Character_Braille.VISIBLE)
@staticmethod
def get_defaults():
return [Style_Character_Braille.get_default()]
def as_row(self):
return [self.show_braille.name, self.show_letter.name, self.show_number.name]
"""
def input_from_console():
sizes = Size_Character_Braille.get_defaults()
count_sizes = len(sizes)
table_output = PrettyTable()
table_output.field_names = ['index', 'name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius']
for index_size in range(count_sizes):
size_index = sizes[index_size]
table_output.add_row([index_size + 1] + size_index.as_row())
print()
print("Please select product dimensions configuration from below:")
print(table_output)
while True:
size_input = str(input("Product dimensions configuration (name or index): "))
print(size_input + " selected")
if size_input == "#!ERRORCODE!#": exit
for index_size in range(count_sizes):
if size_input == sizes[index_size].name or size_input == str(index_size + 1):
return sizes[index_size]
def input_many_from_console():
sizes_selected = []
print('Inputting many Size_Character_Braille objects')
print()
while True:
try:
count_sizes = int(input('Quantity of size objects to enter:'))
except: continue
for index_size in range(count_sizes):
print(f'Inputting size object {index_size + 1}')
size_new = Size_Character_Braille.input_from_console()
sizes_selected.append(size_new)
break
return sizes_selected
"""
def get_list_headings():
return ['show braille', 'show letter', 'show number']
class Size_Character_Braille(BaseModel, BaseStyle):
# ATTRIBUTE DECLARATION
name: str
spacing_dot: float = Field(ge = 0) # dp distance between dots
height_block: float = Field(ge = 0) # hblock height of
spacing_character: float = Field(ge = 0) # spacing between keys on keyboard
height_base: float = Field(ge = 0) # height of
height_dot: float = Field(ge = 0) # height of Braille dots
radius_bottom_dot: float = Field(ge = 0) # base radius of Braille dots
radius_top_dot : float = Field(ge = 0) # top radius of Braille dots
width_character_braille: float = 0
R_block_letter: List[float] = [0, 0, 0]
R_block_braille: List[float] = [0, 0, 0]
R_block_number: List[float] = [0, 0, 0]
size_font_alphabetic: float = 0
size_font_numeric: float = 0
sf_size_font_word_length: float = 0
sf_size_font_number_length: float = 0
def __init__(self, name, spacing_dot, height_block, spacing_character, height_base, height_dot, radius_bottom_dot, radius_top_dot):
BaseModel.__init__(self, name=name, spacing_dot=spacing_dot, height_block=height_block, spacing_character=spacing_character, height_base=height_base, height_dot=height_dot, radius_bottom_dot=radius_bottom_dot, radius_top_dot=radius_top_dot)
self.width_character_braille = self.spacing_dot + 2 * self.spacing_character + self.radius_bottom_dot * 2
self.R_block_letter = [self.width_character_braille, self.width_character_braille, self.height_block] # alphabet block dimensions [x, y]
self.R_block_braille = [self.width_character_braille, self.width_character_braille + self.spacing_dot, self.height_block] # braille block dimensions [x, y]
self.R_block_number = [self.width_character_braille, self.width_character_braille - 2 * self.spacing_character, self.height_block] #np.array(* i_s_num # number block dimensions [x, y] ' adjust to scalar coefficient rather than linear translation
self.size_font_alphabetic = self.R_block_letter[0] - 4 * self.spacing_character
self.size_font_numeric = self.size_font_alphabetic * 0.75
self.sf_size_font_word_length = 0.65 # scale factor for shrinking number text to fit more letters in single char space
self.sf_size_font_number_length = 0.75 # scale factor for shrinking message text to fit more letters in single char space
"""
# METHODS
def __new__(cls, name, dp, hblock, s, base_height, hcyl, rcyl, rsphere):
# FUNCTION
# Initialise class object
# ARGUMENTS
# str name - name size scheme
# float dp - distance between braille pins
# float hblock - height of base of each key
# float s - spacing
# float base_height - height of base block - board
# float hcyl - height of braille pins
# float rcyl - base radius of braille pins
# float rsphere - tip radius of braille pins
# ARGUMENT VALIDATION
_m = 'scrabble_dimensions.__new__'
v_arg_type = 'class attribute'
av.val_str(name, 'name', _m, 1, v_arg_type = v_arg_type)
av.full_val_float(dp, 'dp', _m, 0, v_arg_type = v_arg_type)
av.full_val_float(hblock, 'hblock', _m, v_arg_type = v_arg_type)
av.full_val_float(s, 's', _m, 0, v_arg_type = v_arg_type)
av.full_val_float(base_height, 'base_height', _m, 0, v_arg_type = v_arg_type)
av.full_val_float(hcyl, 'hcyl', _m, 0, v_arg_type = v_arg_type)
av.full_val_float(rcyl, 'rcyl', _m, 0, v_arg_type = v_arg_type)
av.full_val_float(rsphere, 'rsphere', _m, 0, v_arg_type = v_arg_type)
# RETURNS
return super(scrabble_dimensions, cls).__new__(cls)
def __init__(self, name, dp, hblock, s, base_height, hcyl, rcyl, rsphere):
# FUNCTION
# Construct class object
# ARGUMENTS
# str name
# float dp
# float hblock
# float s
# float base_height
# float hcyl
# float rcyl
# float rsphere
# ARGUMENT VALIDATION
# see __new__()
# ATTRIBUTE INSTANTIATION
self.name = name
self.dp = dp
self.hblock = hblock
self.s = s
self.base_height = base_height
self.hcyl = hcyl
self.rcyl = rcyl
self.rsphere = rsphere
"""
def __repr__(self):
# FUNCTION
# Convert object to str representation
# RETURNS
return f"name = {self.name}, spacing_dot = {self.spacing_dot}, height_block = {self.height_block}, spacing_character = {self.spacing_character}, height_base = {self.height_base}, height_dot = {self.height_dot}, radius_bottom_dot = {self.radius_bottom_dot}, radius_top_dot = {self.radius_top_dot}"
def as_dict(self):
# FUNCTION
# Convert object attribute, value pairs to dictionary representation
# RETURNS
return {'name': self.name, 'spacing_dot': self.spacing_dot, 'height_block': self.height_block, 'spacing_character': self.spacing_character, 'height_base': self.height_base, 'height_dot': self.height_dot, 'radius_bottom_dot': self.radius_bottom_dot, 'radius_top_dot': self.radius_top_dot}
def as_row(self):
return [self.name, self.spacing_dot, self.height_block, self.spacing_character, self.height_base, self.height_dot, self.radius_bottom_dot, self.radius_top_dot]
def get_defaults():
k = 2.3622
s = 1
sizes = []
sizes.append(Size_Character_Braille('sz_1', 2.5, 2*s, s, 4*s, 1.2, 2/3, 1/2))
sizes.append(Size_Character_Braille('sz_2', 4, 1.28, s, 4*s, 1.2, 3/2, 1))
sizes.append(Size_Character_Braille('sz_3', 8, 2.5, s, 6*s, 1.2, 3/2, 1))
sizes.append(Size_Character_Braille('sz_4', 10, 3, 1, 6*s, 1.2, 3/2, 1))
sizes.append(Size_Character_Braille('sz_5', 10, 1, 1, 6*s, 1.2, 3/2, 1))
sizes.append(Size_Character_Braille('keyboard', 2.5, 0.8, 0.5, 4, 1.2, 2/3, 0.5))
sizes.append(Size_Character_Braille('poster', 2.5, 0.8, 0.5, 2, 1.2, 2/3, 0.5))
sizes.append(Size_Character_Braille('poster_big', 2.5*k, 0.8, 0.5*k, 2, 1.2, 2/3*k, 0.5*k))
# print('szs_scrabble')
return sizes
def get_default():
sizes_default = Size_Character_Braille.get_defaults()
return sizes_default['Character_Braille'].apply(lambda x: x if x.name == 'Keyboard' else None).dropna()[0]
"""
def input_from_console():
sizes = Size_Character_Braille.get_defaults()
count_sizes = len(sizes)
table_output = PrettyTable()
table_output.field_names = ['index', 'name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius']
for index_size in range(count_sizes):
size_index = sizes[index_size]
table_output.add_row([index_size + 1] + size_index.as_row())
print()
print("Please select product dimensions configuration from below:")
print(table_output)
while True:
size_input = str(input("Product dimensions configuration (name or index): "))
print(size_input + " selected")
if size_input == "#!ERRORCODE!#": exit
for index_size in range(count_sizes):
if size_input == sizes[index_size].name or size_input == str(index_size + 1):
return sizes[index_size]
def input_many_from_console():
sizes_selected = []
print('Inputting many Size_Character_Braille objects')
print()
while True:
try:
count_sizes = int(input('Quantity of size objects to enter:'))
except: continue
for index_size in range(count_sizes):
print(f'Inputting size object {index_size + 1}')
size_new = Size_Character_Braille.input_from_console()
sizes_selected.append(size_new)
break
return sizes_selected
"""
def get_list_headings():
return ['name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius']
"""
class Utils_Size_Character_Braille:
@staticmethod
@validate_arguments
def is_valid_size_input(size_input: str, sizes_valid: List[Size_Character_Braille]):
count_sizes_valid = len(sizes_valid)
for i_size_valid in range(count_sizes_valid):
if size_input == sizes_valid[i_size_valid].name:
return True
return False
"""
class Enum_Justification_Text(Enum):
LEFT = 0
CENTRE = 1
RIGHT = 2
def minimum():
return min([e.value for e in Enum_Visibility_Character_Braille])
def maximum():
return max([e.value for e in Enum_Visibility_Character_Braille])
def input_from_console(cls):
print("Please select justification for text:")
print("0. Left")
print("1. Centre")
print("2. Right")
while True:
justification_input = input("Justification (0, 1, 2): ")
print(str(justification_input) + " selected")
if justification_input == "#!ERRORCODE!#": exit
try:
justification_input = int(justification_input)
except: continue
# if justification_input is not int: continue
if justification_input < Enum_Justification_Text.minimum() or justification_input > Enum_Justification_Text.maximum(): continue
return Enum_Justification_Text(justification_input)
def get_default():
return Enum_Justification_Text(0)
def input_many_from_console():
return BaseStyle.input_many_from_console(Enum_Justification_Text)
class Keyboard_3D(ModelOpenSCAD): #, BaseModel):
size_characters: Size_Character_Braille
style_characters: Style_Character_Braille
colour_theme: Colour_Theme_Character_Braille
justification_text: Enum_Justification_Text
max_characters_per_row: int
translation: Translation_Braille # List[List[Character_Braille]]
# fn: int = Field(ge=0, default=25)
# filename: str = ''
def __init__(self, **kwargs): # , size_characters, style_characters, colour_theme, justification_text, path_dir, max_characters_per_row, translation, fn=25, filename=''):
# print(f'size_characters, style_characters, colour_theme, justification_text, path_dir, max_characters_per_row, translation, fn, filename: {size_characters, style_characters, colour_theme, justification_text, path_dir, max_characters_per_row, translation, fn, filename}')
# BaseModel.__init__(self, size_characters=size_characters, style_characters=style_characters, colour_theme=colour_theme, justification_text=justification_text, path_dir=path_dir, max_characters_per_row=max_characters_per_row, translation=translation, fn=fn, filename=filename)
# BaseModel.__init__(self, size_characters=size_characters, style_characters=style_characters, justification_text=justification_text, max_characters_per_row=max_characters_per_row, translation=translation, filename='')
# self.filename = self.get_filename()
ModelOpenSCAD.__init__(self, **{**kwargs, 'filename': '', 'model': None}) # , path_dir=path_dir, filename=filename, colour_theme=colour_theme, fn=fn)
# BaseModel.__init__(self, size_characters=size_characters, style_characters=style_characters, justification_text=justification_text, max_characters_per_row=max_characters_per_row, translation=translation)
# BaseModel.__init__(self, **kwargs) # , size_characters=size_characters, style_characters=style_characters, colour_theme=colour_theme, justification_text=justification_text, path_dir=path_dir, max_characters_per_row=max_characters_per_row, translation=translation, fn=fn, filename=filename)
self.filename = self.get_filename()
def get_filename(self): #, sz_scheme, col_theme, my_style, path_file = "C:\\Users\\edwar\\OneDrive\\Documents\\Programming\\Python Scripts\\Braille_Scrabble", suffix = "stl", presuffix=""):
"""
av.val_str(path_file, 'path_file', _m)
av.val_str(suffix, 'suffix', _m)
av.val_str(presuffix, 'presuffix', _m)
"""
return f"{self.size_characters.name}_{self.colour_theme.name}{self.style_characters.get_text_filename()}"
def get_path_file(self, suffix):
return f"{self.path_dir}/{self.filename}.{suffix}"
@staticmethod
@validate_arguments
def make_from_styles_and_plaintext_and_proficiency_level(size_characters: Size_Character_Braille, style_characters: Style_Character_Braille, colour_theme: Colour_Theme_Character_Braille, justification_text: Enum_Justification_Text, path_dir: str, max_characters_per_row: int, plaintext: str, proficiency_level: Enum_Braille_Proficiency_Level):
braille_translation = Translation_Braille(plaintext, proficiency_level)
return Keyboard_3D(size_characters = size_characters, style_characters = style_characters, colour_theme = colour_theme, justification_text = justification_text, path_dir = path_dir, max_characters_per_row = max_characters_per_row, translation = braille_translation)
def make_model_openpyscad(self):
# integer boolean conversions for position
show_braille = (self.style_characters.show_braille == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_braille == Enum_Visibility_Character_Braille.EMBOSSED)
show_letter = (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_letter == Enum_Visibility_Character_Braille.EMBOSSED)
show_number = (self.style_characters.show_number == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_number == Enum_Visibility_Character_Braille.EMBOSSED)
# dimensions
"""
width_character_braille = self.size_characters.spacing_dot + 2 * self.size_characters.spacing_character + self.size_characters.radius_bottom_dot * 2
R_base_letter = [width_character_braille, width_character_braille, self.size_characters.height_block] # alphabet block dimensions [x, y]
R_base_braille = [width_character_braille, width_character_braille + self.size_characters.spacing_dot, self.size_characters.height_block] # braille block dimensions [x, y]
R_base_number = [width_character_braille, width_character_braille - 2 * self.size_characters.spacing_character, self.size_characters.height_block] #np.array(* i_s_num # number block dimensions [x, y] ' adjust to scalar coefficient rather than linear translation
"""
# _fn = self.fn
model_positive = ops.Union()
model_negative = ops.Union()
count_rows = 0
count_characters_in_row = 0
size_character = np.array([
self.size_characters.spacing_character + self.size_characters.width_character_braille,
self.size_characters.R_base_braille[1] * show_braille + self.size_characters.R_base_letter[1] * show_letter + self.size_characters.R_base_number[1] * show_number + self.size_characters.spacing_character * (show_braille + show_letter + show_number),
0
])
origin_character = np.array([-self.size_characters.spacing_character, -self.size_characters.spacing_character, 0])
for braille_translation in self.translation:
length_translation = len(braille_translation.braille_text)
if count_characters_in_row + length_translation > self.max_characters_per_row or (braille_translation.plaintext == 'NEWLINE' and braille_translation.list_dots_braille == [0, 0, 0, 0, 0, 0] and count_characters_in_row > 0):
count_rows += 1
count_characters_in_row = 0
for character in braille_translation.braille_text:
model_character_positive, model_character_negative = self.make_model_openscad_from_character(character) # character.make_model_openpyscad()
position_character = origin_character + np.array([
(self.size_characters.spacing_character + size_character[0]) * count_characters_in_row,
(self.size_characters.spacing_character + size_character[1]) * count_rows,
0
])
model_character_positive.translate(position_character)
model_positive.append(model_character_positive)
model_character_negative.translate(position_character)
model_negative.append(model_character_negative)
count_characters_in_row += 1
self.model = ops.Difference()
self.model.append(model_character_positive)
self.model.append(model_character_negative)
return self.model
@validate_arguments
def make_model_openscad_from_character(self, character: Character_Braille): # origin_character: List[float] , show_braille: bool, show_letter: bool, show_number: bool
show_braille = (self.style_characters.show_braille == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_braille == Enum_Visibility_Character_Braille.EMBOSSED)
show_letter = (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE or self.style_characters.show_letter == Enum_Visibility_Character_Braille.EMBOSSED)
show_number = (self.style_characters.show_number == Enum_Visibility_Character_Braille.VISIBLE) # or self.style_characters.show_number == Enum_Visibility_Character_Braille.EMBOSSED)
model_positive = ops.Union()
model_negative = ops.Union()
origin_block = np.array([0, 0, 0])
if show_braille:
block = self.make_model_openscad_block_braille_from_character(character)
block.translate(origin_block)
model_positive.append(block)
origin_block += np.array([
0,
-self.size_characters.spacing_character - self.size_characters.R_block_braille[1],
0
])
if show_letter:
block = self.make_model_openscad_block_letter_from_character(character)
block.translate(origin_block)
if self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE:
model_positive.append(block)
else:
model_negative.append(block)
origin_block += np.array([
0,
-self.size_characters.spacing_character - self.size_characters.R_block_letter[1],
0
])
if show_number:
block = self.make_model_openscad_block_number_from_character(character)
block.translate(origin_block)
model_positive.append(block)
return model_positive, model_negative
"""
@validator('origin_character')
def validate_origin_character(cls, value):
if len(value) != 3:
raise ValueError("origin_character must have 3 elements")
for element in value:
if not isinstance(element, (int, float)):
raise ValueError("origin_character must be a list of integers or floats")
return value
@validator('R_block_braille')
def validate_R_block_braille(cls, value):
if len(value) != 3:
raise ValueError("R_block_braille must have 3 elements")
return value
@validator('R_block_letter')
def validate_R_block_letter(cls, value):
if len(value) != 3:
raise ValueError("R_block_letter must have 3 elements")
return value
@validator('R_block_number')
def validate_R_block_number(cls, value):
if len(value) != 3:
raise ValueError("R_block_number must have 3 elements")
return value
"""
@validate_arguments
def make_model_openscad_block_braille_from_character(self, character: Character_Braille):
model_block_braille = ops.Union()
if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.HIDDEN): return model_block_braille
if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE):
block = ops.Cube(self.size_characters.R_block_braille, center = False)
block.translate([0, -self.size_characters.R_block_braille[1], -self.size_characters.R_block_braille[2]])
block.color(self.colour_theme.colour_base)
model_block_braille.append(block)
if (self.style_characters.show_braille == Enum_Visibility_Character_Braille.VISIBLE):
for index_dot_braille_y in range(3):
for index_dot_braille_x in range(2):
if (character.matrix_braille_dots[index_dot_braille_y][index_dot_braille_x]):
dot_braille = ops.Cylinder(
h = self.size_characters.height_cylinder,
r1 = self.size_characters.radius_bottom_cylinder,
r2 = self.size_characters.radius_top_cylinder,
center = True,
_fn = self.fn
)
dot_braille.translate([
index_dot_braille_x * self.size_characters.spacing_dot,
-index_dot_braille_y * self.size_characters.spacing_dot,
0
])
dot_braille.color(self.colour_theme.colour_top)
model_block_braille.append(dot_braille)
return model_block_braille
@validate_arguments
def make_model_openscad_block_letter_from_character(self, character: Character_Braille):
font = '"Arial:style=Bold"'
model_block_letter = ops.Union()
if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.HIDDEN): return model_block_letter
if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE):
block = ops.Cube(self.size_characters.R_block_letter, center = False)
block.translate([0, -self.size_characters.R_block_letter[1], -self.size_characters.R_block_letter[2]])
block.color(self.colour_theme.colour_base)
model_block_letter.append(block)
size_text = self.size_characters.size_font_alphabetic * self.size_characters.scale_text ** (len(character.plaintext) - 1)
model_letter = ops.Text(f'"{character.plaintext}"', size_text, font, halign = '"center"', valign = '"center"', _fn = self.fn)
model_letter.linear_extrude(self.size_characters.height_dot, center = False)
model_letter.color(self.colour_theme.colour_top)
model_letter.translate([
self.size_characters.R_block_letter[0] / 2,
self.size_characters.R_block_letter[1] / 2 if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE) else self.size_characters.R_block_braille[1] / 2,
0 if (self.style_characters.show_letter == Enum_Visibility_Character_Braille.VISIBLE) else self.size_characters.height_dot - self.size_characters.height_block - self.size_characters.height_base
])
model_block_letter.append(model_letter)
return model_block_letter
@validate_arguments
def make_model_openscad_block_number_from_character(self, character: Character_Braille):
model_block_number = ops.Union()
if (self.style_characters.show_number == Enum_Visibility_Character_Braille.HIDDEN or self.style_characters.show_number == Enum_Visibility_Character_Braille.EMBOSSED or len(character.plaintext) != 1): return model_block_number
font = '"Arial:style=Bold"'
number = string.ascii_lowercase.index(character.plaintext.lower()) + 1
length_number = len(str(number))
if (number < 1 or number > 26): return model_block_number
block = ops.Cube(self.size_characters.R_block_number, center = True)
block.translate([])
block.color(self.colour_theme.colour_base)
model_block_number.append(block)
size_text = (self.size_characters.R_block_number[1] - self.size_characters.spacing_character * (len(number) + 1)) / (len(number) ** self.size_characters.sf_size_font_number_length)
model_number = ops.Text(f'"{number}"', size_text, font, halign = '"center"', valign = '"center"', _fn = self.fn)
model_number.linear_extrude(self.size_characters.height_dot, center = True)
model_number.color(self.colour_theme.colour_top)
model_number.translate([
self.size_characters.R_block_number[0] / 2 if (length_number == 1) else self.size_characters.R_block_number[0] / 2 + 1.6 * size_text * (number - (length_number - 1) / 2),
self.size_characters.R_block_number[1] * 0.25,
self.size_characters.height_dot / 2
])
model_block_number.append(model_number)
return model_block_number
def make_file_openscad(self):
if self.model is None:
self.make_model_openpyscad()
self.model.write(self.get_path_file('scad'))
def make_file_stl(self):
if not os.path.exists(self.get_path_file('scad')):
self.make_file_openscad()
render_openscad(self.get_path_file('scad'), self.get_path_file('stl'))
def make_file_png(self):
if not os.path.exists(self.get_path_file('scad')):
self.make_file_openscad()
render_openscad(self.get_path_file('scad'), self.get_path_file('png'))