在项目中,我需要将墙的原始几何体导出到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导出程序srouce代码。
以下是我用于获取原始几何的代码段:
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;
}
答案 0 :(得分: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更改隔离,而不是在整个代码库中重复使用相同的代码块。
答案 1 :(得分:0)
如果你想检索Windows,门和墙上的任何其他开口,这是正确的代码:
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的更多信息 - &gt; http://revitapisearch.com/html/58990230-38cb-3af7-fd25-96ed3215a43d.htm
其他示例 - &gt; http://spiderinnet.typepad.com/blog/2012/04/get-wall-inserts-using-the-revit-wallfindinserts-net-api.html