You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:46:43