<commit_before>from .materials import Material
from .logging_unit import logger
from .math import correct_normal

EPSILON = 1E-6

class Scene:
    """
    Class used to define the Scene. It encodes all the objects
    that interfere with light rays.
    """

    def __init__(self, objects):
        self.faces = []  # All the faces in the Scene
        self.solids = []  # All the solids in the Scene
        self.name_of_solid = {}
        self.materials = {}  # Assign the materials to objects
        self.boundaries = {}  # Assign boundary faces to solids
        # self.sum_energy = 0.0 # Energy of the Scene
        self.epsilon = EPSILON # Tolerance for solid containment # 2 nm.
        self.boundbox = None

        for obj in objects:
            # noinspection PyNoneFunctionAssignment
            material = Material.get_from_label(obj.Label)
            if not material:
                logger.info("Material not found for object %s", obj.Label)
                continue
            solids = obj.Shape.Solids
            faces = obj.Shape.Faces
            if solids:  # Object is a solid
                for solid in solids:
                    self.name_of_solid[solid] = obj.Label
                    self.materials[solid] = material
            else:  # Object is made of faces
                for face in faces:
                    self.materials[face] = material
            self.solids.extend(solids)
            self.faces.extend(faces)
            # self.materials[obj] = material ## Cal?
            if not self.boundbox:
                self.boundbox = obj.Shape.BoundBox
            else:
                self.boundbox.add(obj.Shape.BoundBox)

        self.remove_duplicate_faces()

        for solid in self.solids:
            self.boundaries[solid] = []
            for face in self.faces:
                if len(solid.common(face).Faces) > 0:
                    self.boundaries[solid].append(face)

        self.diameter = self.boundbox.DiagonalLength

    def remove_duplicate_faces(self):
        faces_with_material = [face for face in self.faces if
                               face in self.materials]
        faces_no_material = [face for face in self.faces if
                             face not in self.materials]
        if not faces_no_material:
            return
        complex_no_material = faces_no_material[0]
        for face in faces_no_material[1:]:
            complex_no_material = complex_no_material.fuse(face)
        for face in faces_with_material:
            complex_no_material = complex_no_material.cut(face)
        self.faces = faces_with_material
        self.faces.extend(complex_no_material.Faces)

    def solid_at_point(self, point):
        """
        Returns the solid that a point is inside.
        """
        for solid in self.solids:
            if solid.isInside(point, self.epsilon, False):
                return solid
        return None

    def face_at_point(self, point):
        """
        Returns the face that a point is inside.
        """
        for face in self.faces:
            if face.isInside(point, self.epsilon, True):
                return face
        return None

    def next_solid_at_point_in_direction(self, point, normal, direction):
        external_normal = correct_normal(normal, direction)
        point_plus_epsilon = point + external_normal * (-2) * self.epsilon
        return self.solid_at_point(point_plus_epsilon)<commit_msg>renamed epsilon in scee.py. changed factor for next solid<commit_after>from .materials import Material
from .logging_unit import logger
from .math import correct_normal

SCENE_EPSILON = 1E-6

class Scene:
    """
    Class used to define the Scene. It encodes all the objects
    that interfere with light rays.
    """

    def __init__(self, objects):
        self.faces = []  # All the faces in the Scene
        self.solids = []  # All the solids in the Scene
        self.name_of_solid = {}
        self.materials = {}  # Assign the materials to objects
        self.boundaries = {}  # Assign boundary faces to solids
        # self.sum_energy = 0.0 # Energy of the Scene
        self.epsilon = SCENE_EPSILON # Tolerance for solid/face containment Default 1 nm.
        self.boundbox = None

        for obj in objects:
            # noinspection PyNoneFunctionAssignment
            material = Material.get_from_label(obj.Label)
            if not material:
                logger.info("Material not found for object %s", obj.Label)
                continue
            solids = obj.Shape.Solids
            faces = obj.Shape.Faces
            if solids:  # Object is a solid
                for solid in solids:
                    self.name_of_solid[solid] = obj.Label
                    self.materials[solid] = material
            else:  # Object is made of faces
                for face in faces:
                    self.materials[face] = material
            self.solids.extend(solids)
            self.faces.extend(faces)
            # self.materials[obj] = material ## Cal?
            if not self.boundbox:
                self.boundbox = obj.Shape.BoundBox
            else:
                self.boundbox.add(obj.Shape.BoundBox)

        self.remove_duplicate_faces()

        for solid in self.solids:
            self.boundaries[solid] = []
            for face in self.faces:
                if len(solid.common(face).Faces) > 0:
                    self.boundaries[solid].append(face)

        self.diameter = self.boundbox.DiagonalLength

    def remove_duplicate_faces(self):
        faces_with_material = [face for face in self.faces if
                               face in self.materials]
        faces_no_material = [face for face in self.faces if
                             face not in self.materials]
        if not faces_no_material:
            return
        complex_no_material = faces_no_material[0]
        for face in faces_no_material[1:]:
            complex_no_material = complex_no_material.fuse(face)
        for face in faces_with_material:
            complex_no_material = complex_no_material.cut(face)
        self.faces = faces_with_material
        self.faces.extend(complex_no_material.Faces)

    def solid_at_point(self, point):
        """
        Returns the solid that a point is inside.
        """
        for solid in self.solids:
            if solid.isInside(point, self.epsilon, False):
                return solid
        return None

    def face_at_point(self, point):
        """
        Returns the face that a point is inside.
        """
        for face in self.faces:
            if face.isInside(point, self.epsilon, True):
                return face
        return None

    def next_solid_at_point_in_direction(self, point, normal, direction):
        external_normal = correct_normal(normal, direction)
        point_plus_epsilon = point + external_normal * (-1) * self.epsilon
        return self.solid_at_point(point_plus_epsilon)
{'fraction_non_alphanumeric': 0.07390366642703092, 'fraction_numerical': 0.0025880661394680087, 'mean_word_length': 1.8438266557645135, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3985195', 'n_tokens_mistral': 1940, 'n_tokens_neox': 1831, 'n_words': 528}