mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Forgot to commit new profile import export in model tool
This commit is contained in:
@@ -17,16 +17,103 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.representation
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
from mathutils import Matrix, Vector
|
||||
from blenderbim.bim import import_ifc
|
||||
from blenderbim.bim.module.geometry.helper import Helper
|
||||
|
||||
|
||||
class Model(blenderbim.core.tool.Model):
|
||||
@classmethod
|
||||
def convert_si_to_unit(cls, value):
|
||||
if isinstance(value, (tuple, list)):
|
||||
return [v / cls.unit_scale for v in value]
|
||||
return value / cls.unit_scale
|
||||
|
||||
@classmethod
|
||||
def convert_unit_to_si(cls, value):
|
||||
if isinstance(value, (tuple, list)):
|
||||
return [v * cls.unit_scale for v in value]
|
||||
return value * cls.unit_scale
|
||||
|
||||
@classmethod
|
||||
def export_curve(cls, position, edge_indices, points=None):
|
||||
position_i = position.inverted()
|
||||
if len(edge_indices) == 2:
|
||||
diameter = edge_indices[0]
|
||||
p1 = cls.bm.verts[diameter[0]].co
|
||||
p2 = cls.bm.verts[diameter[1]].co
|
||||
center = cls.convert_si_to_unit(list(position_i @ p1.lerp(p2, 0.5)))
|
||||
radius = cls.convert_si_to_unit((p1 - p2).length / 2)
|
||||
return tool.Ifc.get().createIfcCircle(
|
||||
tool.Ifc.get().createIfcAxis2Placement2D(tool.Ifc.get().createIfcCartesianPoint(center[0:2])), radius
|
||||
)
|
||||
if tool.Ifc.get().schema == "IFC2X3":
|
||||
points = []
|
||||
for edge in edge_indices:
|
||||
local_point = (position_i @ Vector(cls.bm.verts[edge[0]].co)).to_2d()
|
||||
points.append(tool.Ifc.get().createIfcCartesianPoint(cls.convert_si_to_unit(local_point)))
|
||||
points.append(points[0])
|
||||
return tool.Ifc.get().createIfcPolyline(points)
|
||||
segments = []
|
||||
for segment in edge_indices:
|
||||
if len(segment) == 2:
|
||||
segments.append(tool.Ifc.get().createIfcLineIndex([i + 1 for i in segment]))
|
||||
elif len(segment) == 3:
|
||||
segments.append(tool.Ifc.get().createIfcArcIndex([i + 1 for i in segment]))
|
||||
return tool.Ifc.get().createIfcIndexedPolyCurve(cls.points, segments, False)
|
||||
|
||||
@classmethod
|
||||
def export_points(cls, position, indices):
|
||||
position_i = position.inverted()
|
||||
points = []
|
||||
for point in indices:
|
||||
local_point = (position_i @ point).to_2d()
|
||||
points.append(cls.convert_si_to_unit(list(local_point)))
|
||||
return tool.Ifc.get().createIfcCartesianPointList2D(points)
|
||||
|
||||
@classmethod
|
||||
def export_profile(cls, obj, position=None):
|
||||
if position is None:
|
||||
position = Matrix()
|
||||
|
||||
cls.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
|
||||
helper = Helper(tool.Ifc.get())
|
||||
indices = helper.auto_detect_arbitrary_profile_with_voids(obj, obj.data)
|
||||
|
||||
if isinstance(indices, tuple) and indices[0] is False: # Ugly
|
||||
return
|
||||
|
||||
cls.bm = bmesh.new()
|
||||
cls.bm.from_mesh(obj.data)
|
||||
cls.bm.verts.ensure_lookup_table()
|
||||
cls.bm.edges.ensure_lookup_table()
|
||||
|
||||
if indices["inner_curves"]:
|
||||
profile = tool.Ifc.get().createIfcArbitraryProfileDefWithVoids("AREA")
|
||||
else:
|
||||
profile = tool.Ifc.get().createIfcArbitraryClosedProfileDef("AREA")
|
||||
|
||||
if tool.Ifc.get().schema != "IFC2X3":
|
||||
cls.points = cls.export_points(position, indices["points"])
|
||||
|
||||
profile.OuterCurve = cls.export_curve(position, indices["profile"])
|
||||
if indices["inner_curves"]:
|
||||
results = []
|
||||
for inner_curve in indices["inner_curves"]:
|
||||
results.append(cls.export_curve(position, inner_curve))
|
||||
profile.InnerCurves = results
|
||||
|
||||
cls.bm.free()
|
||||
return profile
|
||||
|
||||
@classmethod
|
||||
def generate_occurrence_name(cls, element_type, ifc_class):
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
@@ -52,6 +139,126 @@ class Model(blenderbim.core.tool.Model):
|
||||
else:
|
||||
break
|
||||
|
||||
@classmethod
|
||||
def import_profile(cls, profile, obj=None, position=None):
|
||||
cls.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
|
||||
if position is None:
|
||||
position = Matrix()
|
||||
|
||||
cls.vertices = []
|
||||
cls.edges = []
|
||||
cls.arcs = []
|
||||
cls.circles = []
|
||||
|
||||
if profile.is_a("IfcArbitraryClosedProfileDef"):
|
||||
cls.import_curve(obj, position, profile.OuterCurve)
|
||||
if profile.is_a("IfcArbitraryProfileDefWithVoids"):
|
||||
for inner_curve in profile.InnerCurves:
|
||||
cls.import_curve(obj, position, inner_curve)
|
||||
elif profile.is_a() == "IfcRectangleProfileDef":
|
||||
cls.import_rectangle(obj, position, profile)
|
||||
|
||||
mesh = bpy.data.meshes.new("Profile")
|
||||
mesh.from_pydata(cls.vertices, cls.edges, [])
|
||||
mesh.BIMMeshProperties.is_profile = True
|
||||
|
||||
if obj is None:
|
||||
obj = bpy.data.objects.new("Profile", mesh)
|
||||
else:
|
||||
obj.data = mesh
|
||||
|
||||
for arc in cls.arcs:
|
||||
group = obj.vertex_groups.new(name="IFCARCINDEX")
|
||||
group.add(arc, 1, "REPLACE")
|
||||
|
||||
for circle in cls.circles:
|
||||
group = obj.vertex_groups.new(name="IFCCIRCLE")
|
||||
group.add(circle, 1, "REPLACE")
|
||||
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def import_curve(cls, obj, position, curve):
|
||||
offset = len(cls.vertices)
|
||||
|
||||
if curve.is_a("IfcPolyline"):
|
||||
total_points = len(curve.Points)
|
||||
last_index = len(curve.Points) - 1
|
||||
for i, point in enumerate(curve.Points):
|
||||
if i == last_index:
|
||||
continue
|
||||
global_point = position @ Vector(cls.convert_unit_to_si(point.Coordinates)).to_3d()
|
||||
cls.vertices.append(global_point)
|
||||
cls.edges.extend([(i, i + 1) for i in range(offset, len(cls.vertices))])
|
||||
cls.edges[-1] = (len(cls.vertices) - 1, offset) # Close the loop
|
||||
elif curve.is_a("IfcIndexedPolyCurve"):
|
||||
is_arc = False
|
||||
if curve.Segments:
|
||||
for segment in curve.Segments:
|
||||
if len(segment[0]) == 3: # IfcArcIndex
|
||||
is_arc = True
|
||||
local_point = cls.convert_unit_to_si(curve.Points.CoordList[segment[0][0] - 1])
|
||||
global_point = position @ Vector(local_point).to_3d()
|
||||
cls.vertices.append(global_point)
|
||||
local_point = cls.convert_unit_to_si(curve.Points.CoordList[segment[0][1] - 1])
|
||||
global_point = position @ Vector(local_point).to_3d()
|
||||
cls.vertices.append(global_point)
|
||||
cls.arcs.append([len(cls.vertices) - 2, len(cls.vertices) - 1])
|
||||
else:
|
||||
local_point = cls.convert_unit_to_si(curve.Points.CoordList[segment[0][0] - 1])
|
||||
global_point = position @ Vector(local_point).to_3d()
|
||||
cls.vertices.append(global_point)
|
||||
if is_arc:
|
||||
cls.arcs[-1].append(len(cls.vertices) - 1)
|
||||
is_arc = False
|
||||
else:
|
||||
for local_point in curve.Points.CoordList:
|
||||
global_point = position @ Vector(cls.convert_unit_to_si(local_point)).to_3d()
|
||||
cls.vertices.append(global_point)
|
||||
# Curves without segments are cls closing
|
||||
del cls.vertices[-1]
|
||||
|
||||
cls.edges.extend([(i, i + 1) for i in range(offset, len(cls.vertices))])
|
||||
cls.edges[-1] = (len(cls.vertices) - 1, offset) # Close the loop
|
||||
elif curve.is_a("IfcCircle"):
|
||||
center = cls.convert_unit_to_si(
|
||||
Matrix(ifcopenshell.util.placement.get_axis2placement(curve.Position).tolist()).col[3].to_3d()
|
||||
)
|
||||
radius = cls.convert_unit_to_si(curve.Radius)
|
||||
cls.vertices.extend(
|
||||
[
|
||||
position @ Vector((center[0], center[1] - curve.Radius, 0.0)),
|
||||
position @ Vector((center[0], center[1] + curve.Radius, 0.0)),
|
||||
]
|
||||
)
|
||||
cls.circles.append([offset, offset + 1])
|
||||
cls.edges.append((offset, offset + 1))
|
||||
|
||||
@classmethod
|
||||
def import_rectangle(cls, obj, position, profile):
|
||||
if profile.Position:
|
||||
p_position = Matrix(ifcopenshell.util.placement.get_axis2placement(profile.Position).tolist())
|
||||
p_position[0][3] *= cls.unit_scale
|
||||
p_position[1][3] *= cls.unit_scale
|
||||
p_position[2][3] *= cls.unit_scale
|
||||
else:
|
||||
p_position = Matrix()
|
||||
|
||||
x = cls.convert_unit_to_si(profile.XDim)
|
||||
y = cls.convert_unit_to_si(profile.YDim)
|
||||
|
||||
cls.vertices.extend(
|
||||
[
|
||||
position @ p_position @ Vector((-x / 2, -y / 2, 0.0)),
|
||||
position @ p_position @ Vector((x / 2, -y / 2, 0.0)),
|
||||
position @ p_position @ Vector((x / 2, y / 2, 0.0)),
|
||||
position @ p_position @ Vector((-x / 2, y / 2, 0.0)),
|
||||
]
|
||||
)
|
||||
cls.edges.extend([(i, i + 1) for i in range(0, len(cls.vertices))])
|
||||
cls.edges[-1] = (len(cls.vertices) - 1, 0) # Close the loop
|
||||
|
||||
@classmethod
|
||||
def load_openings(cls, element, openings):
|
||||
if not openings:
|
||||
|
||||
Reference in New Issue
Block a user