Resize object to storey now works for a variable number of storeys

This commit is contained in:
Dion Moult
2021-10-28 19:06:27 +11:00
parent 4bb549f3e9
commit d013d6ed09
10 changed files with 50 additions and 31 deletions
@@ -117,6 +117,7 @@ class ResizeToStorey(bpy.types.Operator, Operator):
bl_idname = "bim.resize_to_storey"
bl_label = "Resize To Storey"
bl_options = {"REGISTER", "UNDO"}
total_storeys: bpy.props.IntProperty()
@classmethod
def poll(cls, context):
@@ -124,7 +125,7 @@ class ResizeToStorey(bpy.types.Operator, Operator):
def _execute(self, context):
for obj in context.selected_objects:
core.resize_to_storey(tool.Misc, obj=obj)
core.resize_to_storey(tool.Misc, obj=obj, total_storeys=self.total_storeys)
class SplitAlongEdge(bpy.types.Operator, Operator):
@@ -32,6 +32,7 @@ from bpy.props import (
class BIMMiscProperties(PropertyGroup):
total_storeys: IntProperty(name="Total Storeys", default=1)
override_colour: FloatVectorProperty(
name="Override Colour", subtype="COLOR", default=(1, 0, 0, 1), min=0.0, max=1.0, size=4
)
@@ -38,7 +38,8 @@ class BIM_PT_misc_utilities(bpy.types.Panel):
row.operator("bim.set_viewport_shadow_from_sun")
row = layout.row()
row.operator("bim.snap_spaces_together")
row = layout.row()
row.operator("bim.resize_to_storey")
row = layout.split(factor=0.2, align=True)
row.prop(props, "total_storeys", text="")
row.operator("bim.resize_to_storey").total_storeys = props.total_storeys
row = layout.row()
row.operator("bim.split_along_edge")
+2 -2
View File
@@ -17,11 +17,11 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
def resize_to_storey(misc, obj=None):
def resize_to_storey(misc, obj=None, total_storeys=None):
storey = misc.get_object_storey(obj)
if not storey:
return
height = misc.get_storey_height_in_si(storey)
height = misc.get_storey_height_in_si(storey, total_storeys)
if not height:
return
misc.set_object_origin_to_bottom(obj)
+10 -10
View File
@@ -19,30 +19,30 @@
import blenderbim.core
def assign_container(ifc, collector, container, structure_obj=None, element_obj=None):
if not container.can_contain(structure_obj, element_obj):
def assign_container(ifc, collector, spatial, structure_obj=None, element_obj=None):
if not spatial.can_contain(structure_obj, element_obj):
return
rel = ifc.run(
"spatial.assign_container",
product=ifc.get_entity(element_obj),
relating_structure=ifc.get_entity(structure_obj),
)
container.disable_editing(element_obj)
spatial.disable_editing(element_obj)
collector.assign(element_obj)
return rel
def enable_editing_container(container, obj=None):
container.enable_editing(obj)
container.import_containers()
def enable_editing_container(spatial, obj=None):
spatial.enable_editing(obj)
spatial.import_containers()
def disable_editing_container(container, obj=None):
container.disable_editing(obj)
def disable_editing_container(spatial, obj=None):
spatial.disable_editing(obj)
def change_spatial_level(container, parent=None):
container.import_containers(parent=parent)
def change_spatial_level(spatial, parent=None):
spatial.import_containers(parent=parent)
def remove_container(ifc, collector, obj=None):
+1 -1
View File
@@ -101,7 +101,7 @@ class Material:
class Misc:
def get_object_storey(cls, obj): pass
def get_storey_elevation_in_si(cls, storey): pass
def get_storey_height_in_si(cls, storey): pass
def get_storey_height_in_si(cls, storey, total_storeys): pass
def mark_object_as_edited(cls, obj): pass
def move_object_to_elevation(cls, obj, elevation): pass
def run_root_copy_class(cls, obj=None): pass
+4 -6
View File
@@ -40,7 +40,7 @@ class Misc(blenderbim.core.tool.Misc):
return elevation * unit_scale
@classmethod
def get_storey_height_in_si(cls, storey):
def get_storey_height_in_si(cls, storey, total_storeys):
building = ifcopenshell.util.element.get_aggregate(storey)
related_objects = []
for rel in building.IsDecomposedBy:
@@ -50,14 +50,12 @@ class Misc(blenderbim.core.tool.Misc):
related_objects.append((element, ifcopenshell.util.placement.get_storey_elevation(element)))
related_objects = sorted(related_objects, key=lambda e: e[1])
storey_elevation = None
next_storey_elevation = None
for related_object in related_objects:
for i, related_object in enumerate(related_objects):
if related_object[0] == storey:
storey_elevation = related_object[1]
elif storey_elevation is not None:
next_storey_elevation = related_object[1]
break
if next_storey_elevation:
if i + total_storeys < len(related_objects):
next_storey_elevation = related_objects[i + total_storeys][1]
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
return (next_storey_elevation - storey_elevation) * unit_scale
+1 -1
View File
@@ -33,7 +33,7 @@ Scenario: Resize to storey
And the object "IfcWall/Cube" is selected
And the variable "storey" is "tool.Ifc.get().by_type('IfcBuildingStorey')[0].id()"
And I press "bim.assign_container(structure={storey})"
When I press "bim.resize_to_storey"
When I press "bim.resize_to_storey(total_storeys=1)"
Then nothing happens
Scenario: Split along edge
+5 -5
View File
@@ -24,21 +24,21 @@ class TestResizeToStorey:
def test_run(self, misc):
misc.get_object_storey("obj").should_be_called().will_return("storey")
misc.get_storey_elevation_in_si("storey").should_be_called().will_return("elevation")
misc.get_storey_height_in_si("storey").should_be_called().will_return("height")
misc.get_storey_height_in_si("storey", 1).should_be_called().will_return("height")
misc.set_object_origin_to_bottom("obj").should_be_called()
misc.move_object_to_elevation("obj", "elevation").should_be_called()
misc.scale_object_to_height("obj", "height").should_be_called()
misc.mark_object_as_edited("obj").should_be_called()
subject.resize_to_storey(misc, obj="obj")
subject.resize_to_storey(misc, obj="obj", total_storeys=1)
def test_doing_nothing_when_the_object_has_no_storey(self, misc):
misc.get_object_storey("obj").should_be_called().will_return(None)
subject.resize_to_storey(misc, obj="obj")
subject.resize_to_storey(misc, obj="obj", total_storeys=1)
def test_doing_nothing_when_the_storey_has_no_height(self, misc):
misc.get_object_storey("obj").should_be_called().will_return("storey")
misc.get_storey_height_in_si("storey").should_be_called().will_return(None)
subject.resize_to_storey(misc, obj="obj")
misc.get_storey_height_in_si("storey", 1).should_be_called().will_return(None)
subject.resize_to_storey(misc, obj="obj", total_storeys=1)
class TestSplitAlongEdge:
+21 -3
View File
@@ -88,7 +88,25 @@ class TestGetStoreyHeight(test.bim.bootstrap.NewFile):
storey2.Elevation = 5000
ifcopenshell.api.run("aggregate.assign_object", ifc, product=storey, relating_object=building)
ifcopenshell.api.run("aggregate.assign_object", ifc, product=storey2, relating_object=building)
assert subject.get_storey_height_in_si(storey) == 2.0
assert subject.get_storey_height_in_si(storey, 1) == 2.0
def test_getting_a_double_storey_height(self):
ifc = ifcopenshell.file()
ifc.createIfcProject()
unit = ifcopenshell.api.run("unit.add_si_unit", ifc, prefix="MILLI")
ifcopenshell.api.run("unit.assign_unit", ifc, units=[unit])
tool.Ifc.set(ifc)
building = ifc.createIfcBuilding()
storey = ifc.createIfcBuildingStorey()
storey.Elevation = 3000
storey2 = ifc.createIfcBuildingStorey()
storey2.Elevation = 5000
storey3 = ifc.createIfcBuildingStorey()
storey3.Elevation = 9000
ifcopenshell.api.run("aggregate.assign_object", ifc, product=storey, relating_object=building)
ifcopenshell.api.run("aggregate.assign_object", ifc, product=storey2, relating_object=building)
ifcopenshell.api.run("aggregate.assign_object", ifc, product=storey3, relating_object=building)
assert subject.get_storey_height_in_si(storey, 2) == 6.0
def test_only_considering_storeys_in_the_same_building(self):
ifc = ifcopenshell.file()
@@ -99,7 +117,7 @@ class TestGetStoreyHeight(test.bim.bootstrap.NewFile):
storey2 = ifc.createIfcBuildingStorey()
storey2.Elevation = 5000
ifcopenshell.api.run("aggregate.assign_object", ifc, product=storey, relating_object=building)
assert subject.get_storey_height_in_si(storey) is None
assert subject.get_storey_height_in_si(storey, 1) is None
def test_returning_none_if_the_storey_height_is_undefined(self):
ifc = ifcopenshell.file()
@@ -107,7 +125,7 @@ class TestGetStoreyHeight(test.bim.bootstrap.NewFile):
building = ifc.createIfcBuilding()
storey = ifc.createIfcBuildingStorey()
ifcopenshell.api.run("aggregate.assign_object", ifc, product=storey, relating_object=building)
assert subject.get_storey_height_in_si(storey) is None
assert subject.get_storey_height_in_si(storey, 1) is None
class TestSetObjectOriginToBottom(test.bim.bootstrap.NewFile):