This commit is contained in:
Andrej730
2026-03-18 19:34:56 +05:00
parent 3bf0edeca2
commit 30551cb288
7 changed files with 58 additions and 27 deletions
+3 -3
View File
@@ -34,8 +34,8 @@ client_id, client_secret = "", ""
class OAuthReceiver(http.server.BaseHTTPRequestHandler): class OAuthReceiver(http.server.BaseHTTPRequestHandler):
def do_GET(self) -> None: def do_GET(self) -> None:
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
self.server.auth_code = query.get("code", [""])[0] # type: ignore self.server.auth_code = query.get("code", [""])[0]
self.server.auth_state = query.get("state", [""])[0] # type: ignore self.server.auth_state = query.get("state", [""])[0]
self.send_response(200) self.send_response(200)
self.send_header("Content-type", "text/plain") self.send_header("Content-type", "text/plain")
self.end_headers() self.end_headers()
@@ -255,7 +255,7 @@ class BcfClient:
project_id: str = "", project_id: str = "",
topics: str = "", topics: str = "",
query_string: Optional[str] = None, query_string: Optional[str] = None,
) -> list[Any]: ) -> None:
# return self.get( # return self.get(
# f"/projects/{project_id}/topics", # f"/projects/{project_id}/topics",
# { # {
@@ -1285,7 +1285,7 @@ class SnapManager:
continue continue
coords = np.empty(vertex_count * 3, dtype=np.float32) coords = np.empty(vertex_count * 3, dtype=np.float32)
mesh.vertices.foreach_get("co", coords) # type: ignore[arg-type] mesh.vertices.foreach_get("co", coords)
coords = coords.reshape(-1, 3) coords = coords.reshape(-1, 3)
matrix = np.array(obj_eval.matrix_world, dtype=np.float32) matrix = np.array(obj_eval.matrix_world, dtype=np.float32)
@@ -139,7 +139,9 @@ def update_local_coordinates(self: "BIMGeoreferenceProperties", context: bpy.typ
tool.Georeference.set_coordinates( tool.Georeference.set_coordinates(
"blender", "blender",
ifcopenshell.util.geolocation.enh2xyz( ifcopenshell.util.geolocation.enh2xyz(
*local_coordinates, local_coordinates[0],
local_coordinates[1],
local_coordinates[2],
float(props.blender_offset_x), float(props.blender_offset_x),
float(props.blender_offset_y), float(props.blender_offset_y),
float(props.blender_offset_z), float(props.blender_offset_z),
@@ -162,7 +164,9 @@ def update_map_coordinates(self: "BIMGeoreferenceProperties", context: bpy.types
tool.Georeference.set_coordinates( tool.Georeference.set_coordinates(
"blender", "blender",
ifcopenshell.util.geolocation.enh2xyz( ifcopenshell.util.geolocation.enh2xyz(
*local_coordinates, local_coordinates[0],
local_coordinates[1],
local_coordinates[2],
float(props.blender_offset_x), float(props.blender_offset_x),
float(props.blender_offset_y), float(props.blender_offset_y),
float(props.blender_offset_z), float(props.blender_offset_z),
+38 -16
View File
@@ -18,7 +18,7 @@
import copy import copy
from math import atan2, degrees, pi, radians from math import atan2, degrees, pi, radians
from typing import Any, Literal, Optional, Union from typing import TYPE_CHECKING, Any, Literal, Optional, Union
import bpy import bpy
import ifcopenshell import ifcopenshell
@@ -49,7 +49,7 @@ ProfileFrom2PointsReturn = Union[dict[str, Any], None]
class DumbProfileGenerator: class DumbProfileGenerator:
def __init__(self, relating_type): def __init__(self, relating_type: ifcopenshell.entity_instance):
self.relating_type = relating_type self.relating_type = relating_type
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
@@ -201,7 +201,7 @@ class DumbProfileGenerator:
class DumbProfileRegenerator: class DumbProfileRegenerator:
def regenerate_from_profile_def(self, profile): def regenerate_from_profile_def(self, profile: ifcopenshell.entity_instance) -> None:
self.file = tool.Ifc.get() self.file = tool.Ifc.get()
objs = [] objs = []
if not profile: if not profile:
@@ -221,7 +221,7 @@ class DumbProfileRegenerator:
for element in self.get_element_types_using_profile(profile): for element in self.get_element_types_using_profile(profile):
tool.Model.mark_thumbnail_for_update(element) tool.Model.mark_thumbnail_for_update(element)
def regenerate_from_profile(self, usecase_path, ifc_file, settings): def regenerate_from_profile(self, usecase_path: str, ifc_file: ifcopenshell.file, settings: dict[str, Any]) -> None:
self.file = ifc_file self.file = ifc_file
objs = [] objs = []
profile = settings["profile"].Profile profile = settings["profile"].Profile
@@ -233,7 +233,7 @@ class DumbProfileRegenerator:
objs.append(obj) objs.append(obj)
DumbProfileRecalculator().recalculate(objs) DumbProfileRecalculator().recalculate(objs)
def get_elements_using_profile(self, profile): def get_elements_using_profile(self, profile: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
results = [] results = []
profile_sets = [ profile_sets = [
mp.ToMaterialProfileSet[0] for mp in self.file.get_inverse(profile) if mp.is_a("IfcMaterialProfile") mp.ToMaterialProfileSet[0] for mp in self.file.get_inverse(profile) if mp.is_a("IfcMaterialProfile")
@@ -252,7 +252,7 @@ class DumbProfileRegenerator:
results.extend(rel.RelatedObjects) results.extend(rel.RelatedObjects)
return results return results
def get_element_types_using_profile(self, profile): def get_element_types_using_profile(self, profile: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
results = [] results = []
profile_sets = [ profile_sets = [
mp.ToMaterialProfileSet[0] for mp in self.file.get_inverse(profile) if mp.is_a("IfcMaterialProfile") mp.ToMaterialProfileSet[0] for mp in self.file.get_inverse(profile) if mp.is_a("IfcMaterialProfile")
@@ -269,12 +269,18 @@ class ExtendProfile(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.extend_profile" bl_idname = "bim.extend_profile"
bl_label = "Extend Profile" bl_label = "Extend Profile"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
join_type: bpy.props.StringProperty() join_type: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration]
items=[("-", "Unjoin", ""), ("L", "L", ""), ("V", "V", ""), ("T", "T", "")],
default="-",
)
if TYPE_CHECKING:
join_type: Literal["-", "L", "V", "T"]
def _execute(self, context): def _execute(self, context):
selected_objs = context.selected_objects selected_objs = context.selected_objects
joiner = DumbProfileJoiner() joiner = DumbProfileJoiner()
if not self.join_type: if self.join_type == "-":
for obj in selected_objs: for obj in selected_objs:
joiner.unjoin(obj) joiner.unjoin(obj)
return {"FINISHED"} return {"FINISHED"}
@@ -626,11 +632,15 @@ class DumbProfileJoiner:
if connection1 == "ATEND": if connection1 == "ATEND":
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
plane = self.get_profile_plane(profile2, furthest_plane) plane = self.get_profile_plane(profile2, furthest_plane)
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
self.body[1] = intersect self.body[1] = intersect
else: else:
plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False) plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False)
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
max_dim = self.get_max_bound_box_dimension(profile1) max_dim = self.get_max_bound_box_dimension(profile1)
self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
@@ -673,11 +683,15 @@ class DumbProfileJoiner:
elif connection1 == "ATSTART": elif connection1 == "ATSTART":
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
plane = self.get_profile_plane(profile2, furthest_plane) plane = self.get_profile_plane(profile2, furthest_plane)
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
self.body[0] = intersect self.body[0] = intersect
else: else:
plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False) plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False)
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
max_dim = self.get_max_bound_box_dimension(profile1) max_dim = self.get_max_bound_box_dimension(profile1)
self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
@@ -721,7 +735,9 @@ class DumbProfileJoiner:
if connection1 == "ATEND": if connection1 == "ATEND":
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane) plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane)
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
self.body[1] = intersect self.body[1] = intersect
else: else:
plane = self.get_profile_plane( plane = self.get_profile_plane(
@@ -729,7 +745,9 @@ class DumbProfileJoiner:
furthest_plane if is_relating else closest_plane, furthest_plane if is_relating else closest_plane,
z_inwards=False if is_relating else True, z_inwards=False if is_relating else True,
) )
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
max_dim = self.get_max_bound_box_dimension(profile1) max_dim = self.get_max_bound_box_dimension(profile1)
self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
self.clippings.append( self.clippings.append(
@@ -742,7 +760,9 @@ class DumbProfileJoiner:
elif connection1 == "ATSTART": elif connection1 == "ATSTART":
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane) plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane)
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
self.body[0] = intersect self.body[0] = intersect
else: else:
plane = self.get_profile_plane( plane = self.get_profile_plane(
@@ -750,7 +770,9 @@ class DumbProfileJoiner:
furthest_plane if is_relating else closest_plane, furthest_plane if is_relating else closest_plane,
z_inwards=False if is_relating else True, z_inwards=False if is_relating else True,
) )
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) intersect = mathutils.geometry.intersect_line_plane(
axis1[0], axis1[1], plane.translation, plane.col[2].to_3d()
)
max_dim = self.get_max_bound_box_dimension(profile1) max_dim = self.get_max_bound_box_dimension(profile1)
self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
self.clippings.append( self.clippings.append(
@@ -28,6 +28,7 @@ import ifcopenshell.util.representation
import ifcopenshell.util.unit import ifcopenshell.util.unit
import ifcopenshell.util.unit as ifcunit import ifcopenshell.util.unit as ifcunit
import numpy as np import numpy as np
import numpy.typing as npt
from mathutils import Vector from mathutils import Vector
import bonsai.tool as tool import bonsai.tool as tool
@@ -478,7 +479,7 @@ class ShaderInfo:
"""get the args to the point shader""" """get the args to the point shader"""
location = np.array(location) location = np.array(location)
indices = [] indices = []
direction_dict = { direction_dict: dict[str, tuple[npt.NDArray, ...]] = {
"fx": (np.array((1, 0, 0)), np.array((0, 1, 0)), np.array((0, 0, 1))), "fx": (np.array((1, 0, 0)), np.array((0, 1, 0)), np.array((0, 0, 1))),
"fy": (np.array((0, 1, 0)), np.array((1, 0, 0)), np.array((0, 0, 1))), "fy": (np.array((0, 1, 0)), np.array((1, 0, 0)), np.array((0, 0, 1))),
"fz": (np.array((0, 0, 1)), np.array((0, 1, 0)), np.array((1, 0, 0))), "fz": (np.array((0, 0, 1)), np.array((0, 1, 0)), np.array((1, 0, 0))),
+4 -2
View File
@@ -32,6 +32,8 @@ import bonsai.core.tool
import bonsai.tool as tool import bonsai.tool as tool
if TYPE_CHECKING: if TYPE_CHECKING:
from bsdd.bsdd import ClassContractV1, ClassPropertyContractV1, PropertyContractV5
from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDDictionary from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDDictionary
@@ -39,8 +41,8 @@ class Bsdd(bonsai.core.tool.Bsdd):
default_identifier_url = "https://identifier.buildingsmart.org" default_identifier_url = "https://identifier.buildingsmart.org"
default_api_url = "https://api.bsdd.buildingsmart.org/api/" default_api_url = "https://api.bsdd.buildingsmart.org/api/"
client = bsdd.Client() client = bsdd.Client()
bsdd_classes: dict[str, dict] = {} bsdd_classes: dict[str, ClassContractV1] = {}
bsdd_properties: dict[str, dict] = {} bsdd_properties: dict[str, ClassPropertyContractV1 | PropertyContractV5] = {}
@classmethod @classmethod
def identifier_url(cls) -> str: def identifier_url(cls) -> str:
@@ -199,11 +199,13 @@ def open(
for ty in bypass_types: for ty in bypass_types:
f.bypass_type(ty) f.bypass_type(ty)
if mmap: if mmap:
f.initialize(str(path.absolute()), mmap=mmap) # mmap parameter is only available for builds with USE_MMAP, not used in our main builds
f.initialize(str(path.absolute()), mmap=mmap) # type: ignore[unknown-argument]
else: else:
f.initialize(str(path.absolute())) f.initialize(str(path.absolute()))
elif mmap: elif mmap:
f = ifcopenshell_wrapper.open(str(path.absolute()), mmap=mmap) # mmap parameter is only available for builds with USE_MMAP, not used in our main builds
f = ifcopenshell_wrapper.open(str(path.absolute()), mmap=mmap) # type: ignore[unknown-argument]
else: else:
f = ifcopenshell_wrapper.open(str(path.absolute())) f = ifcopenshell_wrapper.open(str(path.absolute()))
return file(f) return file(f)