Building Coder(Revit 二次开发) - 在一个倾斜的面上创建墙

原文链接: 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 属性来获取位置信息。

你可能感兴趣的:(Building Coder(Revit 二次开发) - 在一个倾斜的面上创建墙)