Autodesk Forge:模型比较(BIM 360 功能)

Posted

技术标签:

【中文标题】Autodesk Forge:模型比较(BIM 360 功能)【英文标题】:Autodesk Forge: Model Compare (BIM 360 Feature) 【发布时间】:2017-09-05 16:14:49 【问题描述】:

Bim 360 有一个很棒的工具,称为“比较版本”,它允许查看两个 Revit 模型之间的更改。可以在此处找到有关该功能的更多信息:

Compare versions info

Autodesk Forge 中是否有此功能?我找不到它,我确实看到 forge 有一个 BIM 360 API,但我没有看到这个功能可用。

【问题讨论】:

【参考方案1】:

不,至少现在是这样。会很好,不是吗?也许在未来......

【讨论】:

【参考方案2】:

您可以使用ForgeAuthor sdk 执行此操作。

ForgeAuthor 是一个基于 .net 框架 4.5 的 .net 库,它提供了一种很好的面向对象的方式来操作 Audesk Forge Svf 模型,就像操作 XML 或 JSON 一样简单。

ForgeAuthor 可以读取 Autodesk Forge SVF 模型,比较差异,并生成差异模型。

#region setup materials

                var matUnmodified = new Material
                
                    Color = Vector3D.FromColor(0xffffff), //Darker: Vector3D.FromColor(0x101010)
                    Transparent = 0.95,
                    Reflectivity = 0
                ;

                var matAdd = new Material
                
                    Color = Vector3D.FromColor(Color.GreenYellow)
                ;

                var matDelete = new Material
                
                    Color = Vector3D.FromColor(Color.Red)
                ;

                var matModifiedBefore = new Material
                
                    Color = Vector3D.FromColor(Color.Orange),
                    Transparent = 0.5
                ;

                var matModifiedAfter = new Material
                
                    Color = Vector3D.FromColor(Color.Aqua),
                ;

                #endregion

                var baseModelPath = txtBaseModel.Text;
                var incrModelPath = txtIncrementModel.Text;
                var diffModelPath = txtDiffModel.Text;

                var svfbase = baseModelPath.EndsWith(@"zip")
                    ? SvfDocument.LoadFromZipFile(baseModelPath)
                    : SvfDocument.LoadFromSvfFile(baseModelPath);

                var svfincr = incrModelPath.EndsWith(@"zip")
                    ? SvfDocument.LoadFromZipFile(incrModelPath)
                    : SvfDocument.LoadFromSvfFile(incrModelPath);

                var compareResult = CompareModel(svfbase, svfincr);

                var svfdiff = new SvfDocument();
                svfdiff.Model.Name = @"Diff Model";
                svfdiff.Metadata = svfbase.Metadata;

                var nodeUnmodified = svfdiff.Model.Children.CreateNode();
                nodeUnmodified.Name = @"Unmodified";

                var nodeAdded = svfdiff.Model.Children.CreateNode();
                nodeAdded.Name = @"Added";

                var nodeDeleted = svfdiff.Model.Children.CreateNode();
                nodeDeleted.Name = @"Deleted";

                var nodeModifiedBefore = svfdiff.Model.Children.CreateNode();
                nodeModifiedBefore.Name = @"Modified Before";

                var nodeModifiedAfter = svfdiff.Model.Children.CreateNode();
                nodeModifiedAfter.Name = @"Modified After";

                svfbase.EnumerateNodes(node =>
                
                    if (node.Children?.Count == 0 &&
                        node.Fragments?.Count > 0 &&
                        string.IsNullOrEmpty(node.ExternalId) == false)
                    
                        if (compareResult.Unmodified.Remove(node.ExternalId))
                        
                            ImportNodeWithPath(nodeUnmodified, node, svfbase.Model, matUnmodified);
                        
                        else if (compareResult.Deleted.Remove(node.ExternalId))
                        
                            ImportNodeWithPath(nodeDeleted, node, svfbase.Model, matDelete);
                        
                        else if (compareResult.Modified.Contains(node.ExternalId))
                        
                            var targetNode =
                                ImportNodeWithPath(nodeModifiedBefore, node, svfbase.Model, matModifiedBefore);
                            targetNode.ExternalId += @"_Before";
                        
                    
                , svfbase.Model);

                svfincr.EnumerateNodes(node =>
                
                    if (node.Children?.Count == 0 &&
                        node.Fragments?.Count > 0 &&
                        string.IsNullOrEmpty(node.ExternalId) == false)
                    
                        if (compareResult.Added.Remove(node.ExternalId))
                        
                            ImportNodeWithPath(nodeAdded, node, svfincr.Model, matAdd);
                        
                        else if (compareResult.Modified.Remove(node.ExternalId))
                        
                            ImportNodeWithPath(nodeModifiedAfter, node, svfincr.Model, matModifiedAfter);
                        
                    
                , svfincr.Model);

                svfdiff.SaveToFolder(diffModelPath, true);
                svfdiff.Dispose();

                svfbase.Dispose();
                svfincr.Dispose();



private (HashSet<string> Unmodified, HashSet<string> Added, HashSet<string> Deleted, HashSet<string> Modified)
        CompareModel(SvfDocument svfbase, SvfDocument svfincr)
    
        var baseNodes = new Dictionary<string, SvfNode>();
        svfbase.EnumerateNodes(node =>
        
            if (node.Children?.Count == 0
                && node.Fragments?.Count > 0
                && string.IsNullOrEmpty(node.ExternalId) == false)
            
                baseNodes[node.ExternalId] = node;
            
        , svfbase.Model);

        var elementsAdded = new HashSet<string>();
        var elementsUnmodified = new HashSet<string>();
        var elementsModified = new HashSet<string>();
        var elementsDeleted = new HashSet<string>();

        svfincr.EnumerateNodes(node =>
        
            if (node.Children?.Count == 0
                && node.Fragments?.Count > 0
                && string.IsNullOrEmpty(node.ExternalId) == false)
            
                if (baseNodes.TryGetValue(node.ExternalId, out SvfNode baseNode))
                
                    if (baseNode.Fragments.Equals(node.Fragments))
                    
                        elementsUnmodified.Add(node.ExternalId); //unmdified
                    
                    else
                    
                        elementsModified.Add(node.ExternalId); //modified
                    

                    baseNodes.Remove(node.ExternalId);
                
                else
                
                    elementsAdded.Add(node.ExternalId); //added
                
            
        , svfincr.Model);

        foreach (var p in baseNodes.Keys)
        
            elementsDeleted.Add(p); //deleted
        
        baseNodes.Clear();

        return (elementsUnmodified, elementsAdded, elementsDeleted, elementsModified);
    

    private SvfNode ImportNodeWithPath(SvfNode targetNodeRoot, SvfNode sourceNode, SvfNode sourceNodeRoot, Material material)
    
        var targetNode = sourceNode.Parent == sourceNodeRoot
            ? targetNodeRoot
            : ImportNodeWithPath(targetNodeRoot, sourceNode.Parent, sourceNodeRoot, material);
        var resultNode = targetNode.Children.FirstOrDefault(x => x.Name == sourceNode.Name);
        if (resultNode == null)
        
            resultNode = targetNode.Children.ImportNode(sourceNode, null, false);
            foreach (var fragment in resultNode.Fragments)
            
                fragment.Material = material;
            
        
        return resultNode;
    

snapshot

【讨论】:

以上是关于Autodesk Forge:模型比较(BIM 360 功能)的主要内容,如果未能解决你的问题,请参考以下文章

Autodesk Forge:如何在 BIM 360 Docs 中查找模型的 svf 文件的 URL

Autodesk Forge 中自定义模型的动态位置

如何使用 forge 显示 BIM 360 模型?

广联达的BIMFACE有啥具体的功能?和Autodesk的forge对比如何?

Autodesk Forge 数据管理参考 API 未列出 Revit 参考

如何使用 BIM 360 Web 查看器 (Autodesk Forge)