Revit SDK 介绍:DirectionCalculation

前言

如何做方向的计算?来看看 SDK 的例子 DirectionCalculation。
找到朝南的墙和朝南的窗户。

找到朝南的墙

步骤:

  1. 找到所有的外墙
  2. 计算墙的方向
  3. 判断是否朝南

找到所有的外墙

组合拳: FilteredElementCollector + OfClass(typeof(Wall)) + LINQ where 语句是否是外墙

protected IEnumerable<Wall> CollectExteriorWalls()
{
   FilteredElementCollector collector = new FilteredElementCollector(Document);
   IList<Element> elementsToProcess = collector.OfClass(typeof(Wall)).ToElements();
   // Use a LINQ query to filter out only Exterior walls
   IEnumerable<Wall> exteriorWalls = from wall in elementsToProcess.Cast<Wall>()
      where IsExterior(Document.GetElement(wall.GetTypeId()) as ElementType)
      select wall;
   return exteriorWalls;
}

计算墙的方向

每堵墙都有它的 LocationCurve,如果是直线,拿到它起点的坐标系,然后把坐标系的 X 方向拿出来即可。如果是其它曲线,用起点指向终点的方向作为方向。
用上面得到的方向和 XYZ.BasisZ 做叉乘,得到墙的方向。(Revit 是左手坐标系,还是右手坐标系,需要研究一下!)
如果墙被 flip 过,那么这个方向也要反转。

protected XYZ GetExteriorWallDirection(Wall wall)
{
   LocationCurve locationCurve = wall.Location as LocationCurve;
   XYZ exteriorDirection = XYZ.BasisZ;

   if (locationCurve != null)
   {
      Curve curve = locationCurve.Curve;
      XYZ direction = XYZ.BasisX;
      if (curve is Line)
      {
         // Obtains the tangent vector of the wall.
         direction = curve.ComputeDerivatives(0, true).BasisX.Normalize();
      }
      else
      {
         // An assumption, for non-linear walls, that the "tangent vector" is the direction
         // from the start of the wall to the end.
         direction = (curve.GetEndPoint(1) - curve.GetEndPoint(0)).Normalize();
      }
      // Calculate the normal vector via cross product.
      exteriorDirection = XYZ.BasisZ.CrossProduct(direction);

      // Flipped walls need to reverse the calculated direction
      if (wall.Flipped) exteriorDirection = -exteriorDirection;
   }

   return exteriorDirection;
}

如果系统有动态项目坐标,还需要调整。

protected XYZ TransformByProjectLocation(XYZ direction)
{
   // Obtain the active project location's position.
   ProjectPosition position = Document.ActiveProjectLocation.GetProjectPosition(XYZ.Zero);
   Transform transform = Transform.CreateRotation(XYZ.BasisZ, position.Angle);
   // Rotate the input direction by the transform
   XYZ rotatedDirection = transform.OfVector(direction);
   return rotatedDirection;
}

判断是否朝南

-XYZ.BasisY 即为朝南的方向。

protected bool IsSouthFacing(XYZ direction)
{
   double angleToSouth = direction.AngleTo(-XYZ.BasisY);
   return Math.Abs(angleToSouth) < Math.PI / 4;
}

找到朝南的窗户

步骤:

  1. 找到所有的窗户
  2. 计算窗户的方向
  3. 判断是否朝南

找到所有的窗户

过滤条件:ElementClassFilter(typeof(FamilyInstance)) + ElementCategoryFilter(BuiltInCategory.OST_Windows)

protected IEnumerable<FamilyInstance> CollectWindows()
{
   // Windows are family instances whose category is correctly set.

   ElementClassFilter familyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));
   ElementCategoryFilter windowCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Windows);
   LogicalAndFilter andFilter = new LogicalAndFilter(familyInstanceFilter, windowCategoryFilter);
   FilteredElementCollector collector = new FilteredElementCollector(Document); 
   ICollection<Element> elementsToProcess = collector.WherePasses(andFilter).ToElements();

   // Convert to IEnumerable of FamilyInstance using LINQ
   IEnumerable<FamilyInstance> windows = from window in elementsToProcess.Cast<FamilyInstance>() select window;

   return windows;
}

计算窗户的方向

窗户是 FamilyInstance,所以它的几何图形是 GeometryInstance,它有属性 instance.Transform。注意是否被 flip 了,窗户有两种 flip。

protected XYZ GetWindowDirection(FamilyInstance window)
{
   Options options = new Options();

   // Extract the geometry of the window.
   GeometryElement geomElem = window.get_Geometry(options);

   //foreach (GeometryObject geomObj in geomElem.Objects)
   IEnumerator<GeometryObject> Objects = geomElem.GetEnumerator();
   while(Objects.MoveNext())
   {
      GeometryObject geomObj = Objects.Current;

      // We expect there to be one main Instance in each window.  Ignore the rest of the geometry.
      GeometryInstance instance = geomObj as GeometryInstance;
      if (instance != null)
      {
         // Obtain the Instance's transform and the nominal facing direction (Y-direction).
         Transform t = instance.Transform;
         XYZ facingDirection = t.BasisY;
         if ((window.FacingFlipped && !window.HandFlipped) || (!window.FacingFlipped && window.HandFlipped))
            facingDirection = -facingDirection;
         return facingDirection;
      }
   }
   return XYZ.BasisZ;
}

判断是否朝南

朝南同判断门是否朝南。

你可能感兴趣的:(Revit,SDK,介绍)