mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 03:14:23 +00:00
typing, format
This commit is contained in:
@@ -23,10 +23,11 @@ import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
from math import pi, pow
|
||||
from mathutils import Vector, Matrix, geometry
|
||||
from typing import Union
|
||||
|
||||
|
||||
class Helper:
|
||||
def __init__(self, file):
|
||||
def __init__(self, file: ifcopenshell.file):
|
||||
self.file = file
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||
|
||||
@@ -34,7 +35,7 @@ class Helper:
|
||||
# edge that shares a single vertex only with that face to find the extrusion
|
||||
# edge. A face with the normal facing down is prioritised. A limited
|
||||
# dissolve ensure that faces are quads and not tris.
|
||||
def auto_detect_rectangle_profile_extruded_area_solid(self, mesh):
|
||||
def auto_detect_rectangle_profile_extruded_area_solid(self, mesh: bpy.types.Mesh) -> dict:
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh)
|
||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
||||
@@ -115,7 +116,9 @@ class Helper:
|
||||
|
||||
return {"profile": profile, "extrusion": extrusion}
|
||||
|
||||
def auto_detect_arbitrary_profile_with_voids(self, obj, mesh):
|
||||
def auto_detect_arbitrary_profile_with_voids(
|
||||
self, obj: bpy.types.Object, mesh: bpy.types.Mesh
|
||||
) -> Union[tuple, dict]:
|
||||
groups = {"IFCARCINDEX": [], "IFCCIRCLE": []}
|
||||
for i, group in enumerate(obj.vertex_groups):
|
||||
if "IFCARCINDEX" in group.name:
|
||||
@@ -148,18 +151,18 @@ class Helper:
|
||||
if total_groups > 1: # A vert can only belong to one group
|
||||
return (False, "AMBIGUOUS_SPECIAL_VERTEX")
|
||||
elif is_circle:
|
||||
pass # Circles are allowed to be unclosed
|
||||
pass # Circles are allowed to be unclosed
|
||||
elif total_groups == 0 and len(vert.link_edges) != 2: # Unclosed loop or forked loop
|
||||
return (False, "UNCLOSED_LOOP")
|
||||
|
||||
for group_type, group_counts in group_verts.items():
|
||||
if group_type == "IFCARCINDEX":
|
||||
for group_count in group_counts.values():
|
||||
if group_count != 3: # Each arc needs 3 verts
|
||||
if group_count != 3: # Each arc needs 3 verts
|
||||
return (False, "3POINT_ARC")
|
||||
elif group_type == "IFCCIRCLE":
|
||||
for group_count in group_counts.values():
|
||||
if group_count != 2: # Each circle needs 2 verts
|
||||
if group_count != 2: # Each circle needs 2 verts
|
||||
return (False, "CIRCLE")
|
||||
|
||||
loop_edges = set(bm.edges)
|
||||
@@ -269,7 +272,7 @@ class Helper:
|
||||
inner_loops.remove(outer_loop)
|
||||
|
||||
# Copy vectors to prevent random data mangling after bmesh is freed.
|
||||
points = [Vector(list(v.co)) for v in bm.verts]
|
||||
points = [v.co.copy() for v in bm.verts]
|
||||
|
||||
bm.to_mesh(mesh)
|
||||
mesh.update()
|
||||
|
||||
@@ -20,9 +20,12 @@ import bpy
|
||||
import json
|
||||
import bmesh
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.type
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.representation
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.type
|
||||
import blenderbim.bim.handler
|
||||
import blenderbim.core.type
|
||||
import blenderbim.core.geometry
|
||||
@@ -698,9 +701,7 @@ class EditExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
new_footprint = ifcopenshell.api.run(
|
||||
"geometry.add_footprint_representation", tool.Ifc.get(), context=footprint_context, curves=curves
|
||||
)
|
||||
old_footprint = ifcopenshell.util.representation.get_representation(
|
||||
element, "Plan", "FootPrint", "SKETCH_VIEW"
|
||||
)
|
||||
old_footprint = ifcopenshell.util.representation.get_representation(element, "Plan", "FootPrint", "SKETCH_VIEW")
|
||||
if old_footprint:
|
||||
for inverse in tool.Ifc.get().get_inverse(old_footprint):
|
||||
ifcopenshell.util.element.replace_attribute(inverse, old_footprint, new_footprint)
|
||||
|
||||
@@ -519,7 +519,7 @@ class Misc:
|
||||
class Model:
|
||||
def convert_si_to_unit(cls, value): pass
|
||||
def convert_unit_to_si(cls, value): pass
|
||||
def export_curve(cls, position, edge_indices, points=None): pass
|
||||
def export_curve(cls, position, edge_indices): pass
|
||||
def export_points(cls, position, indices): pass
|
||||
def export_profile(cls, obj, position=None): pass
|
||||
def generate_occurrence_name(cls, element_type, ifc_class): pass
|
||||
|
||||
@@ -20,6 +20,7 @@ import bpy
|
||||
import json
|
||||
import bmesh
|
||||
import collections
|
||||
import collections.abc
|
||||
import numpy as np
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
@@ -36,23 +37,26 @@ from blenderbim.bim import import_ifc
|
||||
from blenderbim.bim.module.geometry.helper import Helper
|
||||
from blenderbim.bim.module.model.data import AuthoringData, RailingData, RoofData, WindowData, DoorData
|
||||
from ifcopenshell.util.shape_builder import V, ShapeBuilder
|
||||
from typing import Optional, Union, TypeVar, Any
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class Model(blenderbim.core.tool.Model):
|
||||
@classmethod
|
||||
def convert_si_to_unit(cls, value):
|
||||
def convert_si_to_unit(cls, value: T) -> T:
|
||||
if isinstance(value, (tuple, list)):
|
||||
return [v / cls.unit_scale for v in value]
|
||||
return value / cls.unit_scale
|
||||
|
||||
@classmethod
|
||||
def convert_unit_to_si(cls, value):
|
||||
def convert_unit_to_si(cls, value: T) -> T:
|
||||
if isinstance(value, (tuple, list)):
|
||||
return [v * cls.unit_scale for v in value]
|
||||
return value * cls.unit_scale
|
||||
|
||||
@classmethod
|
||||
def convert_data_to_project_units(cls, data, non_si_props=[]):
|
||||
def convert_data_to_project_units(cls, data: dict[str, Any], non_si_props: list[str] = []) -> dict[str, Any]:
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
for prop_name in data:
|
||||
if prop_name in non_si_props:
|
||||
@@ -65,7 +69,7 @@ class Model(blenderbim.core.tool.Model):
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
def convert_data_to_si_units(cls, data, non_si_props=[]):
|
||||
def convert_data_to_si_units(cls, data: dict[str, Any], non_si_props: list[str] = []) -> dict[str, Any]:
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
for prop_name in data:
|
||||
if prop_name in non_si_props:
|
||||
@@ -78,34 +82,35 @@ class Model(blenderbim.core.tool.Model):
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
def export_curve(cls, position, edge_indices, points=None):
|
||||
def export_curve(cls, position: Matrix, edge_indices: list[tuple[int, int]]) -> ifcopenshell.entity_instance:
|
||||
position_i = position.inverted()
|
||||
ifc_file = tool.Ifc.get()
|
||||
if len(edge_indices) == 2:
|
||||
diameter = edge_indices[0]
|
||||
p1 = cls.bm.verts[diameter[0]].co
|
||||
p2 = cls.bm.verts[diameter[1]].co
|
||||
center = cls.convert_si_to_unit(list(position_i @ p1.lerp(p2, 0.5)))
|
||||
radius = cls.convert_si_to_unit((p1 - p2).length / 2)
|
||||
return tool.Ifc.get().createIfcCircle(
|
||||
tool.Ifc.get().createIfcAxis2Placement2D(tool.Ifc.get().createIfcCartesianPoint(center[0:2])), radius
|
||||
return ifc_file.createIfcCircle(
|
||||
ifc_file.createIfcAxis2Placement2D(ifc_file.createIfcCartesianPoint(center[0:2])), radius
|
||||
)
|
||||
if tool.Ifc.get().schema == "IFC2X3":
|
||||
if ifc_file.schema == "IFC2X3":
|
||||
points = []
|
||||
for edge in edge_indices:
|
||||
local_point = (position_i @ Vector(cls.bm.verts[edge[0]].co)).to_2d()
|
||||
points.append(tool.Ifc.get().createIfcCartesianPoint(cls.convert_si_to_unit(local_point)))
|
||||
points.append(ifc_file.createIfcCartesianPoint(cls.convert_si_to_unit(local_point)))
|
||||
points.append(points[0])
|
||||
return tool.Ifc.get().createIfcPolyline(points)
|
||||
return ifc_file.createIfcPolyline(points)
|
||||
segments = []
|
||||
for segment in edge_indices:
|
||||
if len(segment) == 2:
|
||||
segments.append(tool.Ifc.get().createIfcLineIndex([i + 1 for i in segment]))
|
||||
segments.append(ifc_file.createIfcLineIndex([i + 1 for i in segment]))
|
||||
elif len(segment) == 3:
|
||||
segments.append(tool.Ifc.get().createIfcArcIndex([i + 1 for i in segment]))
|
||||
return tool.Ifc.get().createIfcIndexedPolyCurve(cls.points, segments, False)
|
||||
segments.append(ifc_file.createIfcArcIndex([i + 1 for i in segment]))
|
||||
return ifc_file.createIfcIndexedPolyCurve(cls.points, segments, False)
|
||||
|
||||
@classmethod
|
||||
def export_points(cls, position, indices):
|
||||
def export_points(cls, position: Matrix, indices: list[Vector]) -> ifcopenshell.entity_instance:
|
||||
position_i = position.inverted()
|
||||
points = []
|
||||
for point in indices:
|
||||
@@ -114,7 +119,10 @@ class Model(blenderbim.core.tool.Model):
|
||||
return tool.Ifc.get().createIfcCartesianPointList2D(points)
|
||||
|
||||
@classmethod
|
||||
def export_profile(cls, obj, position=None):
|
||||
def export_profile(
|
||||
cls, obj: bpy.types.Object, position: Optional[Matrix] = None
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
"""Returns `None` in case if profile was invalid."""
|
||||
if position is None:
|
||||
position = Matrix()
|
||||
|
||||
@@ -150,7 +158,7 @@ class Model(blenderbim.core.tool.Model):
|
||||
return profile
|
||||
|
||||
@classmethod
|
||||
def export_surface(cls, obj):
|
||||
def export_surface(cls, obj: bpy.types.Object) -> Union[ifcopenshell.entity_instance, None]:
|
||||
p1, p2, p3 = [v.co.copy() for v in obj.data.vertices[0:3]]
|
||||
|
||||
edge1 = p2 - p1
|
||||
@@ -202,7 +210,7 @@ class Model(blenderbim.core.tool.Model):
|
||||
return surface
|
||||
|
||||
@classmethod
|
||||
def generate_occurrence_name(cls, element_type: ifcopenshell.entity_instance, ifc_class: str):
|
||||
def generate_occurrence_name(cls, element_type: ifcopenshell.entity_instance, ifc_class: str) -> str:
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
if props.occurrence_name_style == "CLASS":
|
||||
return ifc_class[3:]
|
||||
@@ -216,7 +224,8 @@ class Model(blenderbim.core.tool.Model):
|
||||
return "Instance"
|
||||
|
||||
@classmethod
|
||||
def get_extrusion(cls, representation):
|
||||
def get_extrusion(cls, representation: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||
"""return first found IfcExtrudedAreaSolid"""
|
||||
item = representation.Items[0]
|
||||
while True:
|
||||
if item.is_a("IfcExtrudedAreaSolid"):
|
||||
|
||||
Reference in New Issue
Block a user