前言
如何做方向的计算?来看看 SDK 的例子 DirectionCalculation。
找到朝南的墙和朝南的窗户。
找到朝南的墙
步骤:
- 找到所有的外墙
- 计算墙的方向
- 判断是否朝南
找到所有的外墙
组合拳: 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;
}
找到朝南的窗户
步骤:
- 找到所有的窗户
- 计算窗户的方向
- 判断是否朝南
找到所有的窗户
过滤条件: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;
}
判断是否朝南
朝南同判断门是否朝南。