Как получить исходную геометрию стены с помощью Revit API?

В проекте мне нужно экспортировать исходную геометрию стены в файл 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 - rac_basic_sample_project.rvt, поставляемый с Revit. Стена, которую я хочу экспортировать, - это стена с идентификатором 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;
}

person user3337449    schedule 21.02.2014    source источник
comment
Не могли бы вы рассказать нам поподробнее?   -  person Shevliaskovic    schedule 21.02.2014
comment
Вы изменили весь смысл вопроса?   -  person Israel Rodriguez    schedule 22.02.2014


Ответы (2)


Я использую следующий метод для получения элементов определенной категории.

    /// <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 в будущем, а не использует одни и те же блоки кода повторно во всей базе кода.

person sweetfa    schedule 22.02.2014

Если вы хотите получить окна, двери и любые другие отверстия в стене, это правильный код:

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

person Israel Rodriguez    schedule 22.02.2014