mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +00:00
black formatting and changes in shader typing
This commit is contained in:
committed by
Dion Moult
parent
80996dee1f
commit
dff9f56ce3
@@ -32,6 +32,7 @@ def refresh():
|
|||||||
BoundaryConditionsData.is_loaded = False
|
BoundaryConditionsData.is_loaded = False
|
||||||
LoadGroupDecorationData.is_loaded = False
|
LoadGroupDecorationData.is_loaded = False
|
||||||
|
|
||||||
|
|
||||||
class LoadGroupDecorationData:
|
class LoadGroupDecorationData:
|
||||||
data = {}
|
data = {}
|
||||||
is_loaded = False
|
is_loaded = False
|
||||||
@@ -44,11 +45,12 @@ class LoadGroupDecorationData:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def load_groups_to_show(cls):
|
def load_groups_to_show(cls):
|
||||||
ret = []
|
ret = []
|
||||||
abrv = {"LOAD_CASE": "L.Case: ",
|
abrv = {
|
||||||
|
"LOAD_CASE": "L.Case: ",
|
||||||
"LOAD_COMBINATION": "L.Comb: ",
|
"LOAD_COMBINATION": "L.Comb: ",
|
||||||
"LOAD_GROUP": "L.Gr: ",
|
"LOAD_GROUP": "L.Gr: ",
|
||||||
"USERDEFINED": "U.Def: ",
|
"USERDEFINED": "U.Def: ",
|
||||||
"NOTDEFINED": "N.Def: "
|
"NOTDEFINED": "N.Def: ",
|
||||||
}
|
}
|
||||||
models = tool.Ifc.get().by_type("IfcStructuralAnalysisModel")
|
models = tool.Ifc.get().by_type("IfcStructuralAnalysisModel")
|
||||||
m = models[0]
|
m = models[0]
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ from gpu_extras.batch import batch_for_shader
|
|||||||
from typing import Iterable, Union
|
from typing import Iterable, Union
|
||||||
from bonsai.bim.module.structural.load_decoration_data import ShaderInfo
|
from bonsai.bim.module.structural.load_decoration_data import ShaderInfo
|
||||||
|
|
||||||
|
|
||||||
class LoadsDecorator:
|
class LoadsDecorator:
|
||||||
"""Decorator to show strucutural loads in 3D"""
|
"""Decorator to show strucutural loads in 3D"""
|
||||||
|
|
||||||
is_installed = False
|
is_installed = False
|
||||||
handlers = []
|
handlers = []
|
||||||
decoration_data = None
|
decoration_data = None
|
||||||
@@ -68,8 +70,8 @@ class LoadsDecorator:
|
|||||||
# set open gl configurations
|
# set open gl configurations
|
||||||
original_blend = gpu.state.blend_get()
|
original_blend = gpu.state.blend_get()
|
||||||
original_depth_test = gpu.state.depth_test_get()
|
original_depth_test = gpu.state.depth_test_get()
|
||||||
gpu.state.blend_set('ALPHA')
|
gpu.state.blend_set("ALPHA")
|
||||||
gpu.state.depth_test_set('LESS_EQUAL')
|
gpu.state.depth_test_set("LESS_EQUAL")
|
||||||
|
|
||||||
self.draw_batch()
|
self.draw_batch()
|
||||||
|
|
||||||
@@ -84,7 +86,7 @@ class LoadsDecorator:
|
|||||||
shader = info["shader"]
|
shader = info["shader"]
|
||||||
args = info["args"]
|
args = info["args"]
|
||||||
indices = info["indices"]
|
indices = info["indices"]
|
||||||
batch = batch_for_shader(shader, 'TRIS', args, indices=indices)
|
batch = batch_for_shader(shader, "TRIS", args, indices=indices)
|
||||||
matrix = bpy.context.region_data.perspective_matrix
|
matrix = bpy.context.region_data.perspective_matrix
|
||||||
shader.bind()
|
shader.bind()
|
||||||
shader.uniform_float("viewProjectionMatrix", matrix)
|
shader.uniform_float("viewProjectionMatrix", matrix)
|
||||||
@@ -129,15 +131,23 @@ class LoadsDecorator:
|
|||||||
view_matrix = rv3d.view_matrix
|
view_matrix = rv3d.view_matrix
|
||||||
point_view_space = view_matrix @ coord
|
point_view_space = view_matrix @ coord
|
||||||
|
|
||||||
|
if perspective == "ORTHO" or -10 < point_view_space.z < 0:
|
||||||
if perspective == 'ORTHO' or -10 < point_view_space.z < 0:
|
|
||||||
prj = rv3d.perspective_matrix @ Vector((coord[0], coord[1], coord[2], 1.0))
|
prj = rv3d.perspective_matrix @ Vector((coord[0], coord[1], coord[2], 1.0))
|
||||||
width_half = context.region.width / 2.0
|
width_half = context.region.width / 2.0
|
||||||
height_half = context.region.height / 2.0
|
height_half = context.region.height / 2.0
|
||||||
coord_2d = Vector((width_half + width_half * (prj.x / prj.w),
|
coord_2d = Vector(
|
||||||
|
(
|
||||||
|
width_half + width_half * (prj.x / prj.w),
|
||||||
height_half + height_half * (prj.y / prj.w),
|
height_half + height_half * (prj.y / prj.w),
|
||||||
point_view_space.z))
|
point_view_space.z,
|
||||||
if coord_2d[0] < 0 or coord_2d[0]> context.region.width or coord_2d[1] > context.region.height or coord_2d[1] < 0:
|
)
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
coord_2d[0] < 0
|
||||||
|
or coord_2d[0] > context.region.width
|
||||||
|
or coord_2d[1] > context.region.height
|
||||||
|
or coord_2d[1] < 0
|
||||||
|
):
|
||||||
return None
|
return None
|
||||||
depth = self.depth_array[int(coord_2d[1])][int(coord_2d[0])]
|
depth = self.depth_array[int(coord_2d[1])][int(coord_2d[0])]
|
||||||
if -0.98 * point_view_space.z > depth:
|
if -0.98 * point_view_space.z > depth:
|
||||||
|
|||||||
@@ -30,38 +30,35 @@ from bonsai.bim.ifc import IfcStore
|
|||||||
from bonsai.bim.module.structural.shader import DecorationShader
|
from bonsai.bim.module.structural.shader import DecorationShader
|
||||||
from typing import Literal, TypedDict, Iterable
|
from typing import Literal, TypedDict, Iterable
|
||||||
|
|
||||||
MemberInfo = TypedDict("MemberInfo",
|
MemberInfo = TypedDict(
|
||||||
{"member": ifcopenshell.entity_instance,
|
"MemberInfo",
|
||||||
"activities": list[tuple[ifcopenshell.entity_instance,float]]})
|
{"member": ifcopenshell.entity_instance, "activities": list[tuple[ifcopenshell.entity_instance, float]]},
|
||||||
|
)
|
||||||
|
|
||||||
LoadConfigItem = TypedDict("LoadConfigItem",
|
LoadConfigItem = TypedDict(
|
||||||
{"pos": float,
|
"LoadConfigItem", {"pos": float, "descr": Literal["start", "end", "middle"], "load values": np.ndarray}
|
||||||
"descr": Literal["start","end", "middle"],
|
)
|
||||||
"load values":np.ndarray})
|
|
||||||
|
|
||||||
DiscreteConfigItem = TypedDict("DiscreteConfigItem",
|
DiscreteConfigItem = TypedDict("DiscreteConfigItem", {"pos": float, "values": list[float]})
|
||||||
{"pos": float,
|
|
||||||
"values": list[float]})
|
|
||||||
|
|
||||||
ParsedLoad = TypedDict("ParsedLoad",
|
ParsedLoad = TypedDict(
|
||||||
{"constant force": list[float],
|
"ParsedLoad",
|
||||||
|
{
|
||||||
|
"constant force": list[float],
|
||||||
"quadratic force": list[float],
|
"quadratic force": list[float],
|
||||||
"sinus force": list[float],
|
"sinus force": list[float],
|
||||||
"linear load configuration": list[list[LoadConfigItem]],
|
"linear load configuration": list[list[LoadConfigItem]],
|
||||||
"point load configuration": list[list[DiscreteConfigItem]]
|
"point load configuration": list[list[DiscreteConfigItem]],
|
||||||
})
|
},
|
||||||
LoadByDirection = TypedDict("LoadByDirection",
|
)
|
||||||
{"constant": float,
|
LoadByDirection = TypedDict(
|
||||||
"quadratic": float,
|
"LoadByDirection", {"constant": float, "quadratic": float, "sinus": float, "polyline": list[list[float]]}
|
||||||
"sinus": float,
|
)
|
||||||
"polyline":list[list[float]]})
|
|
||||||
|
|
||||||
ProcessedLoad = TypedDict("ProcessedLoad",
|
|
||||||
{"linear loads":LoadByDirection,
|
|
||||||
"max linear load": float,
|
|
||||||
"discrete loads": list[list[DiscreteConfigItem]]})
|
|
||||||
|
|
||||||
|
|
||||||
|
ProcessedLoad = TypedDict(
|
||||||
|
"ProcessedLoad",
|
||||||
|
{"linear loads": LoadByDirection, "max linear load": float, "discrete loads": list[list[DiscreteConfigItem]]},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ShaderInfo:
|
class ShaderInfo:
|
||||||
@@ -125,7 +122,7 @@ class ShaderInfo:
|
|||||||
"PASCAL": "Pa",
|
"PASCAL": "Pa",
|
||||||
# conversion based units
|
# conversion based units
|
||||||
"pound-force": "lbf",
|
"pound-force": "lbf",
|
||||||
'pound-force per square inch': "psi",
|
"pound-force per square inch": "psi",
|
||||||
"thou": "th",
|
"thou": "th",
|
||||||
"inch": "in",
|
"inch": "in",
|
||||||
"foot": "ft",
|
"foot": "ft",
|
||||||
@@ -170,16 +167,11 @@ class ShaderInfo:
|
|||||||
symbol += unit_symbols.get(unit.Name.replace("METER", "METRE"), "?")
|
symbol += unit_symbols.get(unit.Name.replace("METER", "METRE"), "?")
|
||||||
return symbol
|
return symbol
|
||||||
|
|
||||||
length_units = [u for u in tool.Ifc.get().by_type("IfcNamedUnit")
|
length_units = [u for u in tool.Ifc.get().by_type("IfcNamedUnit") if u.UnitType == "LENGTHUNIT"]
|
||||||
if u.UnitType == "LENGTHUNIT"]
|
force_units = [u for u in tool.Ifc.get().by_type("IfcNamedUnit") if u.UnitType == "FORCEUNIT"]
|
||||||
force_units = [u for u in tool.Ifc.get().by_type("IfcNamedUnit")
|
linear_force_units = [u for u in tool.Ifc.get().by_type("IfcDerivedUnit") if u.UnitType == "LINEARFORCEUNIT"]
|
||||||
if u.UnitType == "FORCEUNIT"]
|
linear_moment_units = [u for u in tool.Ifc.get().by_type("IfcDerivedUnit") if u.UnitType == "LINEARMOMENTUNIT"]
|
||||||
linear_force_units = [u for u in tool.Ifc.get().by_type("IfcDerivedUnit")
|
planar_force_units = [u for u in tool.Ifc.get().by_type("IfcDerivedUnit") if u.UnitType == "PLANARFORCEUNIT"]
|
||||||
if u.UnitType == "LINEARFORCEUNIT"]
|
|
||||||
linear_moment_units = [u for u in tool.Ifc.get().by_type("IfcDerivedUnit")
|
|
||||||
if u.UnitType == "LINEARMOMENTUNIT"]
|
|
||||||
planar_force_units = [u for u in tool.Ifc.get().by_type("IfcDerivedUnit")
|
|
||||||
if u.UnitType == "PLANARFORCEUNIT"]
|
|
||||||
|
|
||||||
conversion_force_unit = [u for u in force_units if u.is_a("IfcConversionBasedUnit")]
|
conversion_force_unit = [u for u in force_units if u.is_a("IfcConversionBasedUnit")]
|
||||||
if len(conversion_force_unit) == 0:
|
if len(conversion_force_unit) == 0:
|
||||||
@@ -224,10 +216,12 @@ class ShaderInfo:
|
|||||||
def get_strucutural_elements_and_activities(self) -> None:
|
def get_strucutural_elements_and_activities(self) -> None:
|
||||||
"""fills self.point_members, self.curve_members and self.surface_members dictionaries"""
|
"""fills self.point_members, self.curve_members and self.surface_members dictionaries"""
|
||||||
|
|
||||||
def populate_members_dict(dict_name: Literal["point_members", "curve_members", "surface_members"],
|
def populate_members_dict(
|
||||||
|
dict_name: Literal["point_members", "curve_members", "surface_members"],
|
||||||
element: ifcopenshell.entity_instance,
|
element: ifcopenshell.entity_instance,
|
||||||
activity: ifcopenshell.entity_instance,
|
activity: ifcopenshell.entity_instance,
|
||||||
factor: float) -> None:
|
factor: float,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
fills self.point_members, self.curve_members and self.surface_members dictionaries
|
fills self.point_members, self.curve_members and self.surface_members dictionaries
|
||||||
thoses dicts will contain the strucutural member global id as key and a second dict as value
|
thoses dicts will contain the strucutural member global id as key and a second dict as value
|
||||||
@@ -246,18 +240,16 @@ class ShaderInfo:
|
|||||||
return
|
return
|
||||||
member = dic.get(element.GlobalId)
|
member = dic.get(element.GlobalId)
|
||||||
if member is None:
|
if member is None:
|
||||||
dic.update({
|
dic.update({element.GlobalId: {"member": element, "activities": [(activity, factor)]}})
|
||||||
element.GlobalId: {
|
|
||||||
"member": element,
|
|
||||||
"activities": [(activity,factor)]}
|
|
||||||
})
|
|
||||||
else:
|
else:
|
||||||
member["activities"].append((activity, factor))
|
member["activities"].append((activity, factor))
|
||||||
|
|
||||||
def recursive_subgroups(groups: list[ifcopenshell.entity_instance],
|
def recursive_subgroups(
|
||||||
|
groups: list[ifcopenshell.entity_instance],
|
||||||
rec_limit: int,
|
rec_limit: int,
|
||||||
activity_type: Literal["Action", "External Reaction"],
|
activity_type: Literal["Action", "External Reaction"],
|
||||||
factor: float = 1) -> None:
|
factor: float = 1,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Recursively fills self.point_members, self.curve_members and self.surface_members dictionaries
|
Recursively fills self.point_members, self.curve_members and self.surface_members dictionaries
|
||||||
with the structural members to wich the activities in the load group and its subgroups are applied
|
with the structural members to wich the activities in the load group and its subgroups are applied
|
||||||
@@ -278,7 +270,7 @@ class ShaderInfo:
|
|||||||
subgorups = []
|
subgorups = []
|
||||||
activities = []
|
activities = []
|
||||||
relationship = [rel for rel in group.IsGroupedBy]
|
relationship = [rel for rel in group.IsGroupedBy]
|
||||||
coef = getattr(group, 'Coefficient', 1.0)
|
coef = getattr(group, "Coefficient", 1.0)
|
||||||
group_coef = coef if coef is not None else 1.0
|
group_coef = coef if coef is not None else 1.0
|
||||||
rel_factor = 1.0
|
rel_factor = 1.0
|
||||||
|
|
||||||
@@ -301,7 +293,10 @@ class ShaderInfo:
|
|||||||
elif element.is_a("IfcStructuralSurfaceMember"):
|
elif element.is_a("IfcStructuralSurfaceMember"):
|
||||||
populate_members_dict("surface_members", element, activity, factor)
|
populate_members_dict("surface_members", element, activity, factor)
|
||||||
|
|
||||||
elif activity_type == "External Reaction" and getattr(element,"AppliedCondition",None) is not None:
|
elif (
|
||||||
|
activity_type == "External Reaction"
|
||||||
|
and getattr(element, "AppliedCondition", None) is not None
|
||||||
|
):
|
||||||
if element.is_a("IfcStructuralCurveMember"):
|
if element.is_a("IfcStructuralCurveMember"):
|
||||||
populate_members_dict("curve_members", element, activity, factor)
|
populate_members_dict("curve_members", element, activity, factor)
|
||||||
elif element.is_a("IfcStructuralPointConnection"):
|
elif element.is_a("IfcStructuralPointConnection"):
|
||||||
@@ -338,7 +333,7 @@ class ShaderInfo:
|
|||||||
orientation = np.eye(3)
|
orientation = np.eye(3)
|
||||||
if reference_frame == "LOCAL_COORDS":
|
if reference_frame == "LOCAL_COORDS":
|
||||||
orientation = rotation
|
orientation = rotation
|
||||||
blender_object: bpy.types.Object = IfcStore.get_element(getattr(surf, 'GlobalId', None))
|
blender_object: bpy.types.Object = IfcStore.get_element(getattr(surf, "GlobalId", None))
|
||||||
mat = blender_object.matrix_world
|
mat = blender_object.matrix_world
|
||||||
mesh: bpy.types.Mesh = blender_object.data
|
mesh: bpy.types.Mesh = blender_object.data
|
||||||
|
|
||||||
@@ -362,23 +357,19 @@ class ShaderInfo:
|
|||||||
for e in bm.edges:
|
for e in bm.edges:
|
||||||
if len(e.link_faces) > 1:
|
if len(e.link_faces) > 1:
|
||||||
continue
|
continue
|
||||||
indices.append((2*e.verts[0].index,
|
indices.append((2 * e.verts[0].index, 2 * e.verts[0].index + 1, 2 * e.verts[1].index))
|
||||||
2*e.verts[0].index+1,
|
indices.append((2 * e.verts[0].index + 1, 2 * e.verts[1].index, 2 * e.verts[1].index + 1))
|
||||||
2*e.verts[1].index))
|
|
||||||
indices.append((2*e.verts[0].index+1,
|
|
||||||
2*e.verts[1].index,
|
|
||||||
2*e.verts[1].index+1))
|
|
||||||
for p in bm.faces:
|
for p in bm.faces:
|
||||||
indices.append((2*p.verts[0].index+1,
|
indices.append((2 * p.verts[0].index + 1, 2 * p.verts[1].index + 1, 2 * p.verts[2].index + 1))
|
||||||
2*p.verts[1].index+1,
|
|
||||||
2*p.verts[2].index+1))
|
|
||||||
bmesh.ops.dissolve_limit(bm, angle_limit=0.01, verts=bm.verts, edges=bm.edges)
|
bmesh.ops.dissolve_limit(bm, angle_limit=0.01, verts=bm.verts, edges=bm.edges)
|
||||||
bm.faces.ensure_lookup_table()
|
bm.faces.ensure_lookup_table()
|
||||||
center = bm.faces[0].calc_center_bounds()
|
center = bm.faces[0].calc_center_bounds()
|
||||||
|
|
||||||
self.text_info.append(
|
self.text_info.append(
|
||||||
{"position": mat @ center - Vector((orientation@values)*0.2/maximum),
|
{
|
||||||
"text": f'{values[2]:.5f} {self.planar_force_unit}'}
|
"position": mat @ center - Vector((orientation @ values) * 0.2 / maximum),
|
||||||
|
"text": f"{values[2]:.5f} {self.planar_force_unit}",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
self.info.append(
|
self.info.append(
|
||||||
@@ -386,12 +377,13 @@ class ShaderInfo:
|
|||||||
"shader": shader,
|
"shader": shader,
|
||||||
"args": {"position": positions, "coord": coord},
|
"args": {"position": positions, "coord": coord},
|
||||||
"indices": indices,
|
"indices": indices,
|
||||||
"uniforms": [["color", (0.2,0,1,1)],["spacing", 0.2]]
|
"uniforms": [["color", (0.2, 0, 1, 1)], ["spacing", 0.2]],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
def get_planar_loads_values(self,
|
|
||||||
activity_list: list[tuple[ifcopenshell.entity_instance,float]],
|
def get_planar_loads_values(
|
||||||
element_rotation_matrix: np.ndarray) -> np.ndarray:
|
self, activity_list: list[tuple[ifcopenshell.entity_instance, float]], element_rotation_matrix: np.ndarray
|
||||||
|
) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
returns a numpy array with the sum of the values of structural activities
|
returns a numpy array with the sum of the values of structural activities
|
||||||
applied loads in each direction, multiplied by the factors in load combinations
|
applied loads in each direction, multiplied by the factors in load combinations
|
||||||
@@ -411,9 +403,7 @@ class ShaderInfo:
|
|||||||
values += transform @ temp
|
values += transform @ temp
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def get_surface_member_rotation(self,
|
def get_surface_member_rotation(self, surface_member: ifcopenshell.entity_instance) -> np.ndarray:
|
||||||
surface_member: ifcopenshell.entity_instance
|
|
||||||
) -> np.ndarray:
|
|
||||||
"""returns the rotation matrix of a structural surface member"""
|
"""returns the rotation matrix of a structural surface member"""
|
||||||
representation = ifcopenshell.util.representation.get_representation(surface_member, "Model")
|
representation = ifcopenshell.util.representation.get_representation(surface_member, "Model")
|
||||||
repr_item = representation.Items[0]
|
repr_item = representation.Items[0]
|
||||||
@@ -421,9 +411,7 @@ class ShaderInfo:
|
|||||||
rotation = placement[0:3, 0:3]
|
rotation = placement[0:3, 0:3]
|
||||||
return rotation
|
return rotation
|
||||||
|
|
||||||
def get_point_connection_rotation(self,
|
def get_point_connection_rotation(self, point_connection: ifcopenshell.entity_instance) -> np.ndarray:
|
||||||
point_connection: ifcopenshell.entity_instance
|
|
||||||
) -> np.ndarray:
|
|
||||||
"""returns the rotation matrix of a structural point connection"""
|
"""returns the rotation matrix of a structural point connection"""
|
||||||
if point_connection.ConditionCoordinateSystem is not None:
|
if point_connection.ConditionCoordinateSystem is not None:
|
||||||
placement = ifcopenshell.util.placement.get_axis2placement(point_connection.ConditionCoordinateSystem)
|
placement = ifcopenshell.util.placement.get_axis2placement(point_connection.ConditionCoordinateSystem)
|
||||||
@@ -432,9 +420,7 @@ class ShaderInfo:
|
|||||||
rotation = placement[0:3, 0:3]
|
rotation = placement[0:3, 0:3]
|
||||||
return rotation
|
return rotation
|
||||||
|
|
||||||
def get_curve_member_rotation(self,
|
def get_curve_member_rotation(self, curve_member: ifcopenshell.entity_instance) -> np.ndarray:
|
||||||
curve_member: ifcopenshell.entity_instance
|
|
||||||
) -> np.ndarray:
|
|
||||||
"""returns the rotation matrix of a structural surface member"""
|
"""returns the rotation matrix of a structural surface member"""
|
||||||
z = curve_member.Axis.DirectionRatios
|
z = curve_member.Axis.DirectionRatios
|
||||||
edge = curve_member.Representation.Representations[0].Items[0]
|
edge = curve_member.Representation.Representations[0].Items[0]
|
||||||
@@ -445,18 +431,17 @@ class ShaderInfo:
|
|||||||
rotation = placement[0:3, 0:3]
|
rotation = placement[0:3, 0:3]
|
||||||
return rotation
|
return rotation
|
||||||
|
|
||||||
def get_activity_transform_matrix(self,
|
def get_activity_transform_matrix(
|
||||||
activity: ifcopenshell.entity_instance,
|
self, activity: ifcopenshell.entity_instance, element_rotation_matrix: np.ndarray
|
||||||
element_rotation_matrix: np.ndarray
|
|
||||||
) -> np.ndarray:
|
) -> np.ndarray:
|
||||||
"provides the transformation matrix to convert between reference frames"
|
"provides the transformation matrix to convert between reference frames"
|
||||||
global_or_local = activity.GlobalOrLocal
|
global_or_local = activity.GlobalOrLocal
|
||||||
props = bpy.context.scene.BIMStructuralProperties
|
props = bpy.context.scene.BIMStructuralProperties
|
||||||
reference_frame = props.reference_frame
|
reference_frame = props.reference_frame
|
||||||
transform_matrix = np.eye(3)
|
transform_matrix = np.eye(3)
|
||||||
if reference_frame == 'LOCAL_COORDS' and global_or_local != reference_frame:
|
if reference_frame == "LOCAL_COORDS" and global_or_local != reference_frame:
|
||||||
transform_matrix = np.linalg.inv(element_rotation_matrix)
|
transform_matrix = np.linalg.inv(element_rotation_matrix)
|
||||||
elif reference_frame == 'GLOBAL_COORDS' and global_or_local != reference_frame:
|
elif reference_frame == "GLOBAL_COORDS" and global_or_local != reference_frame:
|
||||||
transform_matrix = element_rotation_matrix
|
transform_matrix = element_rotation_matrix
|
||||||
return transform_matrix
|
return transform_matrix
|
||||||
|
|
||||||
@@ -469,18 +454,14 @@ class ShaderInfo:
|
|||||||
activity_list = value["activities"]
|
activity_list = value["activities"]
|
||||||
if len(activity_list) == 0:
|
if len(activity_list) == 0:
|
||||||
continue
|
continue
|
||||||
blender_object = IfcStore.get_element(getattr(conn, 'GlobalId', None))
|
blender_object = IfcStore.get_element(getattr(conn, "GlobalId", None))
|
||||||
if blender_object.type == 'MESH':
|
if blender_object.type == "MESH":
|
||||||
conn_location = blender_object.matrix_world @ blender_object.data.vertices[0].co
|
conn_location = blender_object.matrix_world @ blender_object.data.vertices[0].co
|
||||||
rotation = self.get_point_connection_rotation(conn)
|
rotation = self.get_point_connection_rotation(conn)
|
||||||
loads = self.get_point_loads_values(activity_list, rotation)
|
loads = self.get_point_loads_values(activity_list, rotation)
|
||||||
self.get_point_shader_args(loads, conn_location, rotation)
|
self.get_point_shader_args(loads, conn_location, rotation)
|
||||||
|
|
||||||
def get_point_shader_args(self,
|
def get_point_shader_args(self, loads: Iterable, location: np.ndarray, rotation: np.ndarray) -> None:
|
||||||
loads: Iterable,
|
|
||||||
location: np.ndarray,
|
|
||||||
rotation: np.ndarray
|
|
||||||
) -> None:
|
|
||||||
"""get the args to the point shader"""
|
"""get the args to the point shader"""
|
||||||
location = np.array(location)
|
location = np.array(location)
|
||||||
indices = []
|
indices = []
|
||||||
@@ -533,13 +514,10 @@ class ShaderInfo:
|
|||||||
"shader": shader,
|
"shader": shader,
|
||||||
"args": {"position": position, "coord": coords_for_shader},
|
"args": {"position": position, "coord": coords_for_shader},
|
||||||
"indices": indices,
|
"indices": indices,
|
||||||
"uniforms": [["color", color],["spacing", 0.2]]
|
"uniforms": [["color", color], ["spacing", 0.2]],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.text_info.append(
|
self.text_info.append({"position": location + d1, "text": f"{loads[i]:.2f} {self.force_unit}"})
|
||||||
{"position": location + d1,
|
|
||||||
"text": f'{loads[i]:.2f} {self.force_unit}'}
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
d2 = d2 = direction_dict[key][1]
|
d2 = d2 = direction_dict[key][1]
|
||||||
p1 = location - d2
|
p1 = location - d2
|
||||||
@@ -557,20 +535,19 @@ class ShaderInfo:
|
|||||||
"shader": shader,
|
"shader": shader,
|
||||||
"args": {"position": position, "coord": coords_for_shader},
|
"args": {"position": position, "coord": coords_for_shader},
|
||||||
"indices": indices,
|
"indices": indices,
|
||||||
"uniforms": [["color", color]]
|
"uniforms": [["color", color]],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.text_info.append(
|
self.text_info.append(
|
||||||
{"position": location +0.25*(d1 + d2),
|
{"position": location + 0.25 * (d1 + d2), "text": f"{loads[i]:.2f} {self.moment_unit}"}
|
||||||
"text": f'{loads[i]:.2f} {self.moment_unit}'}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_point_loads_values(self,
|
def get_point_loads_values(
|
||||||
activity_list: list[tuple[ifcopenshell.entity_instance,float]],
|
self, activity_list: list[tuple[ifcopenshell.entity_instance, float]], element_rotation_matrix: np.ndarray
|
||||||
element_rotation_matrix: np.ndarray) -> np.ndarray:
|
) -> np.ndarray:
|
||||||
"""returns a numpy array with the sum of the point load values"""
|
"""returns a numpy array with the sum of the point load values"""
|
||||||
result_list = np.zeros(6)
|
result_list = np.zeros(6)
|
||||||
attr_list = ['ForceX','ForceY','ForceZ','MomentX','MomentY','MomentZ']
|
attr_list = ["ForceX", "ForceY", "ForceZ", "MomentX", "MomentY", "MomentZ"]
|
||||||
for item in activity_list:
|
for item in activity_list:
|
||||||
activity = item[0]
|
activity = item[0]
|
||||||
factor = item[1]
|
factor = item[1]
|
||||||
@@ -587,7 +564,6 @@ class ShaderInfo:
|
|||||||
|
|
||||||
return result_list
|
return result_list
|
||||||
|
|
||||||
|
|
||||||
def get_linear_loads(self) -> None:
|
def get_linear_loads(self) -> None:
|
||||||
position = []
|
position = []
|
||||||
indices = []
|
indices = []
|
||||||
@@ -604,22 +580,21 @@ class ShaderInfo:
|
|||||||
if len(activity_list) == 0:
|
if len(activity_list) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
blender_object = IfcStore.get_element(getattr(member, 'GlobalId', None))
|
blender_object = IfcStore.get_element(getattr(member, "GlobalId", None))
|
||||||
|
|
||||||
start_co = blender_object.matrix_world @ blender_object.data.vertices[0].co
|
start_co = blender_object.matrix_world @ blender_object.data.vertices[0].co
|
||||||
end_co = blender_object.matrix_world @ blender_object.data.vertices[1].co
|
end_co = blender_object.matrix_world @ blender_object.data.vertices[1].co
|
||||||
x_axis = Vector(end_co - start_co).normalized()
|
x_axis = Vector(end_co - start_co).normalized()
|
||||||
z_direction = getattr(member, 'Axis')
|
z_direction = getattr(member, "Axis")
|
||||||
# local coordinates
|
# local coordinates
|
||||||
z_axis = Vector(getattr(z_direction, 'DirectionRatios', None)).normalized()
|
z_axis = Vector(getattr(z_direction, "DirectionRatios", None)).normalized()
|
||||||
y_axis = z_axis.cross(x_axis).normalized()
|
y_axis = z_axis.cross(x_axis).normalized()
|
||||||
z_axis = x_axis.cross(y_axis).normalized()
|
z_axis = x_axis.cross(y_axis).normalized()
|
||||||
rotation = self.get_curve_member_rotation(member)
|
rotation = self.get_curve_member_rotation(member)
|
||||||
|
|
||||||
|
|
||||||
props = bpy.context.scene.BIMStructuralProperties
|
props = bpy.context.scene.BIMStructuralProperties
|
||||||
reference_frame = props.reference_frame
|
reference_frame = props.reference_frame
|
||||||
is_local = reference_frame == 'LOCAL_COORDS'
|
is_local = reference_frame == "LOCAL_COORDS"
|
||||||
x_match = abs(Vector((1, 0, 0)).dot(x_axis)) > 0.99
|
x_match = abs(Vector((1, 0, 0)).dot(x_axis)) > 0.99
|
||||||
y_match = abs(Vector((0, 1, 0)).dot(x_axis)) > 0.99
|
y_match = abs(Vector((0, 1, 0)).dot(x_axis)) > 0.99
|
||||||
z_match = abs(Vector((0, 0, 1)).dot(x_axis)) > 0.99
|
z_match = abs(Vector((0, 0, 1)).dot(x_axis)) > 0.99
|
||||||
@@ -628,10 +603,18 @@ class ShaderInfo:
|
|||||||
"fy": y_axis if is_local else Vector((0, 1, 0)) if not y_match else Vector((1, 0, 1)),
|
"fy": y_axis if is_local else Vector((0, 1, 0)) if not y_match else Vector((1, 0, 1)),
|
||||||
"fz": z_axis if is_local else Vector((0, 0, 1)) if not z_match else Vector((1, 1, 0)),
|
"fz": z_axis if is_local else Vector((0, 0, 1)) if not z_match else Vector((1, 1, 0)),
|
||||||
"mx": z_axis - y_axis if is_local or x_match else Vector((1, 0, 0)).cross(x_axis),
|
"mx": z_axis - y_axis if is_local or x_match else Vector((1, 0, 0)).cross(x_axis),
|
||||||
"my": z_axis if is_local else Vector((-1,0,1)) if y_match else Vector((0,1,0)).cross(x_axis).normalized(),
|
"my": (
|
||||||
"mz": y_axis if is_local else Vector((-1,1,0)) if z_match else Vector((0,0,1)).cross(x_axis).normalized()
|
z_axis
|
||||||
|
if is_local
|
||||||
|
else Vector((-1, 0, 1)) if y_match else Vector((0, 1, 0)).cross(x_axis).normalized()
|
||||||
|
),
|
||||||
|
"mz": (
|
||||||
|
y_axis
|
||||||
|
if is_local
|
||||||
|
else Vector((-1, 1, 0)) if z_match else Vector((0, 0, 1)).cross(x_axis).normalized()
|
||||||
|
),
|
||||||
}
|
}
|
||||||
match_dict = {'fx': x_match or is_local, 'fy': y_match, 'fz': z_match}
|
match_dict = {"fx": x_match or is_local, "fy": y_match, "fz": z_match}
|
||||||
member_length = Vector(end_co - start_co).length
|
member_length = Vector(end_co - start_co).length
|
||||||
processed_loads = self.process_total_linear_loads(activity_list, rotation, member_length)
|
processed_loads = self.process_total_linear_loads(activity_list, rotation, member_length)
|
||||||
linear_loads = processed_loads["linear loads"]
|
linear_loads = processed_loads["linear loads"]
|
||||||
@@ -656,12 +639,12 @@ class ShaderInfo:
|
|||||||
constant = linear_loads[key]["constant"]
|
constant = linear_loads[key]["constant"]
|
||||||
direction = direction_dict[key]
|
direction = direction_dict[key]
|
||||||
color_axis = (0, 0, 1, 1)
|
color_axis = (0, 0, 1, 1)
|
||||||
if 'x' in key:
|
if "x" in key:
|
||||||
color_axis = (1, 0, 0, 1)
|
color_axis = (1, 0, 0, 1)
|
||||||
if 'y' in key:
|
if "y" in key:
|
||||||
color_axis = (0, 1, 0, 1)
|
color_axis = (0, 1, 0, 1)
|
||||||
|
|
||||||
if 'f' in key:
|
if "f" in key:
|
||||||
unit = self.linear_force_unit
|
unit = self.linear_force_unit
|
||||||
if match_dict[key]:
|
if match_dict[key]:
|
||||||
shader = self.shader.new("PARALLEL DISTRIBUTED FORCE")
|
shader = self.shader.new("PARALLEL DISTRIBUTED FORCE")
|
||||||
@@ -685,11 +668,13 @@ class ShaderInfo:
|
|||||||
color.append(color_axis)
|
color.append(color_axis)
|
||||||
|
|
||||||
x = current.x / member_length
|
x = current.x / member_length
|
||||||
func = sin(x*3.1416)*sinus + (-4.*x*x+4.*x)*quadratic+constant+current.y
|
func = sin(x * 3.1416) * sinus + (-4.0 * x * x + 4.0 * x) * quadratic + constant + current.y
|
||||||
if func:
|
if func:
|
||||||
self.text_info.append(
|
self.text_info.append(
|
||||||
{"position": -1*direction*func/maxforce + start_co + x_axis*current.x,
|
{
|
||||||
"text": f'{func:.2f} {unit}'}
|
"position": -1 * direction * func / maxforce + start_co + x_axis * current.x,
|
||||||
|
"text": f"{func:.2f} {unit}",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
position.append(positive)
|
position.append(positive)
|
||||||
@@ -697,12 +682,8 @@ class ShaderInfo:
|
|||||||
sin_quad_lin.append((sinus, quadratic, current.y + constant))
|
sin_quad_lin.append((sinus, quadratic, current.y + constant))
|
||||||
color.append(color_axis)
|
color.append(color_axis)
|
||||||
|
|
||||||
indices.append((0 + counter,
|
indices.append((0 + counter, 1 + counter, 2 + counter))
|
||||||
1 + counter,
|
indices.append((3 + counter, 2 + counter, 1 + counter))
|
||||||
2 + counter))
|
|
||||||
indices.append((3 + counter,
|
|
||||||
2 + counter,
|
|
||||||
1 + counter))
|
|
||||||
if i == len(polyline) - 2:
|
if i == len(polyline) - 2:
|
||||||
negative = -1 * direction + start_co + x_axis * nextitem.x
|
negative = -1 * direction + start_co + x_axis * nextitem.x
|
||||||
positive = direction + start_co + x_axis * nextitem.x
|
positive = direction + start_co + x_axis * nextitem.x
|
||||||
@@ -712,11 +693,15 @@ class ShaderInfo:
|
|||||||
color.append(color_axis)
|
color.append(color_axis)
|
||||||
|
|
||||||
x = nextitem.x / member_length
|
x = nextitem.x / member_length
|
||||||
func = sin(x*3.1416)*sinus + (-4.*x*x+4.*x)*quadratic+constant+nextitem.y
|
func = (
|
||||||
|
sin(x * 3.1416) * sinus + (-4.0 * x * x + 4.0 * x) * quadratic + constant + nextitem.y
|
||||||
|
)
|
||||||
if func:
|
if func:
|
||||||
self.text_info.append(
|
self.text_info.append(
|
||||||
{"position": -1*direction*func/maxforce + start_co + x_axis*nextitem.x,
|
{
|
||||||
"text": f'{func:.2f} {unit}'}
|
"position": -1 * direction * func / maxforce + start_co + x_axis * nextitem.x,
|
||||||
|
"text": f"{func:.2f} {unit}",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
position.append(positive)
|
position.append(positive)
|
||||||
@@ -729,9 +714,13 @@ class ShaderInfo:
|
|||||||
self.info.append(
|
self.info.append(
|
||||||
{
|
{
|
||||||
"shader": shader,
|
"shader": shader,
|
||||||
"args": {"position": position, "sin_quad_lin_forces": sin_quad_lin,"coord": coords_for_shader},
|
"args": {
|
||||||
|
"position": position,
|
||||||
|
"sin_quad_lin_forces": sin_quad_lin,
|
||||||
|
"coord": coords_for_shader,
|
||||||
|
},
|
||||||
"indices": indices,
|
"indices": indices,
|
||||||
"uniforms": [["color", color_axis],["spacing", 0.2],["maxload",maxforce]]
|
"uniforms": [["color", color_axis], ["spacing", 0.2], ["maxload", maxforce]],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
position = []
|
position = []
|
||||||
@@ -741,11 +730,12 @@ class ShaderInfo:
|
|||||||
for info in self.info:
|
for info in self.info:
|
||||||
info["uniforms"][2][1] = maxforce
|
info["uniforms"][2][1] = maxforce
|
||||||
|
|
||||||
|
def process_total_linear_loads(
|
||||||
def process_total_linear_loads(self,
|
self,
|
||||||
activity_list: list[tuple[ifcopenshell.entity_instance, float]],
|
activity_list: list[tuple[ifcopenshell.entity_instance, float]],
|
||||||
element_rotation_matrix: np.ndarray,
|
element_rotation_matrix: np.ndarray,
|
||||||
member_length: float) -> ProcessedLoad:
|
member_length: float,
|
||||||
|
) -> ProcessedLoad:
|
||||||
"""returns a dict with total values for applied loads in each direction
|
"""returns a dict with total values for applied loads in each direction
|
||||||
along with the maximum value for the loads in the member and the discrete loads applied
|
along with the maximum value for the loads in the member and the discrete loads applied
|
||||||
|
|
||||||
@@ -772,7 +762,9 @@ class ShaderInfo:
|
|||||||
final_list.append([member_length, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
|
final_list.append([member_length, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
|
||||||
|
|
||||||
elif len(final_list) > 0:
|
elif len(final_list) > 0:
|
||||||
if final_list[0][0] and any(const+quad+sinus): #if first item location is not 0 append an item at the zero
|
if final_list[0][0] and any(
|
||||||
|
const + quad + sinus
|
||||||
|
): # if first item location is not 0 append an item at the zero
|
||||||
final_list = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] + final_list
|
final_list = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] + final_list
|
||||||
else:
|
else:
|
||||||
del final_list[0]
|
del final_list[0]
|
||||||
@@ -794,12 +786,16 @@ class ShaderInfo:
|
|||||||
}
|
}
|
||||||
max_load = 0
|
max_load = 0
|
||||||
for component, key in enumerate(keys):
|
for component, key in enumerate(keys):
|
||||||
if(any([sinus[component], quad[component], const[component]]) or
|
if any([sinus[component], quad[component], const[component]]) or any(
|
||||||
any(item for item in array[:,component+1])):
|
item for item in array[:, component + 1]
|
||||||
|
):
|
||||||
|
|
||||||
for currentitem in final_list:
|
for currentitem in final_list:
|
||||||
polyline.append([currentitem[0], currentitem[component + 1]])
|
polyline.append([currentitem[0], currentitem[component + 1]])
|
||||||
max_load = max(max_load,abs(sinus[component]+quad[component]+const[component]+currentitem[component+1]))
|
max_load = max(
|
||||||
|
max_load,
|
||||||
|
abs(sinus[component] + quad[component] + const[component] + currentitem[component + 1]),
|
||||||
|
)
|
||||||
inner_dict = distributed_loads[key]
|
inner_dict = distributed_loads[key]
|
||||||
inner_dict["constant"] = const[component]
|
inner_dict["constant"] = const[component]
|
||||||
inner_dict["quadratic"] = quad[component]
|
inner_dict["quadratic"] = quad[component]
|
||||||
@@ -807,10 +803,11 @@ class ShaderInfo:
|
|||||||
inner_dict["polyline"] = polyline
|
inner_dict["polyline"] = polyline
|
||||||
distributed_loads[key] = inner_dict
|
distributed_loads[key] = inner_dict
|
||||||
|
|
||||||
return {"linear loads":distributed_loads,
|
return {
|
||||||
|
"linear loads": distributed_loads,
|
||||||
"max linear load": max_load,
|
"max linear load": max_load,
|
||||||
"discrete loads": loads_dict["point load configuration"]}
|
"discrete loads": loads_dict["point load configuration"],
|
||||||
|
}
|
||||||
|
|
||||||
def getuniquepositionlist(self, load_config_list: list[list[LoadConfigItem]]) -> list[float]:
|
def getuniquepositionlist(self, load_config_list: list[list[LoadConfigItem]]) -> list[float]:
|
||||||
"""return an ordereded list of unique locations based on the load configuration list
|
"""return an ordereded list of unique locations based on the load configuration list
|
||||||
@@ -843,10 +840,7 @@ class ShaderInfo:
|
|||||||
result[i] = self.interp1d(value1, value2, pos) # interpolated [position, force_component]
|
result[i] = self.interp1d(value1, value2, pos) # interpolated [position, force_component]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_before_and_after(self,
|
def get_before_and_after(self, pos: float, load_config_list: list[list[LoadConfigItem]]) -> dict[str, list[float]]:
|
||||||
pos: float,
|
|
||||||
load_config_list:list[list[LoadConfigItem]]
|
|
||||||
) -> dict[str,list[float]]:
|
|
||||||
"""get total values for forces and moments before and after the position
|
"""get total values for forces and moments before and after the position
|
||||||
example:
|
example:
|
||||||
pos = 2.0
|
pos = 2.0
|
||||||
@@ -873,17 +867,17 @@ class ShaderInfo:
|
|||||||
if pos < config[start]["pos"] or pos > config[end]["pos"]:
|
if pos < config[start]["pos"] or pos > config[end]["pos"]:
|
||||||
break
|
break
|
||||||
if config[start]["pos"] == pos:
|
if config[start]["pos"] == pos:
|
||||||
if config[start]["descr"] in ['start','middle']:
|
if config[start]["descr"] in ["start", "middle"]:
|
||||||
load_after += config[start]["load values"]
|
load_after += config[start]["load values"]
|
||||||
|
|
||||||
elif config[start]["descr"] in ['end','middle']:
|
elif config[start]["descr"] in ["end", "middle"]:
|
||||||
load_before += config[start]["load values"]
|
load_before += config[start]["load values"]
|
||||||
|
|
||||||
elif config[end]["pos"] == pos:
|
elif config[end]["pos"] == pos:
|
||||||
if config[end]["descr"] in ['start','middle']:
|
if config[end]["descr"] in ["start", "middle"]:
|
||||||
load_after += config[end]["load values"]
|
load_after += config[end]["load values"]
|
||||||
|
|
||||||
elif config[end]["descr"] in ['end','middle']:
|
elif config[end]["descr"] in ["end", "middle"]:
|
||||||
load_before += config[end]["load values"]
|
load_before += config[end]["load values"]
|
||||||
|
|
||||||
elif end - start == 1:
|
elif end - start == 1:
|
||||||
@@ -891,15 +885,12 @@ class ShaderInfo:
|
|||||||
load_after += self.interpolate(pos, config, start, end, "load values")
|
load_after += self.interpolate(pos, config, start, end, "load values")
|
||||||
start += 1
|
start += 1
|
||||||
end -= 1
|
end -= 1
|
||||||
return_value = {
|
return_value = {"before": load_before.tolist(), "after": load_after.tolist()}
|
||||||
"before": load_before.tolist(),
|
|
||||||
"after": load_after.tolist()
|
|
||||||
}
|
|
||||||
return return_value
|
return return_value
|
||||||
|
|
||||||
def parse_linear_loads_to_dict(self,
|
def parse_linear_loads_to_dict(
|
||||||
activity_list: list[tuple[ifcopenshell.entity_instance,float]],
|
self, activity_list: list[tuple[ifcopenshell.entity_instance, float]], element_rotation_matrix: np.ndarray
|
||||||
element_rotation_matrix: np.ndarray) -> ParsedLoad:
|
) -> ParsedLoad:
|
||||||
"""
|
"""
|
||||||
get load list
|
get load list
|
||||||
activity_list: list of IfcStructuralCurveAction or IfcStructuralCurveReaction
|
activity_list: list of IfcStructuralCurveAction or IfcStructuralCurveReaction
|
||||||
@@ -938,7 +929,7 @@ class ShaderInfo:
|
|||||||
|
|
||||||
def get_load_values(load, transform_matrix, factor=1.0):
|
def get_load_values(load, transform_matrix, factor=1.0):
|
||||||
result = np.zeros(6)
|
result = np.zeros(6)
|
||||||
keys = ['LinearForceX','LinearForceY','LinearForceZ','LinearMomentX','LinearMomentY','LinearMomentZ']
|
keys = ["LinearForceX", "LinearForceY", "LinearForceZ", "LinearMomentX", "LinearMomentY", "LinearMomentZ"]
|
||||||
for i, key in enumerate(keys):
|
for i, key in enumerate(keys):
|
||||||
value = 0 if getattr(load, key, 0) is None else getattr(load, key, 0)
|
value = 0 if getattr(load, key, 0) is None else getattr(load, key, 0)
|
||||||
result[i] += value * factor
|
result[i] += value * factor
|
||||||
@@ -955,58 +946,48 @@ class ShaderInfo:
|
|||||||
transform_6by6[3:6, 3:6] = transform_3by3
|
transform_6by6[3:6, 3:6] = transform_3by3
|
||||||
|
|
||||||
# values for linear loads
|
# values for linear loads
|
||||||
if load.is_a('IfcStructuralLoadConfiguration'):
|
if load.is_a("IfcStructuralLoadConfiguration"):
|
||||||
locations = getattr(load, 'Locations', [])
|
locations = getattr(load, "Locations", [])
|
||||||
values = [l for l in getattr(load, 'Values', None)
|
values = [l for l in getattr(load, "Values", None) if l.is_a() == "IfcStructuralLoadLinearForce"]
|
||||||
if l.is_a() == "IfcStructuralLoadLinearForce"
|
|
||||||
]
|
|
||||||
config_list = []
|
config_list = []
|
||||||
for i, l in enumerate(values):
|
for i, l in enumerate(values):
|
||||||
load_values = get_load_values(l, transform_6by6, factor)
|
load_values = get_load_values(l, transform_6by6, factor)
|
||||||
if i == 0:
|
if i == 0:
|
||||||
descr = 'start'
|
descr = "start"
|
||||||
elif i == len(values) - 1:
|
elif i == len(values) - 1:
|
||||||
descr = 'end'
|
descr = "end"
|
||||||
else:
|
else:
|
||||||
descr = 'middle'
|
descr = "middle"
|
||||||
config_list.append(
|
config_list.append(
|
||||||
{"pos": locations[i][0]*unit_scale,
|
{"pos": locations[i][0] * unit_scale, "descr": descr, "load values": load_values}
|
||||||
"descr": descr,
|
|
||||||
"load values":load_values}
|
|
||||||
)
|
)
|
||||||
linear_load_configurations.append(config_list)
|
linear_load_configurations.append(config_list)
|
||||||
|
|
||||||
# load configurations with point loads
|
# load configurations with point loads
|
||||||
values = [l for l in getattr(load, 'Values', None)
|
values = [l for l in getattr(load, "Values", None) if l.is_a() == "IfcStructuralLoadSingleForce"]
|
||||||
if l.is_a() == "IfcStructuralLoadSingleForce"
|
attr_list = ["ForceX", "ForceY", "ForceZ", "MomentX", "MomentY", "MomentZ"]
|
||||||
]
|
|
||||||
attr_list = ['ForceX','ForceY','ForceZ','MomentX','MomentY','MomentZ']
|
|
||||||
config_list = []
|
config_list = []
|
||||||
for i, val in enumerate(values):
|
for i, val in enumerate(values):
|
||||||
result_list = [0, 0, 0, 0, 0, 0]
|
result_list = [0, 0, 0, 0, 0, 0]
|
||||||
for j, attr in enumerate(attr_list):
|
for j, attr in enumerate(attr_list):
|
||||||
value = 0 if getattr(val, attr, 0) is None else getattr(val, attr, 0)
|
value = 0 if getattr(val, attr, 0) is None else getattr(val, attr, 0)
|
||||||
result_list[j] += value * factor
|
result_list[j] += value * factor
|
||||||
config_list.append(
|
config_list.append({"pos": locations[i][0] * unit_scale, "values": result_list})
|
||||||
{"pos": locations[i][0]*unit_scale,
|
|
||||||
"values": result_list}
|
|
||||||
)
|
|
||||||
point_load_configurations.append(config_list)
|
point_load_configurations.append(config_list)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
load_values = get_load_values(load, transform_6by6, factor)
|
load_values = get_load_values(load, transform_6by6, factor)
|
||||||
if 'CONST' == getattr(activity, 'PredefinedType', None) or activity.is_a('IfcStructuralLinearAction'):
|
if "CONST" == getattr(activity, "PredefinedType", None) or activity.is_a("IfcStructuralLinearAction"):
|
||||||
constant += load_values
|
constant += load_values
|
||||||
elif 'PARABOLA' == getattr(activity, 'PredefinedType', None):
|
elif "PARABOLA" == getattr(activity, "PredefinedType", None):
|
||||||
quadratic += load_values
|
quadratic += load_values
|
||||||
elif 'SINUS' == getattr(activity, 'PredefinedType', None):
|
elif "SINUS" == getattr(activity, "PredefinedType", None):
|
||||||
sinus += load_values
|
sinus += load_values
|
||||||
return_value = {
|
return_value = {
|
||||||
"constant force": constant.tolist(),
|
"constant force": constant.tolist(),
|
||||||
"quadratic force": quadratic.tolist(),
|
"quadratic force": quadratic.tolist(),
|
||||||
"sinus force": sinus.tolist(),
|
"sinus force": sinus.tolist(),
|
||||||
"linear load configuration": linear_load_configurations,
|
"linear load configuration": linear_load_configurations,
|
||||||
"point load configuration": point_load_configurations
|
"point load configuration": point_load_configurations,
|
||||||
}
|
}
|
||||||
return return_value
|
return return_value
|
||||||
|
|
||||||
|
|||||||
@@ -29,24 +29,26 @@ from mathutils import Vector, Matrix
|
|||||||
from bonsai.bim.ifc import IfcStore
|
from bonsai.bim.ifc import IfcStore
|
||||||
from bonsai.bim.module.structural.decorator import LoadsDecorator
|
from bonsai.bim.module.structural.decorator import LoadsDecorator
|
||||||
|
|
||||||
|
|
||||||
class ShowLoads(bpy.types.Operator):
|
class ShowLoads(bpy.types.Operator):
|
||||||
"""Draw decorations to show strucutural actions in 3d view"""
|
"""Draw decorations to show strucutural actions in 3d view"""
|
||||||
|
|
||||||
bl_idname = "bim.show_loads"
|
bl_idname = "bim.show_loads"
|
||||||
bl_label = "Show loads in 3D View"
|
bl_label = "Show loads in 3D View"
|
||||||
|
|
||||||
def modal(self, context, event):
|
def modal(self, context, event):
|
||||||
if event.type == 'F5':
|
if event.type == "F5":
|
||||||
LoadsDecorator.update()
|
LoadsDecorator.update()
|
||||||
for area in context.screen.areas:
|
for area in context.screen.areas:
|
||||||
if area.type == 'VIEW_3D':
|
if area.type == "VIEW_3D":
|
||||||
area.tag_redraw()
|
area.tag_redraw()
|
||||||
if event.type == 'ESC':
|
if event.type == "ESC":
|
||||||
LoadsDecorator.uninstall()
|
LoadsDecorator.uninstall()
|
||||||
for area in context.screen.areas:
|
for area in context.screen.areas:
|
||||||
if area.type == 'VIEW_3D':
|
if area.type == "VIEW_3D":
|
||||||
area.tag_redraw()
|
area.tag_redraw()
|
||||||
return {'FINISHED'}
|
return {"FINISHED"}
|
||||||
return {'PASS_THROUGH'}
|
return {"PASS_THROUGH"}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
collection = bpy.data.collections["IfcStructuralItem"]
|
collection = bpy.data.collections["IfcStructuralItem"]
|
||||||
@@ -60,10 +62,10 @@ class ShowLoads(bpy.types.Operator):
|
|||||||
context.window.cursor_modal_restore()
|
context.window.cursor_modal_restore()
|
||||||
context.window_manager.modal_handler_add(self)
|
context.window_manager.modal_handler_add(self)
|
||||||
for area in context.screen.areas:
|
for area in context.screen.areas:
|
||||||
if area.type == 'VIEW_3D':
|
if area.type == "VIEW_3D":
|
||||||
area.tag_redraw()
|
area.tag_redraw()
|
||||||
|
|
||||||
return {'RUNNING_MODAL'}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
|
||||||
class AddStructuralMemberConnection(bpy.types.Operator, tool.Ifc.Operator):
|
class AddStructuralMemberConnection(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
|||||||
@@ -21,7 +21,12 @@ import bpy
|
|||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bonsai.bim.ifc import IfcStore
|
from bonsai.bim.ifc import IfcStore
|
||||||
from bonsai.bim.prop import StrProperty, Attribute
|
from bonsai.bim.prop import StrProperty, Attribute
|
||||||
from bonsai.bim.module.structural.data import StructuralLoadCasesData, StructuralLoadsData, BoundaryConditionsData, LoadGroupDecorationData
|
from bonsai.bim.module.structural.data import (
|
||||||
|
StructuralLoadCasesData,
|
||||||
|
StructuralLoadsData,
|
||||||
|
BoundaryConditionsData,
|
||||||
|
LoadGroupDecorationData,
|
||||||
|
)
|
||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
PointerProperty,
|
PointerProperty,
|
||||||
@@ -34,14 +39,17 @@ from bpy.props import (
|
|||||||
CollectionProperty,
|
CollectionProperty,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_load_groups_to_show(self, context):
|
def get_load_groups_to_show(self, context):
|
||||||
if not LoadGroupDecorationData.is_loaded:
|
if not LoadGroupDecorationData.is_loaded:
|
||||||
LoadGroupDecorationData.load()
|
LoadGroupDecorationData.load()
|
||||||
return LoadGroupDecorationData.data["load groups to show"]
|
return LoadGroupDecorationData.data["load groups to show"]
|
||||||
|
|
||||||
|
|
||||||
def update_activity_type(self, context):
|
def update_activity_type(self, context):
|
||||||
LoadGroupDecorationData.is_loaded = False
|
LoadGroupDecorationData.is_loaded = False
|
||||||
|
|
||||||
|
|
||||||
def get_applicable_structural_load_types(self, context):
|
def get_applicable_structural_load_types(self, context):
|
||||||
if not StructuralLoadCasesData.is_loaded:
|
if not StructuralLoadCasesData.is_loaded:
|
||||||
StructuralLoadCasesData.load()
|
StructuralLoadCasesData.load()
|
||||||
@@ -162,13 +170,22 @@ class BIMStructuralProperties(PropertyGroup):
|
|||||||
show_loads: BoolProperty(name="Show Loads", default=False)
|
show_loads: BoolProperty(name="Show Loads", default=False)
|
||||||
update_load_repr: BoolProperty(name="Update Load Representation", default=False)
|
update_load_repr: BoolProperty(name="Update Load Representation", default=False)
|
||||||
enable_repr_auto_update: BoolProperty(name="Auto Update", default=False)
|
enable_repr_auto_update: BoolProperty(name="Auto Update", default=False)
|
||||||
reference_frame: EnumProperty(items=[("GLOBAL_COORDS","Global","Show loads in global reference frame"),
|
reference_frame: EnumProperty(
|
||||||
("LOCAL_COORDS","Local","Show loads in local reference frame")], name= "Reference Frame")
|
items=[
|
||||||
activity_type: EnumProperty(items=[("Action","Actions","Show actions loads"),
|
("GLOBAL_COORDS", "Global", "Show loads in global reference frame"),
|
||||||
|
("LOCAL_COORDS", "Local", "Show loads in local reference frame"),
|
||||||
|
],
|
||||||
|
name="Reference Frame",
|
||||||
|
)
|
||||||
|
activity_type: EnumProperty(
|
||||||
|
items=[
|
||||||
|
("Action", "Actions", "Show actions loads"),
|
||||||
("External Reaction", "External Reactions", "Show reactions on boundary conditions"),
|
("External Reaction", "External Reactions", "Show reactions on boundary conditions"),
|
||||||
("Internal Reactions","Internal Reactions","Show internal reactions on members")],
|
("Internal Reactions", "Internal Reactions", "Show internal reactions on members"),
|
||||||
|
],
|
||||||
name="Activity Type",
|
name="Activity Type",
|
||||||
update=update_activity_type)
|
update=update_activity_type,
|
||||||
|
)
|
||||||
load_group_to_show: EnumProperty(items=get_load_groups_to_show, name="Load Groups")
|
load_group_to_show: EnumProperty(items=get_load_groups_to_show, name="Load Groups")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,20 @@
|
|||||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import gpu
|
import gpu
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
class DecorationShader:
|
class DecorationShader:
|
||||||
"shader for the load decorations"
|
"shader for the load decorations"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
def new(self, pattern: str) -> gpu.types.GPUShader:
|
|
||||||
|
def new(self, pattern: Literal["PERPENDICULAR DISTRIBUTED FORCE",
|
||||||
|
"PARALLEL DISTRIBUTED FORCE",
|
||||||
|
"DISTRIBUTED MOMENT",
|
||||||
|
"SINGLE FORCE",
|
||||||
|
"SINGLE MOMENT",
|
||||||
|
"PLANAR LOAD",]) -> gpu.types.GPUShader:
|
||||||
"""pattern: string description of the desired shader
|
"""pattern: string description of the desired shader
|
||||||
Possible values
|
Possible values
|
||||||
PERPENDICULAR DISTRIBUTED FORCE: pattern for distributed force
|
PERPENDICULAR DISTRIBUTED FORCE: pattern for distributed force
|
||||||
@@ -34,21 +42,24 @@ class DecorationShader:
|
|||||||
SINGLE MOMENT: pattern for single moments
|
SINGLE MOMENT: pattern for single moments
|
||||||
PLANAR LOAD: pattern for planar loads
|
PLANAR LOAD: pattern for planar loads
|
||||||
"""
|
"""
|
||||||
valid_patterns = {"PERPENDICULAR DISTRIBUTED FORCE",
|
valid_patterns = {
|
||||||
|
"PERPENDICULAR DISTRIBUTED FORCE",
|
||||||
"PARALLEL DISTRIBUTED FORCE",
|
"PARALLEL DISTRIBUTED FORCE",
|
||||||
"DISTRIBUTED MOMENT",
|
"DISTRIBUTED MOMENT",
|
||||||
"SINGLE FORCE",
|
"SINGLE FORCE",
|
||||||
"SINGLE MOMENT",
|
"SINGLE MOMENT",
|
||||||
"PLANAR LOAD"
|
"PLANAR LOAD",
|
||||||
}
|
}
|
||||||
if pattern not in valid_patterns:
|
if pattern not in valid_patterns:
|
||||||
raise ValueError("""pattern must be one of:
|
raise ValueError(
|
||||||
|
"""pattern must be one of:
|
||||||
PERPENDICULAR DISTRIBUTED FORCE
|
PERPENDICULAR DISTRIBUTED FORCE
|
||||||
PARALLEL DISTRIBUTED FORCE,
|
PARALLEL DISTRIBUTED FORCE,
|
||||||
DISTRIBUTED MOMENT,
|
DISTRIBUTED MOMENT,
|
||||||
SINGLE FORCE,
|
SINGLE FORCE,
|
||||||
SINGLE MOMENT,
|
SINGLE MOMENT,
|
||||||
PLANAR LOAD""")
|
PLANAR LOAD"""
|
||||||
|
)
|
||||||
if "DISTRIBUTED" in pattern.upper():
|
if "DISTRIBUTED" in pattern.upper():
|
||||||
shader = self.get_linear_shader(pattern)
|
shader = self.get_linear_shader(pattern)
|
||||||
return shader
|
return shader
|
||||||
@@ -59,28 +70,30 @@ class DecorationShader:
|
|||||||
shader = self.get_planar_shader()
|
shader = self.get_planar_shader()
|
||||||
return shader
|
return shader
|
||||||
|
|
||||||
def get_linear_shader(self, pattern: str) -> gpu.types.GPUShader:
|
def get_linear_shader(self, pattern: Literal["PERPENDICULAR DISTRIBUTED FORCE",
|
||||||
|
"PARALLEL DISTRIBUTED FORCE",
|
||||||
|
"DISTRIBUTED MOMENT"]) -> gpu.types.GPUShader:
|
||||||
"""pattern: type of pattern
|
"""pattern: type of pattern
|
||||||
PERPENDICULAR DISTRIBUTED FORCE
|
PERPENDICULAR DISTRIBUTED FORCE
|
||||||
PARALLEL DISTRIBUTED FORCE,
|
PARALLEL DISTRIBUTED FORCE,
|
||||||
DISTRIBUTED MOMENT,
|
DISTRIBUTED MOMENT,
|
||||||
"""
|
"""
|
||||||
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
|
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
|
||||||
vert_out.smooth('VEC3', "forces")
|
vert_out.smooth("VEC3", "forces")
|
||||||
vert_out.smooth('VEC3', "co")
|
vert_out.smooth("VEC3", "co")
|
||||||
|
|
||||||
shader_info = gpu.types.GPUShaderCreateInfo()
|
shader_info = gpu.types.GPUShaderCreateInfo()
|
||||||
shader_info.push_constant('MAT4', "viewProjectionMatrix")
|
shader_info.push_constant("MAT4", "viewProjectionMatrix")
|
||||||
shader_info.push_constant('VEC4', "color")
|
shader_info.push_constant("VEC4", "color")
|
||||||
shader_info.push_constant('FLOAT', "spacing")
|
shader_info.push_constant("FLOAT", "spacing")
|
||||||
shader_info.push_constant('FLOAT', "maxload")
|
shader_info.push_constant("FLOAT", "maxload")
|
||||||
|
|
||||||
shader_info.vertex_in(0, 'VEC3', "position")
|
shader_info.vertex_in(0, "VEC3", "position")
|
||||||
shader_info.vertex_in(1, 'VEC3', "sin_quad_lin_forces")
|
shader_info.vertex_in(1, "VEC3", "sin_quad_lin_forces")
|
||||||
shader_info.vertex_in(2, 'VEC3', "coord")
|
shader_info.vertex_in(2, "VEC3", "coord")
|
||||||
|
|
||||||
shader_info.vertex_out(vert_out)
|
shader_info.vertex_out(vert_out)
|
||||||
shader_info.fragment_out(0, 'VEC4', "FragColor")
|
shader_info.fragment_out(0, "VEC4", "FragColor")
|
||||||
|
|
||||||
shader_info.vertex_source(
|
shader_info.vertex_source(
|
||||||
"void main()"
|
"void main()"
|
||||||
@@ -98,11 +111,9 @@ class DecorationShader:
|
|||||||
"float x = co.x;"
|
"float x = co.x;"
|
||||||
"float y = co.y;"
|
"float y = co.y;"
|
||||||
"float abs_y = abs(y);"
|
"float abs_y = abs(y);"
|
||||||
|
|
||||||
"float a = abs(mod(x,spacing)-0.5*spacing)*5.0;"
|
"float a = abs(mod(x,spacing)-0.5*spacing)*5.0;"
|
||||||
"float b = step(a,abs_y)*(step(abs_y,1.2*spacing));"
|
"float b = step(a,abs_y)*(step(abs_y,1.2*spacing));"
|
||||||
"float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));"
|
"float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));"
|
||||||
|
|
||||||
"float sinvalue = forces.x;"
|
"float sinvalue = forces.x;"
|
||||||
"float quadraticvalue = forces.y;"
|
"float quadraticvalue = forces.y;"
|
||||||
"float linearvalue = forces.z;"
|
"float linearvalue = forces.z;"
|
||||||
@@ -111,7 +122,6 @@ class DecorationShader:
|
|||||||
"+(-4.*x*x+4.*x)*quadraticvalue"
|
"+(-4.*x*x+4.*x)*quadraticvalue"
|
||||||
"+linearvalue)/maxload;"
|
"+linearvalue)/maxload;"
|
||||||
"float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);"
|
"float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);"
|
||||||
|
|
||||||
"float top = step(abs(y-f),0.2*1.2*spacing);"
|
"float top = step(abs(y-f),0.2*1.2*spacing);"
|
||||||
"float d = clamp(top+b+c,0.0,0.9)*mask;"
|
"float d = clamp(top+b+c,0.0,0.9)*mask;"
|
||||||
"if (d == 0.0) discard;"
|
"if (d == 0.0) discard;"
|
||||||
@@ -126,7 +136,6 @@ class DecorationShader:
|
|||||||
"float y = co.y;"
|
"float y = co.y;"
|
||||||
"float x = step(0.,y)*(co.z-co.x)+step(y,0.)*(co.x);"
|
"float x = step(0.,y)*(co.z-co.x)+step(y,0.)*(co.x);"
|
||||||
"float abs_y = abs(y);"
|
"float abs_y = abs(y);"
|
||||||
|
|
||||||
"float a = abs(mod(abs_y,spacing)-0.5*spacing)*5.0;"
|
"float a = abs(mod(abs_y,spacing)-0.5*spacing)*5.0;"
|
||||||
"float a2 = mod(x,3.0*spacing);"
|
"float a2 = mod(x,3.0*spacing);"
|
||||||
"float b = step(a,a2)*step(a2,1.2*spacing);"
|
"float b = step(a,a2)*step(a2,1.2*spacing);"
|
||||||
@@ -140,7 +149,6 @@ class DecorationShader:
|
|||||||
"+(-4.*x*x+4.*x)*quadraticvalue"
|
"+(-4.*x*x+4.*x)*quadraticvalue"
|
||||||
"+linearvalue)/maxload;"
|
"+linearvalue)/maxload;"
|
||||||
"float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);"
|
"float mask = step(0.,y)*step(y,f)+step(y,0.)*step(f,y);"
|
||||||
|
|
||||||
"float top = step(abs(y-f),0.2*1.2*spacing);"
|
"float top = step(abs(y-f),0.2*1.2*spacing);"
|
||||||
"float d = clamp(top+b+c,0.0,0.9)*mask;"
|
"float d = clamp(top+b+c,0.0,0.9)*mask;"
|
||||||
"if (d == 0.0) discard;"
|
"if (d == 0.0) discard;"
|
||||||
@@ -159,16 +167,13 @@ class DecorationShader:
|
|||||||
"float abs_y = abs(y);"
|
"float abs_y = abs(y);"
|
||||||
"vec2 st = vec2(1.9*x,y);"
|
"vec2 st = vec2(1.9*x,y);"
|
||||||
"vec2 orig = vec2(0.,0.);"
|
"vec2 orig = vec2(0.,0.);"
|
||||||
|
|
||||||
"float circ = step(distance(st,orig),0.33)*step(0.27,distance(st,orig));"
|
"float circ = step(distance(st,orig),0.33)*step(0.27,distance(st,orig));"
|
||||||
"float tri_mask = step(st.y,st.x)+step(-st.x,st.y);"
|
"float tri_mask = step(st.y,st.x)+step(-st.x,st.y);"
|
||||||
"float circ_arrow = step(st.x,4.0*st.y-0.75)*step(0.25*st.y-0.34,st.x)*(1.-tri_mask);"
|
"float circ_arrow = step(st.x,4.0*st.y-0.75)*step(0.25*st.y-0.34,st.x)*(1.-tri_mask);"
|
||||||
|
|
||||||
"float circmask = step(distance(st,orig),0.1)+step(0.5,distance(st,orig))+step(st.x,0.);"
|
"float circmask = step(distance(st,orig),0.1)+step(0.5,distance(st,orig))+step(st.x,0.);"
|
||||||
"float body = step(-0.03,st.y)*step(st.y,0.03)*step(-0.3,x)*step(x,0.576);"
|
"float body = step(-0.03,st.y)*step(st.y,0.03)*step(-0.3,x)*step(x,0.576);"
|
||||||
"float body_arrow = step(-0.5+3.*st.y,x)*step(-0.5-3.*st.y,x)*step(x,-0.3);"
|
"float body_arrow = step(-0.5+3.*st.y,x)*step(-0.5-3.*st.y,x)*step(x,-0.3);"
|
||||||
"float d = clamp(circmask*(body+body_arrow)+circ_arrow+circ*tri_mask,0.,1.);"
|
"float d = clamp(circmask*(body+body_arrow)+circ_arrow+circ*tri_mask,0.,1.);"
|
||||||
|
|
||||||
"float sinvalue = forces.x;"
|
"float sinvalue = forces.x;"
|
||||||
"float quadraticvalue = forces.y;"
|
"float quadraticvalue = forces.y;"
|
||||||
"float linearvalue = forces.z;"
|
"float linearvalue = forces.z;"
|
||||||
@@ -177,9 +182,7 @@ class DecorationShader:
|
|||||||
"+(-4.*x*x+4.*x)*quadraticvalue"
|
"+(-4.*x*x+4.*x)*quadraticvalue"
|
||||||
"+linearvalue)/maxload;"
|
"+linearvalue)/maxload;"
|
||||||
"float mask = step(0.,co.y)*step(co.y,f)+step(co.y,0.)*step(f,co.y);"
|
"float mask = step(0.,co.y)*step(co.y,f)+step(co.y,0.)*step(f,co.y);"
|
||||||
|
|
||||||
"float top = step(abs(co.y-f),0.2*1.2*spacing);"
|
"float top = step(abs(co.y-f),0.2*1.2*spacing);"
|
||||||
|
|
||||||
"d = clamp(top+d,0.0,0.9)*mask;"
|
"d = clamp(top+d,0.0,0.9)*mask;"
|
||||||
"if (d == 0.0) discard;"
|
"if (d == 0.0) discard;"
|
||||||
"FragColor = vec4(color.xyz,d*color.w);"
|
"FragColor = vec4(color.xyz,d*color.w);"
|
||||||
@@ -191,30 +194,26 @@ class DecorationShader:
|
|||||||
del shader_info
|
del shader_info
|
||||||
return shader
|
return shader
|
||||||
|
|
||||||
def get_point_shader(self, pattern: str) -> gpu.types.GPUShader:
|
def get_point_shader(self, pattern: Literal["SINGLE FORCE","SINGLE MOMENT"]) -> gpu.types.GPUShader:
|
||||||
"""param: pattern: type of pattern
|
"""param: pattern: type of pattern
|
||||||
SINGLE FORCE,
|
SINGLE FORCE,
|
||||||
SINGLE MOMENT"""
|
SINGLE MOMENT"""
|
||||||
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
|
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
|
||||||
vert_out.smooth('VEC3', "co")
|
vert_out.smooth("VEC3", "co")
|
||||||
|
|
||||||
shader_info = gpu.types.GPUShaderCreateInfo()
|
shader_info = gpu.types.GPUShaderCreateInfo()
|
||||||
shader_info.push_constant('MAT4', "viewProjectionMatrix")
|
shader_info.push_constant("MAT4", "viewProjectionMatrix")
|
||||||
shader_info.push_constant('VEC4', "color")
|
shader_info.push_constant("VEC4", "color")
|
||||||
shader_info.push_constant('FLOAT', "spacing")
|
shader_info.push_constant("FLOAT", "spacing")
|
||||||
|
|
||||||
shader_info.vertex_in(0, 'VEC3', "position")
|
shader_info.vertex_in(0, "VEC3", "position")
|
||||||
shader_info.vertex_in(1, 'VEC3', "coord")
|
shader_info.vertex_in(1, "VEC3", "coord")
|
||||||
|
|
||||||
shader_info.vertex_out(vert_out)
|
shader_info.vertex_out(vert_out)
|
||||||
shader_info.fragment_out(0, 'VEC4', "FragColor")
|
shader_info.fragment_out(0, "VEC4", "FragColor")
|
||||||
|
|
||||||
shader_info.vertex_source(
|
shader_info.vertex_source(
|
||||||
"void main()"
|
"void main()" "{" " gl_Position = viewProjectionMatrix * vec4(position, 1.0f);" " co = coord;" "}"
|
||||||
"{"
|
|
||||||
" gl_Position = viewProjectionMatrix * vec4(position, 1.0f);"
|
|
||||||
" co = coord;"
|
|
||||||
"}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if pattern == "SINGLE FORCE":
|
if pattern == "SINGLE FORCE":
|
||||||
@@ -250,25 +249,21 @@ class DecorationShader:
|
|||||||
def get_planar_shader(self) -> gpu.types.GPUShader:
|
def get_planar_shader(self) -> gpu.types.GPUShader:
|
||||||
"""shader for planar loads"""
|
"""shader for planar loads"""
|
||||||
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
|
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
|
||||||
vert_out.smooth('VEC3', "co")
|
vert_out.smooth("VEC3", "co")
|
||||||
|
|
||||||
shader_info = gpu.types.GPUShaderCreateInfo()
|
shader_info = gpu.types.GPUShaderCreateInfo()
|
||||||
shader_info.push_constant('MAT4', "viewProjectionMatrix")
|
shader_info.push_constant("MAT4", "viewProjectionMatrix")
|
||||||
shader_info.push_constant('VEC4', "color")
|
shader_info.push_constant("VEC4", "color")
|
||||||
shader_info.push_constant('FLOAT', "spacing")
|
shader_info.push_constant("FLOAT", "spacing")
|
||||||
|
|
||||||
shader_info.vertex_in(0, 'VEC3', "position")
|
shader_info.vertex_in(0, "VEC3", "position")
|
||||||
shader_info.vertex_in(1, 'VEC3', "coord")
|
shader_info.vertex_in(1, "VEC3", "coord")
|
||||||
|
|
||||||
shader_info.vertex_out(vert_out)
|
shader_info.vertex_out(vert_out)
|
||||||
shader_info.fragment_out(0, 'VEC4', "FragColor")
|
shader_info.fragment_out(0, "VEC4", "FragColor")
|
||||||
|
|
||||||
shader_info.vertex_source(
|
shader_info.vertex_source(
|
||||||
"void main()"
|
"void main()" "{" " gl_Position = viewProjectionMatrix * vec4(position, 1.0f);" " co = coord;" "}"
|
||||||
"{"
|
|
||||||
" gl_Position = viewProjectionMatrix * vec4(position, 1.0f);"
|
|
||||||
" co = coord;"
|
|
||||||
"}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
shader_info.fragment_source(
|
shader_info.fragment_source(
|
||||||
@@ -277,14 +272,10 @@ class DecorationShader:
|
|||||||
"float x = co.x;"
|
"float x = co.x;"
|
||||||
"float y = co.y;"
|
"float y = co.y;"
|
||||||
"float abs_y = abs(y);"
|
"float abs_y = abs(y);"
|
||||||
|
|
||||||
"float a = abs(mod(x,spacing)-0.5*spacing)*5.0;"
|
"float a = abs(mod(x,spacing)-0.5*spacing)*5.0;"
|
||||||
"float b = step(a,abs_y)*(step(abs_y,1.2*spacing));"
|
"float b = step(a,abs_y)*(step(abs_y,1.2*spacing));"
|
||||||
"float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));"
|
"float c = step(0.8*spacing,mod(x+0.4*spacing,spacing))*(step(1.2*spacing,abs_y));"
|
||||||
|
|
||||||
|
|
||||||
"float mask = step(0.,y)*step(y,0.98)+step(y,0.)*step(0.98,y);"
|
"float mask = step(0.,y)*step(y,0.98)+step(y,0.)*step(0.98,y);"
|
||||||
|
|
||||||
"float top = step(abs(y-0.98),0.2*1.2*spacing);"
|
"float top = step(abs(y-0.98),0.2*1.2*spacing);"
|
||||||
"float d = clamp(0.2*y+(top+b+c)*mask,0.0,0.4);"
|
"float d = clamp(0.2*y+(top+b+c)*mask,0.0,0.4);"
|
||||||
"FragColor = vec4(color.xyz,d*color.w);"
|
"FragColor = vec4(color.xyz,d*color.w);"
|
||||||
|
|||||||
@@ -444,6 +444,7 @@ class BIM_UL_structural_activities(UIList):
|
|||||||
row.label(text=item.name)
|
row.label(text=item.name)
|
||||||
row.label(text=item.applied_load_class)
|
row.label(text=item.applied_load_class)
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_show_structural_activities(Panel):
|
class BIM_PT_show_structural_activities(Panel):
|
||||||
bl_label = "Show Loads"
|
bl_label = "Show Loads"
|
||||||
bl_idname = "BIM_PT_show_structural_activities"
|
bl_idname = "BIM_PT_show_structural_activities"
|
||||||
|
|||||||
Reference in New Issue
Block a user