Minor fix where you'd randomly get incorrect ports connected based on the first birdsong of spring

This commit is contained in:
Dion Moult
2025-03-14 14:41:14 +11:00
parent 8f6cd18288
commit 069b630b16
4 changed files with 57 additions and 6 deletions
+7 -3
View File
@@ -921,11 +921,11 @@ class MEPAddBend(bpy.types.Operator, tool.Ifc.Operator):
start_element = tool.Ifc.get_entity(start_object)
end_element = tool.Ifc.get_entity(end_object)
if not start_element or not end_element:
self.report({"ERROR"}, f"Two IFC elements should be selected for the bend.")
self.report({"ERROR"}, "Two IFC elements should be selected for the bend.")
return {"CANCELLED"}
else:
self.report({"ERROR"}, f"Two IFC elements should be provided for the bend.")
self.report({"ERROR"}, "Two IFC elements should be provided for the bend.")
return {"CANCELLED"}
# check rotation difference
@@ -1248,10 +1248,14 @@ class MEPAddBend(bpy.types.Operator, tool.Ifc.Operator):
return matrix
fitting_obj.matrix_world = get_fitting_matrix()
tool.Model.sync_object_ifc_position(fitting_obj)
# add ports and connect them
ports = tool.System.get_ports(tool.Ifc.get_entity(fitting_obj))
if not start_port_match:
start_co = ifcopenshell.util.placement.get_local_placement(start_port.ObjectPlacement)[:,3]
port0_co = ifcopenshell.util.placement.get_local_placement(ports[0].ObjectPlacement)[:,3]
# We cannot use start_port_match because tool.System.get_ports is unordered
if not np.allclose(start_co, port0_co):
start_port, end_port = end_port, start_port
tool.Ifc.run("system.connect_port", port1=ports[0], port2=start_port, direction="NOTDEFINED")
tool.Ifc.run("system.connect_port", port1=ports[1], port2=end_port, direction="NOTDEFINED")
@@ -495,15 +495,16 @@ class AddOccurrence(bpy.types.Operator, tool.Ifc.Operator):
elif props.rl_mode == "CURSOR":
pass
tool.Model.sync_object_ifc_position(obj)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
for port in ifcopenshell.util.system.get_ports(relating_type):
mat = Matrix(ifcopenshell.util.placement.get_local_placement(port.ObjectPlacement))
mat.translation *= unit_scale
mat = obj.matrix_world @ mat
new_port = tool.Ifc.run("root.create_entity", ifc_class="IfcDistributionPort")
new_port = tool.Ifc.run("system.add_port", element=element)
new_port.PredefinedType = port.PredefinedType
new_port.SystemType = port.SystemType
tool.Ifc.run("system.assign_port", element=element, port=new_port)
tool.Ifc.run("geometry.edit_object_placement", product=new_port, matrix=mat, is_si=True)
if ifc_class == "IfcDoorType" and len(context.selected_objects) >= 1:
@@ -159,6 +159,45 @@ Scenario: Connect MEP elements
And the object "IfcActuator/Actuator" is at "5.5,0.0,1.0"
And the variable "connected_elements" is "set(tool.System.get_connected_elements({ifc}.by_type('IfcActuator')[0]))"
Scenario: Add bend - and regenerate with no changes
Given an empty IFC project
And I create default MEP types
And the variable "segment_types" is "[str(e.id()) for e in {ifc}.by_type('IfcDuctSegmentType')]"
And the variable "actuator_type_id" is "{ifc}.by_type('IfcActuatorType')[0].id()"
# segment1
And I set "scene.BIMModelProperties.ifc_class" to "IfcDuctSegmentType"
And I set "scene.BIMModelProperties.relating_type_id" to "{segment_types}[0]"
And I set "scene.BIMModelProperties.extrusion_depth" to "5.0"
And I press "bim.add_occurrence"
And I rename the object "IfcDuctSegment/DuctSegment" to "IfcDuctSegment/Seg1"
# segment2
And I set "scene.BIMModelProperties.relating_type_id" to "{segment_types}[0]"
And I press "bim.add_occurrence"
And I rename the object "IfcDuctSegment/DuctSegment" to "IfcDuctSegment/Seg2"
And the object "IfcDuctSegment/Seg2" is rotated by "0,0,90" deg
# bend between segments 1 and 2
When the object "IfcDuctSegment/Seg1" is selected
And additionally the object "IfcDuctSegment/Seg2" is selected
And I press "bim.mep_add_bend"
Then the object "IfcDuctSegment/Seg1" is at "0.5,0,1"
And the object "IfcDuctSegment/Seg2" is at "0,0.5,1"
And the object "IfcDuctFitting/DuctFitting" is at "0,0.5,1"
And the object "IfcDuctFitting/DuctFitting" dimensions are "0.7,0.2,0.7"
And the object "IfcDuctSegment/Seg1" dimensions are "0.4,0.2,4.5"
And the object "IfcDuctSegment/Seg2" dimensions are "0.4,0.2,4.5"
When I press "bim.regenerate_distribution_element"
Then the object "IfcDuctSegment/Seg1" is at "0.5,0,1"
And the object "IfcDuctSegment/Seg2" is at "0,0.5,1"
And the object "IfcDuctFitting/DuctFitting" is at "0,0.5,1"
And the object "IfcDuctFitting/DuctFitting" dimensions are "0.7,0.2,0.7"
And the object "IfcDuctSegment/Seg1" dimensions are "0.4,0.2,4.5"
And the object "IfcDuctSegment/Seg2" dimensions are "0.4,0.2,4.5"
Scenario: Connect MEP elements and regenerate
Given an empty IFC project
And I create default MEP types
+8 -1
View File
@@ -1200,7 +1200,7 @@ def the_object_name_is_at_location(name, location):
obj_location = the_object_name_exists(name).location
assert (
obj_location - Vector([float(co) for co in location.split(",")])
).length < 0.1, f"Object is at {obj_location}"
).length < 0.1, f"Object is at {obj_location} instead of {location}"
@then(parsers.parse('the object "{name}" has a vertex at "{location}"'))
@@ -1451,6 +1451,13 @@ def run_test_code():
pass
@given(parsers.parse("I fail"))
@when(parsers.parse("I fail"))
@then(parsers.parse("I fail"))
def i_fail():
assert False
@given(parsers.parse("I save sample test files"))
@when(parsers.parse("I save sample test files"))
@then(parsers.parse("I save sample test files"))