mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 06:21:40 +00:00
Implement experimental support for mirror modifier
This commit is contained in:
@@ -219,26 +219,94 @@ class IfcParser():
|
|||||||
for product in self.selected_products:
|
for product in self.selected_products:
|
||||||
obj = product['raw']
|
obj = product['raw']
|
||||||
self.add_product(self.get_product(product))
|
self.add_product(self.get_product(product))
|
||||||
self.resolve_array_modifier(product)
|
self.resolve_modifiers(product)
|
||||||
|
|
||||||
def resolve_array_modifier(self, product):
|
def resolve_modifiers(self, product):
|
||||||
obj = product['raw']
|
obj = product['raw']
|
||||||
instance_objects = [(obj, obj.matrix_world.translation)]
|
instance_objects = [(obj, {
|
||||||
global_id_index = 0
|
'location': obj.matrix_world.translation,
|
||||||
for instance in self.get_instances(obj):
|
'scale': obj.scale
|
||||||
|
})]
|
||||||
|
|
||||||
|
for modifier in obj.modifiers:
|
||||||
created_instances = []
|
created_instances = []
|
||||||
for n in range(instance.count - 1):
|
if modifier.type == 'ARRAY':
|
||||||
for o in instance_objects:
|
instance_objects.extend(
|
||||||
location = o[1] + ((n + 1) * instance.offset)
|
self.resolve_array_modifier(product, modifier, instance_objects)
|
||||||
self.add_product(
|
)
|
||||||
self.get_product(
|
elif modifier.type == 'MIRROR':
|
||||||
{'raw': o[0], 'metadata': product['metadata']},
|
instance_objects.extend(
|
||||||
{'location': location},
|
self.resolve_mirror_modifier(product, modifier, instance_objects)
|
||||||
{'GlobalId': self.get_parametric_global_id(obj, global_id_index)}
|
)
|
||||||
)
|
|
||||||
|
def get_array_modifier(self, product, modifier):
|
||||||
|
obj = product['raw']
|
||||||
|
array = ArrayModifier()
|
||||||
|
world_rotation = obj.matrix_world.decompose()[1]
|
||||||
|
array.offset = world_rotation @ Vector(
|
||||||
|
(
|
||||||
|
modifier.constant_offset_displace[0],
|
||||||
|
modifier.constant_offset_displace[1],
|
||||||
|
modifier.constant_offset_displace[2]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if modifier.fit_type == 'FIXED_COUNT':
|
||||||
|
array.count = modifier.count
|
||||||
|
elif modifier.fit_type == 'FIT_LENGTH':
|
||||||
|
array.count = int(modifier.fit_length / array.offset.length)
|
||||||
|
return array
|
||||||
|
|
||||||
|
def resolve_array_modifier(self, product, modifier, instance_objects):
|
||||||
|
modifier = self.get_array_modifier(product, modifier)
|
||||||
|
created_instances = []
|
||||||
|
for obj in instance_objects:
|
||||||
|
for n in range(modifier.count - 1):
|
||||||
|
override = obj[1].copy()
|
||||||
|
location = override['location'] + ((n + 1) * modifier.offset)
|
||||||
|
override['location'] = location
|
||||||
|
self.add_product(
|
||||||
|
self.get_product(
|
||||||
|
{'raw': obj[0], 'metadata': product['metadata']},
|
||||||
|
metadata_override=override,
|
||||||
|
attribute_override={'GlobalId': self.get_parametric_global_id(
|
||||||
|
product['raw'],
|
||||||
|
len(instance_objects)+len(created_instances)-1
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
created_instances.append((o[0], location))
|
)
|
||||||
instance_objects.extend(created_instances)
|
created_instances.append((obj[0], override))
|
||||||
|
return created_instances
|
||||||
|
|
||||||
|
def resolve_mirror_modifier(self, product, modifier, instance_objects):
|
||||||
|
return [] # TODO: not yet stable
|
||||||
|
created_instances = []
|
||||||
|
mirrors = []
|
||||||
|
for axis in [0, 1, 2]:
|
||||||
|
if modifier.use_axis[axis]:
|
||||||
|
mirrors.append(axis)
|
||||||
|
for mirror in mirrors:
|
||||||
|
axis_instances = []
|
||||||
|
for obj in instance_objects:
|
||||||
|
override = obj[1].copy()
|
||||||
|
override['has_scale'] = True
|
||||||
|
override['has_mirror'] = True
|
||||||
|
override['scale'][mirror] *= -1
|
||||||
|
self.add_product(
|
||||||
|
self.get_product(
|
||||||
|
{'raw': obj[0], 'metadata': product['metadata']},
|
||||||
|
metadata_override=override,
|
||||||
|
attribute_override={'GlobalId': self.get_parametric_global_id(
|
||||||
|
product['raw'],
|
||||||
|
len(instance_objects)+len(created_instances)-1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
created_instances.append((obj[0], override))
|
||||||
|
axis_instances.append((obj[0], override))
|
||||||
|
instance_objects.extend(axis_instances)
|
||||||
|
return created_instances
|
||||||
|
|
||||||
def resolve_boolean_modifiers(self):
|
def resolve_boolean_modifiers(self):
|
||||||
for i, product in enumerate(self.products):
|
for i, product in enumerate(self.products):
|
||||||
@@ -289,6 +357,7 @@ class IfcParser():
|
|||||||
'forward_axis': self.get_axis(obj.matrix_world, 0),
|
'forward_axis': self.get_axis(obj.matrix_world, 0),
|
||||||
'right_axis': self.get_axis(obj.matrix_world, 1),
|
'right_axis': self.get_axis(obj.matrix_world, 1),
|
||||||
'has_scale': obj.scale != Vector((1, 1, 1)),
|
'has_scale': obj.scale != Vector((1, 1, 1)),
|
||||||
|
'has_mirror': False,
|
||||||
'scale': obj.scale,
|
'scale': obj.scale,
|
||||||
'class': self.get_ifc_class(obj.name),
|
'class': self.get_ifc_class(obj.name),
|
||||||
'relating_structure': None,
|
'relating_structure': None,
|
||||||
@@ -394,21 +463,6 @@ class IfcParser():
|
|||||||
if child.name == child_collection.name:
|
if child.name == child_collection.name:
|
||||||
return parent_collection
|
return parent_collection
|
||||||
|
|
||||||
def get_instances(self, obj):
|
|
||||||
instances = []
|
|
||||||
for m in obj.modifiers:
|
|
||||||
if m.type == 'ARRAY':
|
|
||||||
array = ArrayModifier()
|
|
||||||
world_rotation = obj.matrix_world.decompose()[1]
|
|
||||||
array.offset = world_rotation @ Vector(
|
|
||||||
(m.constant_offset_displace[0], m.constant_offset_displace[1], m.constant_offset_displace[2]))
|
|
||||||
if m.fit_type == 'FIXED_COUNT':
|
|
||||||
array.count = m.count
|
|
||||||
elif m.fit_type == 'FIT_LENGTH':
|
|
||||||
array.count = int(m.fit_length / array.offset.length)
|
|
||||||
instances.append(array)
|
|
||||||
return instances
|
|
||||||
|
|
||||||
def convert_selected_objects_into_products(self, objects_to_sort, metadata=None):
|
def convert_selected_objects_into_products(self, objects_to_sort, metadata=None):
|
||||||
if not metadata:
|
if not metadata:
|
||||||
metadata = {}
|
metadata = {}
|
||||||
@@ -1419,6 +1473,12 @@ class IfcExporter():
|
|||||||
mapping_source = self.ifc_parser.representations[representation_name]['ifc']
|
mapping_source = self.ifc_parser.representations[representation_name]['ifc']
|
||||||
shape_representation = mapping_source.MappedRepresentation
|
shape_representation = mapping_source.MappedRepresentation
|
||||||
if product['has_scale']:
|
if product['has_scale']:
|
||||||
|
if not product['has_mirror']:
|
||||||
|
product['scale'] = Vector((
|
||||||
|
abs(product['scale'].x),
|
||||||
|
abs(product['scale'].y),
|
||||||
|
abs(product['scale'].z)
|
||||||
|
))
|
||||||
mapping_target = self.file.createIfcCartesianTransformationOperator3DnonUniform(
|
mapping_target = self.file.createIfcCartesianTransformationOperator3DnonUniform(
|
||||||
self.create_direction(product['forward_axis']),
|
self.create_direction(product['forward_axis']),
|
||||||
self.create_direction(product['right_axis']),
|
self.create_direction(product['right_axis']),
|
||||||
@@ -1427,10 +1487,10 @@ class IfcExporter():
|
|||||||
product['location'].y,
|
product['location'].y,
|
||||||
product['location'].z
|
product['location'].z
|
||||||
),
|
),
|
||||||
abs(product['scale'].x),
|
product['scale'].x,
|
||||||
self.create_direction(product['up_axis']),
|
self.create_direction(product['up_axis']),
|
||||||
abs(product['scale'].y),
|
product['scale'].y,
|
||||||
abs(product['scale'].z))
|
product['scale'].z)
|
||||||
else:
|
else:
|
||||||
mapping_target = self.file.createIfcCartesianTransformationOperator3D(
|
mapping_target = self.file.createIfcCartesianTransformationOperator3D(
|
||||||
self.create_direction(Vector((1, 0, 0))),
|
self.create_direction(Vector((1, 0, 0))),
|
||||||
@@ -1805,7 +1865,7 @@ class IfcExporter():
|
|||||||
self.ifc_parser.products[relating_opening_element]['ifc'],
|
self.ifc_parser.products[relating_opening_element]['ifc'],
|
||||||
self.ifc_parser.products[related_building_element]['ifc']
|
self.ifc_parser.products[related_building_element]['ifc']
|
||||||
)
|
)
|
||||||
|
|
||||||
def relate_elements_to_spatial_structures(self):
|
def relate_elements_to_spatial_structures(self):
|
||||||
for relating_structure, related_elements in self.ifc_parser.rel_contained_in_spatial_structure.items():
|
for relating_structure, related_elements in self.ifc_parser.rel_contained_in_spatial_structure.items():
|
||||||
self.file.createIfcRelContainedInSpatialStructure(
|
self.file.createIfcRelContainedInSpatialStructure(
|
||||||
|
|||||||
Reference in New Issue
Block a user