mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 19:27:10 +00:00
Support import of native IfcCircleProfileDef
This commit is contained in:
@@ -458,7 +458,8 @@ class IfcImporter():
|
|||||||
for element in self.file.by_type('IfcExtrudedAreaSolid'):
|
for element in self.file.by_type('IfcExtrudedAreaSolid'):
|
||||||
if element.SweptArea.is_a() not in [
|
if element.SweptArea.is_a() not in [
|
||||||
'IfcArbitraryClosedProfileDef',
|
'IfcArbitraryClosedProfileDef',
|
||||||
'IfcRectangleProfileDef'
|
'IfcRectangleProfileDef',
|
||||||
|
'IfcCircleProfileDef'
|
||||||
]:
|
]:
|
||||||
continue
|
continue
|
||||||
if [e for e in self.file.get_inverse(element) if e.is_a('IfcBooleanResult')]:
|
if [e for e in self.file.get_inverse(element) if e.is_a('IfcBooleanResult')]:
|
||||||
@@ -479,7 +480,7 @@ class IfcImporter():
|
|||||||
inverse_element.RepresentationType = 'Curve'
|
inverse_element.RepresentationType = 'Curve'
|
||||||
for product in self.get_products_from_shape_representation(inverse_element):
|
for product in self.get_products_from_shape_representation(inverse_element):
|
||||||
self.native_elements.setdefault(product.GlobalId, {})[dummy_geometry.id()] = element
|
self.native_elements.setdefault(product.GlobalId, {})[dummy_geometry.id()] = element
|
||||||
self.replace_attribute(inverse_element, element, dummy_geometry)
|
ifcopenshell.util.element.replace_attribute(inverse_element, element, dummy_geometry)
|
||||||
|
|
||||||
def get_dummy_geometry(self):
|
def get_dummy_geometry(self):
|
||||||
point = self.file.createIfcCartesianPoint((0., 0., 0.))
|
point = self.file.createIfcCartesianPoint((0., 0., 0.))
|
||||||
@@ -495,18 +496,6 @@ class IfcImporter():
|
|||||||
products.extend(self.get_products_from_shape_representation(inverse_element))
|
products.extend(self.get_products_from_shape_representation(inverse_element))
|
||||||
return products
|
return products
|
||||||
|
|
||||||
# TODO migrate to utility
|
|
||||||
def replace_attribute(self, element, old, new):
|
|
||||||
for i, attribute in enumerate(element):
|
|
||||||
if attribute == old:
|
|
||||||
element[i] = new
|
|
||||||
elif isinstance(attribute, tuple):
|
|
||||||
new_attribute = list(attribute)
|
|
||||||
for j, item in enumerate(attribute):
|
|
||||||
if item == old:
|
|
||||||
new_attribute[j] = new
|
|
||||||
element[i] = new_attribute
|
|
||||||
|
|
||||||
def filter_ifc(self):
|
def filter_ifc(self):
|
||||||
for element in self.file.by_type('IfcElement'):
|
for element in self.file.by_type('IfcElement'):
|
||||||
if self.diff \
|
if self.diff \
|
||||||
@@ -1053,16 +1042,33 @@ class IfcImporter():
|
|||||||
'name': item.SweptArea.is_a(),
|
'name': item.SweptArea.is_a(),
|
||||||
'vertices': [0, 1, 2, 3]
|
'vertices': [0, 1, 2, 3]
|
||||||
})
|
})
|
||||||
|
elif item.SweptArea.is_a() == 'IfcCircleProfileDef':
|
||||||
|
bm = self.bmesh_from_circle(item.SweptArea.Radius)
|
||||||
|
if item.SweptArea.Position:
|
||||||
|
bmesh.ops.transform(bm, matrix=self.get_axis2placement(item.SweptArea.Position), verts=bm.verts)
|
||||||
|
bmesh.ops.transform(bm, matrix=mathutils.Matrix() * self.unit_scale, verts=bm.verts)
|
||||||
|
subitems.append({
|
||||||
|
'name': item.SweptArea.is_a(),
|
||||||
|
# This strange vertice offset is due to a Blender quirk
|
||||||
|
'vertices': range(1, len(bm.verts)+1)
|
||||||
|
})
|
||||||
else:
|
else:
|
||||||
# TODO: what if we can't handle it?
|
# TODO: what if we can't handle it?
|
||||||
return
|
return
|
||||||
results = bmesh.ops.extrude_face_region(bm, geom=[bm.faces[0]])
|
results = bmesh.ops.extrude_face_region(bm, geom=[bm.faces[0]])
|
||||||
bm.faces.ensure_lookup_table()
|
bm.faces.ensure_lookup_table()
|
||||||
offset = self.unit_scale * item.Depth * mathutils.Vector(item.ExtrudedDirection.DirectionRatios)
|
offset = self.unit_scale * item.Depth * mathutils.Vector(item.ExtrudedDirection.DirectionRatios)
|
||||||
subitems.append({
|
if item.SweptArea.is_a() == 'IfcCircleProfileDef':
|
||||||
'name': 'ExtrudedDirection',
|
# Circle profiles have a quirk apparently in Blender
|
||||||
'vertices': [0, len(subitems[-1]['vertices'])]
|
subitems.append({
|
||||||
})
|
'name': 'ExtrudedDirection',
|
||||||
|
'vertices': [0, 1]
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
subitems.append({
|
||||||
|
'name': 'ExtrudedDirection',
|
||||||
|
'vertices': [0, len(subitems[-1]['vertices'])]
|
||||||
|
})
|
||||||
for geom in results['geom']:
|
for geom in results['geom']:
|
||||||
if isinstance(geom, bmesh.types.BMVert):
|
if isinstance(geom, bmesh.types.BMVert):
|
||||||
geom.co += offset
|
geom.co += offset
|
||||||
@@ -1089,6 +1095,19 @@ class IfcImporter():
|
|||||||
bm.faces.ensure_lookup_table()
|
bm.faces.ensure_lookup_table()
|
||||||
return bm
|
return bm
|
||||||
|
|
||||||
|
def bmesh_from_circle(self, r):
|
||||||
|
bm = bmesh.new()
|
||||||
|
# Segments should be a multiple of 4 to easily measure the diameter
|
||||||
|
si_radius = r * self.unit_scale
|
||||||
|
# I'm arbitrarily deciding that 28 verts is enough for a 1m radius
|
||||||
|
closest_power_of_2 = int(math.log(si_radius, 2) + 0.5)
|
||||||
|
segments = (closest_power_of_2 * 4) + 28
|
||||||
|
bmesh.ops.create_circle(bm, cap_ends=True, segments=segments, radius=r)
|
||||||
|
bm.verts.ensure_lookup_table()
|
||||||
|
bm.edges.ensure_lookup_table()
|
||||||
|
bm.faces.ensure_lookup_table()
|
||||||
|
return bm
|
||||||
|
|
||||||
def merge_aggregates(self):
|
def merge_aggregates(self):
|
||||||
self.merge_objects_inside_aggregates()
|
self.merge_objects_inside_aggregates()
|
||||||
self.convert_aggregate_instances_to_object()
|
self.convert_aggregate_instances_to_object()
|
||||||
|
|||||||
Reference in New Issue
Block a user