mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 02:07:36 +00:00
Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into presentationlayer
This commit is contained in:
@@ -7,7 +7,7 @@ For more information, see
|
|||||||
* [http://ifcopenshell.org](http://ifcopenshell.org)
|
* [http://ifcopenshell.org](http://ifcopenshell.org)
|
||||||
* [http://academy.ifcopenshell.org](http://academy.ifcopenshell.org)
|
* [http://academy.ifcopenshell.org](http://academy.ifcopenshell.org)
|
||||||
|
|
||||||
[](https://api.travis-ci.org/IfcOpenShell/IfcOpenShell)
|
[](https://travis-ci.org/IfcOpenShell/IfcOpenShell)
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
-------------
|
-------------
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ if bpy is not None:
|
|||||||
operator.AddMaterialLayer,
|
operator.AddMaterialLayer,
|
||||||
operator.RemoveMaterialLayer,
|
operator.RemoveMaterialLayer,
|
||||||
operator.MoveMaterialLayer,
|
operator.MoveMaterialLayer,
|
||||||
|
operator.AddMaterialConstituent,
|
||||||
|
operator.RemoveMaterialConstituent,
|
||||||
|
operator.MoveMaterialConstituent,
|
||||||
operator.AddConstraint,
|
operator.AddConstraint,
|
||||||
operator.RemoveConstraint,
|
operator.RemoveConstraint,
|
||||||
operator.AssignConstraint,
|
operator.AssignConstraint,
|
||||||
@@ -169,6 +172,7 @@ if bpy is not None:
|
|||||||
operator.PropagateTextData,
|
operator.PropagateTextData,
|
||||||
operator.PushRepresentation,
|
operator.PushRepresentation,
|
||||||
operator.ConvertLocalToGlobal,
|
operator.ConvertLocalToGlobal,
|
||||||
|
operator.ConvertGlobalToLocal,
|
||||||
operator.GuessQuantity,
|
operator.GuessQuantity,
|
||||||
operator.ExecuteBIMTester,
|
operator.ExecuteBIMTester,
|
||||||
operator.BIMTesterPurge,
|
operator.BIMTesterPurge,
|
||||||
@@ -212,6 +216,8 @@ if bpy is not None:
|
|||||||
operator.UpdateIfcRepresentation,
|
operator.UpdateIfcRepresentation,
|
||||||
prop.StrProperty,
|
prop.StrProperty,
|
||||||
prop.MaterialLayer,
|
prop.MaterialLayer,
|
||||||
|
prop.MaterialConstituent,
|
||||||
|
prop.MaterialSet,
|
||||||
prop.Variable,
|
prop.Variable,
|
||||||
prop.Role,
|
prop.Role,
|
||||||
prop.Address,
|
prop.Address,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import csv
|
import csv
|
||||||
|
import bmesh
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
@@ -426,19 +427,14 @@ class IfcParser:
|
|||||||
for constraint in obj.BIMObjectProperties.constraints:
|
for constraint in obj.BIMObjectProperties.constraints:
|
||||||
self.rel_associates_constraint_object.setdefault(constraint.name, []).append(product)
|
self.rel_associates_constraint_object.setdefault(constraint.name, []).append(product)
|
||||||
|
|
||||||
for slot in obj.material_slots:
|
if obj.BIMObjectProperties.material_type == "IfcMaterial" and obj.BIMObjectProperties.material:
|
||||||
if slot.material is None or slot.link == "OBJECT":
|
self.rel_associates_material.setdefault(obj.BIMObjectProperties.material.name, []).append(product)
|
||||||
continue
|
elif obj.BIMObjectProperties.material_type == "IfcMaterialConstituentSet":
|
||||||
if obj.BIMObjectProperties.material_type == "IfcMaterialLayerSet":
|
self.rel_associates_material_constituent_set[self.product_index] = obj.BIMObjectProperties.material_set
|
||||||
self.rel_associates_material_layer_set.setdefault(self.product_index, []).append(slot.material.name)
|
elif obj.BIMObjectProperties.material_type == "IfcMaterialLayerSet":
|
||||||
elif obj.BIMObjectProperties.material_type == "IfcMaterialConstituentSet":
|
self.rel_associates_material_layer_set[self.product_index] = obj.BIMObjectProperties.material_set
|
||||||
self.rel_associates_material_constituent_set.setdefault(self.product_index, []).append(
|
elif obj.BIMObjectProperties.material_type == "IfcMaterialProfileSet":
|
||||||
slot.material.name
|
pass # TODO
|
||||||
)
|
|
||||||
elif obj.BIMObjectProperties.material_type == "IfcMaterialProfileSet":
|
|
||||||
self.rel_associates_material_profile_set.setdefault(self.product_index, []).append(slot.material.name)
|
|
||||||
else:
|
|
||||||
self.rel_associates_material.setdefault(slot.material.name, []).append(product)
|
|
||||||
|
|
||||||
return product
|
return product
|
||||||
|
|
||||||
@@ -1157,7 +1153,7 @@ class IfcParser:
|
|||||||
continue
|
continue
|
||||||
results[slot.material.name] = {
|
results[slot.material.name] = {
|
||||||
"ifc": None,
|
"ifc": None,
|
||||||
"part_ifc": None,
|
"part_ifc": None, # TODO: check if we deprecate this
|
||||||
"raw": slot.material,
|
"raw": slot.material,
|
||||||
"material_type": obj.BIMObjectProperties.material_type,
|
"material_type": obj.BIMObjectProperties.material_type,
|
||||||
"attributes": self.get_material_attributes(slot.material),
|
"attributes": self.get_material_attributes(slot.material),
|
||||||
@@ -2951,6 +2947,14 @@ class IfcExporter:
|
|||||||
mesh = representation["raw"]
|
mesh = representation["raw"]
|
||||||
if not representation["is_parametric"]:
|
if not representation["is_parametric"]:
|
||||||
mesh = representation["raw_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
mesh = representation["raw_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
||||||
|
if self.ifc_export_settings.should_force_triangulation:
|
||||||
|
mesh = representation["raw_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
||||||
|
bm = bmesh.new()
|
||||||
|
bm.from_mesh(mesh)
|
||||||
|
bmesh.ops.triangulate(bm, faces=bm.faces)
|
||||||
|
bm.to_mesh(mesh)
|
||||||
|
bm.free()
|
||||||
|
del bm
|
||||||
if self.schema_version == "IFC2X3" or self.ifc_export_settings.should_force_faceted_brep:
|
if self.schema_version == "IFC2X3" or self.ifc_export_settings.should_force_faceted_brep:
|
||||||
return self.create_faceted_brep(representation, mesh)
|
return self.create_faceted_brep(representation, mesh)
|
||||||
return self.create_polygonal_face_set(representation, mesh)
|
return self.create_polygonal_face_set(representation, mesh)
|
||||||
@@ -3137,17 +3141,27 @@ class IfcExporter:
|
|||||||
def relate_objects_to_material_sets(self, set_type):
|
def relate_objects_to_material_sets(self, set_type):
|
||||||
if not self.ifc_export_settings.has_representations:
|
if not self.ifc_export_settings.has_representations:
|
||||||
return
|
return
|
||||||
for product_index, related_materials in getattr(
|
for product_index, material_set in getattr(self.ifc_parser, f"rel_associates_material_{set_type}_set").items():
|
||||||
self.ifc_parser, f"rel_associates_material_{set_type}_set"
|
if set_type == "constituent":
|
||||||
).items():
|
materials = self.create_material_constituents(material_set.material_constituents)
|
||||||
material_set = self.file.create_entity(
|
elif set_type == "layer":
|
||||||
f"IfcMaterial{set_type.capitalize()}Set",
|
materials = self.create_material_layers(material_set.material_layers)
|
||||||
**{
|
elif set_type == "profile":
|
||||||
f"Material{set_type.capitalize()}s": [
|
materials = [] # TODO
|
||||||
self.ifc_parser.materials[m]["part_ifc"] for m in related_materials
|
if not materials:
|
||||||
]
|
continue
|
||||||
},
|
|
||||||
)
|
attributes = {
|
||||||
|
f"Material{set_type.capitalize()}s": materials,
|
||||||
|
"Description": material_set.description or None,
|
||||||
|
}
|
||||||
|
|
||||||
|
if set_type == "layer":
|
||||||
|
attributes["LayerSetName"] = material_set.name or None
|
||||||
|
else:
|
||||||
|
attributes["Name"] = material_set.name or None
|
||||||
|
|
||||||
|
material_set = self.file.create_entity(f"IfcMaterial{set_type.capitalize()}Set", **attributes)
|
||||||
self.file.createIfcRelAssociatesMaterial(
|
self.file.createIfcRelAssociatesMaterial(
|
||||||
ifcopenshell.guid.new(),
|
ifcopenshell.guid.new(),
|
||||||
self.owner_history,
|
self.owner_history,
|
||||||
@@ -3157,6 +3171,50 @@ class IfcExporter:
|
|||||||
material_set,
|
material_set,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def create_material_layers(self, layers):
|
||||||
|
results = []
|
||||||
|
for layer in layers:
|
||||||
|
if layer.category == "None":
|
||||||
|
category = None
|
||||||
|
elif layer.category == "Custom":
|
||||||
|
category = layer.custom_category or None
|
||||||
|
else:
|
||||||
|
category = layer.category
|
||||||
|
is_ventilated = layer.is_ventilated == "TRUE" if layer.is_ventilated != "UNKNOWN" else None
|
||||||
|
results.append(
|
||||||
|
self.file.create_entity(
|
||||||
|
"IfcMaterialLayer",
|
||||||
|
**{
|
||||||
|
"Material": self.ifc_parser.materials[layer.material.name]["ifc"] or None,
|
||||||
|
"LayerThickness": layer.layer_thickness,
|
||||||
|
"IsVentilated": is_ventilated,
|
||||||
|
"Name": layer.name or None,
|
||||||
|
"Description": layer.description or None,
|
||||||
|
"Category": category,
|
||||||
|
"Priority": layer.priority,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return results
|
||||||
|
|
||||||
|
def create_material_constituents(self, constituents):
|
||||||
|
results = []
|
||||||
|
# TODO: the correlation for IfcShapeAspect is not yet implemented
|
||||||
|
for constituent in constituents:
|
||||||
|
results.append(
|
||||||
|
self.file.create_entity(
|
||||||
|
"IfcMaterialConstituent",
|
||||||
|
**{
|
||||||
|
"Name": constituent.name or None,
|
||||||
|
"Description": constituent.description or None,
|
||||||
|
"Material": self.ifc_parser.materials[constituent.material.name]["ifc"],
|
||||||
|
"Fraction": constituent.fraction or None,
|
||||||
|
"Category": constituent.category or None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return results
|
||||||
|
|
||||||
def relate_spaces_to_boundary_elements(self):
|
def relate_spaces_to_boundary_elements(self):
|
||||||
for (relating_space_index, relationships,) in self.ifc_parser.rel_space_boundaries.items():
|
for (relating_space_index, relationships,) in self.ifc_parser.rel_space_boundaries.items():
|
||||||
for relationship in relationships:
|
for relationship in relationships:
|
||||||
@@ -3342,6 +3400,7 @@ class IfcExportSettings:
|
|||||||
settings.should_use_presentation_style_assignment = scene_bim.export_should_use_presentation_style_assignment
|
settings.should_use_presentation_style_assignment = scene_bim.export_should_use_presentation_style_assignment
|
||||||
settings.should_guess_quantities = scene_bim.export_should_guess_quantities
|
settings.should_guess_quantities = scene_bim.export_should_guess_quantities
|
||||||
settings.should_force_faceted_brep = scene_bim.export_should_force_faceted_brep
|
settings.should_force_faceted_brep = scene_bim.export_should_force_faceted_brep
|
||||||
|
settings.should_force_triangulation = scene_bim.export_should_force_triangulation
|
||||||
settings.should_roundtrip_native = scene_bim.import_export_should_roundtrip_native
|
settings.should_roundtrip_native = scene_bim.import_export_should_roundtrip_native
|
||||||
settings.context_tree = []
|
settings.context_tree = []
|
||||||
for ifc_context in ["model", "plan"]:
|
for ifc_context in ["model", "plan"]:
|
||||||
|
|||||||
@@ -3598,25 +3598,48 @@ class ConvertLocalToGlobal(bpy.types.Operator):
|
|||||||
bl_label = "Convert Local To Global"
|
bl_label = "Convert Local To Global"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
x, y, z = bpy.context.scene.cursor.location
|
|
||||||
|
|
||||||
if bpy.context.scene.MapConversion.scale:
|
if bpy.context.scene.MapConversion.scale:
|
||||||
scale = float(bpy.context.scene.MapConversion.scale)
|
scale = float(bpy.context.scene.MapConversion.scale)
|
||||||
else:
|
else:
|
||||||
scale = 1.0
|
scale = 1.0
|
||||||
|
results = ifcopenshell.util.geolocation.xyz2enh(
|
||||||
rotation = atan2(
|
bpy.context.scene.cursor.location[0],
|
||||||
float(bpy.context.scene.MapConversion.x_axis_ordinate),
|
bpy.context.scene.cursor.location[1],
|
||||||
|
bpy.context.scene.cursor.location[2],
|
||||||
|
float(bpy.context.scene.MapConversion.eastings),
|
||||||
|
float(bpy.context.scene.MapConversion.northings),
|
||||||
|
float(bpy.context.scene.MapConversion.orthogonal_height),
|
||||||
float(bpy.context.scene.MapConversion.x_axis_abscissa),
|
float(bpy.context.scene.MapConversion.x_axis_abscissa),
|
||||||
|
float(bpy.context.scene.MapConversion.x_axis_ordinate),
|
||||||
|
scale,
|
||||||
)
|
)
|
||||||
a = scale * cos(rotation)
|
print("Coordinates:", results)
|
||||||
b = scale * sin(rotation)
|
bpy.context.scene.cursor.location = results
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
eastings = (a * x) - (b * y) + float(bpy.context.scene.MapConversion.eastings)
|
|
||||||
northings = (b * x) + (a * y) + float(bpy.context.scene.MapConversion.northings)
|
|
||||||
height = z + float(bpy.context.scene.MapConversion.orthogonal_height)
|
|
||||||
|
|
||||||
bpy.context.scene.cursor.location = (eastings, northings, height)
|
class ConvertGlobalToLocal(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.convert_global_to_local"
|
||||||
|
bl_label = "Convert Global To Local"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
if bpy.context.scene.MapConversion.scale:
|
||||||
|
scale = float(bpy.context.scene.MapConversion.scale)
|
||||||
|
else:
|
||||||
|
scale = 1.0
|
||||||
|
results = ifcopenshell.util.geolocation.enh2xyz(
|
||||||
|
float(bpy.context.scene.BIMProperties.eastings),
|
||||||
|
float(bpy.context.scene.BIMProperties.northings),
|
||||||
|
float(bpy.context.scene.BIMProperties.orthogonal_height),
|
||||||
|
float(bpy.context.scene.MapConversion.eastings),
|
||||||
|
float(bpy.context.scene.MapConversion.northings),
|
||||||
|
float(bpy.context.scene.MapConversion.orthogonal_height),
|
||||||
|
float(bpy.context.scene.MapConversion.x_axis_abscissa),
|
||||||
|
float(bpy.context.scene.MapConversion.x_axis_ordinate),
|
||||||
|
scale,
|
||||||
|
)
|
||||||
|
print("Coordinates:", results)
|
||||||
|
bpy.context.scene.cursor.location = results
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -4103,7 +4126,7 @@ class AddMaterialLayer(bpy.types.Operator):
|
|||||||
bl_label = "Add Material Layer"
|
bl_label = "Add Material Layer"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
new = bpy.context.active_object.BIMObjectProperties.material_layers.add()
|
new = bpy.context.active_object.BIMObjectProperties.material_set.material_layers.add()
|
||||||
new.material = bpy.data.materials[0]
|
new.material = bpy.data.materials[0]
|
||||||
new.name = "Material Layer"
|
new.name = "Material Layer"
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
@@ -4115,7 +4138,7 @@ class RemoveMaterialLayer(bpy.types.Operator):
|
|||||||
index: bpy.props.IntProperty()
|
index: bpy.props.IntProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
bpy.context.active_object.BIMObjectProperties.material_layers.remove(self.index)
|
bpy.context.active_object.BIMObjectProperties.material_set.material_layers.remove(self.index)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -4125,7 +4148,7 @@ class MoveMaterialLayer(bpy.types.Operator):
|
|||||||
direction: bpy.props.StringProperty()
|
direction: bpy.props.StringProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
props = bpy.context.active_object.BIMObjectProperties
|
props = bpy.context.active_object.BIMObjectProperties.material_set
|
||||||
index = props.active_material_layer_index
|
index = props.active_material_layer_index
|
||||||
if self.direction == "UP" and index - 1 >= 0:
|
if self.direction == "UP" and index - 1 >= 0:
|
||||||
props.material_layers.move(index, index - 1)
|
props.material_layers.move(index, index - 1)
|
||||||
@@ -4136,6 +4159,44 @@ class MoveMaterialLayer(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class AddMaterialConstituent(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.add_material_constituent"
|
||||||
|
bl_label = "Add Material Constituent"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
new = bpy.context.active_object.BIMObjectProperties.material_set.material_constituents.add()
|
||||||
|
new.material = bpy.data.materials[0]
|
||||||
|
new.name = "Material Constituent"
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveMaterialConstituent(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.remove_material_constituent"
|
||||||
|
bl_label = "Remove Material Constituent"
|
||||||
|
index: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bpy.context.active_object.BIMObjectProperties.material_set.material_constituents.remove(self.index)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class MoveMaterialConstituent(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.move_material_constituent"
|
||||||
|
bl_label = "Move Material Constituent"
|
||||||
|
direction: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
props = bpy.context.active_object.BIMObjectProperties.material_set
|
||||||
|
index = props.active_material_constituent_index
|
||||||
|
if self.direction == "UP" and index - 1 >= 0:
|
||||||
|
props.material_constituents.move(index, index - 1)
|
||||||
|
props.active_material_constituent_index = index - 1
|
||||||
|
elif self.direction == "DOWN" and index + 1 < len(props.material_constituents):
|
||||||
|
props.material_constituents.move(index, index + 1)
|
||||||
|
props.active_material_constituent_index = index + 1
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SelectScheduleFile(bpy.types.Operator):
|
class SelectScheduleFile(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_schedule_file"
|
bl_idname = "bim.select_schedule_file"
|
||||||
bl_label = "Select Documentation IFC File"
|
bl_label = "Select Documentation IFC File"
|
||||||
@@ -4199,10 +4260,10 @@ class SetNorthOffset(bpy.types.Operator):
|
|||||||
bl_label = "Set North Offset"
|
bl_label = "Set North Offset"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
context.scene.sun_pos_properties.north_offset = radians(
|
context.scene.sun_pos_properties.north_offset = -radians(
|
||||||
ifcopenshell.util.geolocation.xy2angle(
|
ifcopenshell.util.geolocation.xy2angle(
|
||||||
float(bpy.context.scene.MapConversion.x_axis_ordinate),
|
|
||||||
float(bpy.context.scene.MapConversion.x_axis_abscissa),
|
float(bpy.context.scene.MapConversion.x_axis_abscissa),
|
||||||
|
float(bpy.context.scene.MapConversion.x_axis_ordinate),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -583,6 +583,7 @@ class MaterialLayer(PropertyGroup):
|
|||||||
description: StringProperty(name="Description")
|
description: StringProperty(name="Description")
|
||||||
category: EnumProperty(
|
category: EnumProperty(
|
||||||
items=[
|
items=[
|
||||||
|
("None", "None", ""),
|
||||||
("LoadBearing", "Load Bearing", ""),
|
("LoadBearing", "Load Bearing", ""),
|
||||||
("Insulation", "Insulation", ""),
|
("Insulation", "Insulation", ""),
|
||||||
("Finish", "Finish", ""),
|
("Finish", "Finish", ""),
|
||||||
@@ -595,6 +596,23 @@ class MaterialLayer(PropertyGroup):
|
|||||||
priority: IntProperty(name="Priority")
|
priority: IntProperty(name="Priority")
|
||||||
|
|
||||||
|
|
||||||
|
class MaterialConstituent(PropertyGroup):
|
||||||
|
name: StringProperty(name="Name")
|
||||||
|
description: StringProperty(name="Description")
|
||||||
|
material: PointerProperty(name="Material", type=bpy.types.Material)
|
||||||
|
fraction: FloatProperty(name="Fraction")
|
||||||
|
category: StringProperty(name="Category")
|
||||||
|
|
||||||
|
|
||||||
|
class MaterialSet(PropertyGroup):
|
||||||
|
name: StringProperty(name="Name")
|
||||||
|
description: StringProperty(name="Description")
|
||||||
|
active_material_layer_index: IntProperty(name="Active Material Layer Index")
|
||||||
|
material_layers: CollectionProperty(name="Material Layers", type=MaterialLayer)
|
||||||
|
active_material_constituent_index: IntProperty(name="Active Material Constituent Index")
|
||||||
|
material_constituents: CollectionProperty(name="Material Constituents", type=MaterialConstituent)
|
||||||
|
|
||||||
|
|
||||||
class Drawing(PropertyGroup):
|
class Drawing(PropertyGroup):
|
||||||
name: StringProperty(name="Name", update=updateDrawingName)
|
name: StringProperty(name="Name", update=updateDrawingName)
|
||||||
camera: PointerProperty(name="Camera", type=bpy.types.Object)
|
camera: PointerProperty(name="Camera", type=bpy.types.Object)
|
||||||
@@ -1411,6 +1429,7 @@ class BIMProperties(PropertyGroup):
|
|||||||
name="Export with Presentation Style Assignment", default=False
|
name="Export with Presentation Style Assignment", default=False
|
||||||
)
|
)
|
||||||
export_should_force_faceted_brep: BoolProperty(name="Export with Faceted Breps", default=False)
|
export_should_force_faceted_brep: BoolProperty(name="Export with Faceted Breps", default=False)
|
||||||
|
export_should_force_triangulation: BoolProperty(name="Export with Triangulation", default=False)
|
||||||
import_should_ignore_site_coordinates: BoolProperty(name="Import Ignoring Site Coordinates", default=False)
|
import_should_ignore_site_coordinates: BoolProperty(name="Import Ignoring Site Coordinates", default=False)
|
||||||
import_should_ignore_building_coordinates: BoolProperty(name="Import Ignoring Building Coordinates", default=False)
|
import_should_ignore_building_coordinates: BoolProperty(name="Import Ignoring Building Coordinates", default=False)
|
||||||
import_should_reset_absolute_coordinates: BoolProperty(name="Import Resetting Absolute Coordinates", default=False)
|
import_should_reset_absolute_coordinates: BoolProperty(name="Import Resetting Absolute Coordinates", default=False)
|
||||||
@@ -1503,6 +1522,9 @@ class BIMProperties(PropertyGroup):
|
|||||||
active_clash_set_index: IntProperty(name="Active Clash Set Index")
|
active_clash_set_index: IntProperty(name="Active Clash Set Index")
|
||||||
constraints: CollectionProperty(name="Constraints", type=Constraint)
|
constraints: CollectionProperty(name="Constraints", type=Constraint)
|
||||||
active_constraint_index: IntProperty(name="Active Constraint Index")
|
active_constraint_index: IntProperty(name="Active Constraint Index")
|
||||||
|
eastings: StringProperty(name="Eastings")
|
||||||
|
northings: StringProperty(name="Northings")
|
||||||
|
orthogonal_height: StringProperty(name="Orthogonal Height")
|
||||||
ifc_patch_recipes: EnumProperty(items=getIfcPatchRecipes, name="Recipes")
|
ifc_patch_recipes: EnumProperty(items=getIfcPatchRecipes, name="Recipes")
|
||||||
ifc_patch_input: StringProperty(default="", name="IFC Patch Input IFC")
|
ifc_patch_input: StringProperty(default="", name="IFC Patch Input IFC")
|
||||||
ifc_patch_output: StringProperty(default="", name="IFC Patch Output IFC")
|
ifc_patch_output: StringProperty(default="", name="IFC Patch Output IFC")
|
||||||
@@ -1665,8 +1687,7 @@ class BIMObjectProperties(PropertyGroup):
|
|||||||
classifications: CollectionProperty(name="Classifications", type=ClassificationReference)
|
classifications: CollectionProperty(name="Classifications", type=ClassificationReference)
|
||||||
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
||||||
material: PointerProperty(name="Material", type=bpy.types.Material)
|
material: PointerProperty(name="Material", type=bpy.types.Material)
|
||||||
material_layers: CollectionProperty(name="Material Layers", type=MaterialLayer)
|
material_set: PointerProperty(name="Material Set", type=MaterialSet)
|
||||||
active_material_layer_index: IntProperty(name="Active Material Layer Index")
|
|
||||||
pset_name: EnumProperty(items=getPsetNames, name="Pset Name")
|
pset_name: EnumProperty(items=getPsetNames, name="Pset Name")
|
||||||
qto_name: EnumProperty(items=getQtoNames, name="Qto Name")
|
qto_name: EnumProperty(items=getQtoNames, name="Qto Name")
|
||||||
has_boundary_condition: BoolProperty(name="Has Boundary Condition")
|
has_boundary_condition: BoolProperty(name="Has Boundary Condition")
|
||||||
|
|||||||
@@ -126,19 +126,28 @@ class BIM_PT_object_material(Panel):
|
|||||||
if props.material_type == "IfcMaterial":
|
if props.material_type == "IfcMaterial":
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(props, "material")
|
row.prop(props, "material")
|
||||||
elif props.material_type == "IfcMaterialLayerSet":
|
else:
|
||||||
|
set_props = props.material_set
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
row.prop(set_props, "name", text="Name")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(set_props, "description", text="Description")
|
||||||
|
row = layout.row()
|
||||||
|
|
||||||
|
if props.material_type == "IfcMaterialLayerSet":
|
||||||
row.template_list(
|
row.template_list(
|
||||||
"MATERIAL_UL_matslots", "", props, "material_layers", props, "active_material_layer_index"
|
"MATERIAL_UL_matslots", "", set_props, "material_layers", set_props, "active_material_layer_index"
|
||||||
)
|
)
|
||||||
col = row.column(align=True)
|
col = row.column(align=True)
|
||||||
col.operator("bim.add_material_layer", icon="ADD", text="")
|
col.operator("bim.add_material_layer", icon="ADD", text="")
|
||||||
col.operator("bim.remove_material_layer", icon="REMOVE", text="").index = props.active_material_layer_index
|
col.operator(
|
||||||
|
"bim.remove_material_layer", icon="REMOVE", text=""
|
||||||
|
).index = set_props.active_material_layer_index
|
||||||
col.operator("bim.move_material_layer", icon="TRIA_UP", text="").direction = "UP"
|
col.operator("bim.move_material_layer", icon="TRIA_UP", text="").direction = "UP"
|
||||||
col.operator("bim.move_material_layer", icon="TRIA_DOWN", text="").direction = "DOWN"
|
col.operator("bim.move_material_layer", icon="TRIA_DOWN", text="").direction = "DOWN"
|
||||||
|
|
||||||
if props.active_material_layer_index < len(props.material_layers):
|
if set_props.active_material_layer_index < len(set_props.material_layers):
|
||||||
material = props.material_layers[props.active_material_layer_index]
|
material = set_props.material_layers[set_props.active_material_layer_index]
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(material, "material")
|
row.prop(material, "material")
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
@@ -153,7 +162,38 @@ class BIM_PT_object_material(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(material, "layer_thickness")
|
row.prop(material, "layer_thickness")
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
row.prop(material, "is_ventilated")
|
||||||
|
row = layout.row()
|
||||||
row.prop(material, "priority")
|
row.prop(material, "priority")
|
||||||
|
elif props.material_type == "IfcMaterialConstituentSet":
|
||||||
|
row.template_list(
|
||||||
|
"MATERIAL_UL_matslots",
|
||||||
|
"",
|
||||||
|
set_props,
|
||||||
|
"material_constituents",
|
||||||
|
set_props,
|
||||||
|
"active_material_constituent_index",
|
||||||
|
)
|
||||||
|
col = row.column(align=True)
|
||||||
|
col.operator("bim.add_material_constituent", icon="ADD", text="")
|
||||||
|
col.operator(
|
||||||
|
"bim.remove_material_constituent", icon="REMOVE", text=""
|
||||||
|
).index = set_props.active_material_constituent_index
|
||||||
|
col.operator("bim.move_material_constituent", icon="TRIA_UP", text="").direction = "UP"
|
||||||
|
col.operator("bim.move_material_constituent", icon="TRIA_DOWN", text="").direction = "DOWN"
|
||||||
|
|
||||||
|
if set_props.active_material_constituent_index < len(set_props.material_constituents):
|
||||||
|
material = set_props.material_constituents[set_props.active_material_constituent_index]
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(material, "material")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(material, "name")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(material, "description")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(material, "fraction")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(material, "category")
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_object_psets(Panel):
|
class BIM_PT_object_psets(Panel):
|
||||||
@@ -881,6 +921,13 @@ class BIM_PT_gis(Panel):
|
|||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.operator("bim.convert_local_to_global")
|
row.operator("bim.convert_local_to_global")
|
||||||
|
|
||||||
|
layout.row().prop(scene.BIMProperties, "eastings")
|
||||||
|
layout.row().prop(scene.BIMProperties, "northings")
|
||||||
|
layout.row().prop(scene.BIMProperties, "orthogonal_height")
|
||||||
|
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.operator("bim.convert_global_to_local")
|
||||||
|
|
||||||
if hasattr(bpy.context.scene, "sun_pos_properties"):
|
if hasattr(bpy.context.scene, "sun_pos_properties"):
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.operator("bim.get_north_offset")
|
row.operator("bim.get_north_offset")
|
||||||
@@ -1921,6 +1968,16 @@ class BIM_PT_mvd(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(bim_properties, "import_should_auto_set_workarounds")
|
row.prop(bim_properties, "import_should_auto_set_workarounds")
|
||||||
|
|
||||||
|
layout.label(text="RIB iTWO Workarounds:")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(bim_properties, "export_should_force_faceted_brep")
|
||||||
|
|
||||||
|
layout.label(text="Navisworks Workarounds:")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(bim_properties, "export_should_force_triangulation")
|
||||||
|
|
||||||
layout.label(text="Tekla Workarounds:")
|
layout.label(text="Tekla Workarounds:")
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
|||||||
@@ -1736,9 +1736,11 @@ IfcSchema::IfcRelVoidsElement::list::ptr IfcGeom::Kernel::find_openings(IfcSchem
|
|||||||
// Filter openings in Reference view, solely marked as Reference.
|
// Filter openings in Reference view, solely marked as Reference.
|
||||||
IfcSchema::IfcRelVoidsElement::list::ptr openings(new IfcSchema::IfcRelVoidsElement::list);
|
IfcSchema::IfcRelVoidsElement::list::ptr openings(new IfcSchema::IfcRelVoidsElement::list);
|
||||||
std::for_each(rs.begin(), rs.end(), [&openings](IfcSchema::IfcRelVoidsElement* rel) {
|
std::for_each(rs.begin(), rs.end(), [&openings](IfcSchema::IfcRelVoidsElement* rel) {
|
||||||
auto reps = rel->RelatedOpeningElement()->Representation()->Representations();
|
if (rel->RelatedOpeningElement()->hasObjectPlacement() && rel->RelatedOpeningElement()->hasRepresentation()) {
|
||||||
if (!(reps->size() == 1 && (*reps->begin())->RepresentationIdentifier() == "Reference")) {
|
auto reps = rel->RelatedOpeningElement()->Representation()->Representations();
|
||||||
openings->push(rel);
|
if (!(reps->size() == 1 && (*reps->begin())->RepresentationIdentifier() == "Reference")) {
|
||||||
|
openings->push(rel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,18 @@ def xyz2enh(x, y, z, eastings, northings, orthogonal_height, x_axis_abscissa, x_
|
|||||||
return (eastings, northings, height)
|
return (eastings, northings, height)
|
||||||
|
|
||||||
|
|
||||||
|
def enh2xyz(e, n, h, eastings, northings, orthogonal_height, x_axis_abscissa, x_axis_ordinate, scale=None):
|
||||||
|
if scale is None:
|
||||||
|
scale = 1.0
|
||||||
|
rotation = math.atan2(x_axis_ordinate, x_axis_abscissa)
|
||||||
|
a = scale * math.cos(rotation)
|
||||||
|
b = scale * math.sin(rotation)
|
||||||
|
x = ((b * n) - (b * northings) - (a * eastings) + (a * e)) / ((a * a) + (b * b))
|
||||||
|
y = ((a * n) - (a * northings) + (b * eastings) - (b * e)) / ((a * a) + (b * b))
|
||||||
|
z = h - orthogonal_height
|
||||||
|
return (x, y, z)
|
||||||
|
|
||||||
|
|
||||||
# Used for converting the X and Y vectors of the X Axis in IFC geolocation
|
# Used for converting the X and Y vectors of the X Axis in IFC geolocation
|
||||||
def xy2angle(x, y):
|
def xy2angle(x, y):
|
||||||
return math.degrees(math.atan2(y, x))
|
return math.degrees(math.atan2(y, x))
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcsverchok.helper
|
import ifcsverchok.helper
|
||||||
from bpy.props import StringProperty
|
from bpy.props import StringProperty, EnumProperty
|
||||||
from sverchok.node_tree import SverchCustomTreeNode
|
from sverchok.node_tree import SverchCustomTreeNode
|
||||||
from sverchok.data_structure import updateNode
|
from sverchok.data_structure import updateNode
|
||||||
|
from blenderbim.bim import schema
|
||||||
|
|
||||||
|
|
||||||
class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||||
bl_idname = "SvIfcByType"
|
bl_idname = "SvIfcByType"
|
||||||
bl_label = "IFC By Type"
|
bl_label = "IFC By Type"
|
||||||
|
ifc_element_types = [(t, t, t) for t in schema.IfcSchema().IfcElementType.keys()]
|
||||||
file: StringProperty(name="file", update=updateNode)
|
file: StringProperty(name="file", update=updateNode)
|
||||||
type: StringProperty(name="type", update=updateNode)
|
type: EnumProperty(name="type", items=ifc_element_types)
|
||||||
|
|
||||||
def sv_init(self, context):
|
def sv_init(self, context):
|
||||||
self.inputs.new("SvStringsSocket", "file").prop_name = "file"
|
self.inputs.new("SvStringsSocket", "file").prop_name = "file"
|
||||||
|
|||||||
Reference in New Issue
Block a user