如何从Revit结构框架元素生成排序后的多级Dimensions列表(无循环)
嘿,我来帮你搞定这个Revit API的问题!你的核心需求是从结构框架元素中提取参数生成Dimensions列表,还要避免用for/foreach循环,同时完成排序——之前的错误是把整数值列表赋值给单个Dimensions对象的属性,这确实不对,因为每个结构框架元素对应一个Dimensions实例,我们需要批量生成这些实例,而不是把所有值塞给一个对象。
下面是正确的实现方式,全程用LINQ完成,没有显式的循环:
首先,先确认你的Dimensions类大概是这样的(如果还没定义的话):
public class Dimensions { public int B { get; set; } public int D { get; set; } public int CutLength { get; set; } }
接下来是核心的Revit API处理代码,用LINQ链式操作直接生成排序后的Dimensions列表:
using Autodesk.Revit.DB; using System.Linq; // 假设你已经获取到Revit的Document对象doc var structuralFramingCollector = new FilteredElementCollector(doc) .OfCategory(BuiltInCategory.OST_StructuralFraming) .WhereElementIsNotElementType() // 只筛选结构框架实例,排除类型本身 .Cast<FamilyInstance>(); // 用LINQ生成并排序Dimensions列表,全程无显式for/foreach var sortedDimensionsList = structuralFramingCollector .Select(frame => { // 获取结构框架的类型对象,提取b和d参数(类型参数) var frameType = frame.Symbol; int b = 0; int d = 0; // 提取b参数,处理可能的空值和单位转换 var bParam = frameType.LookupParameter("b"); // 如果是内置参数,建议用BuiltInParameter更可靠 if (bParam != null && bParam.HasValue) { // Revit内部长度单位是英尺,转成毫米取整(根据你的需求调整单位) b = (int)(bParam.AsDouble() * 304.8); // 如果b是整数类型参数,直接用bParam.AsInteger() } // 提取d参数,逻辑和b一致 var dParam = frameType.LookupParameter("d"); if (dParam != null && dParam.HasValue) { d = (int)(dParam.AsDouble() * 304.8); } // 提取Cut Length实例参数,用内置参数ID避免本地化问题 var cutLengthParam = frame.get_Parameter(BuiltInParameter.CUT_LENGTH); int cutLength = 0; if (cutLengthParam != null && cutLengthParam.HasValue) { cutLength = (int)(cutLengthParam.AsDouble() * 304.8); } // 返回当前框架对应的Dimensions实例 return new Dimensions { B = b, D = d, CutLength = cutLength }; }) // 按b、d、CutLength依次升序排序 .OrderBy(dim => dim.B) .ThenBy(dim => dim.D) .ThenBy(dim => dim.CutLength) .ToList();
关键说明:
- 避免显式循环:用LINQ的
Select方法遍历每个结构框架元素并投影成Dimensions对象,不需要自己写for/foreach,完全符合你的要求。 - 参数区分:b和d是类型参数,必须从
FamilyInstance.Symbol(即元素类型)中提取;Cut Length是实例参数,直接从FamilyInstance本身提取。 - 可靠性优化:提取Cut Length时用
BuiltInParameter.CUT_LENGTH,而不是硬编码参数名称,这样在不同语言版本的Revit中都能正常工作。 - 空值与单位处理:添加了参数空值检查,避免空引用异常;同时把Revit内部的英尺单位转换成毫米(或你需要的整数单位)再取整,确保得到整数数值。
最后,如果要输出多级列表,比如按B分组、再按D分组展示,可以继续用LINQ分组后输出(这里的循环是用于输出,不是创建列表,符合你的要求):
// 按B分组输出多级列表 foreach (var bGroup in sortedDimensionsList.GroupBy(d => d.B)) { Console.WriteLine($"# B = {bGroup.Key}"); foreach (var dGroup in bGroup.GroupBy(d => d.D)) { Console.WriteLine($"## D = {dGroup.Key}"); foreach (var item in dGroup) { Console.WriteLine($"- 切割长度: {item.CutLength}"); } } }
内容的提问来源于stack exchange,提问作者Dalia
相关产品推荐
相关产品推荐

