0

在一个项目中,我需要将墙的原始几何图形导出到 IFC 文件。所谓原始几何就是墙体的几何形状,没有被墙上的门窗切割,没有与屋顶、地板、梁、柱等连接。我想要的原始几何通常应该是一个像盒子一样的形状.

不幸的是,没有直接的 Revit API 可以为我提供墙的原始几何图形。element.get_Geometry 方法返回由门、窗和连接的地板、屋顶等切割的最终几何图形。

获得墙的原始几何图形的一种可能方法是我自己根据墙的参数重建几何图形,但我懒惰的方法是让 Revit 完成这项工作。我的方法有以下五个步骤:

步骤 1:启动 Revit 事务。

第 2 步:在调用 element.get_Geometry 之前,从 Revit 文档中临时删除墙中承载的门窗,以及与墙相连的屋顶和地板。

第 3 步:调用 document.Regenerate 方法来更新文档中的元素。当然,墙的几何形状也应该更新。

第 4 步:调用 element.get_Geometry 以获取我想要的原始几何图形。

第 5 步:回滚事务以使 Revit 文档保持不变。

问题出现在第 2 步。即使我删除了门窗,返回的几何图形中仍然存在开口。

我的问题是,如何删除与墙相关的所有元素?

我的 Revit 版本是 2013。我使用的 .rvt 文件是 Revit 附带的 rac_basic_sample_project.rvt。我要导出的墙是 id 为 117698 或 117654 的墙。

我的项目基于 Revit IFC 导出器源代码。

以下是我用来获取原始几何图形的代码段:

private GeometryElement GetOriginalWallGeometry2(Element element)
{
    Document doc = element.Document;
    GeometryElement geomElem = null;
    //Step 1
    using (Transaction t = new Transaction(doc))
    {
        //Step 2:

        //delete wall joins
        Autodesk.Revit.DB.Wall wall = element as Autodesk.Revit.DB.Wall;

        //assert element is a wall
        //the joined floors or roofs can be deleted as expected.
        if (null != wall)
        {
            while (Autodesk.Revit.DB.WallUtils.IsWallJoinAllowedAtEnd(wall, 0))
            {
                Autodesk.Revit.DB.WallUtils.DisallowWallJoinAtEnd(wall, 0);
            }
            while (Autodesk.Revit.DB.WallUtils.IsWallJoinAllowedAtEnd(wall, 1))
            {
                Autodesk.Revit.DB.WallUtils.DisallowWallJoinAtEnd(wall, 1);
            }
        }

        //The following code of deleting doors doesn't work as expected.
        {
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            ICollection<Element> elementsList = collector.OfCategory(BuiltInCategory.OST_Doors).ToElements(); //here should be OST_Doors or others?

            foreach (Element elem in elementsList)
            {
                try
                {
                    doc.Delete(elem);
                }
                catch (System.Exception ex)
                {
                }
            }
        }

        //The following code of deleting windows doesn't work as expected.
        {
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            ICollection<Element> elementsList = collector.OfCategory(BuiltInCategory.OST_Windows).ToElements();//here should be OST_Windows or others?

            foreach (Element elem in elementsList)
            {
                try
                {
                    doc.Delete(elem);
                }
                catch (System.Exception ex)
                {
                }
            }
        }


        //The following code also doesn't work as expected.
        Autodesk.Revit.DB.HostObject hostObj = element as Autodesk.Revit.DB.HostObject;
        if (hostObj != null)
        {
            IList<ElementId> idlist = hostObj.FindInserts(true, true, true, true);
            foreach (ElementId id in idlist)
            {
                try
                {
                    doc.Delete(id);
                }
                catch (System.Exception ex)
                {
                }
            }
        }

        //Floors can be deteled as expected.
        {
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            ICollection<Element> linkList = collector.OfCategory(BuiltInCategory.OST_Floors).ToElements();

            foreach (Element elelink in linkList)
            {
                try
                {
                    doc.Delete(elelink);
                }
                catch (System.Exception ex)
                {

                }
            }
        }

        //Roofs can be deteled as expected.
        {
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            ICollection<Element> linkList = collector.OfCategory(BuiltInCategory.OST_Roofs).ToElements();

            foreach (Element elelink in linkList)
            {
                try
                {
                    doc.Delete(elelink);
                }
                catch (System.Exception ex)
                {

                }
            }
        }

        //Step 3
        doc.Regenerate();

        //Step 4
        Options options;
        View ownerView = element.Document.GetElement(element.OwnerViewId) as View;
        if (ownerView == null)
        {
            options = GeometryUtil.GetIFCExportGeometryOptions();
        }
        else
        {
            options = new Options();
            options.View = ownerView;
        }
        geomElem = element.get_Geometry(options);

        //Step 5
        FailureHandlingOptions failureOptions = t.GetFailureHandlingOptions();
        failureOptions.SetClearAfterRollback(true);
        failureOptions.SetDelayedMiniWarnings(true);
        t.SetFailureHandlingOptions(failureOptions);
        try
        {
            t.RollBack();
        }
        catch (System.Exception ex)
        {
        }
    }

    return geomElem;
}
4

2 回答 2

0

我使用以下方法来检索特定类别的元素。

    /// <summary>
    /// Get all elements of the specified type that fall into the specified category
    /// <para>The specified type must derive from Element, or you can use Element but you get everything :)</para>
    /// </summary>
    /// <typeparam name="T">The type of element to get</typeparam>
    /// <param name="builtInCategory">The BuiltinCategory to discriminate the element set</param>
    /// <returns>The collection of elements that match the type and specified categry</returns>
    public IEnumerable<T> GetElements<T>(BuiltInCategory builtInCategory) where T : Element
    {
        FilteredElementCollector collector = new FilteredElementCollector(Document);
        // Seems you must be a subclass of element to use the OfClass method
        if (typeof(T) != typeof(Element))
            collector.OfClass(typeof(T));
        collector.OfCategory(builtInCategory);
        return collector.Cast<T>();
    }

如果您想获得门窗,那么它将被用作

var doors = GetElements<FamilyInstance>(BuiltInCategory.OST_DOORS);
var windows = GetElements<FamilyInstance>(BuiltInCategory.OST_WINDOWS);

这假定您正在寻找的开口是门或窗。

如果您正在寻找墙壁或其他类型的开口内的空隙挤压等,那么您需要在您的问题中更加具体。

作为上面显示的函数的更复杂版本,当我还希望对正在检索的元素应用过滤器时,我使用以下方法。

        /// <summary>
    /// Get the collection of elements of the specified type that are within the provided category that also pass the filter.
    /// <para>The specified type must derive from Element, or you can use Element but you get everything :)</para>
    /// </summary>
    /// <typeparam name="T">The type of element to get</typeparam>
    /// <param name="builtInCategory">The BuiltinCategory to discriminate the element set</param>
    /// <param name="filter">The filter to check the element against</param>
    /// <returns>The collection of elements of the specified type and specified category that pass the filter</returns>
    public IEnumerable<T> GetElements<T>(BuiltInCategory builtInCategory, ElementFilter filter) where T : Element
    {
        FilteredElementCollector collector = new FilteredElementCollector(Document);
        // Seems you must be a subclass of element to use the OfClass method
        if (typeof(T) != typeof(Element))
            collector.OfClass(typeof(T));
        collector.OfCategory(builtInCategory);
        collector.WherePasses(filter);
        return collector.Cast<T>();
    }

使用上面定义的方法方法的优点是它将您的代码与将来的 Revit API 更改隔离开来,而不是在整个代码库中重复使用相同的代码块。

于 2014-02-22T00:48:03.483 回答
0

如果您想检索窗户、门和墙上的任何其他开口,这是正确的代码:

var ids = (yourCurrentWallElement as Wall).FindInserts(true, true, true, true);
foreach (ElementId id in ids)
{
    var el = doc.GetElement(id);

    Debug.WriteLine(" Id: " + el.Id);
    Debug.WriteLine(" Type: " + el.GetType().Name);
    Debug.WriteLine(" Category: " + el.Category.Name);
    Debug.WriteLine(" Type: " + el.GetType().Name);

    if (el is FamilyInstance)
    {
        var fi = el as FamilyInstance;
        if (fi != null)
            Debug.WriteLine(" Symbol Name: " + fi.Symbol.Name);
    }
}

有关 FindInserts 的更多信息 -> http://revitapisearch.com/html/58990230-38cb-3af7-fd25-96ed3215a43d.htm

其他示例-> http://spiderinnet.typepad.com/blog/2012/04/get-wall-inserts-using-the-revit-wallfindinserts-net-api.html

于 2014-02-22T03:11:40.010 回答