Source code for xopto.mcvox.mcsurface.lambertian

# -*- coding: utf-8 -*-
################################ Begin license #################################
# Copyright (C) Laboratory of Imaging technologies,
#               Faculty of Electrical Engineering,
#               University of Ljubljana.
#
# This file is part of PyXOpto.
#
# PyXOpto is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyXOpto is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyXOpto. If not, see <https://www.gnu.org/licenses/>.
################################# End license ##################################

import numpy as np

from xopto.mcvox import mcobject
from xopto.mcvox import cltypes
from .base import SurfaceLayoutAny


[docs]class LambertianReflector(SurfaceLayoutAny):
[docs] @staticmethod def cl_type(mc: mcobject.McObject) -> cltypes.Structure: T = mc.types class ClLambertianReflector(cltypes.Structure): ''' Structure that is passed to the Monte carlo simulator kernel. Fields ------ reflectance: mc_fp_t Total reflectance of the Lambertian reflector. Use a value between 0 and 1. specular: mc_fp_t Fraction of specular reflections. Use a value of 0 for a pure lambertian reflector. ''' _fields_ = [ ('reflectance', T.mc_fp_t), ('specular', T.mc_fp_t) ] return ClLambertianReflector
[docs] def cl_declaration(self, mc: mcobject.McObject) -> str: ''' Structure that defines the reflector in the Monte Carlo simulator. ''' loc = self.location.capitalize() return '\n'.join(( 'struct MC_STRUCT_ATTRIBUTES Mc{}SurfaceLayout{{'.format(loc), ' mc_fp_t reflectance;', ' mc_fp_t specular;', '};' ))
[docs] def cl_implementation(self, mc: mcobject.McObject) -> str: ''' Implementation of the reflector in the Monte Carlo simulator. ''' loc = self.location Loc = loc.capitalize() return '\n'.join(( 'void dbg_print_{}_surface_layout('.format(loc), ' __mc_surface_mem const Mc{}SurfaceLayout *layout){{'.format(Loc), ' dbg_print("Mc{}SurfaceLayout - Lambertian reflector:");'.format(Loc), ' dbg_print_float(INDENT "reflectance:", layout->reflectance);', ' dbg_print_float(INDENT "specular:", layout->specular);', '};', '', 'inline int mcsim_{}_surface_layout_handler('.format(loc), ' McSim *mcsim, mc_fp_t *n2, mc_fp_t *cc){', ' __mc_surface_mem const struct Mc{}SurfaceLayout *layout = '.format(Loc), ' mcsim_{}_surface_layout(mcsim);'.format(loc), ' mc_fp_t sin_fi, cos_fi, sin_theta, cos_theta;', '', ' dbg_print_point3f("{} LambertianReflector hit: ", '.format(Loc), ' mcsim_direction(mcsim));', '', ' if (mcsim_random(mcsim) > layout->specular){', ' dbg_print("{} LambertianReflector: Lambertian reflection");'.format(Loc), ' /* Lambertian reflection */', ' sin_theta = mc_sqrt(mcsim_random(mcsim));', ' cos_theta = mc_sqrt(FP_1 - sin_theta*sin_theta);', '', ' mc_sincos(mcsim_random(mcsim)*FP_2PI, &sin_fi, &cos_fi);', '', ' mcsim_set_direction_coordinates(', ' mcsim,', ' cos_fi*sin_theta,', ' sin_fi*sin_theta,', ' mc_fsign(-mcsim_direction_z(mcsim))*cos_theta', ' );', ' } else {', ' dbg_print("{} LambertianReflector: specular reflection");'.format(Loc), ' /* Specular reflection */', ' mcsim_reverse_direction_z(mcsim);', ' };', '' ' dbg_print_point3f("{} LambertianReflector reflected dir: ", '.format(Loc), ' mcsim_direction(mcsim));', '', ' mcsim_set_weight(mcsim, mcsim_weight(mcsim)*layout->reflectance);', '', ' return MC_REFLECTED;', '};', ))
def __init__(self, reflectance: float = 1.0, specular: float = 0.0): ''' Base class of Lambertian reflectors. Parameters ---------- reflectance: float Total reflectance of the surface. Use a value between 0 and 1. specular: float Fraction of specular reflections at the surface. Use a value of 0 for an ideal Lambertian reflector or a value of 1.0 for an ideal mirror (with the given reflectance). Any value between 0 and 1 will result in surface that is a combination of a Lambertian and specular reflector. ''' super().__init__() self._reflectance = 1.0 self._specular = 0.0 self._set_reflectance(reflectance) self._set_specular(specular) def _get_reflectance(self) -> float: return self._reflectance def _set_reflectance(self, reflectance: float): self._reflectance = min(max(float(reflectance), 0.0), 1.0) reflectance = property(_get_reflectance, _set_reflectance, None, 'Surface reflectance of the Lambertian reflector') def _get_specular(self) -> float: return self._specular_fraction def _set_specular(self, fraction: float): self._specular_fraction = min(max(float(fraction), 0.0), 1.0) specular = property(_get_specular, _set_specular, None, 'Specular fraction of surface reflectance. A value ' 'of 0 indicate an ideal Lambertian reflector, and ' 'a value of 1 a perfect mirror.')
[docs] def cl_pack(self, mc: mcobject.McObject, target: cltypes.Structure = None) \ -> cltypes.Structure: ''' Fills the structure (target) with the data required by the Monte Carlo simulator. See the :py:meth:`LambertianReflector.cl_type` for a detailed list of fields. Parameters ---------- mc: mcobject.McObject Monte Carlo simulator instance. target: cltypes.Structure Structure that is filled with the source data. Returns ------- target: cltypes.Structure Filled ctypes structure received as an input argument or a new instance if the input argument target is None. ''' if target is None: target_type = self.cl_type(mc) target = target_type() target.reflectance = self._reflectance target.specular = self._specular return target
def __str__(self): return 'LambertianReflector(reflectance={}, specular={})'.format( self._reflectance, self._specular) def __repr__(self): return '{} #{}'.format(self.__str__(), id(self))