From 9ec9f5d21d2da3c317c1d8f7967fe97d6c6c1a81 Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 9 Jan 2023 10:39:57 +0100 Subject: [PATCH] Add Text in available Vedo objects. --- examples/Core/rendering/text.py | 26 ++++++++++++++++++ src/Core/Rendering/VedoActor.py | 45 ++++++++++++++++++++++++++++--- src/Core/Rendering/VedoFactory.py | 44 ++++++++++++++++++++++++++++++ src/Core/Rendering/VedoTable.py | 29 ++++++++++++++++++-- 4 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 examples/Core/rendering/text.py diff --git a/examples/Core/rendering/text.py b/examples/Core/rendering/text.py new file mode 100644 index 0000000..77ad723 --- /dev/null +++ b/examples/Core/rendering/text.py @@ -0,0 +1,26 @@ +from time import sleep + +from SSD.Core.Rendering.VedoFactory import VedoFactory +from SSD.Core.Rendering.VedoVisualizer import VedoVisualizer + + +# 1. Create the rendering and the Factory, bind them to a new Database +visualizer = VedoVisualizer(database_name='text', + remove_existing=True) +factory = VedoFactory(database=visualizer.get_database()) + + +# 2. Add objects to the Factory then init the rendering +factory.add_text(content='Static Bold Text', + at=0, corner='TM', c='grey', font='Times', size=3., bold=True) +factory.add_text(content='Static Italic Text', + at=0, corner='BM', c='green7', font='Courier', size=2., italic=True) +factory.add_text(content='0', at=0) +visualizer.init_visualizer() + + +# 3. Run a few step +for step in range(50): + factory.update_text(object_id=2, content=f'{step}') + visualizer.render() + sleep(0.05) diff --git a/src/Core/Rendering/VedoActor.py b/src/Core/Rendering/VedoActor.py index cb70651..01f86ce 100644 --- a/src/Core/Rendering/VedoActor.py +++ b/src/Core/Rendering/VedoActor.py @@ -1,6 +1,6 @@ from typing import Any, Optional, Dict from numpy import array, tile -from vedo import Mesh, Points, Arrows, Marker, Glyph +from vedo import Mesh, Points, Arrows, Marker, Glyph, Text2D class VedoActor: @@ -23,12 +23,14 @@ def __init__(self, 'Points': self.__create_points, 'Arrows': self.__create_arrows, 'Markers': self.__create_markers, - 'Symbols': self.__create_symbols} + 'Symbols': self.__create_symbols, + 'Text': self.__create_text} update = {'Mesh': self.__update_mesh, 'Points': self.__update_points, 'Arrows': self.__update_arrows, 'Markers': self.__update_markers, - 'Symbols': self.__update_symbols} + 'Symbols': self.__update_symbols, + 'Text': self.__update_text} self.create = create[self.actor_type] self.update = update[self.actor_type] @@ -233,3 +235,40 @@ def __update_symbols(self, c=self.actor_data['c'], alpha=self.actor_data['alpha']) return self + + ######## + # TEXT # + ######## + + def __create_text(self, + data: Dict[str, Any]): + + # Register Actor data + self.actor_data = data + + # Get Text position + coord = {'B': 'bottom', 'L': 'left', 'M': 'middle', 'R': 'right', 'T': 'top'} + corner = data['corner'] + pos = f'{coord[corner[0].upper()]}-{coord[corner[1].upper()]}' + + # Create instance + self.instance = Text2D(txt=data['content'], + pos=pos, + s=data['size'], + font=data['font'], + bold=data['bold'], + italic=data['italic'], + c=data['c']) + return self + + def __update_text(self, + data: Dict[str, Any]): + + # Register Actor data + for key, value in data.items(): + if value is not None: + self.actor_data[key] = value + + # Update instance + self.instance.text(self.actor_data['content']).c(self.actor_data['c']) + return self diff --git a/src/Core/Rendering/VedoFactory.py b/src/Core/Rendering/VedoFactory.py index 0dc3100..f0b5bb7 100644 --- a/src/Core/Rendering/VedoFactory.py +++ b/src/Core/Rendering/VedoFactory.py @@ -391,3 +391,47 @@ def update_symbols(self, object_id = self.__check_id(object_id, 'Symbols') return self.__update_object(object_id, locals()) + + ######## + # TEXT # + ######## + + def add_text(self, + content: str, + at: int = 0, + corner: str = 'BR', + c: str = 'black', + font: str = 'Arial', + size: float = 1., + bold: bool = False, + italic: bool = False): + """ + Add new 2D Text to the Factory. + + :param content: Content of the Text. + :param at: Index of the window in which the Text will be rendered. + :param corner: Horizontal and vertical positions of the Text between T (top), M (middle) and B (bottom) - for + instance, 'BR' stands for 'bottom-right'. + :param c: Text color. + :param font: Font of the Text. + :param size: Size of the font. + :param bold: Apply bold style to the Text. + :param italic: Apply italic style to the Text. + """ + + return self.__add_object('Text', locals()) + + def update_text(self, + object_id: int, + content: Optional[str] = None, + c: Optional[str] = None): + """ + Update existing Text in the Factory. + + :param object_id: Index of the object (follows the global order of creation). + :param content: Content of the Text. + :param c: Text color. + """ + + object_id = self.__check_id(object_id, 'Text') + return self.__update_object(object_id, locals()) diff --git a/src/Core/Rendering/VedoTable.py b/src/Core/Rendering/VedoTable.py index d0c54a7..2c15e19 100644 --- a/src/Core/Rendering/VedoTable.py +++ b/src/Core/Rendering/VedoTable.py @@ -21,12 +21,14 @@ def __init__(self, 'Points': self.__create_points_columns, 'Arrows': self.__create_arrows_columns, 'Markers': self.__create_markers_columns, - 'Symbols': self.__create_symbols_columns} + 'Symbols': self.__create_symbols_columns, + 'Text': self.__create_text_columns} format_data = {'Mesh': self.__format_mesh_data, 'Points': self.__format_points_data, 'Arrows': self.__format_arrows_data, 'Markers': self.__format_markers_data, - 'Symbols': self.__format_symbols_data} + 'Symbols': self.__format_symbols_data, + 'Text': self.__format_text_data} self.create_columns = create_columns[self.table_type] self.format_data = format_data[self.table_type] @@ -126,6 +128,19 @@ def __create_symbols_columns(self): ]) return self + def __create_text_columns(self): + + self.database.create_table(table_name=self.table_name, + fields=[('content', str), + ('corner', str), + ('c', str), + ('font', str), + ('size', float), + ('bold', bool), + ('italic', bool), + ('at', int, 0)]) + return self + ####################### # FORMAT DATA METHODS # ####################### @@ -196,6 +211,16 @@ def __format_symbols_data(cls, data_dict[field] = cls.parse_vector(value, coords=field in ['positions', 'orientations']) return data_dict + @classmethod + def __format_text_data(cls, + data_dict: Dict[str, Any]): + + data_dict_copy = data_dict.copy() + for field, value in data_dict_copy.items(): + if value is None: + data_dict.pop(field) + return data_dict + @classmethod def parse_vector(cls, vec,