Skip to content

Commit 09a6f56

Browse files
committed
IfcOpenShell#2319 Add documentation for IfcDiff
1 parent 35ce8c2 commit 09a6f56

4 files changed

Lines changed: 159 additions & 27 deletions

File tree

src/ifcdiff/ifcdiff.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,38 @@
3434

3535

3636
class IfcDiff:
37+
"""Main IfcDiff application
38+
39+
If you are using IfcDiff as a library, this is the class you should use.
40+
41+
:param old_file: Filepath to the old file
42+
:type old_file: string
43+
:param new_file: Filepath to the new file
44+
:type new_file: string
45+
:param output_file: Filepath to the output JSON file to store the diff
46+
results
47+
:type output_file: string
48+
:param relationships: List of relationships to check. An empty list means
49+
that only geometry and attributes are compared.
50+
:type relationships: list[string]
51+
:param is_shallow: True if you want only the first difference to be listed.
52+
False if you want all differences to be checked. Choosing False means
53+
that comparisons will take longer.
54+
:type is_shallow: bool
55+
:param filter_elements: An IFC filter query if you only want to compare a
56+
subset of elements. For example: ``.IfcWall`` to only compare walls.
57+
:type filter_elements: string
58+
59+
Example::
60+
61+
from ifcdiff import IfcDiff
62+
63+
ifc_diff = IfcDiff("/path/to/old.ifc", "/path/to/new.ifc", "/path/to/diff.json")
64+
ifc_diff.diff()
65+
print(ifc_diff.change_register)
66+
ifc_diff.export()
67+
"""
68+
3769
def __init__(self, old_file, new_file, output_file, relationships=None, is_shallow=True, filter_elements=None):
3870
self.old_file = old_file
3971
self.new_file = new_file
@@ -56,7 +88,7 @@ def diff(self):
5688
selector = ifcopenshell.util.selector.Selector()
5789
old_elements = set(e.GlobalId for e in selector.parse(self.old, self.filter_elements))
5890
new_elements = set(e.GlobalId for e in selector.parse(self.new, self.filter_elements))
59-
else:
91+
else:
6092
old_elements = set(e.GlobalId for e in self.old.by_type("IfcProduct"))
6193
new_elements = set(e.GlobalId for e in self.new.by_type("IfcProduct"))
6294

@@ -101,7 +133,6 @@ def export(self):
101133
},
102134
diff_file,
103135
indent=4,
104-
cls=DiffEncoder,
105136
)
106137

107138
def load(self):
@@ -173,9 +204,9 @@ def diff_element_relationships(self, old, new):
173204
def diff_element_geometry(self, old, new):
174205
old_placement = ifcopenshell.util.placement.get_local_placement(old.ObjectPlacement)
175206
new_placement = ifcopenshell.util.placement.get_local_placement(new.ObjectPlacement)
176-
if not np.allclose(old_placement[:,3], new_placement[:,3], atol=self.precision):
207+
if not np.allclose(old_placement[:, 3], new_placement[:, 3], atol=self.precision):
177208
return True
178-
if not np.allclose(old_placement[0:3,0:3], new_placement[0:3,0:3], atol=1e-2):
209+
if not np.allclose(old_placement[0:3, 0:3], new_placement[0:3, 0:3], atol=1e-2):
179210
return True
180211
old_openings = [o.RelatedOpeningElement.GlobalId for o in getattr(old, "HasOpenings", []) or []]
181212
new_openings = [o.RelatedOpeningElement.GlobalId for o in getattr(new, "HasOpenings", []) or []]
@@ -218,7 +249,7 @@ def diff_representation_item(self, old_item, new_item):
218249
new_item.get_info_2(recursive=True),
219250
custom_operators=[DiffTerminator()] if self.is_shallow else [],
220251
math_epsilon=self.precision,
221-
exclude_regex_paths=[r".*id']$"]
252+
exclude_regex_paths=[r".*id']$"],
222253
)
223254
except:
224255
return True
@@ -249,14 +280,6 @@ def give_up_diffing(self, level, diff_instance) -> bool:
249280
raise Exception("Terminated")
250281

251282

252-
class DiffEncoder(json.JSONEncoder):
253-
def default(self, obj):
254-
try:
255-
return json.JSONEncoder.default(self, obj)
256-
except:
257-
return str(obj)
258-
259-
260283
if __name__ == "__main__":
261284
parser = argparse.ArgumentParser(description="Show the difference between two IFC files")
262285
parser.add_argument("old", type=str, help="The old IFC file")

src/ifcopenshell-python/docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
autoapi_type = 'python'
6161

6262
# autoapi works by reading source code instead of importing modules
63-
autoapi_dirs = ['../ifcopenshell']
63+
autoapi_dirs = ['../ifcopenshell', '../../ifcdiff']
6464

6565
# autoapi_options doesn't have show-module-summary, as it tends to create one
6666
# page per function which contradicts the presentation of showing all functions
Lines changed: 118 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,124 @@
11
IfcDiff
22
=======
33

4-
This documentation is free software! You are free to contribute and help write
5-
this document.
4+
IfcDiff is both a CLI utility and library that lets you compare the changes
5+
between two IFC models. Changes are made on the assumption that the GlobalId of
6+
an element in one model is consistent with the same element in another model.
7+
You may compare geometric changes, and changes in various IFC relationships and
8+
properties. IfcDiff supports comparing across different IFC schema versions.
69

7-
.. toctree::
8-
:maxdepth: 1
9-
:caption: Contents:
10+
Changes will be sorted into three lists:
1011

11-
Indices and tables
12-
------------------
12+
- **Added**: a list of GlobalIds of elements present in the new file but not
13+
present in the old file.
14+
- **Deleted**: a list of GlobalIds of elements present in the old file but not
15+
present in the new file.
16+
- **Changed**: A list of GlobalIds of elements present in both the old and new
17+
file, but changes were detected. A list of changes are provided.
1318

14-
* :ref:`genindex`
15-
* :ref:`modindex`
16-
* :ref:`search`
19+
There are different methods of installation, depending on your situation.
20+
21+
1. **Source installation** is recommended for users wanting to use the latest
22+
code as a library or a CLI utility.
23+
2. **Using the BlenderBIM Add-on** is recommended for non-developers wanting a
24+
graphical interface.
25+
26+
Source installation
27+
-------------------
28+
29+
1. :doc:`Install IfcOpenShell <ifcopenshell-python/installation>`
30+
2. `Clone the source code <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.7.0/src/ifcdiff>`_.
31+
3. ``pip install -r requirements.txt``
32+
33+
Here is a minimal example of how to use IfcDiff as a Python module or CLI
34+
utility:
35+
36+
::
37+
38+
$ python -m ifcdiff -h
39+
usage: ifcdiff.py [-h] [-o OUTPUT] [-r RELATIONSHIPS] old new
40+
41+
Show the difference between two IFC files
42+
43+
positional arguments:
44+
old The old IFC file
45+
new The new IFC file
46+
47+
options:
48+
-h, --help show this help message and exit
49+
-o OUTPUT, --output OUTPUT
50+
The JSON diff file to output. Defaults to diff.json
51+
-r RELATIONSHIPS, --relationships RELATIONSHIPS
52+
A list of space-separated relationships, chosen from "type", "property", "container", "aggregate", "classification"
53+
$ python -m ifcdiff old.ifc new.ifc
54+
$ cat diff.json
55+
56+
Here is a minimal example of how to use IfcDiff as a library:
57+
58+
.. code-block:: python
59+
60+
from ifcdiff import IfcDiff
61+
62+
ifc_diff = IfcDiff("/path/to/old.ifc", "/path/to/new.ifc", "/path/to/diff.json")
63+
ifc_diff.diff()
64+
print(ifc_diff.change_register)
65+
ifc_diff.export()
66+
67+
.. seealso::
68+
69+
For more information on how to use IfcDiff as a library, check out the :doc:`API
70+
reference <autoapi/ifcdiff/index>`.
71+
72+
73+
Using the BlenderBIM Add-on
74+
---------------------------
75+
76+
The BlenderBIM Add-on is a Blender based graphical interface to IfcOpenShell.
77+
Other than providing a graphical IFC authoring platform, it also comes with
78+
IfcOpenShell, its utilities, and a Python shell built-in. This means you don't
79+
need to install Python first, and you also can compare your IfcOpenShell
80+
scripting to what you see with a visual model viewer, or use a graphical
81+
interface to access the IfcOpenShell utilities.
82+
83+
1. Install the BlenderBIM Add-on by following the `BlenderBIM Add-on
84+
installation documentation
85+
<https://blenderbim.org/docs/users/installation.html>`_.
86+
87+
2. Launch Blender. Change to the **Scene Properties** tab in the **Properties
88+
Panel**. Scroll down to the **IFC Quality Control > IFC Diff** panel.
89+
90+
3. Browse to your old IFC file, new IFC file.
91+
92+
4. Optionally add any relationships you want to check.
93+
94+
5. Optionally type in a filter query.
95+
96+
6. Press **Execute IFC Diff**
97+
98+
TODO: add pictures and make this clearer for non-developers.
99+
100+
Geometry changes
101+
----------------
102+
103+
IfcDiff compares geometry changes using the underlying IFC geometric definition.
104+
This means that if a shape is described in one file as an extrusion, and as a
105+
mesh in another file, it is considered to be a change in geometry, even if they
106+
resolve to be the same boundary representation.
107+
108+
Geometric tolerance is defined using the precision defined in the new IFC model.
109+
110+
Relationships
111+
-------------
112+
113+
By default, IfcDiff only compares changes in attributes and geometry. You may
114+
wish to optionally specify more relationships to compare. You may choose from:
115+
116+
- **type**: detects changes in the type relationship, such as when an
117+
occurrence now belongs to a different type.
118+
- **property**: detects changes in property sets, properties, quantity sets,
119+
and quantities. Also includes detected changes in inherited properties.
120+
- **container**: detects changes in the spatial container, handling indirect
121+
containment such as when an element is part of an aggregate.
122+
- **aggregate**: detects changes in aggregation.
123+
- **classification**: detects changes in classification references. Also
124+
includes detected changes in inherited classifications.

src/ifcopenshell-python/docs/ifcopenshell-python/installation.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,10 @@ Using the BlenderBIM Add-on
9191

9292
The BlenderBIM Add-on is a Blender based graphical interface to IfcOpenShell.
9393
Other than providing a graphical IFC authoring platform, it also comes with
94-
IfcOpenShell and a Python shell built-in. This means you don't need to install
95-
Python first, and you also can compare your IfcOpenShell scripting to what you
96-
see with a visual model viewer.
94+
IfcOpenShell, its utilities, and a Python shell built-in. This means you don't
95+
need to install Python first, and you also can compare your IfcOpenShell
96+
scripting to what you see with a visual model viewer, or use a graphical
97+
interface to access the IfcOpenShell utilities.
9798

9899
1. Install the BlenderBIM Add-on by following the `BlenderBIM Add-on
99100
installation documentation

0 commit comments

Comments
 (0)