C#开发BIMFACE系列27 服务端API之获取模型数据12:获取构件分类树

BIMFACE官方示例中,加载三维模型后,模型浏览器中左上角默认提供了“目录树”的功能,清晰地展示了模型的完整构成及上下级关系。
本篇介绍如何获取单个模型的构件分类树信息。
请求地址:POST https://api.bimface.com/data/v2/files/{fileId}/tree
说明:单模型构件分类树, treeType 接受两个值:default 和 customized,默认为 default。
v参数用来区别 treeType 为 default 时返回树的格式, customized总是返回格式2.0的构件树。
参数:
v参数用来区别 treeType 为 default 时返回树的格式, customized总是返回格式2.0的构件树。
当 treeType 为"customized"时,desiredHierarchy 表示了筛选树的层次,可选值有building,systemType,specialty,floor,category,family,familyType,如:desiredHierarchy=specialty,systemtype。
customizedNodeKeys:用来指定筛选树每个维度用id或者是name作为唯一标识, 如"floor":"id"。
请求 path(示例):https://api.bimface.com/data/v2/files/1211223382064960/tree?v=2.0
请求 header(示例):"Authorization: Bearer dc671840-bacc-4dc5-a134-97c1918d664b"
请求 body(示例):可以为空,不传递。
HTTP响应示例(200):
{ "code": "success", "message": null, "data": [ { "actualName": "1F", "data": null, "elementCount": 18, "id": "694", "items": [ { "actualName": "栏杆扶手", "data": null, "elementCount": 18, "id": "-2000126", "items": [ { "actualName": "栏杆扶手", "data": null, "elementCount": 18, "id": "", "items": [ { "actualName": "栏杆", "data": null, "elementCount": 1, "id": null, "items": [], "name": "栏杆", "type": "familyType" } ], "name": "栏杆扶手", "type": "family" } ], "name": "栏杆扶手", "type": "category" } ], "name": "1F", "type": "floor" } ] }
返回的结果结构比较复杂,封装成对应的C#类如下:
/// <summary> /// 获取单个模型的构件分类树(2.0的默认分类树 floor, category, family, familyType)返回的结果类(默认模式) /// </summary> [Serializable] public class SingleModelTree : GeneralResponse<List<TreeItem>> { }
调用的 TreeItem 类
[Serializable] public class TreeItem { /// <summary> /// 项的名称 /// </summary> [JsonProperty("actualName")] public string ActualName { get; set; } [JsonProperty("data")] public string Data { get; set; } [JsonProperty("elementCount")] public int? ElementCount { get; set; } [JsonProperty("id")] public string Id { get; set; } [JsonProperty("items")] public TreeItem[] Items { get; set; } [JsonProperty("name")] public string Name { get; set; } /// <summary> /// 例如:familyType、family、category /// </summary> [JsonProperty("type")] public string Type { get; set; } /// <summary>返回表示当前对象的字符串。</summary> /// <returns>表示当前对象的字符串。</returns> public override string ToString() { return String.Format("[actualName={0}, data={1}, elementCount={2}, id={3}, items={4}, name={5}, type={6}]", ActualName, Data, ElementCount, Id, Items.ToStringLine(), Name, Type); } }
请注意 TreeItem 类中的 public TreeItem[] Items { get; set; } 属性,类型是该类本身。属于递归引用。
Newtonsoft.Json.dll 默认支持递归引用类的序列化与反序列化。
C#实现方法:
1 /// <summary> 2 /// 获取单个模型中构件的默认分类树 3 /// </summary> 4 /// <param name="accessToken">【必填】令牌</param> 5 /// <param name="fileId">【必填】代表该单模型的文件ID</param> 6 /// <param name="v">【非必填】用来区别treeType为default时返回树的格式</param> 7 /// <param name="request">【非必填】其他过滤参数类对象</param> 8 /// <returns></returns> 9 public virtual SingleModelTree GetSingleModelTreeByDefault(string accessToken, long fileId, string v = "2.0", FileTreeRequestBody request = null) 10 { 11 //return GetSingleModelTree(accessToken, fileId, TreeType.Default, v, request); 12 /* 单模型构件分类树, 13 (1)treeType 接受两个值:default 和 customized,默认为 default。 14 (2)v 参数用来区别 treeType 为 default 时返回树的格式, customized 总是返回格式2.0的构件树。 15 (3)当 treeType 为"customized"时,FileTreeRequestBody 类的 desiredHierarchy 属性 表示了筛选树的层次,可选值有building,systemType,specialty,floor,category,family,familyType, 16 如:desiredHierarchy=specialty,systemtype。 17 customizedNodeKeys: 用来指定筛选树每个维度用id或者是name作为唯一标识, 如"floor":"id" 18 */ 19 20 // POST https://api.bimface.com/data/v2/files/{fileId}/tree 21 string url = string.Format(BimfaceConstants.API_HOST + "/data/v2/files/{0}/tree?treeType=default", fileId); 22 23 if (!string.IsNullOrWhiteSpace(v)) 24 { 25 url = url + "&v=" + v; 26 } 27 28 string data = string.Empty; 29 if (request != null) 30 { 31 data = request.SerializeToJson(); 32 } 33 34 BimFaceHttpHeaders headers = new BimFaceHttpHeaders(); 35 headers.AddOAuth2Header(accessToken); 36 37 try 38 { 39 SingleModelTree response; 40 41 HttpManager httpManager = new HttpManager(headers); 42 HttpResult httpResult = httpManager.Post(url, data); 43 if (httpResult.Status == HttpResult.STATUS_SUCCESS) 44 { 45 response = httpResult.Text.DeserializeJsonToObject<SingleModelTree>(); 46 } 47 else 48 { 49 response = new SingleModelTree 50 { 51 Message = httpResult.RefText 52 }; 53 } 54 55 return response; 56 } 57 catch (Exception ex) 58 { 59 throw new Exception("[获取单个模型中构件的默认分类树]发生异常!", ex); 60 } 61 }
其中调用到的 httpManager.Post() 方法,请参考《C# HTTP系列》
在BIMFACE的控制台中可以看到我们上传的文件列表,模型状态均为转换成功。
使用“A4.rvt”为例测试上述方法。

完整的分类树为
success [ { "actualName": "标高 1", "data": null, "elementCount": 4, "id": "311", "items": [ { "actualName": "墙", "data": null, "elementCount": 4, "id": "-2000011", "items": [ { "actualName": "基本墙", "data": null, "elementCount": 4, "id": "", "items": [ { "actualName": "常规 - 200mm", "data": null, "elementCount": 4, "id": "398", "items": [], "name": "常规 - 200mm", "type": "familyType" } ], "name": "基本墙", "type": "family" } ], "name": "墙", "type": "category" } ], "name": "标高 1", "type": "floor" } ]
测试代码如下:
// 获取构件分类树(默认) protected void btnGetSingleModelTreeByDefault_Click(object sender, EventArgs e) { long fileId = txtFileID.Text.Trim().ToLong(); FileConvertApi api = new FileConvertApi(); SingleModelTree response = api.GetSingleModelTreeByDefault(txtAccessToken.Text, fileId); txtResult.Text = response.Code.ToString2() + Environment.NewLine + response.Message.ToString2() + Environment.NewLine + response.Data.ToStringLine(); }
请求 path(示例):https://api.bimface.com/data/v2/files/1211223382064960/tree?v=2.0&treeType=customized
请求 header(示例):"Authorization: Bearer dc671840-bacc-4dc5-a134-97c1918d664b"
请求 body(示例):
{ "desiredHierarchy": [ "category", "family" ], "customizedNodeKeys": { "category": "name" } }
请求体不能为 NULL ,必须传递值。 否则请求失败,提示 system.error. customized tree request body is null
HTTP响应示例(200):
{ "code": "success", "message": null, "data": { "items": [ { "actualName": "专用设备", "data": null, "elementCount": 6, "id": "-2001350", "items": [ { "actualName": "投影仪-基于天花板 3D", "data": null, "elementCount": 3, "id": "", "items": [ ], "name": "投影仪-基于天花板 3D", "type": "family" }, { "actualName": "投影屏幕-基于天花板 3D", "data": null, "elementCount": 3, "id": "", "items": [ ], "name": "投影屏幕-基于天花板 3D", "type": "family" } ], "name": "卫浴装置", "type": "category" } ], "root": "category" } }
返回的结果结构比较复杂,封装成对应的C#类如下:
/// <summary> /// 获取单个模型的构件分类树(自定义树floor, category, family, familyType)返回的结果类 /// </summary> [Serializable] public class SingleModelTreeByCustomized : GeneralResponse<SingleModelTreeByCustomized> { [JsonProperty("root")] public string Root { get; set; } [JsonProperty("items")] public TreeItem[] Items { get; set; } /// <summary>返回表示当前对象的字符串。</summary> /// <returns>表示当前对象的字符串。</returns> public override string ToString() { return String.Format("[root={0}, items={1}]", Root, Items.ToStringLine()); } }
C#实现方法:
1 /// <summary> 2 /// 获取单个模型中构件的自定义分类树 3 /// </summary> 4 /// <param name="accessToken">【必填】令牌</param> 5 /// <param name="fileId">【必填】代表该单模型的文件ID</param> 6 /// <param name="v">【非必填】用来区别treeType为default时返回树的格式</param> 7 /// <param name="request">【非必填】其他过滤参数类对象</param> 8 /// <returns></returns> 9 public virtual SingleModelTreeByCustomized GetSingleModelTreeByCustomized(string accessToken, long fileId, string v = "2.0", FileTreeRequestBody request = null) 10 { 11 //return GetSingleModelTree(accessToken, fileId, TreeType.Default, v, request); 12 /* 单模型构件分类树, 13 (1)treeType 接受两个值:default 和 customized,默认为 default。 14 (2)v 参数用来区别 treeType 为 default 时返回树的格式, customized 总是返回格式2.0的构件树。 15 (3)当 treeType 为"customized"时,FileTreeRequestBody 类的 desiredHierarchy 属性 表示了筛选树的层次,可选值有building,systemType,specialty,floor,category,family,familyType, 16 如:desiredHierarchy=specialty,systemtype。 17 customizedNodeKeys: 用来指定筛选树每个维度用id或者是name作为唯一标识, 如"floor":"id" 18 */ 19 20 // POST https://api.bimface.com/data/v2/files/{fileId}/tree 21 string url = string.Format(BimfaceConstants.API_HOST + "/data/v2/files/{0}/tree?treeType=customized", fileId); 22 23 if (!string.IsNullOrWhiteSpace(v)) 24 { 25 url = url + "&v=" + v; 26 } 27 28 string data = string.Empty; 29 if (request != null) 30 { 31 data = request.SerializeToJson(); 32 } 33 34 BimFaceHttpHeaders headers = new BimFaceHttpHeaders(); 35 headers.AddOAuth2Header(accessToken); 36 37 try 38 { 39 SingleModelTreeByCustomized response; 40 41 HttpManager httpManager = new HttpManager(headers); 42 HttpResult httpResult = httpManager.Post(url, data); 43 if (httpResult.Status == HttpResult.STATUS_SUCCESS) 44 { 45 response = httpResult.Text.DeserializeJsonToObject<SingleModelTreeByCustomized>(); 46 } 47 else 48 { 49 response = new SingleModelTreeByCustomized 50 { 51 Message = httpResult.RefText 52 }; 53 } 54 55 return response; 56 } 57 catch (Exception ex) 58 { 59 throw new Exception("[获取单个模型中构件的自定义分类树]发生异常!", ex); 60 } 61 }
测试:
同样使用“A4.rvt”为例测试上述方法。

完整的分类树为
success [root=单体, items=[actualName=, data=, elementCount=4, id=0, items=[actualName=, data=, elementCount=4, id=0, items=[actualName=, data=, elementCount=4, id=0, items=[actualName=标高 1, data=, elementCount=4, id=311, items=[actualName=墙, data=, elementCount=4, id=-2000011, items=[actualName=基本墙, data=, elementCount=4, id=, items=[actualName=常规 - 200mm, data=, elementCount=4, id=398, items=, name=常规 - 200mm, type=familyType ], name=基本墙, type=family ], name=墙, type=category ], name=标高 1, type=floor ], name=未设专业, type=specialty ], name=未设系统类型, type=systemType ], name=未设单体, type=building ] ]
界面上的筛选树的层次是过滤条件,主要用于筛选 type 属性。
测试代码如下:
// 获取构件分类树(自定义) protected void btnGetSingleModelTreeByCustomized_Click(object sender, EventArgs e) { long fileId = txtFileID.Text.Trim().ToLong(); List<string> lstDesiredHierarchy = new List<string>(); if (chkTreeBuilding.Checked) { lstDesiredHierarchy.Add("building"); } if (chkTreeSystemType.Checked) { lstDesiredHierarchy.Add("systemType"); } if (chkTreeSpecialty.Checked) { lstDesiredHierarchy.Add("specialty"); } if (chkTreeFloor.Checked) { lstDesiredHierarchy.Add("floor"); } if (chkTreeCategory.Checked) { lstDesiredHierarchy.Add("category"); } if (chkTreeFamily.Checked) { lstDesiredHierarchy.Add("family"); } if (chkTreeFamilyType.Checked) { lstDesiredHierarchy.Add("familyType"); } FileTreeRequestBody request = new FileTreeRequestBody(); request.DesiredHierarchy = lstDesiredHierarchy.ToArray();// new[] { "building", "systemType", "specialty", "floor", "category", "family", "familyType" }; request.CustomizedNodeKeys = new Dictionary<string, string> { { "category", "name" } }; FileConvertApi api = new FileConvertApi(); SingleModelTreeByCustomized response = api.GetSingleModelTreeByCustomized(txtAccessToken.Text, fileId, "2.0", request); txtResult.Text = response.Code.ToString2() + Environment.NewLine + response.Message.ToString2() + Environment.NewLine + response.Data; }

成在管理,败在经验;嬴在选择,输在不学! 贵在坚持!
个人作品
BIMFace.SDK.NET
开源地址:https://gitee.com/NAlps/BIMFace.SDK
系列博客:https://www.cnblogs.com/SavionZhang/p/11424431.html
系列视频:https://www.cnblogs.com/SavionZhang/p/14258393.html
技术栈
1、AI、DeepSeek、MiniMax、通义千问
2、Visual Studio、.NET Core/.NET、MVC、Web API、RESTful API、gRPC、SignalR、Java、Python
3、jQuery、Vue.js、Bootstrap、ElementUI
4、数据库:分库分表、读写分离、SQLServer、MySQL、PostgreSQL、Redis、MongoDB、ElasticSearch、达梦DM、GaussDB、OpenGauss
5、架构:DDD、ABP、SpringBoot、jFinal
6、环境:跨平台、Windows、Linux
7、移动App:Android、IOS、HarmonyOS、微信小程序、钉钉、uni-app、MAUI
8、分布式、高并发、云原生、微服务、Docker、CI/CD、DevOps、K8S;Dapr、RabbitMQ、Kafka、RPC、Elasticsearch
欢迎关注作者头条号 张传宁IT讲堂,获取更多IT文章、视频等优质内容。
出处:www.cnblogs.com/SavionZhang
作者:张传宁 技术顾问、培训讲师、微软MCP、系统架构设计师、系统集成项目管理工程师、科技部创新工程师。
专注于企业级通用开发平台、工作流引擎、自动化项目(代码)生成器、SOA 、DDD、 云原生(Docker、微服务、DevOps、CI/CD);PDF、CAD、BIM 审图等研究与应用。
多次参与电子政务、图书教育、生产制造等企业级大型项目研发与管理工作。
熟悉中小企业软件开发过程:可行调研、需求分析、架构设计、编码测试、实施部署、项目管理。通过技术与管理帮助中小企业实现互联网转型升级全流程解决方案。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如有问题,可以通过邮件905442693@qq.com联系。共同交流、互相学习。
如果您觉得文章对您有帮助,请点击文章右下角【推荐】。您的鼓励是作者持续创作的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?