diff --git a/ansys_optical_automation/application/Source_to_Lightfield.py b/ansys_optical_automation/application/Source_to_Lightfield.py new file mode 100644 index 00000000..60befa8a --- /dev/null +++ b/ansys_optical_automation/application/Source_to_Lightfield.py @@ -0,0 +1,49 @@ +# Python Script, API Version = V23 +""" +The aim of this script is to convert any type of lightsource (surface and rayfile source currently) into Lightfield one. +12/2022 V1.0 capabilities : + - +""" +from ansys_optical_automation.speos_process.speos_sensors import LightFieldSensor +from ansys_optical_automation.speos_process.speos_sensors import LocalMeshing + +# import sys +# repo_path = r"your_repo_path" +# sys.path.append(repo_path) + + +def import_Dome(path): + world_origin = GetRootPart().CoordinateSystems[-1] + Selection.Create(world_origin).SetActive() + DocumentInsert.Execute(path) + + +def set_dome(surface_name, size): + dome_surface = Selection.CreateByNames(surface_name) + InputHelper.PauseAndGetInput("Please enter a scale value", size) + world_origin_point = GetRootPart().CoordinateSystems[-1].Frame.Origin + Scale.Execute(dome_surface, world_origin_point, size) + + +def set_LocalMeshing(geometries, name, sag_mode, sag_value): + localMeshing = LocalMeshing(name, SpeosSim, SpaceClaim) + localMeshing.set_geometries(geometries) + localMeshing.set_sag(sag_mode, sag_value) + + +def define_LightfieldSensor(sensor_name, sensor_type, incident_sampling, azimuth_sampling, geometries): + lightField = LightFieldSensor(sensor_name, SpeosSim, SpaceClaim) + lightField.set_faces(geometries) + lightField.set_type(sensor_type) + lightField.set_sampling(incident_sampling, azimuth_sampling) + + +def define_DirectSim(sim_name, sensor_name): + pass + + +def main(): + pass + + +main() diff --git a/ansys_optical_automation/application/camera_nhtsa_test.py b/ansys_optical_automation/application/camera_nhtsa_test.py index 724918ac..2635666a 100644 --- a/ansys_optical_automation/application/camera_nhtsa_test.py +++ b/ansys_optical_automation/application/camera_nhtsa_test.py @@ -117,7 +117,7 @@ def prepare_sim_setup(cam_name, sim_name, part_names, cam_model): """ Prepares a simulation model based on the given input: creates/edits the Camera with name cam_name based on the predefined Ccam_model, - positions it at axissystem "Cam_pos_1" + positions it at axis system "Cam_pos_1" creates/edits the Simulation with name sim_name adds all geometries of the parts given in part_names Parameters diff --git a/ansys_optical_automation/speos_process/speos_geometry_properties.py b/ansys_optical_automation/speos_process/speos_geometry_properties.py new file mode 100644 index 00000000..9d5db2d3 --- /dev/null +++ b/ansys_optical_automation/speos_process/speos_geometry_properties.py @@ -0,0 +1,138 @@ +from ansys_optical_automation.scdm_core.base import BaseSCDM + + +class GeometryProperties(BaseSCDM): + """ + Provides the parent class for all Speos Geometry properties types. + + This class contains methods and properties that are common to all geometry properties elements. + It shouldn't be used by itself. Subclasses should be used instead. + """ + + def __init__(self, name, SpeosSim, SpaceClaim): + super(GeometryProperties, self).__init__(SpaceClaim, ["V19", "V20", "V21", "V22", "V23"]) + self.speos_sim = SpeosSim + self.name = name + self.speos_object = None + self.geometries_list = [] + + def set_geometries(self, geometries): + """ + set geometries, e.g. bodies and faces, to Speos geometry properties. + + Parameters + ---------- + geometries : list + a list of SCDM bodies and faces + + Returns + ------- + + + """ + if len(self.geometries_list) == 0: + selection = self.Selection.Create(geometries) + self.speos_object.Geometries.Set(selection.Items) + else: + self.geometries_list.extend(geometries) + selection = self.Selection.Create(self.geometries_list) + self.speos_object.Geometries.Set(selection.Items) + + +# TODO add unittest +class LocalMeshing(GeometryProperties): + """ + Provides methods for defining the Speos LocalMeshing. + """ + + def __init__(self, name, SpeosSim, SpaceClaim): + super(LocalMeshing, self).__init__(name, SpeosSim, SpaceClaim) + if self.speos_sim.LocalMeshing.Find(name): + self.speos_object = self.speos_sim.LocalMeshing.Find(name) + for item in self.speos_object.Geometries.LinkedObjects: + self.geometries_list.append(item) + else: + self.speos_object = self.speos_sim.LocalMeshing.Create() + self.speos_object.Name = name + + def set_sag(self, sag_mode, sag_value): + """ + Define Sag Mode and apply a value on it. + Parameters + ---------- + sag_mode : str + In Sag Meshing, 3 kind of modes are available. + + sag_value : float + Meshing value. Depending of sag_mode value, sag_value might be an int or a float. + + Returns + ------- + + + """ + sag_mode = sag_mode.lower() + if sag_mode == "proportional to face size": + self.speos_object.MeshingSagMode = self.speos_sim.LocalMeshing.EnumMeshingSagMode.ProportionalFace + float(sag_value) + self.speos_object.MeshingSagValue = sag_value + elif sag_mode == "proportional to body size": + self.speos_object.MeshingSagMode = self.speos_sim.LocalMeshing.EnumMeshingSagMode.ProportionalBody + float(sag_value) + self.speos_object.MeshingSagValue = sag_value + elif sag_mode == "fixed": + self.speos_object.MeshingSagMode = self.speos_sim.LocalMeshing.EnumMeshingSagMode.Fixed + float(sag_value) + self.speos_object.MeshingSagValue = sag_value + else: + error_message = "please provide a valid Sag Mode" + raise ValueError(error_message) + + def set_step(self, step_mode, step_value): + """ + Define step values for local meshing. + + Parameters + ---------- + step_mode : str + step mode + step_value : float + step value + + Returns + ------- + + + """ + step_mode = step_mode.lower() + if step_mode == "proportional to face size": + self.speos_object.MeshingStepMode = self.speos_sim.LocalMeshing.EnumMeshingStepMode.ProportionalFace + float(step_value) + self.speos_object.MeshingStepValue = step_value + elif step_mode == "proportional to body size": + self.speos_object.MeshingStepMode = self.speos_sim.LocalMeshing.EnumMeshingStepMode.ProportionalBody + float(step_value) + self.speos_object.MeshingStepValue = step_value + elif step_mode == "fixed": + self.speos_object.MeshingStepMode = self.speos_sim.LocalMeshing.EnumMeshingStepMode.Fixed + float(step_value) + self.speos_object.MeshingStepValue = step_value + else: + error_message = "please provide a valid Sag Mode" + raise ValueError(error_message) + + +class UVMapping(GeometryProperties): + """ + Provides methods for defining the Speos UVMapping. + """ + + def __init__(self, name, SpeosSim, SpaceClaim): + super(UVMapping, self).__init__(name, SpeosSim, SpaceClaim) + if self.speos_sim.LocalMeshing.Find(name): + self.speos_object = self.speos_sim.UVMapping.Find(name) + for item in self.speos_object.Geometries.LinkedObjects: + self.geometries_list.append(item) + else: + self.speos_object = self.speos_sim.UVMapping.Create() + self.speos_object.Name = name diff --git a/ansys_optical_automation/speos_process/speos_sensors.py b/ansys_optical_automation/speos_process/speos_sensors.py index f3b371d1..070263d6 100644 --- a/ansys_optical_automation/speos_process/speos_sensors.py +++ b/ansys_optical_automation/speos_process/speos_sensors.py @@ -679,3 +679,94 @@ def set_fov(self, horizontal_fov, vertical_fov, horizontal_sampling, vertical_sa self.speos_object.VPlane = vertical_fov self.speos_object.HNbSamples = horizontal_sampling self.speos_object.VNbSamples = vertical_sampling + + +class SensorLightField(Sensor): + """ + LightFieldSensor has to be computed after its definition by using command like this: object.Compute() + """ + + def __init__(self, name, SpeosSim, SpaceClaim): + super(SensorLightField, self).__init__(name, SpeosSim, SpaceClaim) + speos_object = self.speos_sim.SensorLightField.Find(self.name) + if not speos_object: + speos_object = self.speos_sim.SensorLightField.Create() + speos_object.Name = name + self.speos_object = speos_object + + def set_faces(self, selection): + # TODO please correct this method and comment section + """ + Make the faces selection and apply them in Lightfield Sensor + Parameters + ---------- + selection : active selection + return a list? + + Returns + ------- + + + """ + face_selection = self.Selection.Create(selection) + self.speos_sim.SensorLightField.OrientedFaces.Set(face_selection.Items) + + def set_type(self, sensor_type): + # TODO double check if everything is fine: Just a copy/past from Radiance sensor set_type function with small + # adaptations + """ + Set Sensor Type for Lightfield sensor. Only Radiometric, Photometric and Spectral are available for it. + Parameters + ---------- + sensor_type : str + return the stype of sensor + + Returns + ------- + + + """ + sensor_type = sensor_type.lower() + if sensor_type == "photometric": + self.speos_object.SensorType = self.speos_sim.SensorLightfield.EnumSensorType.Photometric + elif sensor_type == "radiometric": + self.speos_object.SensorType = self.speos_sim.SensorLightfield.EnumSensorType.Radiometric + elif sensor_type == "spectral": + self.speos_object.SensorType = self.speos_sim.SensorLightfield.EnumSensorType.Spectral + else: + error_message = "please provide a valid Lightfield sensor type" + raise ValueError(error_message) + + def set_sampling(self, incident_sampling=None, azimuth_sampling=None): + """Set the number of samples on the axes. + + Parameters + ---------- + incident_sampling : int, optionl + Number of samples on the incident angle. The default is ``None``. + azimuth_sampling : int + Number of samples on the azimuth_sampling. The default is ``None``. + """ + if not incident_sampling and not azimuth_sampling: + raise NameError("No inputs provided.") + if incident_sampling: + self.speos_object.IncidentAngleSamples = incident_sampling + if azimuth_sampling: + self.speos_object.AzimuthAngleNbSamples = azimuth_sampling + + def set_resolution(self, incident_resolution=None, azimuth_resolution=None): + """Set the number of samples on the axes. + + Parameters + ---------- + incident_resolution : int, optionl + Number of resolution on the incident angle. The default is ``None``. + azimuth_resolution : int + Number of resolution on the azimuth_sampling. The default is ``None``. + """ + if not incident_resolution and not azimuth_resolution: + raise NameError("No inputs provided.") + if incident_resolution: + self.speos_object.IncidentAngleResolution = incident_resolution + if azimuth_resolution: + self.speos_object.AzimuthAngleResolution = azimuth_resolution diff --git a/ansys_optical_automation/speos_process/speos_simulations.py b/ansys_optical_automation/speos_process/speos_simulations.py index f7af4301..026df081 100644 --- a/ansys_optical_automation/speos_process/speos_simulations.py +++ b/ansys_optical_automation/speos_process/speos_simulations.py @@ -268,3 +268,26 @@ def linked_export_simulation(self): save_path, r"SPEOS isolated files", os.path.basename(doc_path).split(".")[0], export_name, export_name ) return sim_path + + def append_source(simulation_name): + """ + Append a list of source in a simulation. + Returns + ------- + + """ + speos_source_list = [] + for items in GetRootPart().CustomObjects: + if items.Type == "SPEOS_SC.SIM.SpeosWrapperSourceSurface": + speos_source_list.append(items) + if items.Type == "SPEOS_SC.SIM.SpeosWrapperSourceRayFile": + speos_source_list.append(items) + else: + print("No Light source found") + + Direct_Sim = SpeosSim.SimulationDirect.Find(simulation_name) + for source_index in range(Direct_Sim.Sources.Count): + source_sim = Direct_Sim.Sources.Item[source_index] + speos_source_list.append(source_sim) + Direct_Sim.Sources.Set(speos_source_list) + return speos_source_list diff --git a/ansys_optical_automation/speos_process/speos_sources.py b/ansys_optical_automation/speos_process/speos_sources.py new file mode 100644 index 00000000..ae3630dc --- /dev/null +++ b/ansys_optical_automation/speos_process/speos_sources.py @@ -0,0 +1,30 @@ +from ansys_optical_automation.scdm_core.base import BaseSCDM + + +class Source(BaseSCDM): + """ + Provides the parent class for all Speos Source types. + + This class contains methods and properties that are common to all Source elements. + It shouldn't be used by itself. Subclasses should be used instead. + """ + + def __init__(self, name, SpeosSim, SpaceClaim): + super(Source, self).__init__(SpaceClaim, ["V19", "V20", "V21", "V22", "V23"]) + self.speos_sim = SpeosSim + self.name = name + self.speos_object = None + + +class SourceLightField(Source): + """ + Provides methods for defining the Speos LocalMeshing. + """ + + def __init__(self, name, SpeosSim, SpaceClaim): + super(SourceLightField, self).__init__(name, SpeosSim, SpaceClaim) + if self.speos_sim.SourceLightField.Find(self.name): + self.speos_object = self.speos_sim.SourceLightField.Find(self.name) + else: + self.speos_object = self.speos_sim.SourceLightField.Create() + self.speos_object.Name = self.name