27 Mar 2022
Find model difference by Model Properties API
It is a typical requirement that people want to inspect the difference of model versions e.g. added/removed/changed elements and updated properties/geometries. Forge Viewer has provided DiffTool extension that compares models. It requires aggregating the models to viewer firstly and it runs the comparison on client(browser) side.
With Model Properties API, we now can get comparison on the cloud with more efficiency and flexible query (also called diff indexing). The API can tell added/removed/changed elements, properties hash and geometry hash of previous and current versions, and also bounding-box of the geometry element. In addition, the SQL-like query is also supported. We can use the schema to get the comparison with specific conditions. This API has been adopted in Design Collaboration of BIM360/ACC workflow, running as robust service to track changes version by version.
This tutorial describes the steps how to get comparison (diff indexing). It is very straightforward to get the properties results of diff. Similar to indexing only, the first is to ask Model Properties API to build indexing of the model (for diff), then query with conditions to filter out specific elements. The two steps can also be combined in one call.
e.g. without query, the payload will be the array only with the previous version urn and current version urn
{
"diffs": [
{
"prevVersionUrn": "urn:adsk.wipprod:fs.file:vf.R2CfQt3AS6WL0Bmmnld3uQ?version=1",
"curVersionUrn": "urn:adsk.wipprod:fs.file:vf.R2CfQt3AS6WL0Bmmnld3uQ?version=2"
}
]
}
- basic attributes: ids of svf2Id, lmvId(svf id), changeType etc
- props: all common properties of current version.
- prev: basic attributes, bounding box data etc of previous model version, and especially, the different properties
- propsHash: the hash that determines whether object properties have changed between different versions.
- geomHash: if it is geometry element, the hash determines whether the object geometry has changed between different versions.
- bboxMin, bboxMax: bounding box data if it is geometry element, in previous and current version.
So, the differences can be in geometries and properties. The elements may be added, modified and removed. If added, it has not properties in previous, if removed, it has not properties in current.
{
"type": "OBJECT_CHANGED",
"svf2Id": 127,
"otgId": 127,
"externalId": "4fcbe8e4-7bda-49d6-8863-f0ba387a7892-000ccf8f",
"changeType": "Transform",
"lmvId": 2608,
"lineageId": "81204bae",
"databaseId": "3d0bd846",
"props": {
"p002932a2": 0.0,
"p01bbdcf2": "Arch-FIRST FLOOR",
"p0337db30": true,
"p07bfebb5": 14.0,
"p09faf620": "1 D",
"p13b6b3a0": "1 D",
"p153cb174": "Round Elbow [839567]",
"p1b2aabe1": 8.750000000000028,
"p20d8441e": "Duct Fittings",
... ... ...
},
"propsHash": "608b8f68",
"propsIgnored": {
"p6a81eafd": 2588,
"p93e93af5": 2589,
"pedfa76dc": "839567"
},
"geomHash": "35w/2kXfdhGb+Hqh23vEqQ",
"bboxMin": {
"x": 29.311146955028047,
"y": -17.986398379990533,
"z": 32.969199978804575
},
"bboxMax": {
"x": 29.97224404688642,
"y": -17.325301288132156,
"z": 33.3248000030279
},
"views": [
"f109b687",
"f24d458"
],
"prev": {
"svf2Id": 127,
"otgId": 127,
"externalId": "4fcbe8e4-7bda-49d6-8863-f0ba387a7892-000ccf8f",
"lmvId": 2608,
"lineageId": "18291a14",
"databaseId": "936acb06",
"props": {
"p1b2aabe1": 10.666666666666671
},
"propsHash": "95064165",
"propsIgnored": {
"p6a81eafd": 2588,
"p93e93af5": 2589,
"pedfa76dc": "839567"
},
"geomHash": "EEmlccavNc/o2bYUORx21w",
"bboxMin": {
"x": 29.311146955028047,
"y": -17.986398379990533,
"z": 33.55340000756978
},
"bboxMax": {
"x": 29.97224404688642,
"y": -17.325301288132156,
"z": 33.908999990916236
},
"views": [
"f109b687",
"8e525582"
]
}
}
With query, we can build conditions to check specific changes of elements. e.g. Only check those items that are added or removed (note: the single quote mark for string type value).
{
"query": {
"$or":{
"$eq": [
"s.type",
"'OBJECT_REMOVED'"
],
"$eq": [
"s.type",
"'OBJECT_ADDED'"
]
}
}
}
{
"query": {
"$ne": [
"s.props.p517898a5",
"s.prev.props.p517898a5"
]
}
}
Or, check by some special algorithm, e.g. previous value of one property is less than that of current, and previous value of another property is greater than double of current.
{
"query": {
"$and":{
"$lt": [
"s.props.p5c9e9b62",
"s.prev.props.p5c9e9b62"
],
"$gt": [
"s.props.pae56a872",
{"$mul":["s.prev.props.pae56a872",2]}
]
}
}
}
{
"query": {
"$ne": [
"s.geomHash",
"s.prev.geomHash"
]
}
}
Although Model Properties API does not tell mesh of the geometry, the bounding-box data could be a reference the updated range of the shape. In addition, Model Properties API provides an attribute changeType that indicates if it is transform change (position, rotation only), or geometry change (size, dimension, shape )etc. So to check transform change only, the payload can be:
{
"query": {
"$eq": [
"s.changeType",
"’Transform’"
]
}
}
Of course, if we want to check the shape in details what exactly is changed, we just need to switch to design tool or viewer (like Forge Viewer).
Similarly to properties indexing, we can also specify Columns to transform the desired properties to the final results, instead of getting all properties. E.g. the query below only extracts some basic attributes and that specific property.
{
"query": {
"$ne": [
"s. pae56a872",
"s.prev. pae56a872"
]
},
"columns":{
"svf2Id": "s.svf2Id",
"externalId": "s.externalId",
"my_concerned_property_pre":"s.prev.props.pae56a872",
"my_concerned_property_cur":"s.props.pae56a872"
}
}
https://github.com/Autodesk-Forge/forge-model.properties-versions.difference
This sample downloads all differences and categorized to Added, Removed and Changed. It can isolate all added/removed/changed items and can also focus on specific different item, showing them in the viewers of previous version and current version respectively. For changed items, it also sort it out with that if the element has property change and which properties are changed.