mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
Import rebar as an extruded circle instead of a brep
This commit is contained in:
@@ -5,6 +5,7 @@ import os
|
||||
import json
|
||||
import time
|
||||
import mathutils
|
||||
import math
|
||||
import multiprocessing
|
||||
from .helper import SIUnitHelper
|
||||
from . import schema
|
||||
@@ -193,6 +194,7 @@ class IfcImporter():
|
||||
self.time = 0
|
||||
self.unit_scale = 1
|
||||
self.added_data = {}
|
||||
self.native_data = {}
|
||||
|
||||
self.material_creator = MaterialCreator(ifc_import_settings)
|
||||
|
||||
@@ -210,6 +212,7 @@ class IfcImporter():
|
||||
if self.ifc_import_settings.should_import_opening_elements:
|
||||
self.create_openings_collection()
|
||||
self.purge_diff()
|
||||
self.parse_native_products()
|
||||
self.filter_ifc()
|
||||
self.patch_ifc()
|
||||
self.create_type_products()
|
||||
@@ -258,6 +261,52 @@ class IfcImporter():
|
||||
or abs(point.Coordinates[1]) > 1000000 \
|
||||
or abs(point.Coordinates[2]) > 1000000
|
||||
|
||||
def parse_native_products(self):
|
||||
# TODO: simple code for now as we only treat rebar specially
|
||||
for element in self.file.by_type('IfcReinforcingBar'):
|
||||
for representation in element.Representation.Representations:
|
||||
self.replace_with_directrix(representation, element)
|
||||
for item in representation.Items:
|
||||
if item.is_a('IfcMappedItem'):
|
||||
self.replace_with_directrix(item.MappingSource.MappedRepresentation, element)
|
||||
for global_id, data in self.native_data.items():
|
||||
bevel_object = bpy.data.objects.new('rebar-profile', self.create_bezier_circle(data['radius']))
|
||||
bpy.context.scene.collection.objects.link(bevel_object)
|
||||
data['bevel_object'] = bevel_object
|
||||
|
||||
def create_bezier_circle(self, radius):
|
||||
curve = bpy.data.curves.new('circle-profile', type='CURVE')
|
||||
spline = curve.splines.new('BEZIER')
|
||||
spline.use_cyclic_u = True
|
||||
spline.bezier_points.add(3)
|
||||
approx_distance = (4/3)*math.tan(math.pi/(2*4))
|
||||
for i in range(0, 4):
|
||||
spline.bezier_points[i].handle_left_type = 'AUTO'
|
||||
spline.bezier_points[i].handle_right_type = 'AUTO'
|
||||
spline.bezier_points[0].co = mathutils.Vector((-radius, 0, 0))
|
||||
spline.bezier_points[0].handle_left = mathutils.Vector((-radius, -approx_distance, 0))
|
||||
spline.bezier_points[0].handle_right = mathutils.Vector((-radius, approx_distance, 0))
|
||||
spline.bezier_points[1].co = mathutils.Vector((0, radius, 0))
|
||||
spline.bezier_points[1].handle_left = mathutils.Vector((-approx_distance, radius, 0))
|
||||
spline.bezier_points[1].handle_right = mathutils.Vector((approx_distance, radius, 0))
|
||||
spline.bezier_points[2].co = mathutils.Vector((radius, 0, 0))
|
||||
spline.bezier_points[2].handle_left = mathutils.Vector((radius, approx_distance, 0))
|
||||
spline.bezier_points[2].handle_right = mathutils.Vector((radius, -approx_distance, 0))
|
||||
spline.bezier_points[3].co = mathutils.Vector((0, -radius, 0))
|
||||
spline.bezier_points[3].handle_left = mathutils.Vector((approx_distance, -radius, 0))
|
||||
spline.bezier_points[3].handle_right = mathutils.Vector((-approx_distance, -radius, 0))
|
||||
return curve
|
||||
|
||||
def replace_with_directrix(self, representation, element):
|
||||
new_items = []
|
||||
for item in representation.Items:
|
||||
if item.is_a('IfcSweptDiskSolid'):
|
||||
new_items.append(item.Directrix)
|
||||
self.native_data[element.GlobalId] = { 'radius': item.Radius }
|
||||
else:
|
||||
new_items.append(item)
|
||||
representation.Items = new_items
|
||||
|
||||
def filter_ifc(self):
|
||||
for element in self.file.by_type('IfcElement'):
|
||||
if self.diff \
|
||||
@@ -387,7 +436,13 @@ class IfcImporter():
|
||||
mesh_name = f'mesh-{shape.geometry.id}'
|
||||
mesh = self.meshes.get(mesh_name)
|
||||
if mesh is None:
|
||||
mesh = self.create_mesh(element, shape)
|
||||
# TODO: figure out a design pattern for native objects
|
||||
if element.is_a('IfcReinforcingBar'):
|
||||
mesh = self.create_mesh(element, shape, is_curve=True)
|
||||
mesh.bevel_object = self.native_data[element.GlobalId]['bevel_object']
|
||||
mesh.use_fill_caps = True
|
||||
else:
|
||||
mesh = self.create_mesh(element, shape)
|
||||
self.meshes[mesh_name] = mesh
|
||||
else:
|
||||
mesh = None
|
||||
@@ -790,12 +845,16 @@ class IfcImporter():
|
||||
and representation.RepresentationType == 'MappedRepresentation':
|
||||
return representation.Items[0].MappingTarget
|
||||
|
||||
def create_mesh(self, element, shape):
|
||||
def create_mesh(self, element, shape, is_curve=False):
|
||||
try:
|
||||
if hasattr(shape, 'geometry'):
|
||||
geometry = shape.geometry
|
||||
else:
|
||||
geometry = shape
|
||||
|
||||
if is_curve:
|
||||
return self.create_curve(geometry)
|
||||
|
||||
mesh = bpy.data.meshes.new(geometry.id)
|
||||
f = geometry.faces
|
||||
e = geometry.edges
|
||||
@@ -822,6 +881,28 @@ class IfcImporter():
|
||||
except:
|
||||
self.ifc_import_settings.logger.error('Could not create mesh for {}: {}/{}'.format(element.GlobalId, self.get_name(element)))
|
||||
|
||||
def create_curve(self, geometry):
|
||||
curve = bpy.data.curves.new(geometry.id, type='CURVE')
|
||||
curve.dimensions = '3D'
|
||||
curve.resolution_u = 2
|
||||
polyline = curve.splines.new('POLY')
|
||||
e = geometry.edges
|
||||
v = geometry.verts
|
||||
vertices = [[v[i], v[i + 1], v[i + 2], 1]
|
||||
for i in range(0, len(v), 3)]
|
||||
edges = [[e[i], e[i + 1]]
|
||||
for i in range(0, len(e), 2)]
|
||||
v2 = None
|
||||
for edge in edges:
|
||||
v1 = vertices[edge[0]]
|
||||
if v1 != v2:
|
||||
polyline = curve.splines.new('POLY')
|
||||
polyline.points[-1].co = v1
|
||||
v2 = vertices[edge[1]]
|
||||
polyline.points.add(1)
|
||||
polyline.points[-1].co = v2
|
||||
return curve
|
||||
|
||||
def a2p(self, o, z, x):
|
||||
y = z.cross(x)
|
||||
r = mathutils.Matrix((x, y, z, o))
|
||||
|
||||
Reference in New Issue
Block a user