mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 09:32:37 +00:00
WIP you can now partially edit the object placement of an object. See #1222.
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
import numpy as np
|
||||||
|
import ifcopenshell.util.placement
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
|
def __init__(self, file, settings=None):
|
||||||
|
self.file = file
|
||||||
|
self.settings = {
|
||||||
|
"product": None,
|
||||||
|
"matrix": np.eye(4)
|
||||||
|
}
|
||||||
|
for key, value in settings.items():
|
||||||
|
self.settings[key] = value
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
|
if not self.settings["product"].ObjectPlacement:
|
||||||
|
placement_rel_to = None
|
||||||
|
else:
|
||||||
|
placement_rel_to = self.settings["product"].ObjectPlacement.PlacementRelTo
|
||||||
|
placement = self.file.createIfcLocalPlacement(
|
||||||
|
placement_rel_to, self.get_relative_placement(placement_rel_to)
|
||||||
|
)
|
||||||
|
self.settings["product"].ObjectPlacement = placement
|
||||||
|
return placement
|
||||||
|
|
||||||
|
def get_relative_placement(self, placement_rel_to):
|
||||||
|
if placement_rel_to:
|
||||||
|
relating_object_matrix = ifcopenshell.util.placement.get_local_placement(placement_rel_to)
|
||||||
|
relating_object_matrix[0][3] = self.convert_unit_to_si(relating_object_matrix[0][3])
|
||||||
|
relating_object_matrix[1][3] = self.convert_unit_to_si(relating_object_matrix[1][3])
|
||||||
|
relating_object_matrix[2][3] = self.convert_unit_to_si(relating_object_matrix[2][3])
|
||||||
|
else:
|
||||||
|
relating_object_matrix = np.eye(4)
|
||||||
|
m = self.settings["matrix"]
|
||||||
|
x = np.array((m[0][0], m[1][0], m[2][0]))
|
||||||
|
z = np.array((m[0][2], m[1][2], m[2][2]))
|
||||||
|
o = np.array((m[0][3], m[1][3], m[2][3]))
|
||||||
|
object_matrix = ifcopenshell.util.placement.a2p(o, z, x)
|
||||||
|
#relative_placement_matrix = relating_object_matrix.inverted() @ object_matrix
|
||||||
|
relative_placement_matrix = relating_object_matrix @ object_matrix
|
||||||
|
return self.create_ifc_axis_2_placement_3d(
|
||||||
|
relative_placement_matrix[:,3][0:3],
|
||||||
|
relative_placement_matrix[:,2][0:3],
|
||||||
|
relative_placement_matrix[:,0][0:3],
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_ifc_axis_2_placement_3d(self, point, up, forward):
|
||||||
|
return self.file.createIfcAxis2Placement3D(
|
||||||
|
self.create_cartesian_point(point),
|
||||||
|
self.file.createIfcDirection(up.tolist()),
|
||||||
|
self.file.createIfcDirection(forward.tolist()),
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_cartesian_point(self, co):
|
||||||
|
co = self.convert_si_to_unit(co)
|
||||||
|
return self.file.createIfcCartesianPoint(co.tolist())
|
||||||
|
|
||||||
|
def convert_si_to_unit(self, co):
|
||||||
|
return co / self.unit_scale
|
||||||
|
|
||||||
|
def convert_unit_to_si(self, co):
|
||||||
|
return co * self.unit_scale
|
||||||
@@ -21,26 +21,13 @@ class Usecase:
|
|||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if self.settings["unit_scale"] is None:
|
if self.settings["unit_scale"] is None:
|
||||||
self.settings["unit_scale"] = self.calculate_unit_scale()
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
if self.settings["context"].ContextType == "Model":
|
if self.settings["context"].ContextType == "Model":
|
||||||
return self.create_model_representation()
|
return self.create_model_representation()
|
||||||
elif self.settings["context"].ContextType == "Plan":
|
elif self.settings["context"].ContextType == "Plan":
|
||||||
return self.create_plan_representation()
|
return self.create_plan_representation()
|
||||||
return self.create_variable_representation()
|
return self.create_variable_representation()
|
||||||
|
|
||||||
def calculate_unit_scale(self):
|
|
||||||
units = self.file.by_type("IfcUnitAssignment")[0]
|
|
||||||
unit_scale = 1
|
|
||||||
for unit in units.Units:
|
|
||||||
if not hasattr(unit, "UnitType") or unit.UnitType != "LENGTHUNIT":
|
|
||||||
continue
|
|
||||||
while unit.is_a("IfcConversionBasedUnit"):
|
|
||||||
unit_scale *= unit.ConversionFactor.ValueComponent.wrappedValue
|
|
||||||
unit = unit.ConversionFactor.UnitComponent
|
|
||||||
if unit.is_a("IfcSIUnit"):
|
|
||||||
unit_scale *= ifcopenshell.util.unit.get_prefix_multiplier(unit.Prefix)
|
|
||||||
return unit_scale
|
|
||||||
|
|
||||||
def create_model_representation(self):
|
def create_model_representation(self):
|
||||||
if self.settings["context"].is_a() == "IfcGeometricRepresentationContext":
|
if self.settings["context"].is_a() == "IfcGeometricRepresentationContext":
|
||||||
return self.create_variable_representation()
|
return self.create_variable_representation()
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import ifcopenshell.util.geolocation
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.schema
|
import ifcopenshell.util.schema
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import numpy as np
|
||||||
from . import export_ifc
|
from . import export_ifc
|
||||||
from . import import_ifc
|
from . import import_ifc
|
||||||
from . import qto
|
from . import qto
|
||||||
@@ -4351,6 +4352,13 @@ class BakeParametricGeometry(bpy.types.Operator):
|
|||||||
self.file = ifc.IfcStore.get_file()
|
self.file = ifc.IfcStore.get_file()
|
||||||
element = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
|
element = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
|
||||||
|
|
||||||
|
import blenderbim.bim.module.geometry.add_object_placement as add_object_placement
|
||||||
|
usecase = add_object_placement.Usecase(self.file, {
|
||||||
|
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
||||||
|
"matrix": np.array(obj.matrix_world)
|
||||||
|
})
|
||||||
|
result = usecase.execute()
|
||||||
|
|
||||||
import blenderbim.bim.module.geometry.add_shape_representation as add_shape_representation
|
import blenderbim.bim.module.geometry.add_shape_representation as add_shape_representation
|
||||||
usecase = add_shape_representation.Usecase(self.file, {
|
usecase = add_shape_representation.Usecase(self.file, {
|
||||||
"context": element.ContextOfItems,
|
"context": element.ContextOfItems,
|
||||||
|
|||||||
@@ -142,3 +142,17 @@ def convert(value, from_prefix, from_unit, to_prefix, to_unit):
|
|||||||
value *= 1 / get_prefix_multiplier(to_prefix)
|
value *= 1 / get_prefix_multiplier(to_prefix)
|
||||||
value *= 1 / get_prefix_multiplier(to_prefix)
|
value *= 1 / get_prefix_multiplier(to_prefix)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_unit_scale(file):
|
||||||
|
units = file.by_type("IfcUnitAssignment")[0]
|
||||||
|
unit_scale = 1
|
||||||
|
for unit in units.Units:
|
||||||
|
if not hasattr(unit, "UnitType") or unit.UnitType != "LENGTHUNIT":
|
||||||
|
continue
|
||||||
|
while unit.is_a("IfcConversionBasedUnit"):
|
||||||
|
unit_scale *= unit.ConversionFactor.ValueComponent.wrappedValue
|
||||||
|
unit = unit.ConversionFactor.UnitComponent
|
||||||
|
if unit.is_a("IfcSIUnit"):
|
||||||
|
unit_scale *= get_prefix_multiplier(unit.Prefix)
|
||||||
|
return unit_scale
|
||||||
|
|||||||
Reference in New Issue
Block a user