Skip to content

Commit 22e4eb4

Browse files
committed
Allow to diff inverse relationships
1 parent 82c38f6 commit 22e4eb4

1 file changed

Lines changed: 35 additions & 5 deletions

File tree

src/ifcdiff/ifcdiff.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,20 @@
99

1010

1111
class IfcDiff():
12-
def __init__(self, old_file, new_file, output_file):
12+
def __init__(self, old_file, new_file, output_file, inverse_classes=None):
1313
self.old_file = old_file
1414
self.new_file = new_file
1515
self.output_file = output_file
1616
self.change_register = {}
1717
self.representation_ids = []
18+
self.inverse_classes = inverse_classes
1819

1920
def diff(self):
2021
print('# IFC Diff')
2122
self.load()
2223

23-
old_elements = set(e.GlobalId for e in self.old.by_type('IfcElement'))
24-
new_elements = set(e.GlobalId for e in self.new.by_type('IfcElement'))
24+
old_elements = set(e.GlobalId for e in self.old.by_type('IfcProduct'))
25+
new_elements = set(e.GlobalId for e in self.new.by_type('IfcProduct'))
2526

2627
self.deleted_elements = old_elements - new_elements
2728
self.added_elements = new_elements - old_elements
@@ -42,6 +43,9 @@ def diff(self):
4243
new_element = self.new.by_id(global_id)
4344
self.diff_element(old_element, new_element)
4445

46+
if self.inverse_classes:
47+
self.diff_element_inverse_relationships(old_element, new_element)
48+
4549
representation_id = self.get_representation_id(new_element)
4650
if representation_id in self.representation_ids:
4751
continue
@@ -81,6 +85,26 @@ def diff_element(self, old_element, new_element):
8185
if diff and new_element.GlobalId:
8286
self.change_register.setdefault(new_element.GlobalId, {}).update(diff)
8387

88+
def diff_element_inverse_relationships(self, old_element, new_element):
89+
old_relationships_all = self.old.get_inverse(old_element)
90+
new_relationships_all = self.new.get_inverse(new_element)
91+
old_relationships = [x for x in old_relationships_all if x.is_a() in self.inverse_classes]
92+
new_relationships = [x for x in new_relationships_all if x.is_a() in self.inverse_classes]
93+
94+
diff = DeepDiff(old_relationships, new_relationships,
95+
significant_digits=2, ignore_string_type_changes=True, ignore_numeric_type_changes=True,
96+
exclude_regex_paths=[
97+
r'root.*id$',
98+
r'.*GlobalId.*',
99+
r'.*OwnerHistory.*',
100+
r'.*RelatedObjects.*',
101+
r'.*RelatingObject.*',
102+
r'.*RelatingDefinitions.*',
103+
r'.*RelatedObjectsType.*', # Deprecated in IFC4 anyway
104+
])
105+
if diff and new_element.GlobalId:
106+
self.change_register.setdefault(new_element.GlobalId, {}).update(diff)
107+
84108
def diff_element_geometry(self, old_element, new_element):
85109
try:
86110
DeepDiff(old_element.ObjectPlacement, new_element.ObjectPlacement,
@@ -126,8 +150,14 @@ def default(self, obj):
126150
type=str,
127151
help='The JSON diff file to output. Defaults to diff.json',
128152
default='diff.json')
153+
parser.add_argument(
154+
'-r',
155+
'--relationships',
156+
type=str,
157+
help='A list of IFC classes to check in inverse relationships, like "IfcRelDefinesByProperties".',
158+
default='')
129159
args = parser.parse_args()
130-
131-
ifc_diff = IfcDiff(args.old, args.new, args.output)
160+
161+
ifc_diff = IfcDiff(args.old, args.new, args.output, args.relationships.split())
132162
ifc_diff.diff()
133163
ifc_diff.export()

0 commit comments

Comments
 (0)