This commit is contained in:
Andrej730
2024-06-10 14:53:14 +05:00
parent 6552463ed9
commit 51f859d8e4
5 changed files with 49 additions and 35 deletions
+2 -2
View File
@@ -896,7 +896,7 @@ class IfcImporter:
def create_generic_shape(
self, element: ifcopenshell.entity_instance
) -> Union[ifcopenshell_wrapper.TriangulationElement, None]:
) -> Union[ifcopenshell.geom.ShapeElementType, None]:
for settings in self.context_settings:
try:
result = ifcopenshell.geom.create_shape(settings, element)
@@ -1730,7 +1730,7 @@ class IfcImporter:
) -> bpy.types.Mesh:
try:
if hasattr(shape, "geometry"):
# shape is ifcopenshell_wrapper.TriangulationElement
# shape is ShapeElementType
geometry = shape.geometry
else:
geometry = shape
@@ -26,6 +26,7 @@ import platform
import subprocess
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.geom
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.representation
@@ -47,6 +47,7 @@ from math import radians
from pathlib import Path
from mathutils import Vector, Matrix
from bpy.app.handlers import persistent
from ifcopenshell.geom import ShapeElementType, ShapeType
from blenderbim.bim.module.project.data import LinksData
from blenderbim.bim.module.project.decorator import ProjectDecorator, ClippingPlaneDecorator
from typing import Union
@@ -1453,7 +1454,7 @@ class LoadLinkedProject(bpy.types.Operator):
break
return {"FINISHED"}
def is_local(self, shape):
def is_local(self, shape: ShapeElementType) -> bool:
m = shape.transformation.matrix
if max([abs(co) for co in (m[9], m[10], m[11])]) > 1000:
return False
@@ -1461,7 +1462,7 @@ class LoadLinkedProject(bpy.types.Operator):
return False
return True
def process_occurrence(self, shape):
def process_occurrence(self, shape: ShapeElementType) -> None:
element = self.file.by_id(shape.id)
matrix = shape.transformation.matrix
faces = shape.geometry.faces
@@ -27,7 +27,7 @@ from ..entity_instance import entity_instance
from . import has_occ
from typing import TypeVar, Union, Optional, Generator
from typing import TypeVar, Union, Optional, Generator, Any
T = TypeVar("T")
ShapeElementType = Union[
@@ -87,7 +87,12 @@ class settings_mixin:
def rname(k):
return k.upper().replace('-', '_')
def set(self, k, v):
def set(self, k: str, v: Any) -> None:
"""
Set value of the setting named `k` to `v`.
:raises RuntimeError: If there is no setting with name `k`.
"""
if k == "USE_PYTHON_OPENCASCADE":
if not has_occ:
raise ArgumentError("Python OpenCASCADE is not installed")
@@ -98,7 +103,13 @@ class settings_mixin:
else:
self.set_(self.name(k), v)
def get(self, k):
def get(self, k: str) -> Any:
"""
Return value of the setting named `k`.
:raises RuntimeError: If there is no setting with name `k`.
"""
return self.get_(self.name(k))
def __getattr__(self, k):
@@ -247,7 +258,7 @@ class tree(ifcopenshell_wrapper.tree):
def create_shape(
settings: settings, inst: entity_instance, repr: Optional[entity_instance] = None
) -> ifcopenshell_wrapper.TriangulationElement:
) -> ShapeElementType:
"""
Return a geometric representation from STEP-based IFCREPRESENTATIONSHAPE
or
@@ -23,6 +23,7 @@ import numpy.typing as npt
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.representation
from ifcopenshell.geom import ShapeElementType, ShapeType
from typing import Optional, Literal, Union, Iterable
tol = 1e-6
@@ -50,7 +51,7 @@ def is_x(value: float, x: float, tolerance: Optional[float] = None) -> bool:
return abs(x - value) < tolerance
def get_volume(geometry) -> float:
def get_volume(geometry: ShapeType) -> float:
"""Calculates the total internal volume of a geometry
Volumes of non-manifold geometry will be unpredictable.
@@ -81,7 +82,7 @@ def get_volume(geometry) -> float:
return abs(sum(volumes))
def get_x(geometry) -> float:
def get_x(geometry: ShapeType) -> float:
"""Calculates the X length of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -93,7 +94,7 @@ def get_x(geometry) -> float:
return max(x_values) - min(x_values)
def get_y(geometry) -> float:
def get_y(geometry: ShapeType) -> float:
"""Calculates the Y length of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -105,7 +106,7 @@ def get_y(geometry) -> float:
return max(y_values) - min(y_values)
def get_z(geometry) -> float:
def get_z(geometry: ShapeType) -> float:
"""Calculates the Z length of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -117,7 +118,7 @@ def get_z(geometry) -> float:
return max(z_values) - min(z_values)
def get_max_xy(geometry) -> float:
def get_max_xy(geometry: ShapeType) -> float:
"""Gets the maximum X or Y length of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -128,7 +129,7 @@ def get_max_xy(geometry) -> float:
return max(get_x(geometry), get_y(geometry))
def get_max_xyz(geometry) -> float:
def get_max_xyz(geometry: ShapeType) -> float:
"""Gets the maximum X, Y, or Z length of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -139,7 +140,7 @@ def get_max_xyz(geometry) -> float:
return max(get_x(geometry), get_y(geometry), get_z(geometry))
def get_min_xyz(geometry) -> float:
def get_min_xyz(geometry: ShapeType) -> float:
"""Gets the minimum X, Y, or Z length of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -150,7 +151,7 @@ def get_min_xyz(geometry) -> float:
return min(get_x(geometry), get_y(geometry), get_z(geometry))
def get_shape_matrix(shape) -> MatrixType:
def get_shape_matrix(shape: ShapeElementType) -> MatrixType:
"""Formats the transformation matrix of a shape as a 4x4 numpy array
:param shape: Shape output calculated by IfcOpenShell
@@ -161,7 +162,7 @@ def get_shape_matrix(shape) -> MatrixType:
return np.array(shape.transformation.matrix).reshape((4, 4), order="F")
def get_bbox_centroid(geometry) -> tuple[float, float, float]:
def get_bbox_centroid(geometry: ShapeType) -> tuple[float, float, float]:
"""Calculates the bounding box centroid of the geometry
The centroid is in local coordinates relative to the object's placement.
@@ -206,7 +207,7 @@ def get_element_bbox_centroid(element: ifcopenshell.entity_instance, geometry) -
return (mat @ np.array([*centroid, 1.0]))[0:3]
def get_shape_bbox_centroid(shape, geometry) -> npt.NDArray[np.float64]:
def get_shape_bbox_centroid(shape: ShapeType, geometry: ShapeType) -> npt.NDArray[np.float64]:
"""Calculates the shape's bounding box centroid
The centroid is in global coordinates. Note that if you do not have the
@@ -223,7 +224,7 @@ def get_shape_bbox_centroid(shape, geometry) -> npt.NDArray[np.float64]:
return (get_shape_matrix(shape) @ np.array([*centroid, 1.0]))[0:3]
def get_vertices(geometry) -> npt.NDArray[np.float64]:
def get_vertices(geometry: ShapeType) -> npt.NDArray[np.float64]:
"""Get all the vertices as a numpy array
Vertices are in local coordinates.
@@ -239,7 +240,7 @@ def get_vertices(geometry) -> npt.NDArray[np.float64]:
return np.array([np.array([verts[i], verts[i + 1], verts[i + 2]]) for i in range(0, len(verts), 3)])
def get_edges(geometry) -> npt.NDArray[np.int32]:
def get_edges(geometry: ShapeType) -> npt.NDArray[np.int32]:
"""Get all the edges as a numpy array
Results are a nested numpy array e.g. [[e1v1, e1v2], [e2v1, e2v2], ...]
@@ -257,7 +258,7 @@ def get_edges(geometry) -> npt.NDArray[np.int32]:
return np.array([[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)])
def get_faces(geometry) -> npt.NDArray[np.int32]:
def get_faces(geometry: ShapeType) -> npt.NDArray[np.int32]:
"""Get all the faces as a numpy array
Faces are always triangulated. If the shape is a BRep and you want to get
@@ -274,7 +275,7 @@ def get_faces(geometry) -> npt.NDArray[np.int32]:
return np.array([[faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)])
def get_shape_vertices(shape, geometry) -> npt.NDArray[np.float64]:
def get_shape_vertices(shape: ShapeType, geometry: ShapeType) -> npt.NDArray[np.float64]:
"""Get the shape's vertices as a numpy array
Vertices are in global coordinates. If you do not have the shape, you can
@@ -294,7 +295,7 @@ def get_shape_vertices(shape, geometry) -> npt.NDArray[np.float64]:
return np.delete((mat @ np.hstack((verts, np.ones((len(verts), 1)))).T).T, -1, axis=1)
def get_element_vertices(element: ifcopenshell.entity_instance, geometry) -> npt.NDArray[np.float64]:
def get_element_vertices(element: ifcopenshell.entity_instance, geometry: ShapeType) -> npt.NDArray[np.float64]:
"""Get the element's vertices as a numpy array
Vertices are in global coordinates. Note that if you have the shape, it is
@@ -316,7 +317,7 @@ def get_element_vertices(element: ifcopenshell.entity_instance, geometry) -> npt
return np.delete((mat @ np.hstack((verts, np.ones((len(verts), 1)))).T).T, -1, axis=1)
def get_bottom_elevation(geometry) -> float:
def get_bottom_elevation(geometry: ShapeType) -> float:
"""Gets the lowest local Z ordinate of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -328,7 +329,7 @@ def get_bottom_elevation(geometry) -> float:
return min(z_values)
def get_top_elevation(geometry) -> float:
def get_top_elevation(geometry: ShapeType) -> float:
"""Gets the highest local Z ordinate of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -340,7 +341,7 @@ def get_top_elevation(geometry) -> float:
return max(z_values)
def get_shape_bottom_elevation(shape, geometry) -> float:
def get_shape_bottom_elevation(shape: ShapeType, geometry: ShapeType) -> float:
"""Gets the lowest global Z ordinate of the shape
If you do not have the shape, you can use ``get_element_bottom_elevation``
@@ -356,7 +357,7 @@ def get_shape_bottom_elevation(shape, geometry) -> float:
return min([v[2] for v in get_shape_vertices(shape, geometry)])
def get_shape_top_elevation(shape, geometry) -> float:
def get_shape_top_elevation(shape: ShapeType, geometry: ShapeType) -> float:
"""Gets the highest global Z ordinate of the shape
If you do not have the shape, you can use ``get_element_top_elevation``
@@ -372,7 +373,7 @@ def get_shape_top_elevation(shape, geometry) -> float:
return max([v[2] for v in get_shape_vertices(shape, geometry)])
def get_element_bottom_elevation(element: ifcopenshell.entity_instance, geometry) -> float:
def get_element_bottom_elevation(element: ifcopenshell.entity_instance, geometry: ShapeType) -> float:
"""Gets the lowest global Z ordinate of the element
Note that if you have the shape, it is more efficient to use
@@ -388,7 +389,7 @@ def get_element_bottom_elevation(element: ifcopenshell.entity_instance, geometry
return min([v[2] for v in get_element_vertices(element, geometry)])
def get_element_top_elevation(element: ifcopenshell.entity_instance, geometry) -> float:
def get_element_top_elevation(element: ifcopenshell.entity_instance, geometry: ShapeType) -> float:
"""Gets the highest global Z ordinate of the element
Note that if you have the shape, it is more efficient to use
@@ -451,7 +452,7 @@ def get_area_vf(vertices: npt.NDArray[np.float64], faces: npt.NDArray[np.int32])
return mesh_area
def get_area(geometry) -> float:
def get_area(geometry: ShapeType) -> float:
"""Calculates the surface area of the geometry
:param geometry: Geometry output calculated by IfcOpenShell
@@ -467,7 +468,7 @@ def get_area(geometry) -> float:
def get_side_area(
geometry,
geometry: ShapeType,
axis: AXIS_LITERAL = "Y",
direction: Optional[VECTOR_3D] = None,
) -> float:
@@ -518,7 +519,7 @@ def get_side_area(
return get_area_vf(vertices, filtered_faces)
def get_max_side_area(geometry) -> float:
def get_max_side_area(geometry: ShapeType) -> float:
"""Returns the maximum X, Y, or Z side area
See :func:`get_side_area` for how side area is calculated.
@@ -532,7 +533,7 @@ def get_max_side_area(geometry) -> float:
def get_footprint_area(
geometry,
geometry: ShapeType,
axis: AXIS_LITERAL = "Z",
direction: Optional[VECTOR_3D] = None,
) -> float:
@@ -615,7 +616,7 @@ def get_footprint_area(
return unioned_polygon.area
def get_outer_surface_area(geometry) -> float:
def get_outer_surface_area(geometry: ShapeType) -> float:
"""Calculates the outer surface area (i.e. all sides except for top and bottom)
This is typically useful for calculating painted areas of beams which
@@ -645,7 +646,7 @@ def get_outer_surface_area(geometry) -> float:
return get_area_vf(vertices, filtered_faces)
def get_footprint_perimeter(geometry) -> float:
def get_footprint_perimeter(geometry: ShapeType) -> float:
"""Calculates the footprint perimeter of the geometry
All faces with a negative Z normal are considered and the distance of all