In the construction drawing review system, the designer submits the designed model / drawing, and the review expert reviews the model / drawing. If any non-compliance is found during the review, the process shall be returned to the design unit, and the design unit's personnel shall readjust the design according to the review comments, and submit it to the review expert again after the adjustment. At this time, in order to facilitate expert review, it is necessary to know what changes have taken place between the model / drawing of the current round and the model / drawing of the previous round, and review the changes.
Let's see the effect first
The effect is shown above. On the left is the model of the current review round, in the middle is the model of the previous round, and on the right is the list of changes generated by the comparison of the two models.
(1) Click the component in "add build" to automatically locate the new target component in the current round. The change component is indicated in light green. Two model perspectives move synchronously.
(2) Click the component in "delete build" to automatically locate the target component in the previous round. The component in this round is deleted, so it is not displayed. The change component is indicated in light green. Two model perspectives move synchronously.
(3) click the component in "modify build" to automatically locate the component modified in the current round and the component corresponding to the previous round. The change component is indicated in light green. Two model perspectives move synchronously.
Before BIMFACE, there was no three-dimensional model linkage and comparison function. After I communicated with Meili, the technical support team of BIMFACE, they incorporated my requirements into their product requirements. After the hard work of engineers working overtime, they soon realized this function. Thank you to all the partners of BIMFACE team, for your trust and acceptance of developers, and for your hard work.
Dishuizhien, when Yongquan reported to each other, dedicated to the personal BIMFace C ා SDK open source project.
Open source address: https://gitee.com/NAlps/BIMFace.SDK
Author: Zhang CHUANNING QQ: 905442693 wechat: savionzhang
Welcome to download, exchange and share.
The following describes the principle and implementation of BIMFACE model comparison function.
Model comparison can analyze the differences between the two files / models, and determine the geometric and attribute differences between the two files / models, including added components, deleted components and modified components. Model correspondence can be used for version comparison of files / models.
Special note: model comparison is carried out in BIMFACE cloud, which usually takes 5-10 minutes. When the model comparison is completed, BIMFACE can inform the comparison results.
- You need to upload the modified and modified models to the cloud and convert them successfully before initiating model comparison;
- Currently, only. rvt single file model comparison is supported.
- Model comparison is initiated through the server API (fileId of model files before and after comparison);
- Wait for the cloud comparison task to execute;
- After the comparison, the difference model is displayed by calling JavaScript API on the web page;
- In addition to displaying the difference model, you also need to call the server API to obtain the comparison results (including the list of new, deleted and modified components).
After the model file is transformed in the cloud, the data package defined by BIMFACE is generated. Therefore, to compare two model files, you actually need to compare the packets of the two files. As shown in the figure below, file B is the modified version of file A. after comparison, the result includes two parts:
- Geometric differences;
- Change components and properties.
BIMFACE provides a server-side API for initiating comparison, obtaining comparison status and results. Please refer to my blog:
After calling the API of the server to obtain the comparison results, the front-end needs to use JS to achieve the synchronous linkage effect, and automatically locate to the perspective of the component after clicking the change component.
1 // Simultaneous translation and rotation of old and new models 2 function correspond() { 3 latestViewer = latest.getViewer(); 4 var state, focus; 5 6 prevViewer = prev.getViewer(); 7 view1Bind = function (data) { 8 //Update old model state with new model state 9 var latestState = latestViewer.getCurrentState(); 10 prev.setState(latestState); 11 prev.getViewer().camera.up.copy(latestViewer.getViewer().camera.up); 12 } 13 14 view2Bind = function (data) { 15 //Update the state of the new model with the state of the old model 16 var prevState = prev.getCurrentState(); 17 latestViewer.setState(prevState); 18 latestViewer.getViewer().camera.up.copy(prev.getViewer().camera.up); 19 } 20 21 //Considering the influence of the dead cycle, we can't listen to the render event at the same time, so we mainly listen to the mouse location model 22 document.querySelector('#container').addEventListener('mousemove', 23 function (e) { 24 if (focus == undefined) { 25 var width = document.querySelector('.latest').offsetWidth; 26 if (e.clientX > width) { 27 focus = 1; 28 latestViewer.removeEventListener('Rendered', view1Bind); 29 prev.addEventListener('Rendered', view2Bind); 30 } else { 31 focus = 0; 32 prev.removeEventListener('Rendered', view2Bind); 33 latestViewer.addEventListener('Rendered', view1Bind); 34 } 35 } 36 }); 37 38 view1.addEventListener('mouseover', 39 function (e) { 40 if (focus == 0) { 41 return; 42 } 43 focus = 0; 44 // Unbind and rebind events to synchronize the Rendered of old and new models 45 prev.removeEventListener('Rendered', view2Bind); 46 latestViewer.addEventListener('Rendered', view1Bind); 47 }); 48 49 view2.addEventListener('mouseover', 50 function () { 51 if (focus == 1) { 52 return; 53 } 54 focus = 1; 55 // Unbind and rebind events to synchronize the Rendered of old and new models 56 latestViewer.removeEventListener('Rendered', view1Bind); 57 prev.addEventListener('Rendered', view2Bind); 58 }); 59 60 // Synchronizing Hover events of old and new models 61 prev.addEventListener('ComponentsHoverChanged', 62 function (e) { 63 latestViewer.getViewer().modelManager.sceneState.setHoverId(e.objectId); 64 }); 65 66 latestViewer.addEventListener('ComponentsHoverChanged', 67 function (e) { 68 prev.getViewer().modelManager.sceneState.setHoverId(e.objectId); 69 }); 70 71 var ViewerEvent = Glodon.Bimface.Viewer.Viewer3D; 72 latestViewer.setCameraAnimation(false); 73 prev.setCameraAnimation(false); 74 }
1 //Create change list and click event of component 2 function createDom(result) { 3 // Set UI of component difference component tree 4 var newItems = result.newItems, 5 deleteItems = result.deleteItems, 6 changeItems = result.changeItems; 7 var typeBoxs = document.querySelectorAll('.type-box'); 8 typeBoxs[0].innerHTML = 9 `<div class="title"><i class="icon arrow"></i><i class="icon-type new"></i>New components( ${newItems.length})</div> 10 <ul id="addElement" class="type-ul">${createDomNode(newItems)}</ul>`; 11 12 // Delete component list 13 typeBoxs[1].innerHTML = 14 `<div class="title"><i class="icon arrow"></i><i class="icon-type remove"></i>Delete component( ${deleteItems.length})</div> 15 <ul id="removeElement" class="type-ul">${createDomNode(deleteItems)}</ul>`; 16 17 // Modify component list 18 typeBoxs[2].innerHTML = 19 `<div class="title"><i class="icon arrow"></i><i class="icon-type revise"></i>Modifying components( ${changeItems.length})</div> 20 <ul id="reviseElement" class="type-ul">${createDomNode(changeItems)}</ul>`; 21 22 // Difference component tree list 23 document.querySelector('.compare-content').addEventListener('click', 24 function (e) { 25 var element = e.target; 26 if (element.tagName == 'I' && element.hasClass('arrow')) { 27 if (element.hasClass('close')) { 28 element.removeClass('close'); 29 element.parentElement.nextElementSibling.removeClass('close'); 30 } else { 31 element.addClass('close'); 32 element.parentElement.nextElementSibling.addClass('close'); 33 } 34 } else if (element.tagName == 'SPAN' && element.getAttribute('type')) { 35 var type = element.getAttribute('type'), 36 id = element.parentElement.getAttribute('data-oid'); 37 if (type == 'NEW') { 38 latestViewer.setSelectedComponentsById([id]);// Highlight the selected component 39 latestViewer.zoomToSelectedComponents(); // Location 40 view1Bind(); 41 } else if (type == 'DELETE') { 42 prev.setSelectedComponentsById([id]);// Highlight the selected component 43 prev.zoomToSelectedComponents(); // Location 44 view2Bind(); 45 } else { 46 latestViewer.setSelectedComponentsById([id]); // Highlight the selected component 47 latestViewer.zoomToSelectedComponents();// location; 48 view1Bind(); 49 prev.setSelectedComponentsById([id]); 50 } 51 } 52 }); 53 }