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

如何筛选用户指定的两台机械设备之间的关联构件?

Solution to Filter Components Between Two Specific Mechanical Equipment

Got it, let's fix this to target exactly the connected components between two user-specified mechanical equipment. Your current approach uses bounding box intersection, which can pick up unrelated elements that just happen to overlap with the equipment's box. Instead, we'll leverage Revit's connector system to trace actual physical connections between the two devices.

Step 1: Define How to Select the Two Target Equipment

First, we need a way to identify the two specific equipment the user cares about. For this example, we'll use the ALL_MODEL_INSTANCE_COMMENTS parameter to match user-defined labels (like "EM-01" and "EM-02"). You could also adapt this to let users pick the equipment directly via a selection dialog if needed.

Step 2: Trace Connected Components Recursively

We'll recursively traverse the connectors starting from the first equipment, collecting all relevant pipes, fittings, and accessories until we reach the second equipment. This ensures we only get elements that are actually part of the connection path between the two devices.

Adjusted Code Implementation

using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Collections.Generic;
using System.Linq;

public void FilterComponentsBetweenTwoEquipment(UIDocument uiDoc)
{
    Document doc = uiDoc.Document;
    
    // --- Step 1: Get the two target mechanical equipment (customize this to match your user's selection method)
    string targetEM1Comment = "EM-01"; // Replace with user's first equipment identifier
    string targetEM2Comment = "EM-02"; // Replace with user's second equipment identifier

    FilteredElementCollector equipmentCollector = new FilteredElementCollector(doc)
        .OfClass(typeof(FamilyInstance))
        .OfCategory(BuiltInCategory.OST_MechanicalEquipment);

    FamilyInstance em1 = equipmentCollector
        .Cast<FamilyInstance>()
        .FirstOrDefault(em => em.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS)?.AsString() == targetEM1Comment);

    FamilyInstance em2 = equipmentCollector
        .Cast<FamilyInstance>()
        .FirstOrDefault(em => em.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS)?.AsString() == targetEM2Comment);

    if (em1 == null || em2 == null)
    {
        TaskDialog.Show("Error", "Could not find one or both target mechanical equipment.");
        return;
    }

    // --- Step 2: Define the types of elements we want to collect
    HashSet<ElementId> collectedElementIds = new HashSet<ElementId>();
    HashSet<Connector> visitedConnectors = new HashSet<Connector>();

    // Recursive function to trace connected elements
    void TraceConnectedElements(Connector startConnector)
    {
        if (visitedConnectors.Contains(startConnector)) return;
        visitedConnectors.Add(startConnector);

        Element currentElement = startConnector.Owner;

        // Add the element to our collection if it's a pipe, fitting, or accessory
        if (currentElement.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves
            || currentElement.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting
            || currentElement.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeAccessory)
        {
            collectedElementIds.Add(currentElement.Id);
        }

        // Check if we've reached the second equipment
        if (currentElement.Id == em2.Id)
        {
            return;
        }

        // Traverse all connected connectors
        foreach (Connector connectedConnector in startConnector.AllRefs)
        {
            TraceConnectedElements(connectedConnector);
        }
    }

    // Start tracing from all connectors on the first equipment
    foreach (Connector connector in em1.MEPModel.Connectors)
    {
        TraceConnectedElements(connector);
    }

    // --- Step 3: Display the results
    string report = string.Empty;
    foreach (ElementId elemId in collectedElementIds)
    {
        Element elem = doc.GetElement(elemId);
        report += $"Name = {elem.Name} | Element Id: {elemId}\n";
    }

    TaskDialog.Show("Connected Components Between Equipment", 
        $"Found {collectedElementIds.Count} elements in the connection path:\n\n{report}");
}

Key Improvements Over Your Original Code

  • Targeted Equipment Selection: We explicitly pick the two user-specified devices instead of iterating all equipment in the view.
  • Connection-Based Tracing: Uses Revit's Connector system to follow actual physical connections, so we don't get false positives from bounding box overlaps.
  • Recursive Traversal: Ensures we capture all elements along the path between the two devices, including pipes, fittings, and accessories.

Customization Tips

  • If you want users to select the equipment interactively, replace the parameter-based selection with uiDoc.Selection.PickObjects(ObjectType.Element, ...) to let them click the two devices.
  • You can expand the category filter to include other element types (like ducts, if needed) by adding their BuiltInCategory values to the check in the recursive function.

内容的提问来源于stack exchange,提问作者Nathan Franco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 14:08:15