原文链接: Create FaceWall on Slanted Mass Face
问题
我想在一个倾斜的面上创建一面墙。是否有例子代码可以参考?
Jeremy
这里有一段简单的代码,对象文档是包含一个概念块(Conceptual Mass)族实例的项目。代码首先检索概念块上法向方向为 (-1, 0, 1) 的面,然后在这个面上创建墙。
void CreateFaceWall( Document doc )
{
FilteredElementCollector collector = new FilteredElementCollector( doc );
FamilyInstance fi = collector.OfClass( typeof( FamilyInstance ) ).FirstElement() as FamilyInstance;
XYZ nnorm = new XYZ( -1, 0, 1 ).Normalize();
if( fi != null )
{
Options op = new Options();
op.IncludeNonVisibleObjects = true;
//op.DetailLevel = DetailLevels.Undefined;
op.ComputeReferences = true;
// 译者注:个人认为这个类名起得不好,不太像一个集合类。如果叫 GeometryObjectSet 会更符合 Revit API 的类命名习惯。
GeometryElement ge = fi.get_Geometry( op );
if( ge != null )
{
foreach( GeometryObject obj in ge )
{
Solid solid = obj as Solid;
// 译者注:类型转换之后判断是否为 NULL 是一个很好的习惯。因为 Revit API 往往会将不同类型的对象放在同一个集合中。
// 下面的 PlanarFace pf = f as PlanarFace; 也是相同的道理。
if( solid != null && solid.Faces.Size > 0 )
{
foreach( Face f in solid.Faces )
{
PlanarFace pf = f as PlanarFace;
if( pf != null )
{
XYZ fnorm = pf.Normal.Normalize();
// 译者注:经常被问到如何进行向量计算。其实 Revit API 已经为绝大多数向量计算提供了直接的方法。不用再费劲地翻线性代数书了 :)
if( fnorm.IsAlmostEqualTo( nnorm ) )
{
string log = "";
bool done = false;
foreach( WallType t in doc.WallTypes )
{
if( t != null )
{
ElementId id = t.Id;
using( Transaction trans = new Transaction( doc ) )
{
trans.Start( "Add wall" );
try
{
// 译者注:这里是亮点。注意创建非垂直的墙体应该使用 FaceWall,而不是 Wall。
// 从 API 文档可以发现,与 Wall 一样,FaceWall 直接派生于 HostObject。
FaceWall fw = FaceWall.Create( doc, id, WallLocationLine.CoreExterior, f.Reference );
if( fw != null )
{
TaskDialog.Show("Succeeded", "Succeeded" );
done = true;
}
}
catch( Exception ex )
{
log += t.Name + ": " + ex.Message + "\r\n";
}
trans.Commit();
}
if( done )
break;
}
}
TaskDialog.Show( "Failed", log );
}
}
}
}
}
}
}
}
无法访问的位置(Location)属性
问题
我试图访问一个 FaceWall 对象的位置属性。不过返回的无论是 LocationCurve 还是 LocationPoint,值都是 NULL。
Reference r1 = doc.Selection.PickObject( ObjectType.Element, "Please pick a wall: " );
Element e1 = doc.GetElement( r1 );
FaceWall faceWall = e1 as FaceWall;
LocationCurve theCurve = faceWall.Location as LocationCurve;
LocationPoint thePoint = faceWall.Location as LocationPoint;
Jeremy
这是 Revit 目前的一个限制。如果元素的位置信息比较复杂,无法用一个点或者线段来表示,那么 Location 属性的内容可能是一个复杂的无法用 Revit API 访问的对象,或者干脆就是 NULL。显然 FaceWall 的位置信息就属于这种情况。所以你应该通过分析它的 GeometryElement 属性来获取位置信息。