Source code for blenderproc.python.filter.Filter

"""Filter classes to filter entities based on certain attributes"""

from typing import Any, Type, List
import re

import numpy as np

from blenderproc.python.types.StructUtility import Struct


[docs] def all_with_type(elements: List[Struct], filtered_data_type: Type[Struct] = None) -> List[Struct]: """ Returns all elements from the given list having a given type. :param elements: A list of elements. :param filtered_data_type: If not None, only elements from the given type are returned. :return: All mesh objects from the given list. """ if filtered_data_type is not None: return list(filter(lambda x: isinstance(x, filtered_data_type), elements)) return elements
[docs] def by_attr(elements: List[Struct], attr_name: str, value: Any, filtered_data_type: Type[Struct] = None, regex: bool = False) -> List[Struct]: """ Returns all elements from the given list whose specified attribute has the given value. :param elements: A list of elements. :param attr_name: The name of the attribute to look for. :param value: The value the attribute should have. :param filtered_data_type: If not None, only elements from the given type are returned. :param regex: If True, string values will be matched via regex. :return: The elements from the given list that match the given value at the specified attribute. """ elements = all_with_type(elements, filtered_data_type) return list(filter(lambda struct: _Filter.check_equality(struct.get_attr(attr_name), value, regex), elements))
[docs] def one_by_attr(elements: List[Struct], attr_name: str, value: Any, filtered_data_type: Type[Struct] = None, regex: bool = False) -> Struct: """ Returns the one element from the given list whose specified attribute has the given value. An error is thrown is more than one or no element has been found. :param elements: A list of elements. :param attr_name: The name of the attribute to look for. :param value: The value the attribute should have. :param filtered_data_type: If not None, only elements from the given type are returned. :param regex: If True, string values will be matched via regex. :return: The one element from the given list that matches the given value at the specified attribute. """ elements = by_attr(elements, attr_name, value, filtered_data_type, regex) return _Filter.check_list_has_length_one(elements)
[docs] def by_cp(elements: List[Struct], cp_name: str, value: Any, filtered_data_type: Type[Struct] = None, regex: bool = False) -> List[Struct]: """ Returns all elements from the given list whose specified custom property has the given value. :param elements: A list of elements. :param cp_name: The name of the custom property to look for. :param value: The value the custom property should have. :param filtered_data_type: If not None, only elements from the given type are returned. :param regex: If True, string values will be matched via regex. :return: The elements from the given list that match the given value at the specified custom property. """ elements = all_with_type(elements, filtered_data_type) return list( filter(lambda struct: struct.has_cp(cp_name) and _Filter.check_equality(struct.get_cp(cp_name), value, regex), elements))
[docs] def one_by_cp(elements: List[Struct], cp_name: str, value: Any, filtered_data_type: Type[Struct] = None, regex: bool = False) -> Struct: """ Returns the one element from the given list whose specified custom property has the given value. An error is thrown is more than one or no element has been found. :param elements: A list of elements. :param cp_name: The name of the custom property to look for. :param value: The value the custom property should have. :param filtered_data_type: If not None, only elements from the given type are returned. :param regex: If True, string values will be matched via regex. :return: The one element from the given list that matches the given value at the specified custom property. """ elements = by_cp(elements, cp_name, value, filtered_data_type, regex) return _Filter.check_list_has_length_one(elements)
[docs] def by_attr_in_interval(elements: List[Struct], attr_name: str, min_value: Any = None, max_value: Any = None, filtered_data_type: Type[Struct] = None) -> List[Struct]: """ Returns all elements from the given list whose specified attribute has a value in the given interval (including the boundaries). :param elements: A list of elements. :param attr_name: The name of the attribute to look for. :param min_value: The minimum value of the interval. :param max_value: The maximum value of the interval. :param filtered_data_type: If not None, only elements from the given type are returned. :return: The elements from the given list that match the given value at the specified attribute. """ elements = all_with_type(elements, filtered_data_type) return list(filter(lambda struct: (min_value is None or min_value <= struct.get_attr(attr_name)) and ( max_value is None or max_value >= struct.get_attr(attr_name)), elements))
[docs] def by_attr_outside_interval(elements: List[Struct], attr_name: str, min_value: Any = None, max_value: Any = None, filtered_data_type: Type[Struct] = None) -> List[Struct]: """ Returns all elements from the given list whose specified attribute has a value outside the given interval. :param elements: A list of elements. :param attr_name: The name of the attribute to look for. :param min_value: The minimum value of the interval. :param max_value: The maximum value of the interval. :param filtered_data_type: If not None, only elements from the given type are returned. :return: The elements from the given list that match the given value at the specified attribute. """ elements = all_with_type(elements, filtered_data_type) in_interval = by_attr_in_interval(elements, attr_name, min_value, max_value) return [e for e in elements if e not in in_interval]
[docs] class _Filter: """Static class for filtering elements based on different elements. """
[docs] @staticmethod def check_list_has_length_one(elements: List[Any]) -> Any: """ Checks if the given list only contains one element and returns it. :param elements: The list of elements to check. :return: The one element of the list. """ if len(elements) > 1: raise Exception("More than one element with the given condition has been found.") if len(elements) == 0: raise Exception("No element with the given condition has been found.") return elements[0]
[docs] @staticmethod def check_equality(attr_value: Any, filter_value: Any, regex: bool = False) -> bool: """ Checks whether the two values are equal. If the values have multiple elements, they must all match (uses broadcasting). :param attr_value: The first value. :param filter_value: The second value. :param regex: If True, string values will be matched via regex. :return: True, if the two values are equal. """ # If desired do regex matching for strings if isinstance(attr_value, str) and regex: return re.fullmatch(filter_value, attr_value) try: return np.all(np.array(filter_value) == np.array(attr_value)) except Exception as e: raise RuntimeError(f'Could not broadcast attribute {attr_value} with shape {np.array(attr_value).shape} ' f'to filter_value {filter_value} with shape {np.array(filter_value).shape}!') from e