Source code for blenderproc.python.modules.object.FloorExtractorModule
import warnings
from math import radians
from blenderproc.python.modules.loader.LoaderInterface import LoaderInterface
from blenderproc.python.modules.main.Module import Module
from blenderproc.python.modules.utility.Config import Config
from blenderproc.python.types.MeshObjectUtility import MeshObject
from blenderproc.python.object.FaceSlicer import extract_floor
[docs]class FloorExtractorModule(Module):
"""
Will search for the specified object and splits the surfaces which point upwards at a specified level away
Example 1, in which no height_list_path is set, here the floor is extracted automatically. By finding the group
of polygons with the lowest median in Z direction.
.. code-block:: yaml
{
"module": "object.FloorExtractor",
"config": {
"selector": { # this will select the object, which gets splitt up
"provider": "getter.Entity",
"conditions": {
"name": "wall"
}
},
"compare_angle_degrees" : 7.5, # this is the maximum angle in degree, in which the face can be twisted
"compare_height": 0.15, # the compare height is used after finding the floor
}
}
Example 2, here the ceiling is extracted and not the floor. This is done by using the `up_vector_upwards` key,
which is set to False here, so the polygons have to face in `[0, 0, -1]` direction. This will also flip, the search
mechanism, now the highest group of polygons are used, not the lowest.
.. code-block:: yaml
{
"module": "object.FloorExtractor",
"config": {
"selector": {
"provider": "getter.Entity",
"conditions": {
"name": "wall" # the wall object here contains the ceiling
}
},
"up_vector_upwards": False, # the polygons are now facing downwards: [0, 0, -1]
"compare_angle_degrees" : 7.5,
"compare_height": 0.15,
"name_for_split_obj": "Ceiling" # this is the new name of the object
}
}
Example 3, if you are using this to extract the floor of replica scenes, to place objects on top of them.
.. code-block:: yaml
{
"module": "object.FloorExtractor",
"config": {
"selector": {
"provider": "getter.Entity",
"conditions": {
"name": "mesh" # the wall object here contains the ceiling
}
},
"compare_angle_degrees" : 7.5,
"compare_height": 0.15,
"name_for_split_obj": "floor"
}
}
**Configuration**:
.. list-table::
:widths: 25 100 10
:header-rows: 1
* - Parameter
- Description
- Type
* - selector
- Objects to where all polygons will be extracted.
- Provider
* - compare_angle_degrees
- Maximum difference between the up vector and the current polygon normal in degrees. Default: 7.5.
- float
* - compare_height
- Maximum difference in Z direction between the polygons median point and the specified height of the
room. Default: 0.15.
- float
* - height_list_path
- Path to a file with height values. If none is provided, a ceiling and floor is automatically detected. \
This might fail. The height_list_values can be specified in a list like fashion in the file: [0.0, 2.0]. \
These values are in the same size the dataset is in, which is usually meters. The content must always be \
a list, e.g. [0.0].
- string
* - name_for_split_obj
- Name for the newly created object, which faces fulfill the given parameters. Default: "Floor".
- string
* - up_vector_upwards
- If this is True the `up_vec` points upwards -> [0, 0, 1] if not it points downwards: [0, 0, -1] in world \
coordinates. This vector is used for the `compare_angle_degrees` option. Default: True.
- bool
* - add_properties
- With `add_properties` it is possible to set custom properties for the newly separated objects. Use `cp_` \
prefix for keys.
- dict
* - should_skip_if_object_is_already_there
- If this is true no extraction will be done, if an object is there, which has the same name as
name_for_split_obj, which would be used for the newly created object. Default: False.
- bool
"""
def __init__(self, config):
Module.__init__(self, config)
[docs] def run(self):
""" Extracts floors in the following steps:
1. Searchs for the specified object.
2. Splits the surfaces which point upwards at a specified level away.
"""
mesh_objects = []
for obj in self.config.get_list("selector"):
if obj.type != "MESH":
warnings.warn("The object: {} is not a mesh but was selected in the FloorExtractor!".format(obj.name))
continue
mesh_objects.append(MeshObject(obj))
floors = extract_floor(
mesh_objects=mesh_objects,
compare_angle_degrees=radians(self.config.get_float('compare_angle_degrees', 7.5)),
compare_height=self.config.get_float('compare_height', 0.15),
new_name_for_object=self.config.get_string("name_for_split_obj", "Floor"),
should_skip_if_object_is_already_there=self.config.get_bool("should_skip_if_object_is_already_there", False)
)
add_properties = self.config.get_raw_dict("add_properties", {})
if add_properties:
config = Config({"add_properties": add_properties})
loader_interface = LoaderInterface(config)
loader_interface._set_properties(floors)