import copy
import numpy as np
from stl import mesh
from src.core.transforms.translation import Translation_Transform
from src.core.transforms.rotation import Rotation_Transform
from src.core.transforms.flexibility import Flexibility_Transform
[docs]
class Object3D:
"""
Object3D Class
==============
A class representing a 3D object with a mesh that can undergo transformations
including flexibility, rotation, and translation.
This class allows for the application of transformations to the mesh of a 3D object,
which can include deformations (flexibility), rotations, and translations. The
transformations are applied sequentially to the mesh data, and the transformed mesh
is returned.
Attributes
----------
name : str
The name of the 3D object.
stl_mesh : mesh.Mesh
The mesh of the 3D object, typically in the form of an STL file.
translation_transform : Translation_Transform
The transformation applied to the object for translation.
rotation_transform : Rotation_Transform
The transformation applied to the object for rotation.
flexibility_transform : Flexibility_Transform
The transformation applied to the object for flexibility (deformation).
Methods
-------
__init__(name, stl_mesh, translation_transform, rotation_transform, flexibility_transform):
Initializes the 3D object with its name, mesh, and transformation functions.
transform(position, angles, t):
Transforms the mesh by applying flexibility, rotation, and translation transformations
at a given time.
"""
def __init__(self, name:str, stl_mesh:mesh.Mesh, translation_transform:Translation_Transform, rotation_transform:Rotation_Transform, flexibility_transform:Flexibility_Transform):
"""
Initialize the 3D object with its name, mesh, and transformation functions.
This constructor takes the mesh data of the object, applies the specified
transformations (translation, rotation, and flexibility), and stores them as
attributes for later use when applying transformations.
Parameters
----------
name : str
The name of the 3D object.
stl_mesh : mesh.Mesh
The mesh of the 3D object, typically in the form of an STL file.
translation_transform : Translation_Transform
The transformation applied to the object for translation.
rotation_transform : Rotation_Transform
The transformation applied to the object for rotation.
flexibility_transform : Flexibility_Transform
The transformation applied to the object for flexibility (deformation).
Attributes
----------
name : str
Stores the name of the 3D object.
stl_mesh : mesh.Mesh
Stores the mesh data of the 3D object.
translation_transform : Translation_Transform
Stores the translation transformation function for the object.
rotation_transform : Rotation_Transform
Stores the rotation transformation function for the object.
flexibility_transform : Flexibility_Transform
Stores the flexibility transformation function for the object.
"""
self.name = name
self.stl_mesh = stl_mesh
self.translation_transform = translation_transform
self.rotation_transform = rotation_transform
self.flexibility_transform = flexibility_transform
[docs]
class Sprite:
"""
Sprite Class
============
A class representing a 3D sprite object that can be transformed over time based on
its positions and angles.
This class uses an `Object3D` instance to represent the sprite and applies
transformations (translation and rotation) over time. The spriteβs position and
rotation are stored for each time step and can be used to compute its transformation.
Attributes
----------
object_ : Object3D
The 3D object that represents the sprite.
positions : np.array of shape (n, 3)
An array of 3D positions (x, y, z) at different time steps.
angles : np.array of shape (n, 3)
An array of rotation angles (alpha, beta, gamma) at different time steps.
frame_origin : list of length 3
The origin of the sprite's local frame of reference (default is [0, 0, 0]).
frame_orientation : list of length 3
The orientation of the sprite's local frame of reference (default is [0, 0, 0]).
Methods
-------
__init__(object_, positions, angles):
Initializes the sprite object with a 3D object, position and angle arrays.
transform(t):
Transforms the sprite based on its position and rotation at the given time step `t`.
"""
def __init__(self, object_: Object3D, positions: np.array, angles: np.array):
"""
Initialize the sprite object with a 3D object, position, and angle arrays.
This constructor takes an `Object3D` instance, positions, and angles, and reshapes
them to ensure correct dimensions for later use in transformation computations.
Parameters
----------
object_ : Object3D
The 3D object that represents the sprite.
positions : np.array of shape (n, 3)
An array of 3D positions (x, y, z) at different time steps.
angles : np.array of shape (n, 3)
An array of rotation angles (alpha, beta, gamma) at different time steps.
Attributes
----------
object_ : Object3D
Stores the 3D object for the sprite.
positions : np.array of shape (n, 3)
Stores the array of positions for each time step.
angles : np.array of shape (n, 3)
Stores the array of rotation angles for each time step.
frame_origin : list of length 3
Stores the origin of the sprite's local frame of reference.
frame_orientation : list of length 3
Stores the orientation of the sprite's local frame of reference.
"""
self.object_ = object_
self.positions = positions.reshape(-1, 3)
self.angles = angles.reshape(-1, 3)
self.frame_origin = [0, 0, 0]
self.frame_orientation = [0, 0, 0]
[docs]
class Scene:
"""
Scene Class
===========
A class representing a 3D scene containing multiple sprite objects that can be
transformed over time. Each sprite in the scene is an instance of the `Sprite` class,
and the transformations applied to the scene depend on the time step.
This class provides a `transform` method to apply transformations to each sprite in
the scene, either returning their original or transformed meshes based on the time step.
Attributes
----------
objects : list of Sprite
A list of `Sprite` objects that make up the 3D scene.
Methods
-------
__init__(objects):
Initializes the scene with a list of `Sprite` objects.
transform(t):
Applies transformations to all sprite objects in the scene at the given time step `t`.
"""
def __init__(self, objects: list):
"""
Initialize the scene with a list of sprite objects.
This constructor takes a list of `Sprite` objects that represent the individual
elements in the 3D scene. Each sprite in the scene can be transformed over time
using the `transform` method.
Parameters
----------
objects : list of Sprite
A list of `Sprite` objects that will be included in the scene.
"""
self.objects = objects
[docs]
def save_stl(self, t, reflect_xy = False, reflect_yz = False, reflect_xz = False):
"""
Save the transformed meshes to STL files with optional reflections.
This method applies transformations to all objects in the scene at the given time step `t`.
If reflection flags are set (e.g., `reflect_xy`, `reflect_yz`, or `reflect_xz`), it applies
the corresponding reflection to the objects in the scene. The method then combines the transformed
meshes and their reflected versions into a single mesh and returns it.
Parameters
----------
t : float
The time step used to apply transformations to the objects in the scene.
reflect_xy : bool, optional
If set to True, the objects are reflected across the xy-plane.
reflect_yz : bool, optional
If set to True, the objects are reflected across the yz-plane.
reflect_xz : bool, optional
If set to True, the objects are reflected across the xz-plane.
Returns
-------
combined_mesh : mesh.Mesh
A single `mesh.Mesh` object containing all the transformed and optionally reflected objects.
Methods Called
--------------
transform(t)
Applies transformations to the objects in the scene at the given time step `t`.
copy.deepcopy()
Creates a copy of each object for applying reflections.
"""
if reflect_xy:
# Make reflection of the objects in the scene with respect to the xy-plane
transformed_objects = self.transform(t)
reflected_objects = []
for obj in transformed_objects:
temp_mesh_copy = copy.deepcopy(obj)
# Flip the y-coordinates of the vertices
temp_mesh_copy.vectors[:,:,1] = -temp_mesh_copy.vectors[:,:,1]
# Append the reflected object to the list
reflected_objects.append(temp_mesh_copy)
full_objects = transformed_objects + reflected_objects
combined_mesh = mesh.Mesh(np.concatenate([obj.data for obj in full_objects]))
return combined_mesh
elif reflect_yz:
# Make reflection of the objects in the scene with respect to the yz-plane
transformed_objects = self.transform(t)
reflected_objects = []
for obj in transformed_objects:
temp_mesh_copy = copy.deepcopy(obj)
# Flip the x-coordinates of the vertices
temp_mesh_copy.vectors[:,:,0] = -temp_mesh_copy.vectors[:,:,0]
# Append the reflected object to the list
reflected_objects.append(temp_mesh_copy)
full_objects = transformed_objects + reflected_objects
combined_mesh = mesh.Mesh(np.concatenate([obj.data for obj in full_objects]))
return combined_mesh
elif reflect_xz:
# Make reflection of the objects in the scene with respect to the xz-plane
transformed_objects = self.transform(t)
reflected_objects = []
for obj in transformed_objects:
temp_mesh_copy = copy.deepcopy(obj)
# Flip the y-coordinates of the vertices
temp_mesh_copy.vectors[:,:,1] = -temp_mesh_copy.vectors[:,:,1]
# Append the reflected object to the list
reflected_objects.append(temp_mesh_copy)
full_objects = transformed_objects + reflected_objects
combined_mesh = mesh.Mesh(np.concatenate([obj.data for obj in full_objects]))
return combined_mesh
else:
transformed_objects = self.transform(t)
combined_mesh = mesh.Mesh(np.concatenate([obj.data for obj in transformed_objects]))
return combined_mesh