mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Add basic support for sloped walls, sloping along the local X axis
This commit is contained in:
@@ -31,6 +31,7 @@ classes = (
|
||||
workspace.Hotkey,
|
||||
wall.AlignWall,
|
||||
wall.ChangeExtrusionDepth,
|
||||
wall.ChangeExtrusionXAngle,
|
||||
wall.ChangeLayerLength,
|
||||
wall.FlipWall,
|
||||
wall.JoinWall,
|
||||
|
||||
@@ -229,6 +229,7 @@ class BIMModelProperties(PropertyGroup):
|
||||
y: bpy.props.FloatProperty(name="Y", default=0.5)
|
||||
z: bpy.props.FloatProperty(name="Z", default=0.5)
|
||||
rl: bpy.props.FloatProperty(name="RL", default=1)
|
||||
x_angle: bpy.props.FloatProperty(name="X Angle", default=0)
|
||||
type_page: bpy.props.IntProperty(name="Type Page", default=1, update=update_type_page)
|
||||
type_template: bpy.props.EnumProperty(
|
||||
items=(
|
||||
|
||||
@@ -34,7 +34,7 @@ import blenderbim.tool as tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from ifcopenshell.api.pset.data import Data as PsetData
|
||||
from ifcopenshell.api.material.data import Data as MaterialData
|
||||
from math import pi, degrees
|
||||
from math import pi, sin, cos, degrees, radians
|
||||
from mathutils import Vector, Matrix
|
||||
|
||||
|
||||
@@ -243,6 +243,37 @@ class ChangeExtrusionDepth(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.change_extrusion_x_angle"
|
||||
bl_label = "Change Extrusion X Angle"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
x_angle: bpy.props.FloatProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.selected_objects
|
||||
|
||||
def _execute(self, context):
|
||||
wall_objs = []
|
||||
x_angle = radians(self.x_angle)
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
return
|
||||
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
if not representation:
|
||||
return
|
||||
extrusion = tool.Model.get_extrusion(representation)
|
||||
if not extrusion:
|
||||
return
|
||||
extrusion.ExtrudedDirection.DirectionRatios = (0.0, sin(x_angle), cos(x_angle))
|
||||
if element.is_a("IfcWall"):
|
||||
wall_objs.append(obj)
|
||||
if wall_objs:
|
||||
DumbWallRecalculator().recalculate(wall_objs)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ChangeLayerLength(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.change_layer_length"
|
||||
bl_label = "Change Layer Length"
|
||||
@@ -419,6 +450,7 @@ class DumbWallGenerator:
|
||||
self.length = props.length * self.unit_scale
|
||||
self.rotation = 0.0
|
||||
self.location = Vector((0, 0, 0))
|
||||
self.x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else radians(props.x_angle)
|
||||
|
||||
if self.has_sketch():
|
||||
return # For now
|
||||
@@ -571,6 +603,7 @@ class DumbWallGenerator:
|
||||
offset=self.layers["offset"],
|
||||
length=self.length,
|
||||
height=self.height,
|
||||
x_angle=self.x_angle,
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", tool.Ifc.get(), product=element, representation=representation
|
||||
@@ -993,7 +1026,9 @@ class DumbWallJoiner:
|
||||
axis = body = tool.Model.get_wall_axis(obj)["reference"]
|
||||
self.axis = copy.deepcopy(axis)
|
||||
self.body = copy.deepcopy(body)
|
||||
height = self.get_height(tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id))
|
||||
extrusion_data = self.get_extrusion_data(tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id))
|
||||
height = extrusion_data["height"]
|
||||
x_angle = extrusion_data["x_angle"]
|
||||
self.clippings = []
|
||||
layers = tool.Model.get_material_layer_parameters(element)
|
||||
|
||||
@@ -1045,6 +1080,7 @@ class DumbWallJoiner:
|
||||
context=self.body_context,
|
||||
length=length,
|
||||
height=height,
|
||||
x_angle=x_angle,
|
||||
offset=layers["offset"],
|
||||
thickness=layers["thickness"],
|
||||
clippings=self.clippings,
|
||||
@@ -1106,18 +1142,21 @@ class DumbWallJoiner:
|
||||
)
|
||||
)
|
||||
|
||||
def get_height(self, representation):
|
||||
height = 3.0
|
||||
def get_extrusion_data(self, representation):
|
||||
results = {"height": 3.0, "x_angle": 0}
|
||||
item = representation.Items[0]
|
||||
while True:
|
||||
if item.is_a("IfcExtrudedAreaSolid"):
|
||||
height = item.Depth * self.unit_scale
|
||||
results["height"] = item.Depth * self.unit_scale
|
||||
x, y, z = item.ExtrudedDirection.DirectionRatios
|
||||
if not tool.Cad.is_x(x, 0) or not tool.Cad.is_x(y, 0) or not tool.Cad.is_x(z, 1):
|
||||
results["x_angle"] = Vector((0, 1)).angle(Vector((y, z)))
|
||||
break
|
||||
elif item.is_a("IfcBooleanClippingResult"):
|
||||
item = item.FirstOperand
|
||||
else:
|
||||
break
|
||||
return height
|
||||
return results
|
||||
|
||||
def join(self, wall1, wall2, connection1, connection2, is_relating=True, description="BUTT"):
|
||||
element1 = tool.Ifc.get_entity(wall1)
|
||||
|
||||
@@ -101,6 +101,9 @@ class BimToolUI:
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
row.prop(data=cls.props, property="length", text="Length")
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
row.prop(data=cls.props, property="x_angle", text="X Angle")
|
||||
elif cls.props.ifc_class in ("IfcColumnType", "IfcBeamType", "IfcMemberType"):
|
||||
row = cls.layout.row(align=True)
|
||||
row.prop(data=cls.props, property="cardinal_point", text="Axis")
|
||||
@@ -125,6 +128,11 @@ class BimToolUI:
|
||||
op = row.operator("bim.change_layer_length", icon="FILE_REFRESH", text="")
|
||||
op.length = cls.props.length
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
row.prop(data=cls.props, property="x_angle", text="X Angle")
|
||||
op = row.operator("bim.change_extrusion_x_angle", icon="FILE_REFRESH", text="")
|
||||
op.x_angle = cls.props.x_angle
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_E")
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from math import sin, cos
|
||||
import ifcopenshell.util.unit
|
||||
|
||||
|
||||
@@ -28,10 +29,12 @@ class Usecase:
|
||||
"height": 3.0,
|
||||
"offset": 0.0,
|
||||
"thickness": 0.2,
|
||||
# Sloped walls along the wall's X axis, provided in radians
|
||||
"x_angle": 0,
|
||||
# Planes are defined as a matrix. The XY plane is the clipping boundary and +Z is removed.
|
||||
# [{"type": "IfcBooleanClippingResult", "operand_type": "IfcHalfSpaceSolid", "matrix": [...]}, {...}]
|
||||
"clippings": [], # A list of planes that define clipping half space solids
|
||||
"booleans": [], # Any existing IfcBooleanResults
|
||||
"booleans": [], # Any existing IfcBooleanResults
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
@@ -59,6 +62,12 @@ class Usecase:
|
||||
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
|
||||
else:
|
||||
curve = self.file.createIfcIndexedPolyCurve(self.file.createIfcCartesianPointList2D(points), None, False)
|
||||
if self.settings["x_angle"]:
|
||||
extrusion_direction = self.file.createIfcDirection(
|
||||
(0.0, sin(self.settings["x_angle"]), cos(self.settings["x_angle"]))
|
||||
)
|
||||
else:
|
||||
extrusion_direction = self.file.createIfcDirection((0.0, 0.0, 1.0))
|
||||
extrusion = self.file.createIfcExtrudedAreaSolid(
|
||||
self.file.createIfcArbitraryClosedProfileDef("AREA", None, curve),
|
||||
self.file.createIfcAxis2Placement3D(
|
||||
@@ -66,7 +75,7 @@ class Usecase:
|
||||
self.file.createIfcDirection((0.0, 0.0, 1.0)),
|
||||
self.file.createIfcDirection((1.0, 0.0, 0.0)),
|
||||
),
|
||||
self.file.createIfcDirection((0.0, 0.0, 1.0)),
|
||||
extrusion_direction,
|
||||
self.convert_si_to_unit(self.settings["height"]),
|
||||
)
|
||||
if self.settings["booleans"]:
|
||||
|
||||
Reference in New Issue
Block a user