mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 15:08:51 +00:00
typing
This commit is contained in:
@@ -262,7 +262,7 @@ def update_titleblocks(self, context):
|
|||||||
SheetsData.data["titleblocks"] = SheetsData.titleblocks()
|
SheetsData.data["titleblocks"] = SheetsData.titleblocks()
|
||||||
|
|
||||||
|
|
||||||
def update_should_draw_decorations(self, context):
|
def update_should_draw_decorations(self, context: bpy.types.Context) -> None:
|
||||||
if self.should_draw_decorations:
|
if self.should_draw_decorations:
|
||||||
# TODO: design a proper text variable templating renderer
|
# TODO: design a proper text variable templating renderer
|
||||||
collection = context.scene.camera.BIMObjectProperties.collection
|
collection = context.scene.camera.BIMObjectProperties.collection
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ import ifcopenshell.util.shape
|
|||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from math import pi, pow
|
from math import pi, pow
|
||||||
from mathutils import Vector, Matrix, geometry
|
from mathutils import Vector, Matrix, geometry
|
||||||
from typing import Union
|
from typing import Union, Any, TypeVar, Optional
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class Helper:
|
class Helper:
|
||||||
@@ -39,7 +41,7 @@ class Helper:
|
|||||||
# edge that shares a single vertex only with that face to find the extrusion
|
# 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
|
# edge. A face with the normal facing down is prioritised. A limited
|
||||||
# dissolve ensure that faces are quads and not tris.
|
# dissolve ensure that faces are quads and not tris.
|
||||||
def auto_detect_rectangle_profile_extruded_area_solid(self, mesh: bpy.types.Mesh) -> dict:
|
def auto_detect_rectangle_profile_extruded_area_solid(self, mesh: bpy.types.Mesh) -> dict[str, Any]:
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.from_mesh(mesh)
|
bm.from_mesh(mesh)
|
||||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
||||||
@@ -63,7 +65,7 @@ class Helper:
|
|||||||
# only ngon (this assumes the circle has at least a facetation of > 4 edges.
|
# only ngon (this assumes the circle has at least a facetation of > 4 edges.
|
||||||
# The extrusion direction is any edge that only shares a single vertex with
|
# The extrusion direction is any edge that only shares a single vertex with
|
||||||
# the profile. We prioritise the profile that has a downwards normal.
|
# the profile. We prioritise the profile that has a downwards normal.
|
||||||
def auto_detect_circle_profile_extruded_area_solid(self, mesh):
|
def auto_detect_circle_profile_extruded_area_solid(self, mesh: bpy.types.Mesh) -> dict[str, Any]:
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.from_mesh(mesh)
|
bm.from_mesh(mesh)
|
||||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
||||||
@@ -91,7 +93,7 @@ class Helper:
|
|||||||
# Failing that, it is equivalent to a rectangular profile. The extrusion
|
# Failing that, it is equivalent to a rectangular profile. The extrusion
|
||||||
# direction is any edge that only shares a single vertex with the profile.
|
# direction is any edge that only shares a single vertex with the profile.
|
||||||
# We prioritise the profile that has a downwards normal.
|
# We prioritise the profile that has a downwards normal.
|
||||||
def auto_detect_arbitrary_closed_profile_extruded_area_solid(self, mesh):
|
def auto_detect_arbitrary_closed_profile_extruded_area_solid(self, mesh: bpy.types.Mesh) -> dict[str, Any]:
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.from_mesh(mesh)
|
bm.from_mesh(mesh)
|
||||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
||||||
@@ -131,7 +133,7 @@ class Helper:
|
|||||||
# set of edges. Then, connected edges (i.e. sharing a vertex) are joined to
|
# set of edges. Then, connected edges (i.e. sharing a vertex) are joined to
|
||||||
# form distinct loops. Finally, the outer loop is distinguished by being
|
# form distinct loops. Finally, the outer loop is distinguished by being
|
||||||
# the loop with the greatest area.
|
# the loop with the greatest area.
|
||||||
def auto_detect_arbitrary_profile_with_voids_extruded_area_solid(self, mesh):
|
def auto_detect_arbitrary_profile_with_voids_extruded_area_solid(self, mesh: bpy.types.Mesh) -> dict[str, Any]:
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.from_mesh(mesh)
|
bm.from_mesh(mesh)
|
||||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
||||||
@@ -228,7 +230,7 @@ class Helper:
|
|||||||
# Before we begin we check that all faces are coplanar instead of finding suitable face.
|
# Before we begin we check that all faces are coplanar instead of finding suitable face.
|
||||||
# Then we process the same way.
|
# Then we process the same way.
|
||||||
# Only 2 parameters are returned as there is no extrusion.
|
# Only 2 parameters are returned as there is no extrusion.
|
||||||
def auto_detect_curve_bounded_plane(self, mesh, tolerance=0.001):
|
def auto_detect_curve_bounded_plane(self, mesh: bpy.types.Mesh, tolerance: float = 0.001) -> dict[str, Any]:
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.from_mesh(mesh)
|
bm.from_mesh(mesh)
|
||||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
|
||||||
@@ -316,9 +318,8 @@ class Helper:
|
|||||||
|
|
||||||
# An extrusion edge is an edge that shares a single vertex with a profile
|
# An extrusion edge is an edge that shares a single vertex with a profile
|
||||||
# face and is not on the plane of the face.
|
# face and is not on the plane of the face.
|
||||||
def detect_extrusion_edge(self, bm, profile_face):
|
def detect_extrusion_edge(self, bm: bmesh.types.BMesh, profile_face: bmesh.types.BMFace) -> Union[list[int], None]:
|
||||||
bm.edges.ensure_lookup_table()
|
bm.edges.ensure_lookup_table()
|
||||||
extrusion = None
|
|
||||||
face_verts_set = set(profile_face.verts)
|
face_verts_set = set(profile_face.verts)
|
||||||
for edge in bm.edges:
|
for edge in bm.edges:
|
||||||
unshared_verts = set(edge.verts) - face_verts_set
|
unshared_verts = set(edge.verts) - face_verts_set
|
||||||
@@ -336,7 +337,9 @@ class Helper:
|
|||||||
return [edge.verts[0].index, edge.verts[1].index]
|
return [edge.verts[0].index, edge.verts[1].index]
|
||||||
return [edge.verts[1].index, edge.verts[0].index]
|
return [edge.verts[1].index, edge.verts[0].index]
|
||||||
|
|
||||||
def create_extruded_area_solid(self, mesh, extrusion_indices, profile_def):
|
def create_extruded_area_solid(
|
||||||
|
self, mesh: bpy.types.Mesh, extrusion_indices: list[int], profile_def: dict[str, Any]
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
position = self.create_ifc_axis_2_placement_3d(
|
position = self.create_ifc_axis_2_placement_3d(
|
||||||
profile_def["curve_ucs"]["center"], profile_def["curve_ucs"]["z_axis"], profile_def["curve_ucs"]["x_axis"]
|
profile_def["curve_ucs"]["center"], profile_def["curve_ucs"]["z_axis"], profile_def["curve_ucs"]["x_axis"]
|
||||||
)
|
)
|
||||||
@@ -349,13 +352,15 @@ class Helper:
|
|||||||
self.convert_si_to_unit(direction.length),
|
self.convert_si_to_unit(direction.length),
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_arbitrary_closed_profile_def(self, mesh, profile_indices):
|
def create_arbitrary_closed_profile_def(self, mesh: bpy.types.Mesh, profile_indices: list[int]) -> dict[str, Any]:
|
||||||
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
||||||
outer_curve = self.create_polyline_from_loop(mesh, profile_indices, curve_ucs)
|
outer_curve = self.create_polyline_from_loop(mesh, profile_indices, curve_ucs)
|
||||||
curve = self.file.createIfcArbitraryClosedProfileDef("AREA", None, outer_curve)
|
curve = self.file.createIfcArbitraryClosedProfileDef("AREA", None, outer_curve)
|
||||||
return {"curve_ucs": curve_ucs, "curve": curve}
|
return {"curve_ucs": curve_ucs, "curve": curve}
|
||||||
|
|
||||||
def create_arbitrary_profile_def_with_voids(self, mesh, profile_indices, inner_curve_indices):
|
def create_arbitrary_profile_def_with_voids(
|
||||||
|
self, mesh: bpy.types.Mesh, profile_indices: list[int], inner_curve_indices: list[int]
|
||||||
|
) -> dict[str, Any]:
|
||||||
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
||||||
outer_curve = self.create_polyline_from_loop(mesh, profile_indices, curve_ucs)
|
outer_curve = self.create_polyline_from_loop(mesh, profile_indices, curve_ucs)
|
||||||
inner_curves = [
|
inner_curves = [
|
||||||
@@ -364,7 +369,7 @@ class Helper:
|
|||||||
curve = self.file.createIfcArbitraryProfileDefWithVoids("AREA", None, outer_curve, inner_curves)
|
curve = self.file.createIfcArbitraryProfileDefWithVoids("AREA", None, outer_curve, inner_curves)
|
||||||
return {"curve_ucs": curve_ucs, "curve": curve}
|
return {"curve_ucs": curve_ucs, "curve": curve}
|
||||||
|
|
||||||
def create_rectangle_profile_def(self, mesh, profile_indices):
|
def create_rectangle_profile_def(self, mesh: bpy.types.Mesh, profile_indices: list[int]) -> dict[str, Any]:
|
||||||
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
||||||
xdim = self.convert_si_to_unit(
|
xdim = self.convert_si_to_unit(
|
||||||
(mesh.vertices[profile_indices[0]].co - mesh.vertices[profile_indices[1]].co).length
|
(mesh.vertices[profile_indices[0]].co - mesh.vertices[profile_indices[1]].co).length
|
||||||
@@ -378,7 +383,7 @@ class Helper:
|
|||||||
curve = self.file.createIfcRectangleProfileDef("AREA", None, position, xdim, ydim)
|
curve = self.file.createIfcRectangleProfileDef("AREA", None, position, xdim, ydim)
|
||||||
return {"curve_ucs": curve_ucs, "curve": curve}
|
return {"curve_ucs": curve_ucs, "curve": curve}
|
||||||
|
|
||||||
def create_circle_profile_def(self, mesh, profile_indices):
|
def create_circle_profile_def(self, mesh: bpy.types.Mesh, profile_indices: list[int]) -> dict[str, Any]:
|
||||||
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
curve_ucs = self.get_curve_profile_coordinate_system(mesh, profile_indices)
|
||||||
radius = self.convert_si_to_unit(
|
radius = self.convert_si_to_unit(
|
||||||
abs(
|
abs(
|
||||||
@@ -395,13 +400,13 @@ class Helper:
|
|||||||
return {"curve_ucs": curve_ucs, "curve": curve}
|
return {"curve_ucs": curve_ucs, "curve": curve}
|
||||||
|
|
||||||
# Not used anywhere, but probably useful in the future
|
# Not used anywhere, but probably useful in the future
|
||||||
def get_loop_from_v_indices(self, obj, indices):
|
def get_loop_from_v_indices(self, obj: bpy.types.Object, indices: list[int]) -> list[int]:
|
||||||
edges = self.get_edges_in_v_indices(obj, indices)
|
edges = self.get_edges_in_v_indices(obj, indices)
|
||||||
loop = self.get_loop_from_edges(edges)
|
loop = self.get_loop_from_edges(edges)
|
||||||
loop.pop(-1)
|
loop.pop(-1)
|
||||||
return loop
|
return loop
|
||||||
|
|
||||||
def get_loop_from_edges(self, edges):
|
def get_loop_from_edges(self, edges: list[bpy.types.MeshEdge]) -> list[int]:
|
||||||
while edges:
|
while edges:
|
||||||
currentEdge = edges.pop()
|
currentEdge = edges.pop()
|
||||||
startVert = currentEdge.vertices[0]
|
startVert = currentEdge.vertices[0]
|
||||||
@@ -436,10 +441,10 @@ class Helper:
|
|||||||
del edges[i]
|
del edges[i]
|
||||||
return polyLine
|
return polyLine
|
||||||
|
|
||||||
def get_edges_in_v_indices(self, obj, indices):
|
def get_edges_in_v_indices(self, obj: bpy.types.Object, indices: list[int]) -> list[bpy.types.MeshEdge]:
|
||||||
return [e for e in obj.data.edges if (e.vertices[0] in indices and e.vertices[1] in indices)]
|
return [e for e in obj.data.edges if (e.vertices[0] in indices and e.vertices[1] in indices)]
|
||||||
|
|
||||||
def get_curve_profile_coordinate_system(self, mesh, loop):
|
def get_curve_profile_coordinate_system(self, mesh: bpy.types.Mesh, loop: list[int]) -> dict[str, Any]:
|
||||||
profile_face = bpy.data.meshes.new("profile_face")
|
profile_face = bpy.data.meshes.new("profile_face")
|
||||||
profile_verts = [(mesh.vertices[p].co.x, mesh.vertices[p].co.y, mesh.vertices[p].co.z) for p in loop]
|
profile_verts = [(mesh.vertices[p].co.x, mesh.vertices[p].co.y, mesh.vertices[p].co.z) for p in loop]
|
||||||
profile_faces = [tuple(range(0, len(profile_verts)))]
|
profile_faces = [tuple(range(0, len(profile_verts)))]
|
||||||
@@ -461,10 +466,12 @@ class Helper:
|
|||||||
"matrix": matrix.to_4x4() @ Matrix.Translation(-center),
|
"matrix": matrix.to_4x4() @ Matrix.Translation(-center),
|
||||||
}
|
}
|
||||||
|
|
||||||
def convert_si_to_unit(self, co):
|
def convert_si_to_unit(self, co: T) -> T:
|
||||||
return co / self.unit_scale
|
return co / self.unit_scale
|
||||||
|
|
||||||
def create_polyline_from_loop(self, mesh, loop, curve_ucs):
|
def create_polyline_from_loop(
|
||||||
|
self, mesh: bpy.types.Mesh, loop: list[int], curve_ucs: dict[str, Any]
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
points = []
|
points = []
|
||||||
for point in loop:
|
for point in loop:
|
||||||
transformed_point = curve_ucs["matrix"] @ mesh.vertices[point].co
|
transformed_point = curve_ucs["matrix"] @ mesh.vertices[point].co
|
||||||
@@ -472,7 +479,7 @@ class Helper:
|
|||||||
points.append(points[0])
|
points.append(points[0])
|
||||||
return self.file.createIfcPolyline(points)
|
return self.file.createIfcPolyline(points)
|
||||||
|
|
||||||
def create_cartesian_point(self, x, y, z=None):
|
def create_cartesian_point(self, x: float, y: float, z: Optional[float] = None) -> ifcopenshell.entity_instance:
|
||||||
x = self.convert_si_to_unit(x)
|
x = self.convert_si_to_unit(x)
|
||||||
y = self.convert_si_to_unit(y)
|
y = self.convert_si_to_unit(y)
|
||||||
if z is None:
|
if z is None:
|
||||||
@@ -480,22 +487,28 @@ class Helper:
|
|||||||
z = self.convert_si_to_unit(z)
|
z = self.convert_si_to_unit(z)
|
||||||
return self.file.createIfcCartesianPoint((x, y, z))
|
return self.file.createIfcCartesianPoint((x, y, z))
|
||||||
|
|
||||||
def get_extrusion_direction(self, mesh, extrusion_indices, curve_ucs):
|
def get_extrusion_direction(
|
||||||
|
self, mesh: bpy.types.Mesh, extrusion_indices: list[int], curve_ucs: dict[str, Any]
|
||||||
|
) -> Vector:
|
||||||
return curve_ucs["matrix"] @ (
|
return curve_ucs["matrix"] @ (
|
||||||
curve_ucs["center"] + (mesh.vertices[extrusion_indices[1]].co - mesh.vertices[extrusion_indices[0]].co)
|
curve_ucs["center"] + (mesh.vertices[extrusion_indices[1]].co - mesh.vertices[extrusion_indices[0]].co)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_start_and_end_of_extrusion(self, profile_points, extrusion_edge):
|
def get_start_and_end_of_extrusion(
|
||||||
|
self, profile_points: list[int], extrusion_edge: bpy.types.MeshEdge
|
||||||
|
) -> tuple[int, int]:
|
||||||
if extrusion_edge.vertices[0] in profile_points:
|
if extrusion_edge.vertices[0] in profile_points:
|
||||||
return (extrusion_edge.vertices[0], extrusion_edge.vertices[1])
|
return (extrusion_edge.vertices[0], extrusion_edge.vertices[1])
|
||||||
return (extrusion_edge.vertices[1], extrusion_edge.vertices[0])
|
return (extrusion_edge.vertices[1], extrusion_edge.vertices[0])
|
||||||
|
|
||||||
def create_ifc_axis_2_placement_2d(self, point, forward):
|
def create_ifc_axis_2_placement_2d(self, point: Vector, forward: Vector) -> ifcopenshell.entity_instance:
|
||||||
return self.file.createIfcAxis2Placement2D(
|
return self.file.createIfcAxis2Placement2D(
|
||||||
self.create_cartesian_point(point.x, point.y), self.file.createIfcDirection((forward.x, forward.y))
|
self.create_cartesian_point(point.x, point.y), self.file.createIfcDirection((forward.x, forward.y))
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_ifc_axis_2_placement_3d(self, point, up, forward):
|
def create_ifc_axis_2_placement_3d(
|
||||||
|
self, point: Vector, up: Vector, forward: Vector
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
return self.file.createIfcAxis2Placement3D(
|
return self.file.createIfcAxis2Placement3D(
|
||||||
self.create_cartesian_point(point.x, point.y, point.z),
|
self.create_cartesian_point(point.x, point.y, point.z),
|
||||||
self.file.createIfcDirection((up.x, up.y, up.z)),
|
self.file.createIfcDirection((up.x, up.y, up.z)),
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
import os
|
import os
|
||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.attribute
|
||||||
from ifcopenshell.util.doc import get_attribute_doc
|
from ifcopenshell.util.doc import get_attribute_doc
|
||||||
from bonsai.bim.module.pset_template.data import PsetTemplatesData
|
from bonsai.bim.module.pset_template.data import PsetTemplatesData
|
||||||
from bonsai.bim.prop import StrProperty, Attribute
|
from bonsai.bim.prop import StrProperty, Attribute
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
import isodate
|
import isodate
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
from datetime import timedelta
|
from datetime import timedelta, datetime
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
def parse_datetime(value):
|
def parse_datetime(value):
|
||||||
@@ -36,7 +37,7 @@ def parse_duration(value):
|
|||||||
return ifcopenshell.util.date.parse_duration(value)
|
return ifcopenshell.util.date.parse_duration(value)
|
||||||
|
|
||||||
|
|
||||||
def canonicalise_time(time):
|
def canonicalise_time(time: Union[datetime, None]) -> str:
|
||||||
if not time:
|
if not time:
|
||||||
return "-"
|
return "-"
|
||||||
return time.strftime("%d/%m/%y")
|
return time.strftime("%d/%m/%y")
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from bonsai.bim.module.sequence.data import (
|
|||||||
TaskICOMData,
|
TaskICOMData,
|
||||||
AnimationColorSchemeData,
|
AnimationColorSchemeData,
|
||||||
)
|
)
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_status(Panel):
|
class BIM_PT_status(Panel):
|
||||||
@@ -1007,7 +1008,7 @@ class BIM_PT_work_calendars(Panel):
|
|||||||
if self.props.active_work_time_id == work_time["id"]:
|
if self.props.active_work_time_id == work_time["id"]:
|
||||||
self.draw_editable_work_time_ui(work_time)
|
self.draw_editable_work_time_ui(work_time)
|
||||||
|
|
||||||
def draw_editable_work_time_ui(self, work_time):
|
def draw_editable_work_time_ui(self, work_time: dict[str, Any]) -> None:
|
||||||
draw_attributes(self.props.work_time_attributes, self.layout)
|
draw_attributes(self.props.work_time_attributes, self.layout)
|
||||||
if work_time["RecurrencePattern"]:
|
if work_time["RecurrencePattern"]:
|
||||||
self.draw_editable_recurrence_pattern_ui(
|
self.draw_editable_recurrence_pattern_ui(
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ def edit_assigned_product(
|
|||||||
ifc: tool.Ifc, drawing: tool.Drawing, obj: bpy.types.Object, product: Optional[ifcopenshell.entity_instance] = None
|
ifc: tool.Ifc, drawing: tool.Drawing, obj: bpy.types.Object, product: Optional[ifcopenshell.entity_instance] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
element = ifc.get_entity(obj)
|
element = ifc.get_entity(obj)
|
||||||
|
assert element
|
||||||
existing_product = drawing.get_assigned_product(element)
|
existing_product = drawing.get_assigned_product(element)
|
||||||
if existing_product != product:
|
if existing_product != product:
|
||||||
if existing_product:
|
if existing_product:
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ from shapely.ops import unary_union
|
|||||||
from lxml import etree
|
from lxml import etree
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from typing import Optional, Union, Iterable, Any, Literal
|
from typing import Optional, Union, Iterable, Any, Literal, Sequence
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_annotation_object_type(
|
def is_annotation_object_type(
|
||||||
cls, element: ifcopenshell.entity_instance, object_types: Union[str, list[str]]
|
cls, element: ifcopenshell.entity_instance, object_types: Union[str, Sequence[str]]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if not isinstance(object_types, collections.abc.Iterable):
|
if not isinstance(object_types, collections.abc.Iterable):
|
||||||
object_types = [object_types]
|
object_types = [object_types]
|
||||||
|
|||||||
@@ -56,7 +56,9 @@ def get_total_quantity(root_element: ifcopenshell.entity_instance) -> Union[floa
|
|||||||
|
|
||||||
|
|
||||||
def calculate_applied_value(
|
def calculate_applied_value(
|
||||||
root_element: ifcopenshell.entity_instance, cost_value: ifcopenshell.entity_instance, category_filter=None
|
root_element: ifcopenshell.entity_instance,
|
||||||
|
cost_value: ifcopenshell.entity_instance,
|
||||||
|
category_filter: Optional[str] = None,
|
||||||
) -> float:
|
) -> float:
|
||||||
if cost_value.ArithmeticOperator and cost_value.Components:
|
if cost_value.ArithmeticOperator and cost_value.Components:
|
||||||
component_values = []
|
component_values = []
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ def string_to_duration(duration_string):
|
|||||||
return isodate.duration_isoformat(datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds))
|
return isodate.duration_isoformat(datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds))
|
||||||
|
|
||||||
|
|
||||||
def parse_duration(value):
|
def parse_duration(value: Union[str, None]) -> Union[datetime.timedelta, None]:
|
||||||
if not value:
|
if not value:
|
||||||
return None
|
return None
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
|||||||
@@ -246,6 +246,9 @@ class BatchReassignClass:
|
|||||||
|
|
||||||
|
|
||||||
class Migrator:
|
class Migrator:
|
||||||
|
migrated_ids: dict[int, int]
|
||||||
|
attribute_overrides: dict[int, dict[int, str]]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.migrated_ids = {}
|
self.migrated_ids = {}
|
||||||
self.attribute_overrides = {}
|
self.attribute_overrides = {}
|
||||||
@@ -308,7 +311,7 @@ class Migrator:
|
|||||||
"User": None,
|
"User": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
def preprocess(self, old_file: ifcopenshell.file, new_file: ifcopenshell.file):
|
def preprocess(self, old_file: ifcopenshell.file, new_file: ifcopenshell.file) -> None:
|
||||||
to_delete = set()
|
to_delete = set()
|
||||||
|
|
||||||
if old_file.schema == "IFC2X3" and new_file.schema == "IFC4":
|
if old_file.schema == "IFC2X3" and new_file.schema == "IFC4":
|
||||||
@@ -381,7 +384,13 @@ class Migrator:
|
|||||||
new_element = new_file.create_entity(self.class_2x3_to_4[ifc_class])
|
new_element = new_file.create_entity(self.class_2x3_to_4[ifc_class])
|
||||||
return new_element
|
return new_element
|
||||||
|
|
||||||
def migrate_attributes(self, element, new_file, new_element, new_element_schema):
|
def migrate_attributes(
|
||||||
|
self,
|
||||||
|
element: ifcopenshell.entity_instance,
|
||||||
|
new_file: ifcopenshell.file,
|
||||||
|
new_element: ifcopenshell.entity_instance,
|
||||||
|
new_element_schema: ifcopenshell_wrapper.declaration,
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
for attribute_index, value in self.attribute_overrides.get(element.id(), {}).items():
|
for attribute_index, value in self.attribute_overrides.get(element.id(), {}).items():
|
||||||
new_element[attribute_index] = value
|
new_element[attribute_index] = value
|
||||||
for i, attribute in enumerate(new_element_schema.all_attributes()):
|
for i, attribute in enumerate(new_element_schema.all_attributes()):
|
||||||
|
|||||||
Reference in New Issue
Block a user