几何

Autodesk.Revit.DB 命名空间包含许多与几何和图形相关类型相关的类,用于描述 API 中的图形表示。几何相关的类包括:

  • GeometryObject class - 包含从几何对象类派生的类。
  • Geometry Helper Classes - 包含从 APIObject 类派生出的类和值类型
  • Geometry Utility Classes - 包含创建非元素几何体和查找实体交点的类
  • Collection Classes - 包括从 IEnumerable 或 IEnumerator 接口派生的类。

在这一节中,您将学习如何使用各种图形相关类型,如何从元素中检索几何数据,如何变换元素,以及更多内容。

本节页面

  • 从墙壁中检索几何数据
  • GeometryObject类
  • 几何辅助类
  • 集合类
  • 从梁中检索几何数据
  • 固体挤压分析
  • 通过光线投影寻找几何图形
  • 几何工具类
  • 房间与空间几何

示例:从墙壁中检索几何数据

本教程演示了如何从墙壁获取几何数据。以下信息被涵盖:

  • 获取墙体几何边缘。
  • 获取墙体几何面。

注意:在本例中,由于未考虑实例,从元素中检索几何数据受到限制。例如,包含在墙中的放样在示例代码中不可用。本指南的目标是让您对如何检索几何数据有一个基本了解,但并不涵盖所有情况。有关从元素中检索几何数据的更多信息,请参阅示例:从梁中检索几何数据。

代码区域20-1:创建 Geometry.Options

1
2
3
4
5
6
7
8
9
10
11
Autodesk.Revit.DB.Options geomOption = application.Create.NewGeometryOptions();
if (null != geomOption)
{
geomOption.ComputeReferences = true;
geomOption.DetailLevel = Autodesk Autodesk.Revit.DB.DetailLevels.Fine;

// Either the DetailLevel or the View can be set, but not both
//geomOption.View = commandData.Application.ActiveUIDocument.Document.ActiveView;

TaskDialog.Show("Revit", "Geometry Option created successfully.");
}

注意:有关详细信息,请参阅几何辅助类。

检索面和边

墙几何图形是由面和边组成的实体。完成以下步骤以获取面和边:

1.使用Wall类的Geometry属性创建一个Geometry.Element实例。此实例包含“对象”属性中的所有几何体对象,如实体、直线等。

2.迭代Object属性以获取几何体实体实例,该实例包含“面”和“边”属性中的所有几何体面和边。

3.迭代“面”属性以获取所有几何体面。

4.迭代Edges属性以获取所有几何体边。

示例代码如下:

代码区域20-2:检索面和边

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void GetFacesAndEdges(Wall wall)
{
String faceInfo = "";

Autodesk.Revit.DB.Options opt = new Options();
Autodesk.Revit.DB.GeometryElement geomElem = wall.get_Geometry(opt);
foreach (GeometryObject geomObj in geomElem)
{
Solid geomSolid = geomObj as Solid;
if (null != geomSolid)
{
int faces = 0;
double totalArea = 0;
foreach (Face geomFace in geomSolid.Faces)
{
faces++;
faceInfo += "Face " + faces + " area: " + geomFace.Area.ToString() + "\n";
totalArea += geomFace.Area;
}
faceInfo += "Number of faces: " + faces + "\n";
faceInfo += "Total area: " + totalArea.ToString() + "\n";
foreach (Edge geomEdge in geomSolid.Edges)
{
// get wall's geometry edges
}
}
}
TaskDialog.Show("Revit", faceInfo);
}

GeometryObject类

索引属性Element.Geometry[]可用于提取任何模型元素(3D元素)的几何图形。这既适用于系统族实例(如墙、楼板和屋顶),也适用于许多类别的族实例(如门、窗、家具或体量)。

提取的几何图形将作为Autodesk. Revit. DB. GeometryElement返回给您。可以使用GetEnumerator()方法遍历该元素的几何成员。

通常,在提取的几何图形的顶层返回的对象将是以下对象之一:

  • Solids, Faces and Edges-由面和边组成的边界表示
  • Meshes-三角形的3D阵列
  • Curves-有界3D曲线
  • Points – 给定3D位置处的可见基准点
  • PolyLines – 由3D点定义的一系列线段
  • GeometryInstances-位于元素内的几何元素的实例

该图说明了通过几何体提取找到的对象的层次结构。

本节中的页面

  • Curves
  • GeometryInstances
  • Meshes
  • Points
  • PolyLines
  • Solids, Faces and Edges

Curves

曲线表示Revit模型中的二维或三维路径。曲线可以表示元素几何形状的整个范围(例如CurveElements),也可以显示为元素几何形状的一部分(例如墙或风管的中心线)。曲线和曲线集合在API的许多元素创建方法中用作输入。

本节中的页面

  • 曲线分析
  • 曲线工作
  • 曲线集合
  • 曲线创建
  • 曲线参数化
  • 曲线类型
  • 曲线类型的数学表示

曲线分析

有几种曲线方法是适用于几何分析的工具。

在某些情况下,这些API所做的事情比您通过快速查看其名称所期望的要多。

Intersect()

“相交”方法允许您比较两条曲线,以找出它们的不同之处或相似之处。它可以以您可能期望的方式使用,以获得两条曲线彼此相交的点,但它也可以用于识别:

  • Collinear lines 共线的线
  • Overlapping lines 重叠线
  • Identical curves 相同曲线
  • Totally distinct curves with no intersections 完全不同的曲线,没有交叉点

返回值标识这些不同的结果,输出IntersectionSetResult包含有关交点的信息。

Project()

Project方法将点投影到曲线上,并返回有关曲线上最近点、其参数以及与投影点的距离的信息。

Tessellate()

这会将曲线分割为一系列线性段,精确度在默认公差范围内。对于Curve.Tessellate(),公差略大于1/16”。此近似公差是Revit内部使用的公差,足以满足显示目的。

请注意,只有直线可以被分割成只有两个细分点的输出;非线性曲线将总是输出两个以上的点,即使曲线具有极大的半径,在数学上可能等同于直线。

曲线工作

Curve类提供了使用曲线的有用方法。

除了对分析有用的方法外,Curve类还提供了用于修改曲线或获取有关曲线的基本信息的属性和方法。

改变界限

MakeBound()方法可用于更改曲线的边界或为先前未绑定的曲线创建边界。MakeUnbound()将使曲线未绑定。对于这两种方法,如果曲线标记为只读(因为它是直接从Revit图元或集合/聚合对象中提取的),则调用此方法会导致对象更改为包含原始曲线的断开连接的副本。修改不会影响原始曲线或提供原始曲线的对象。

图形样式

Curve从GeometryObject继承GraphicsStyleId只读属性,GeometryObject提供指定给Curve的GraphicsStyle的ElementId。方法Curve.SetGraphicsStyleId()可用于设置Curve的GraphicsStyle Id。Revit API中的许多方法将不使用与此曲线关联的图形样式。例如,用作图元草图一部分的曲线将不会读取此属性。新创建的曲线元素也不会使用此值,因为它们从其关联类别继承图形特性。

曲线长度

曲线有两个与长度相关的属性。Length属性将返回曲线的精确长度。我使用解析或数值积分计算曲线的长度。对于直线和圆弧没有性能影响。对于更快的近似,ApproximateLength属性可以快速估计曲线的长度,但在某些情况下可能会偏离2倍。此计算对于直线和圆弧是精确的。

曲线集合

Revit API使用不同类型的曲线集合作为输入。

注意:较新的API方法使用Curves的.NET集合代替CurveArray和CurveArrArray。

CurveLoop

curveloop表示端到端连接的特定曲线链。它可以表示一个闭环或一个开环。curveloop的成员可以直接迭代,因为该类实现了IEnumerable。迭代提供了直接包含在循环中的曲线的副本;曲线的修改不会影响loop中包含的曲线。可以使用以下方法创建CurveLoops:

  • CurveLoop.Create()-从曲线列表创建新的CurveLoop。
  • CurveLoop.CreateViaCopy() - 创建新的CurveLoop作为现有CurveLoop的副本。
  • CurveLoop. ViaThumb(Curve,double,XYZ)-通过相对于给定平面加厚输入曲线来创建新的闭合CurveLoop。
  • CurveLoop. curveViaThrottle(CurveLoop,double,XYZ)-通过相对于给定平面加厚输入开放曲线循环来创建新的闭合曲线循环。
  • CurveLoop.CreateViaTransform() - 创建一个新的CurveLoop作为输入CurveLoop的转换副本。请注意,重载ViaThursday()方法的thickness参数必须导致曲线超过Revit的短曲线容差(Application.ShortCurveTolerance),否则将引发异常。

CurveLoop.Transform() 的执行方式与 CreateViaTransform() 类似,但它会变换 CurveLoop 中包含的曲线,而不是创建变换后的副本。

CurveArray

此集合类表示曲线的任意集合。使用其构造函数创建它。

CurveArrArray

此集合类是 CurveArray 的集合。当使用 this 时,此数组的子元素的组织对 this 传递给的方法有意义;例如,在 NewExtrusion() 中,多个 CurveArrays 应该表示不同的闭合循环。

曲线创建

通常需要将曲线作为 Revit API 方法的输入。可以通过多种方式创建它们。

曲线具有许多派生类型,这些类型具有用于创建曲线的静态方法。基类 Curve 还具有从现有曲线创建新曲线的方法。

曲线创建方法会阻止创建短于 Revit 容差的曲线。此容差通过 Application.ShortCurveTolerance 属性公开。

Curve

Curve 类具有多种从现有曲线创建新曲线的方法。

  • Clone() - 创建此曲线的副本。
  • CreateOffset() - 从该曲线创建一个新的曲线偏移。
  • CreateReversed() - 创建一条与现有曲线方向相反的新曲线
  • Curve.CreateTransformed() - 创建曲线的新实例作为该曲线的变换。

Line

有两种静态方法可用于创建新 Line。

  • CreateBound() - 在两点之间创建新的边界线性曲线。
  • CreateUnbound() - 在给定原点和方向的情况下创建新的未绑定线性曲线。

Code Region:创建unbound 的线性曲线

1
2
3
4
5
6
// define start point and direction for unbound line
XYZ startPoint = new XYZ(0, 0, 0);
XYZ directionPt = new XYZ(10, 10, 10);

// create line
Line line = Line.CreateUnbound(startPoint, directionPt);

Arc

重载的静态 Create() 方法允许通过以下三种方式之一创建 Arc:

  • 基于 3 点

  • 代码区域:创建具有 3 个点的圆弧

    1
    2
    3
    4
    5
    6
    // Create a new arc using two ends and a point on the curve
    XYZ end0 = new XYZ(1, 0, 0); // start point of the arc
    XYZ end1 = new XYZ(10, 10, 10); // end point of the arc
    XYZ pointOnCurve = new XYZ(10, 0, 0); // point along arc

    Arc arc = Arc.Create(end0, end1, pointOnCurve);
  • 基于平面、半径和角度

  • 代码区域:使用平面创建圆弧

  • Arc CreateArcByGivingPlane(Autodesk.Revit.ApplicationServices.Application application, Plane plane)
    {
        // Create an arc which is placed on the plane and whose center is the plane's origin
        double radius = 10;
        double startAngle = 0;      // The unit is radian
        double endAngle = 2 * Math.PI;        // this arc will be a circle
        return Arc.Create(plane, radius, startAngle, endAngle);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18



    - based on center, radius, angles and two axes
    基于圆心、半径、角度和两个轴

    代码区域:使用轴创建圆弧

    ```c#
    // Create a new arc defined by its center, radios, angles and 2 axes
    double radius = 10;
    double startAngle = 0; // In radian
    double endAngle = Math.PI; // In radian
    XYZ center = new XYZ(5, 0, 0);
    XYZ xAxis = new XYZ(1, 0, 0); // The x axis to define the arc plane. Must be normalized
    XYZ yAxis = new XYZ(0, 1, 0); // The y axis to define the arc plane. Must be normalized

    Arc arc = Arc.Create(center, radius, startAngle, endAngle, xAxis, yAxis);
    注意,对于后两个选项,如果角度范围等于或大于 2 * PI,则曲线将自动转换为无界圆。

Ellipse

静态 CreateCurve() 方法创建一个椭圆,给定中心、椭圆的 x 向量和 y 向量半径、x 轴和 y 轴以定义椭圆的平面以及开始和结束参数。如果 x 半径和 y 半径几乎相等,它将返回一个圆弧,否则将返回一个椭圆。

Cylindrical Helix

CylindricalHelix 的静态 Create() 方法从轴的基点、半径、x 向量、z 向量、螺距、起始角度(用于指定螺旋线的起点)和结束角度(用于指定螺旋线的终点)创建一个新的 CylindricalHelix。z 向量是轴方向,应垂直于 x 向量。正螺距产生右旋螺旋,而负螺距产生左旋螺旋。

NURBS

NurbSpline 类表示 NURBS 或非均匀有理 B 样条曲线。重载的静态 CreateCurve() 方法提供了多种创建 NURBS 曲线的方法。第一种方法是使用 Revit 在用户界面中绘制样条曲线时使用的相同计算。它需要一个控制点和权重的列表来创建新的 NurbSpline。样条的结和阶数是根据给定的控制点和权重计算的。

第二个选项还需要控制点和权重列表,还需要结列表以及 NurbSpline 的阶数。度数必须为 1 或更大。必须至少有 degree+1 个控制点。结的大小必须等于 degree、control points 数组的大小和 1 之和。第一度 + 1 节应该相同,最后一度 + 1 节也应相同。序列中间的结必须是非递减的。

第三个选项只需要控制点和权重。必须至少有 2 个控制点,并且权重的数量必须等于控制点的数量。所有权重的值都必须为正。

在所有情况下,创建的曲线可以是 NURBSpline 或更简单的曲线,例如直线或圆弧。这与 Revit 的期望一致,即在 Revit 图元中应使用尽可能简单的曲线表示。

Hermite Spline

重载的静态 HermiteSpline.Create() 方法提供了两个用于创建 Hermite 样条的选项。最简单的方法是创建端点处具有默认切线的 Hermite 样条,并且只需要一个控制点列表和一个指示 Hermite 样条是否为周期性的标志。第二个选项将创建在其端点处具有指定切线的 Hermite 样条曲线。它有一个附加的 HermiteSplineTangents 对象参数,用于指定曲线起点和/或终点的切线。

曲线参数化

Revit API 中的曲线可以描述为输入参数“u”的数学函数,其中曲线在 XYZ 空间中任何给定点的位置是“u”的函数。

曲线可以是绑定的,也可以是未绑定的。未绑定曲线没有端点,表示无限抽象(未绑定的直线)或循环曲线(圆或椭圆)。

在 Revit 中,参数“u”可以用两种方式表示:

  • 一个 ‘normalized’ 参数。参数的起始值为 0.0,结束值为 1.0。对于某些曲线类型,这使得沿曲线范围的曲线计算非常容易,例如,直线的中点位于参数 0.5 处。(请注意,对于更复杂的曲线方程式(如 Splines),不能总是做出此假设)。
  • 一个 ‘raw’ 参数。参数的 start 和 end 值可以是任何值。对于给定的曲线,最小和最大原始参数的值可以通过 Curve.GetEndParameter(int) 获取。原始参数非常有用,因为它们的单位与 Revit 默认单位(英尺)相同。因此,要从起点沿曲线获得 5 英尺的位置,您可以在起点处获取 raw 参数,并在其上添加 5。原始参数也是计算未绑定曲线的唯一方法。

方法 Curve.ComputeNormalizedParameter() 和 Curve.ComputeRawParameter() 会自动在两种参数类型之间缩放。方法 Curve.IsInside() 计算原始参数,以查看它是否位于曲线的边界内。

您可以使用参数来计算曲线在任何给定位置的各种属性:

  • 给定曲线的 XYZ 位置。这是从 Curve.Evaluate() 返回的。可以提供 raw 或 normalized 参数。如果您还调用 ComputeDerivatives(),则这也是 .Origin 属性。
  • 给定曲线的第一个导数/切线向量。这是 .Curve.ComputeDerivatives() 返回的 Transform 的 BasisX 属性。
  • 给定曲线的第二个导数/法向量。这是 .BasisY 属性。
  • 给定曲线的次法向量,定义为切线向量和法向量的叉积。这是 .Curve.ComputeDerivatives() 返回的 Transform 的 BasisZ 属性。

返回的所有向量都是非规格化的(但可以使用XYZ.Normalize()规格化Revit API中的任何向量)。请注意,当曲线是直线时,将不会为法线和副法线向量设置值。可以使用切向量计算给定平面中直线的法向量。

API示例“DirectionCalculation”使用墙位置曲线的切线向量来查找朝南的外墙:

寻找并突出显示朝南的外墙

曲线类型

Revit使用各种曲线类型来表示文档中的曲线几何图形。

Curve type 曲线类型 Revit API类** Definition 定义 Notes 注意
Bound line Line 由端点定义的线段。 从Curve.GetEndpoint()获取端点
Unbound line Line 由位置和方向定义的无限线 使用Curve.IsBound标识这些。在原始参数= 0处计算点和切向量,以找到直线方程的输入参数。
Arc Arc 一个有界的圆弧 开始和结束在一定的角度。这些角度可以通过弧的每一端的原始参数值获得。
Circle Arc 一个没有束缚的圆圈 使用Curve.IsBound标识。使用原始参数进行评价(从0到2π)
Cylindrical helix CylindricalHelix 绕在圆柱体上的螺旋线,与圆柱体的轴线成恒定的角度 仅在楼梯和扶手中的特定应用中使用,在访问其他Revit图元和几何图形的曲线时不应使用或遇到。
Elliptical arc Ellipse 一个约束椭圆段
Ellipse Ellipse 无约束椭圆 使用Curve.IsBound标识。使用原始参数进行评价(从0到2π)
NURBS NurbSpline 非均匀有理B样条曲线 用于在各种Revit工具中绘制的样条曲线,以及导入的几何图形
Hermite HermiteSpline 一组点之间的样条插值 用于“逐点曲线”和软风管/管道等工具,以及导入的几何图形

所有Revit曲线类型的数学表示可以在曲线类型的数学表示找到。

曲线类型的数学表示

本节介绍Revit几何图形中遇到的曲线类型、其属性及其数学表示。

Bound lines

Bound lines由其端点定义。在Revit API中,从曲线-标高 GetEndPoint()方法获取线的端点。

Bound lines上的点根据归一化参数“u”和Bound lines上点的方程为:

Unbound lines

Unbound lines在Revit API中进行了专门处理。不能使用大多数曲线属性,但是,当提供原始参数时,Evaluate()和ComputeDerivatives()可用于获取曲线沿着的位置。

根据原始参数“u”以及线原点和归一化方向向量,未绑定线的点的方程为:

Arcs and Circles

圆弧和圆在Revit API中由Arc类表示。它们是根据半径、圆心和垂直于弧平面的矢量定义的,这些参数可以在Revit API中作为属性直接从Arc类访问。

圆的IsBound属性设置为true。这意味着它们只能通过使用原始参数(范围从0到2π)来计算,并且圆上的点的原始参数方程为:

其中假设圆位于XY平面内。

弧的开始和结束都有一定的角度。这些角度可以通过弧的每一端处的原始参数值来获得,并且这些值之间的角度值可以插入到与上述相同的等式中。

圆柱螺旋

圆柱螺旋线在Revit API中由ExtradricalHashion类表示。它们是根据螺旋缠绕的圆柱体的轴的基点、半径、x和y矢量、螺距以及起始角和结束角来定义的。

椭圆和椭圆弧

椭圆和椭圆弧段在Revit API中由Ellipse类表示。与圆弧和圆类似,它们在给定平面中根据其X和Y半径、中心和垂直于椭圆平面的向量来定义。

完整椭圆的IsBound属性设置为true。与圆类似,它们可以通过0和2π之间的原始参数进行评估:

NurbSpline

NURBS用于用户绘制为曲线或3D对象草图的一部分的样条线段。它们还用于表示某些类型的导入几何数据。

NurbSpline的数据包括:

  • 长度为n+1的控制点数组
  • weights数组,长度也是n+1
  • 曲线阶数,其值等于曲线阶数(k)的小一
  • 长度为n + k +1的节点向量

Revit的草图绘制工具中使用的NurbSplines可以使用算法单独从控制点和阶数生成。可以在外部复制Revit算法执行的计算,请参见下面的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
NurbSplinespline = curve.GeometryCurve as NurbSpline;
DoubleArrayknots = spline.Knots;

// Convert to generic collection
List knotList = new List();
for(int i = 0; i < knots.Size; i++)
{
knotList.Add(knots.get_Item(i));
}

// Preparation - get distance between each control point
IList controlPoints = spline.CtrlPoints;
int numControlPoints = controlPoints.Count;
double[] chordLengths = new double[numControlPoints - 1];
for(int iControlPoint = 1; iControlPoint < numControlPoints; ++iControlPoint)
{
double chordLength =
controlPoints[iControlPoint].DistanceTo(controlPoints[iControlPoint - 1]);
chordLengths[iControlPoint - 1] = chordLength;
}

int degree = spline.Degree;
int order = degree + 1;
int numKnots = numControlPoints + order;
double[] computedKnots = new double[numKnots];
int iKnot = 0;

// Start knot with multiplicity degree + 1.
double startKnot = 0.0;
double knot = startKnot;
for(iKnot = 0; iKnot < order; ++iKnot)
{
computedKnots[iKnot] = knot;
}

// Interior knots based on chord lengths
double prevKnot = knot;

for(/*blank*/; iKnot <= numControlPoints; ++iKnot)
// Last loop computes end knot but does not set interior knot.
{
double knotIncrement = 0.0;
for (int jj = iKnot - order; jj < iKnot - 1; ++jj)
{
knotIncrement += chordLengths[jj];
}

knotIncrement /= degree;
knot = prevKnot + knotIncrement;
if (iKnot < numControlPoints)
computedKnots[iKnot] = knot;
else
break; // Leave "knot" set to the end knot; do not increment "ii".

prevKnot = knot;
}

// End knot with multiplicity degree + 1.
for(/*blank*/; iKnot < numKnots; ++iKnot)
{
computedKnots[iKnot] = knot;
}

HermiteSpline

Hermite样条用于在一组控制点之间插值的曲线,如MEP中的逐点曲线和软风管和管道。它们还用于表示某些类型的导入几何数据。在Revit API中,HermiteSpline类提供了通过“控制点”、“切线”和“参数”属性访问点阵列、切线向量和参数的功能。

Hermite样条中两个节点之间的曲线方程为:

其中,Pk和Pk+1表示每个节点处的点,Mk和Mk+1表示切向量,并且uk和uk+1表示节点处的参数,并且基函数为:

GeometryInstances

GeometryInstance表示Revit以默认配置存储的一组几何图形,然后根据图元的属性将其转换到正确的位置。最常见的遇到几何图形的情况是在族实例中。Revit使用几何图形库,允许它存储给定族的几何图形的单个副本,并在多个实例中重复使用该副本。

请注意,并非所有族实例都将包括几何图形。当Revit需要为给定实例制作族几何图形的唯一副本时(由于局部连接、交点以及与实例放置相关的其他因素的影响),不会遇到GeometryInstance;相反,实体几何图形将位于层次的顶层。

GeometryInstance提供了通过GetSymbolGeometry()和GetInstanceGeometry()方法读取其几何体的能力。这些方法返回另一个Autodesk.Revit.DB.GeometryElement,可以像第一级返回一样对其进行分析。

GetSymbolGeometry()返回在族的坐标系中表示的几何图形。例如,当您需要“通用”表格的图片而不考虑项目中的方向和放置位置时,请使用此选项。这也是唯一一个将实际的Revit几何图形对象返回给您而不是复制的重载。这一点很重要,因为使用此几何图形作为输入来创建其他图元的操作(例如,标注尺寸或放置基于面的族)需要参照原始几何图形。

GetInstanceGeometry()返回在放置实例的项目的坐标系中表示的几何图形。例如,当需要项目中实例的特定几何图形的图片时(例如,确保桌子与房间的墙壁平行放置),请使用此选项。这始终会返回图元几何图形的副本,因此,虽然它适用于实施导出器或几何分析工具,但不适合用于创建引用此几何图形的其他Revit图元。

GetInstanceGeometry()和GetSymbolGeometry()也有重载,它们可以通过任意坐标系变换几何体。这些方法始终返回类似于GetInstanceGeometry()的副本。

GeometryInstance还存储了从符号坐标空间到实例坐标的变换。此转换可作为Transform属性访问。它也是通过GetInstanceGeometry()提取几何体副本时使用的变换。有关更多详细信息,请参见几何辅助类。

2个使用不同变换放置的族实例-将从两个族实例中获取相同的几何图形

对于某些族,可以嵌套多层。如果您遇到嵌套实例,则可能会以与第一级实例类似的方式对其进行解析。

给出了两个示例来解释如何解析实例的几何形状。

在此示例中,从GeometryInstance方法GetInstanceGeometry()提取曲线。

代码区域:从实例获取曲线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public void GetAndTransformCurve(Autodesk.Revit.ApplicationServices.Application app,
Autodesk.Revit.DB.Element element, Options geoOptions)
{
// Get geometry element of the selected element
Autodesk.Revit.DB.GeometryElement geoElement = element.get_Geometry(geoOptions);

// Get geometry object
foreach (GeometryObject geoObject in geoElement)
{
// Get the geometry instance which contains the geometry information
Autodesk.Revit.DB.GeometryInstance instance =
geoObject as Autodesk.Revit.DB.GeometryInstance;
if (null != instance)
{
GeometryElement instanceGeometryElement = instance.GetInstanceGeometry();
foreach (GeometryObject o in instanceGeometryElement)
{
// Try to find curves
Curve curve = o as Curve;
if (curve != null)
{
// The curve is already transformed into the project coordinate system
}
}
}
}
}

在此示例中,使用GetSymbolGeometry()从实例中获取实体。然后使用GeometryInstance.Transform将组成点变换到项目坐标系中。

代码区域:从实例获取可靠信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private void GetAndTransformSolidInfo(Application application, Element element, Options geoOptions)
{
// Get geometry element of the selected element
Autodesk.Revit.DB.GeometryElement geoElement = element.get_Geometry(geoOptions);

// Get geometry object
foreach (GeometryObject geoObject in geoElement)
{
// Get the geometry instance which contains the geometry information
Autodesk.Revit.DB.GeometryInstance instance =
geoObject as Autodesk.Revit.DB.GeometryInstance;
if (null != instance)
{
GeometryElement instanceGeometryElement = instance.GetSymbolGeometry();
foreach (GeometryObject instObj in instanceGeometryElement)
{
Solid solid = instObj as Solid;
if (null == solid || 0 == solid.Faces.Size || 0 == solid.Edges.Size)
{
continue;
}

Transform instTransform = instance.Transform;
// Get the faces and edges from solid, and transform the formed points
foreach (Face face in solid.Faces)
{
Mesh mesh = face.Triangulate();
foreach (XYZ ii in mesh.Vertices)
{
XYZ point = ii;
XYZ transformedPoint = instTransform.OfPoint(point);
}
}
foreach (Edge edge in solid.Edges)
{
foreach (XYZ ii in edge.Tessellate())
{
XYZ point = ii;
XYZ transformedPoint = instTransform.OfPoint(point);
}
}
}
}
}
}

注意:有关检索到的族实例几何图形的详细信息,请参见示例:从梁中检索几何图形数据。

网格

网格是三角形边界的集合,它们共同形成3D形状。如果Revit图元是通过某些导入操作创建的,并且还用于某些本机Revit图元(如TopographySurface),则通常会在Revit图元几何图形中遇到网格。还可以通过调用任意给定Revit面的Face.Triangulate()来获取网格。

表示圆环面的网格

以下代码示例说明了如何将Revit面的几何体作为网格获取:

代码区域:提取几何体的网格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void GetTrianglesFromFace(Face face)

{

// Get mesh

Mesh mesh = face.Triangulate();

for (int i = 0; i < mesh.NumTriangles; i++)

{

MeshTriangle triangle = mesh.get_Triangle(i);

XYZ vertex1 = triangle.get_Vertex(0);

XYZ vertex2 = triangle.get_Vertex(1);

XYZ vertex3 = triangle.get_Vertex(2);

}

}

注意:用于Revit显示目的的近似公差在构造网格时由Triangulate()方法(上面使用的)的无参数重载使用。Triangulate()的重载接受一个double,允许将细节级别设置在0(粗糙)和1(精细)之间。

点表示3D空间中的可见坐标。

点通常出现在体量族图元(如ReferencePoint)中。Point类提供对其坐标的读访问,并能够获取对该点的引用,以用作其他函数的输入。

点创建

有两种方法可以创建点:

  • Create(XYZ) - 在给定坐标处创建一个点。
  • Create(XYZ, ElementId) - 在给定坐标处创建一个Point,并根据GraphicsStyle元素(由ElementId指定)为其指定颜色。

PolyLine

PolyLine是由一组坐标点定义的线段的集合。这些通常在导入的几何体中遇到。PolyLine类提供了读取坐标的能力:

  • PolyLine.NumberOfCoordinates – 在坐标系中的点数
  • PolyLine.GetCoordinate() – 通过索引获取坐标
  • PolyLine.GetCoordinates() – 获取对象中所有坐标的集合
  • PolyLine.Evaluate() – 给定一个规格化参数(从0到1),沿整个PolyLine范围沿着计算XYZ点

实体、面和边

实体是一个Revit API对象,表示面和边的集合。通常,在Revit中,这些集合是完全封闭的体积,但也可能遇到壳或部分有界体积。请注意,有时Revit几何图形将包含未使用的实体,这些实体包含零个边和面。选中“边”和面成员以过滤掉这些实体。

Revit API提供了读取面和边的集合以及计算实体的表面积、体积和质心的功能。

本节中的页面

  • 边和面参数化
  • 面分析
  • 面分割
  • 面类型
  • 面类型的数学表示
  • 实体分析
  • 实体和面的创建
边和面参数化

边是给定面的边界曲线。

使用EdgeLoops属性迭代面的边。每个循环表示面上的一个闭合边界。边始终参数化为0到1。可以使用Edge.AsCurve()和Edge.AsCurveFollowingFace()函数提取边缘的Curve表示。

边通常通过计算两个面的相交来定义。但Revit在绘制图形时不会重新计算此交点。因此,边存储一个点列表-直边的端点和曲边的细分列表。这些点是两个面上的参数坐标。这些点可以通过TessellateOnFace()方法获得。

剖面产生“切割边缘”。这些是人工边-不表示模型级几何体的一部分,因此不提供参照。

边的方向

方向通常在第一个面上为顺时针方向(第一个面表示Revit已为特定边标识的任意面)。但是,由于两个不同的面在一个特定的边相交,并且无论您关注的是哪个面,该边都具有相同的参数化方向,因此有时需要确定特定面上的边的方向。

下图说明了这是如何工作的。对于面0,所有边都是顺时针参数化的(???)。对于面1,与面0共享的边不会重新参数化;因此,相对于面1,该边具有相反的方向,并且某些边在两条边的参数均为0(或1)的地方相交。

边参数化

API示例“PanelEdgeLengthAngle”显示了如何识别给定面的反转边。它使用边端点处的切向量来计算相邻边之间的角度,并检测是否在每个交点处翻转切向量以计算适当的角度。

PanelEdgeLengthAngle结果

可以将Revit API中的面描述为两个输入参数“u”和“v”的数学函数,其中面在XYZ空间中任意给定点处的位置是参数的函数。

U和V方向是根据给定面的形状自动确定的。恒定U或V的线可以表示为面上的网格线,如下例所示:

圆柱面上的U和V网格线

可以使用UV参数来评估任意给定位置处的面的各种属性:

  • 参数是否在面的边界内,使用Face.IsInside()
  • 指定UV参数值处给定面的XYZ位置。这是从Face.Evaluate()返回的。如果您还在调用ComputeDerivatives(),则这也是该方法返回的Transform的.Origin属性。
  • 给定面在U方向上的切向量。这是Face.ComputeDerivatives()返回的Transform的.BasisX属性
  • 给定面在V方向上的切向量。这是Face.ComputeDerivatives()返回的Transform的.BasisY属性。
  • 给定面部的法向量。这是Face.ComputeDerivatives()返回的Transform的.BasisZ属性。
  • 关于U的二阶导数。这是Face.ComputeSecondDerivatives()返回的FaceSecondDerivatives的. UUD派生属性。
  • 相对于V的二阶导数。这是Face.ComputeSecondDerivatives()返回的FaceSecondDerivatives的.VVDerivative。
  • 给定面的混合导数。这是Face.ComputeSecondDerivatives()返回的FaceSecondDerivatives的.MixedDerivative。

返回的所有向量都是非单位化的。

面分析

有几种面方法是适用于几何分析的工具。

Intersect()

“相交”方法计算面与曲线之间的相交。它可用于识别:

  • 两个对象之间的交点
  • 如果有一条边靠近该位置,则为距离交点最近的边
  • 与面完全重合的曲线
  • 不相交的曲线和面

Project()

Project方法将点投影到输入面上,并返回有关投影点、到面的距离以及到投影点的最近边的信息。

Triangulate()

Triangulate方法获得一个近似于面的三角形网格。此方法有两个重载。无参数方法与Curve.Tessellate()类似,因为网格的点在Revit使用的输入公差范围内(略大于1/16”)是精确的。第二个Triangulate方法接受一个细节级别作为参数,范围从0(粗略)到1(精细)。

面分割

可以通过“分割面”命令将面分割为面域。Face.HasRegions属性将报告面是否包含使用Split Face命令创建的区域,而Face.GetRegions()方法将返回一个面列表,一个面用于承载Split Face的对象的主面(如地板的墙壁),一个面用于每个Split Face区域。

FaceSplitter类表示拆分面的元素。FaceSplitter.SplitElementId属性提供其面被此元素分割的元素的ID。FaceSplitter类可用于按类型过滤和查找这些面,如下所示。

代码区域:查找面分割元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Autodesk.Revit.DB.Options opt = app.Create.NewGeometryOptions();
opt.ComputeReferences = true;
opt.IncludeNonVisibleObjects = true;
FilteredElementCollector collector = new FilteredElementCollector(doc);
ICollection splitElements = collector.OfClass(typeof(FaceSplitter)).Cast().ToList();
foreach(FaceSplitter faceSplitter in splitElements)
{
Element splitElement = doc.GetElement(faceSplitter.SplitElementId);
Autodesk.Revit.DB.GeometryElement geomElem = faceSplitter.get_Geometry(opt);
foreach (GeometryObject geomObj in geomElem)
{
Line line = geomObj as Line;
if (line != null)
{
XYZ end1 = line.GetEndPoint(0);
XYZ end2 = line.GetEndPoint(1);
double length = line.ApproximateLength;
}
}
}
面类型

Revit使用各种曲线类型来表示文档中的面几何图形。其中包括:

**Face type ** Revit API Class **Definition ** Notes 注意
Plane PlanarFace 由原点与U和V的单位向量定义的平面。
Cylinder CylindricalFace 通过沿着轴拉伸圆定义的面。 Radius提供“半径向量”-圆的单位向量乘以半径值。
Cone ConicalFace 一条线绕一个轴旋转而定义的面。 Radius提供“半径向量”-圆的单位向量乘以半径值。
Revolved face RevolvedFace 由任意曲线绕轴旋转定义的面。 Radius提供旋转平面的单位矢量,不涉及“半径”。
Ruled surface RuledFace 通过放样两条轮廓曲线或一条轮廓曲线和一个点之间的直线而定义的面。 曲线和点都可以作为属性获得。
Hermite face HermiteFace 由点之间的Hermite插值定义的面。

所有Revit面类型的数学表示可以在其中找到:面类型的数学表示。

面类型的数学表示

本节介绍Revit几何图形中遇到的面类型、其属性及其数学表示。

PlanarFace

由原点与U和V的单位向量定义的平面。

CylindricalFace

通过沿轴沿着拉伸圆而定义的面。Revit API提供以下属性:

  • 面的原点。
  • 拉伸轴。
  • 在X和Y中的“径向矢量”。这些向量是圆的单位向量乘以圆的半径。注意,单位向量可以表示右手或左手控制。

此面的参数方程为:

img

ConicalFace

由一条线绕一个轴旋转而定义的面。Revit API提供以下属性:

  • 面的原点。
  • 圆锥体的轴。
  • 在X和Y中的“径向矢量”。这些矢量是单位矢量乘以旋转形成的圆的半径。注意,单位向量可以表示右手或左手控制。
  • The half angle of the face.
    面的半个角。

此面的参数方程为:

img

RevolvedFace

由任意曲线绕轴旋转定义的面。Revit API提供以下属性:

  • 面的原点
  • 面的轴线
  • 轮廓曲线
  • 旋转曲线的单位向量(姑且地称为“半径”)

此面的参数方程为:

img

RuledFace

RuledFace 是通过放样两条轮廓曲线之间或曲线与点之间的直线而创建的。Revit API提供曲线和点作为属性。

该曲面的参数方程为:

img 如果两条曲线都有效。如果其中一条曲线被替换为一个点,则方程简化为以下之一:

img img 没有曲线和两个点的RuledFace是不会被返回。

HermiteFace

立方Hermite样条曲线面。Revit API提供:

  • 样条插值点的u和v参数数组
  • 每个节点上的3D点的数组(数组按u递增,然后v递增的方式组织)
  • 每个节点的切向量数组
  • 每个节点处的扭曲向量数组

在节点(u1,v1)和(u2,v2)之间,该曲面的参数表示为:

其中 imgimgMH是Hermite矩阵:

img
并且B是从插值点处的面属性获得的系数矩阵:

img

实体分析

实体与曲线的交线

方法Solid.IntersectWithCurve()计算闭合体积实体和曲线之间的交点。SolidCurveIntersectionOptions类可以指定IntersectWithCurve()方法的结果是否将包括实体体积内部或外部的曲线段。实体内的曲线段将包括与实体的面重合的曲线段。曲线段和曲线段的参数都可以在结果中使用。

以下示例使用IntersectWithCurve()方法计算柱内钢筋的长度。

代码区域:查找实体和曲线之间的交点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
private void FindColumnRebarIntersections(Document document, FamilyInstance column)
{
// We will be computing the total length of the rebar inside the column
double totalRebarLengthInColumn = 0;

// Find rebar hosted by this column
RebarHostData rebarHostData = RebarHostData.GetRebarHostData(column);
if (rebarHostData == null)
{
return;
}

IList rebars = rebarHostData.GetRebarsInHost();
if (rebars.Count == 0)
{
return;
}

// Retrieve geometry of the column
Options geomOptions = new Options();
geomOptions.ComputeReferences = true;
geomOptions.DetailLevel = ViewDetailLevel.Fine;
GeometryElement elemGeometry = column.get_Geometry(geomOptions);

// Examine all geometry primitives of the column
foreach (GeometryObject elemPrimitive in elemGeometry)
{

// Skip objects that are not geometry instances
GeometryInstance gInstance = elemPrimitive as GeometryInstance;
if (gInstance == null)
{
continue;
}

// Retrieve geometry of each found geometry instance
GeometryElement instGeometry = gInstance.GetInstanceGeometry();
foreach (GeometryObject instPrimitive in instGeometry)
{

// Skip non-solid sobject
Solid solid = instPrimitive as Solid;
if (solid == null)
{
continue;
}

SolidCurveIntersectionOptions intersectOptions = new SolidCurveIntersectionOptions();
foreach (Rebar rebar in rebars)
{
// Get the centerlines for the rebar to find their intersection with the column
bool selfIntersection = false;
bool suppresHooks = false;
bool suppresBends = false;
IList curves = rebar.GetCenterlineCurves(selfIntersection, suppresHooks, suppresBends, MultiplanarOption.IncludeOnlyPlanarCurves, 0);

// Examine every segment of every curve of the centerline
foreach (Curve curve in curves)
{
SolidCurveIntersection intersection = solid.IntersectWithCurve(curve, intersectOptions);
for (int segment = 0; segment <= intersection.SegmentCount - 1; segment++)
{
// Calculate length of the rebar that is inside the column
Curve curveInside = intersection.GetCurveSegment(segment);
double rebarLengthInColumn = curveInside.Length;
totalRebarLengthInColumn = totalRebarLengthInColumn + rebarLengthInColumn;
}
}

}
}
}

}
实体和面的创建

实体和面有时用作其他实用程序的输入。Revit API提供了几个例程,可用于从头开始创建此类几何图形或从其他输入中导出此类几何图形。

Transformed geometry

方法

  • GeometryElement.GetTransformed()

返回应用了变换的输入几何图元的副本。由于此几何图形是副本,因此其成员不能用作其他Revit图元的输入参照,但可用于几何分析和提取。

Geometry creation utilities

GeometryCreationUtilities类是一个允许构造基本实体形状的实用程序类:

  • Extrusion 拉伸
  • Loft
  • Revolution 旋转
  • Sweep 放样
  • Blend 融合
  • SweptBlend 放样融合

生成的几何图形不会作为任何元素的一部分添加到文档中。然而,创建的Solid可用作其他API函数的输入,包括:

  • 作为分析可视化框架(SpatialFieldManager.AddSpatialFieldPrimitive())中方法的输入面-这允许用户相对于文档中的其他元素可视化创建的形状
  • 作为通过相交查找3D元素的输入实体
  • 作为布尔运算的一个或多个输入
  • 作为几何计算的一部分(例如,使用Face.Project()、Face.Intersect()或其他面、实体和边几何方法)

下面的示例使用GeometryCreationUtilities类基于位置和高度创建圆柱形。例如,这可以用于在墙端点周围创建体积,以便查找与墙端点非常接近的其他墙:

代码区域:创建圆柱体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Build cylinder centered at wall end point, extending 3' in diameter
CurveLoop cylinderLoop = new CurveLoop();
XYZ arcCenter = new XYZ(endPoint.X, endPoint.Y, elevation);
Application application = wall.Document.Application;
Arc firstArc = Arc.Create(arcCenter, 1.5, 0, Math.PI, XYZ.BasisX, XYZ.BasisY);
Arc secondArc = Arc.Create(arcCenter, 1.5, Math.PI, 2 * Math.PI, XYZ.BasisX, XYZ.BasisY);

cylinderLoop.Append(firstArc);
cylinderLoop.Append(secondArc);

List singleLoop = new List();
singleLoop.Add(cylinderLoop);

Solid proximityCylinder = GeometryCreationUtilities.CreateExtrusionGeometry(singleLoop, XYZ.BasisZ, height);

Boolean operations

BooleanOperationsUtils类提供用于组合一对实心几何体对象的方法。

ExecuteBooleanOperation()方法获取输入实体的副本,并生成新实体作为结果。它的第一个参数可以是任何实体,可以直接从Revit图元获得,也可以通过其他操作(如GeometryCreationUtils)创建。

方法ExecuteBooleanOperationModifyingOriginalSolid()直接对第一个输入实体执行布尔运算。第一个输入必须是不是直接从Revit图元获得的实体。属性GeometryObject.IsElementGeometry可以标识实体是否适合作为此方法的输入。

这两种方法的选项包括操作类型:并集、差集或交集。下面的示例演示如何获取两个实体的交点,然后查找体积。

代码区域:实体相交的体积

1
2
3
4
5
6
7
8
9
private void ComputeIntersectionVolume(Solid solidA, Solid solidB)

{

Solid intersection = BooleanOperationsUtils.ExecuteBooleanOperation(solidA, solidB, BooleanOperationsType.Intersect);

double volumeOfIntersection = intersection.Volume;

}

方法CutWithHalfSpace()和CutWithHalfSpaceModifyingOriginalSolid()生成一个实体,该实体是输入Solid与给定Plane正侧的半空间的交点。平面的正侧是平面。法线指向的一侧。第一种方法使用结果创建新实体,而第二种方法修改现有实体(必须是由应用程序创建的实体,而不是从Revit图元获得的实体)。

Geometry Helper 类

API中有几个Geometry Helper类。Helper类用于描述某些元素的几何信息,例如使用BoundingBoxXYZ类为视图定义CropBox。

  • BoundingBoxXYZ - 用于定义三维视图截面区域等情况的三维矩形框。
  • Transform - 变换仿射3D空间。
  • Reference -Revit模型中几何对象的稳定参照,在创建尺寸标注等图元时使用。
  • Plane - 几何中的平面。
  • Options - 用于分析几何图形的用户首选项。
  • XYZ - 表示3D空间中坐标的对象。
  • UV - 表示2D空间中坐标的对象。
  • BoundingBoxUV - 平行于坐标轴的2D矩形。

Transform

在Revit应用程序中,变换仅限于3x4变换(矩阵),即相对于模型空间的其余部分和其他对象变换对象在模型空间中的位置。变换是根据模型空间中的位置和方向构建的。三个方向矢量(BasisX、BasisY和BasisZ属性)和原点提供所有变换信息。由四个值形成的矩阵如下:

将变换应用于点如下:

Transform Of Point方法实现了前面的函数。

下面几节将介绍Geometry.Transform类的属性和方法。

Identity

转换Identity

CreateReflection()

反射指定的平面。

图112:墙反射关系

如上图所示,参照平面镜像了一面墙。CreateReflection()方法需要参考平面的几何平面信息。

代码区域20-8:使用反射属性

1
2
3
4
5
6
private Transform Reflect(ReferencePlane refPlane)
{
Transform mirTrans = Transform.CreateReflection(refPlane.GetPlane());

return mirTrans;
}

CreateRotation() and CreateRotationAtPoint()

围绕位于(0,0,0)或指定点的指定轴旋转指定角度。

CreateTranslation()

按指定的向量平移。给定一个矢量XYZ数据,如下创建一个变换:

Determinant

变换行列式

HasReflection

这是一个布尔值,指示变换是否产生反射。

Scale

表示变换比例的值。

Inverse

逆变换。如果存在变换矩阵B使得AB = B A = I(单位元),则变换矩阵A是可逆的。

IsIdentity

指示此转换是否为标识的布尔值。

IsTranslation

布尔值,指示此转变是否是转换。

Multiply

将转换乘以指定的变换并返回结果。

Operator*-将两个指定的转换相乘。

ScaleBasis

缩放基向量并返回结果。

ScaleBasisAndOrigin

缩放基向量,变换原点返回结果。

OfPoint

将transformation到指定点。使用Origin属性。

OfVector

将transform转换为向量。不使用Origin属性。

AlmostEqual

比较两个转换。AlmostEqual与Revit核心代码中的计算机制和精度一致。此外,在Transform类中没有实现Equal和==运算符。

API提供了几种完成几何变换的快捷方式。几个几何体类中的Transformed属性用于执行此工作,如下表所示。

表48:Transformed 方法

Class Name 类名 Function Description 功能描述
Curve.get_Transformed(Transform transform) 将指定的变换转换为曲线
GeometryElement.GetTransformed(Transform transform) 转换原始元素中几何图形的副本。
Profile.get_Transformed(Transform transform) 转换轮廓并返回结果。
Mesh.get_Transformed(Transform transform) M 转换网格并返回结果。

注意:transformed方法克隆自身,然后返回转换后的克隆结果。 除了这些方法之外,Instance类(它是族实例、链接实例和导入的CAD内容等图元的父类)还有两个方法,可以为给定的Instance提供变换。GetTransform()方法根据实例的放置方式获得实例的基本变换,而GetTotalTransform()方法提供使用真北变换修改的变换,例如导入实例。

Reference

Reference 在元素创建中非常有用。 创建尺寸需要参照。 参考以灵活的方式标识几何表示树内的路径。 树用于查看特定的几何表达创建。API基于不同的Pick指针类型公开四种类型的引用。它们以不同的方式从API中检索:

  • 对于点-Curve.GetEndPointReference方法
  • 对于曲线(直线、圆弧等)- Curve.Reference属性
  • 对于面-face.Reference属性
  • 对于剪切边-Edge.Reference property

不能任意使用不同的参考类型。举例来说: NewLineBoundaryConditions()方法需要Line的引用。 NewAreaBoundaryConditions()方法需要面的引用。 NewPointBoundaryConditions()方法需要Point的引用。 Reference. ConvertToStableRepresentation()方法可用于将对几何体对象(例如面、边或曲线)的引用另存为字符串,然后在同一Revit任务中(甚至在存在同一文档的不同任务中)使用ParseFromStableRepresentation()方法以字符串作为输入来获取相同的引用。

Options Geometry 通常从索引属性Element.Geometry中提取。梁、柱或支撑的原始几何图形在实例通过连接、剪切、复制、拉伸或其他后处理进行修改之前,可以使用FamilyInstance. GetOriginalGeometry()方法提取。Element. Geometry和FamilyInstance. GetOriginalGeometry()都接受必须提供的options 类。

options 类根据其属性自定义接收的输出类型:

  • ComputeReferences -指示检索几何信息时是否计算几何参照。默认值为false,因此如果此属性未设置为true,则引用将不可访问。
  • IncludeNonVisibleObjects -指示还返回在默认视图中不可见的几何对象。
  • View -从特定视图获取几何信息。请注意,如果指定了视图,则将使用此视图的详细程度来代替“DetailLevel”。
  • DetailLevel -指示首选详细程度。默认值为“中”。

ComputeReferences 如果将此属性设置为false,则API不计算几何参照。从几何体树检索的所有引用属性都不返回任何内容。有关引用的更多详细信息,请参阅“引用”部分。与FamilyInstance.GetOriginalGeometry()一起使用时,此选项不能设置为true。

IncludeNonVisibleObjects 大多数不可见几何图形是用户在编辑元素时看到的构造和条件几何图形(即,窗族实例的中心平面)。此属性的默认值为false。但是,某些条件可见几何图形表示真实对象(例如Revit中风管周围的隔热层),因此应将其提取。

View 如果用户将“视图”特性设置为其他视图,则检索到的几何图形信息可能会有所不同。有关详细信息,请查看以下示例: 1. 在Revit中,在三维视图中绘制楼梯,然后在三维视图中选择“裁剪区域”、“裁剪区域可见”和“剖面框”属性。在“裁剪区域”中,修改三维视图中的剖面框以显示楼梯的一部分。如果使用API获取楼梯的几何图形信息,并将三维视图设置为Options.View属性,则只能检索楼梯几何图形的一部分。下图显示了Revit应用程序中的楼梯(左图)和使用API绘制的楼梯(右图)。

图113:不同的剖面框显示不同的几何图形

在Revit中绘制楼梯,然后绘制剖面,如左图所示。如果使用API获取此楼梯的信息,并将此剖面视图设置为Options.View属性,则只能检索楼梯几何图形的一部分。使用API绘制的楼梯如右图所示。

图114:检索几何剖面图

DetailLevel API在Geometry.Options.DetailLevels中定义了三个枚举。这三个枚举对应于Revit应用程序中的三个详细程度,如下所示。

图115:三个细节层次

据DetailLevel特性中的不同设置检索不同的几何体信息。例如,在Revit应用程序中绘制梁,然后使用API从梁中获取几何图形进行绘制。以下图片显示了绘制结果:

图116:梁的几何详图

BoundingBoxXYZ BoundingBoxXYZ定义了一个3D矩形框,它需要与任何坐标轴平行。与Instance类类似,BoundingBoxXYZ将数据存储在局部坐标空间中。它具有一个Transform属性,可将数据从框局部坐标空间转换到模型空间。换句话说,要获取模型空间中的长方体边界(与Revit中的长方体边界相同),请使用Transform属性变换每个数据成员。以下各节说明如何使用BoundingBoxXYZ。 #定义视图边界 BoundingBoxXYZ可用于通过View.CropBox属性定义视图边界。下图使用剖面视图显示了如何在Revit应用程序中使用BoundingBoxXYZ。

图117:截面视图中的BoundingBoxXYZ

前面图片中的虚线显示了作为CropBox特性(BoundingBoxXYZ实例)显示的横断面图边界。

图118:创建的截面视图

上一张图片显示了相应的横断面图。视图边界外的墙将不显示。

定义截面框 BoundingBoxXYZ还用于为从View3D.GetSectionBox()方法检索的三维视图定义剖面框。在“特性”对话框中选择“剖面框”特性。剖面框如下图所示:

图119:三维视图剖面框#其他用途在元素的几何图形周围定义一个框。(Element.BoundingBox属性)。

以这种方式检索的BoundingBoxXYZ实例平行于坐标轴。在ViewSection. ViewDetail()方法中使用。下表标识了此类的主要用途。表49:BoundingBoxXYZ属性

**Property Name ** Usage 使用
Max/Min 最大/最小坐标。这两个属性定义了一个平行于任何坐标轴的三维长方体。Transform属性提供了一个可以将长方体变换到适当位置的变换矩阵。
Transform 从长方体坐标空间转换到模型空间。
Enabled 指示是否打开边界框。
MaxEnabled/ MinEnabled 如果裁剪视图处于打开状态,MaxEnabled属性和MinEnabled属性都返回true。img如果裁剪视图处于关闭状态,MaxEnabled属性和MinEnabled属性都返回false。* 定义给定维度的最大/最小界限是否处于活动状态。如果Enable属性为false,这两个属性也应该返回false。 此属性指示视图的裁剪框面是否可用于裁剪元素的视图。 如果从View3D.GetSectionBox()方法检索BoundingBoxXYZ,则返回值取决于是否在“三维视图属性”对话框中选择了“剖面框”属性。如果是,则所有Enabled属性都返回true。 如果从Element.BoundingBox属性检索BoundingBoxXYZ,则所有Enabled属性都为true。
Bounds Max/Min属性的界限。
BoundEnabled MaxEnabled/MinEnabled属性的界限。

下面的代码示例阐释如何旋转BoundingBoxXYZ以修改三维视图剖面框。

代码区域20-9:旋转BoundingBoxXYZ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void RotateBoundingBox(View3D view3d)
{
if (!view3d.IsSectionBoxActive)
{
TaskDialog.Show("Revit","The section box for View3D isn't active.");
return;
}
BoundingBoxXYZ box = view3d.GetSectionBox();

// Create a rotation transform to apply to the section box
XYZ origin = new XYZ(0, 0, 0);
XYZ axis = new XYZ(0, 0, 1);

// Rotate 30 degrees
Transform rotate = Transform.CreateRotationAtPoint(axis, Math.PI/6.0, origin);

// Transform the View3D's section box with the rotation transform
box.Transform = box.Transform.Multiply(rotate);

// Set the section box back to the view (requires an open transaction)
view3d.SetSectionBox(box);
}

BoundingBoxUV

BoundingBoxUV是一个值类,它定义了一个平行于坐标轴的2D矩形。它支持最小和最大数据成员。它们一起定义BoundingBoxUV的边界。BoundingBoxUV从View.Outline属性中检索,该属性是图纸空间视图中的边界视图。

图120:视图轮廓

两个点定义BoundingBoxUV。

  • Min point - 左下角端点。

  • Max point - 右上端点。

图121:BoundingBoxUV最大值和最小值

注意:BoundingBoxUV不能像下图那样呈现倾斜矩形

图122:倾斜矩形

集合类

Revit API中的专用几何图形集合类。

API根据集合类包含的项提供以下集合类:

表50:几何集合类

**Class/Type ** 对应的集合类** 对应的迭代器**
Edge EdgeArray, EdgeArrayArray EdgeArrayIterator, EdgeArrayArrayIterator
Face FaceArray FaceArrayIterator
Reference ReferenceArray ReferenceArrayIterator
Double value DoubleArray DoubleArrayIterator

所有这些类都使用非常相似的方法和属性来完成类似的工作。有关更多详细信息,请参阅集合。

示例:从梁中检索几何图形数据

本节说明如何从梁获取实体和曲线。可以以类似的方式检索柱和支撑几何数据。GeometryElement可以包含所需的几何体作为Solid或GeometryInstance,具体取决于梁是连接的还是独立的,本代码涵盖了这两种情况。

注意:如果要获取梁和支撑驱动曲线,请调用LocationCurve可用的FamilyInstance Location属性。

示例代码如下所示:

代码区域20-10:从梁获取实体和曲线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public void GetCurvesFromABeam(Autodesk.Revit.DB.FamilyInstance beam,
Autodesk.Revit.DB.Options options)
{
Autodesk.Revit.DB.GeometryElement geomElem = beam.get_Geometry(options);

Autodesk.Revit.DB.CurveArray curves = new CurveArray();
System.Collections.Generic.List<Autodesk.Revit.DB.Solid> solids = new System.Collections.Generic.List<Autodesk.Revit.DB.Solid>();

//Find all solids and insert them into solid array
AddCurvesAndSolids(geomElem, ref curves, ref solids);
}

private void AddCurvesAndSolids(Autodesk.Revit.DB.GeometryElement geomElem,
ref Autodesk.Revit.DB.CurveArray curves,
ref System.Collections.Generic.List<Autodesk.Revit.DB.Solid> solids)
{
foreach (Autodesk.Revit.DB.GeometryObject geomObj in geomElem)
{
Autodesk.Revit.DB.Curve curve = geomObj as Autodesk.Revit.DB.Curve;
if (null != curve)
{
curves.Append(curve);
continue;
}
Autodesk.Revit.DB.Solid solid = geomObj as Autodesk.Revit.DB.Solid;
if (null != solid)
{
solids.Add(solid);
continue;
}
//If this GeometryObject is Instance, call AddCurvesAndSolids
Autodesk.Revit.DB.GeometryInstance geomInst = geomObj as Autodesk.Revit.DB.GeometryInstance;
if (null != geomInst)
{
Autodesk.Revit.DB.GeometryElement transformedGeomElem
= geomInst.GetInstanceGeometry(geomInst.Transform);
AddCurvesAndSolids(transformedGeomElem, ref curves, ref solids);
}
}
}

上面的示例使用FamilyInstance.Geometry属性访问梁的真实几何图形。若要在通过连接、剪切、复制、拉伸或其他后期处理修改族实例之前获取其原始几何图形,请使用FamilyInstance.GetOriginalGeometry()方法。

注意:有关如何检索Geometry.Options类型对象的详细信息,请参阅Geometry Helper Classes。

实体的拉伸分析

实用程序类ExtrusionAnalyzer允许您尝试将给定的几何图形“拟合”到拉伸轮廓的形状中。这个类的实例是一次性使用类,应该提供一个立体几何、一个平面和一个方向。初始化ExtrusionAnalyzer后,可以通过以下成员访问结果:

  • GetExtrusionBase()方法返回与输入平面对齐的拉伸实体的计算基础轮廓。
  • CalculateFaceAlignment()方法可用于标识原始几何体中与计算拉伸的面对齐或不对齐的所有面。例如,这对于确定墙的顶部是否有倾斜连接(如果与屋顶有连接,则会出现这种情况)非常有用。如果某个面未对齐,则会将某些内容连接到影响该面的几何体。
  • 若要确定生成非对齐面的元素,请将面传递给Element.GetGeneratingElementIds()。有关此实用程序的更多详细信息,请参阅以下部分。

ExtrusionAnalyzer实用程序最适用于至少有点“类似于拉伸”的几何体,例如,可能会或可能不会受到端点连接、楼板连接、屋顶连接、由门窗切割的洞口或其他修改影响的墙几何体。对于特定的形状和方向组合,分析器可能很少无法确定作为挤出基础的连贯面-在这些情况下将引发InvalidOperationException。

在此示例中,拉伸分析器用于计算并绘制由输入实体和太阳方向形成的阴影的轮廓。

代码区域:使用拉伸分析器计算并绘制阴影轮廓。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/// 
/// Draw the shadow of the indicated solid with the sun direction specified.
///
/// The shadow will be outlined with model curves added to the document.
/// A transaction must be open in the document.
/// The document.
/// The target solid.
/// The target level where to measure and draw the shadow.
/// The direction from the sun (or light source).
/// The curves created for the shadow.
/// Thrown by ExtrusionAnalyzer when the geometry and
/// direction combined do not permit a successful analysis.
private static ICollection DrawShadow(Document document, Solid solid, Level targetLevel, XYZ sunDirection)
{
// Create target plane from level. Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, new XYZ(0, 0, targetLevel.ProjectElevation));

// Create extrusion analyzer.
ExtrusionAnalyzer analyzer = ExtrusionAnalyzer.Create(solid, plane, sunDirection);

// Get the resulting face at the base of the calculated extrusion.
Face result = analyzer.GetExtrusionBase();

// Convert edges of the face to curves.
CurveArray curves = document.Application.Create.NewCurveArray();
foreach (EdgeArray edgeLoop in result.EdgeLoops)
{
foreach (Edge edge in edgeLoop)
{
curves.Append(edge.AsCurve());
}
}

// Get the model curve factory object.
Autodesk.Revit.Creation.ItemFactoryBase itemFactory;
if (document.IsFamilyDocument)
itemFactory = document.FamilyCreate;
else
itemFactory = document.Create;

// Add a sketch plane for the curves. CurveLoop loop = new CurveLoop();
foreach (Curve currentCurve in curves)
{
loop.Append(currentCurve);
}

SketchPlane sketchPlane = SketchPlane.Create(document, loop.GetPlane());
document.Regenerate();

// Add the shadow curves
ModelCurveArray curveElements = itemFactory.NewModelCurveArray(curves, sketchPlane);

// Return the ids of the curves created
List curveElementIds = new List();
foreach (ModelCurve curveElement in curveElements)
{
curveElementIds.Add(curveElement.Id);
}

return curveElementIds;
}

上面的实用程序可用于计算给定质量相对于视图当前日光和阴影设置的阴影:

通过光线投影查找几何图形

ReferenceIntersector类可用于查找与给定射线相交的元素。

ReferenceIntersector

此类允许应用程序使用Revit的拾取工具来查找图元和几何图形。这个类使用从指定方向的点发出的射线来查找射线击中的几何体。

该类仅与3D几何体相交,并且在创建时需要3D视图。可以使用已被剖面框剪切的三维视图,或设置了视图专有几何图元和图形选项的三维视图。输入视图上的可见性设置将确定是否返回特定图元(例如,此工具永远不会返回隐藏图元,几何图形位于视图剖面框之外的图元也不会返回)。

ReferenceIntersector类支持基于元素或引用类型过滤输出。输出可以根据使用的构造函数进行自定义,或者在调用方法执行光线投影之前使用类的方法和属性进行自定义。

有4个构造函数。

Name 名称 Description 描述
ReferenceIntersector(View3D) 构造一个ReferenceIntersector,它被设置为返回所有元素的交集,并表示所有引用目标类型。
ReferenceIntersector(ElementFilter, FindReferenceTarget, View3D) 构造一个ReferenceIntersector,将其设置为返回通过过滤器的任何元素的交集。
ReferenceIntersector(ElementId, FindReferenceTarget, View3D) 构造一个ReferenceIntersector,它被设置为仅返回来自单个目标元素的交集。
ReferenceIntersector(ICollection, FindReferenceTarget, View3D) 构造一个ReferenceIntersector,它被设置为返回一组目标元素中任何一个的交集。

FindReferenceTarget枚举包括以下选项:元素、网格、边、曲线、面或全部。

查找元素

有两种方法可以投影光线,这两种方法都将光线的原点及其方向作为输入。仅返回光线前面的元素的引用。Find()方法返回与ReferenceIntersector的条件匹配的ReferenceWithContext对象的集合。该对象包含光线参照,它可以是与光线相交的元素和几何参照。返回的某些图元参照将具有一个相应的几何对象,该对象也是矩形的(例如,穿过墙中洞口的光线将与墙和洞口图元相交)。如果只对真正的物理交点感兴趣,则应用程序应丢弃其Reference类型为Element的所有引用。 FindNearest()方法的行为与Find()方法类似,但仅返回距离光线原点最近的对象引用。 返回的ReferenceWithContext包含一个接近度参数。这是光线原点与交点之间的距离。应用程序可以使用此距离来排除距离原点太远的项目,以进行特定的几何分析。应用程序还可以使用此距离来处理一些有趣的问题,包括分析模型的几何图形。

注意:这些方法不会返回与不在激活设计选项中的图元的交点。

链接文件中的元素

FindReferencesInRevitLinks属性提供了一个选项,用于返回在Revit链接中遇到的图元结果。如果设置为false,ReferenceIntersector将找不到对Revit链接中任何图元的参照,并且返回的所有参照将仅指向主体文档中的图元。如果设置为true,则结果可能包括对主体中元素的引用和对链接实例中元素的引用。 如果在ReferenceIntersector中设置了目标ElementId的列表,则仅当ElementId与ReferenceRevitLinkInstance的ID匹配时,才会返回引用。如果有匹配,链接中的任何相交元素都将被返回(它们的id将不会与目标id列表进行比较)。 如果应用了ElementFilter,则将根据存储的ElementFilter计算链接中的元素。请注意,如果应用的过滤器是几何过滤器(如BoundingBox过滤器或ElementIntersects过滤器),则结果可能与预期不同。这是因为将针对链接模型坐标中的链接图元计算过滤器,而链接模型坐标可能与图元在主体模型中显示的坐标不匹配。此外,在实例化期间接受Document和/或ElementId作为输入的ElementFilters将无法正确传递链接中出现的元素,因为过滤器将无法将链接元素与过滤器的标准相匹配。 ###查找元素附近的元素 此工具的一个主要用途是查找与其他元素非常接近的元素。这允许应用程序将该工具用作其“眼睛”,并确定尚未具有内置关系的元素之间的关系。 例如,光线跟踪功能可用于查找嵌入墙中的柱。由于柱和墙不直接保持关系,因此此类允许我们通过跟踪墙范围外的光线并查找与柱的交点来查找潜在的候选对象。

示例:查找嵌入墙中的柱

测量距离

这个类也可以用来测量从天窗到最近楼层的垂直距离。

示例:使用ReferenceIntersector.FindNearest()进行测量

代码区域:使用光线投影测量距离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class RayProjection : IExternalCommand
{
public Result Execute(ExternalCommandData revit, ref string message, ElementSet elements)
{
Document doc = revit.Application.ActiveUIDocument.Document;

ICollection selectedIds = revit.Application.ActiveUIDocument.Selection.GetElementIds();

// If skylight is selected, process it.
FamilyInstance skylight = null;
if (selectedIds.Count == 1)
{
foreach (ElementId id in selectedIds)
{
Element e = doc.GetElement(id);
if (e is FamilyInstance)
{
FamilyInstance instance = e as FamilyInstance;
bool isWindow = (instance.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Windows);
bool isHostedByRoof = (instance.Host.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Roofs);

if (isWindow && isHostedByRoof)
{
skylight = instance;
}
}
}
}

if (skylight == null)
{
message = "Please select one skylight.";
return Result.Cancelled;
}

// Calculate the height
Line line = CalculateLineAboveFloor(doc, skylight);

// Create a model curve to show the distance
Plane plane = Plane.CreateByNormalAndOrigin(new XYZ(1, 0, 0), line.GetEndPoint(0));
SketchPlane sketchPlane = SketchPlane.Create(doc, plane);

ModelCurve curve = doc.Create.NewModelCurve(line, sketchPlane);

// Show a message with the length value
TaskDialog.Show("Distance", "Distance to floor: " + String.Format("{0:f2}", line.Length));

return Result.Succeeded;
}

///
/// Determines the line segment that connects the skylight to the nearest floor.
///
/// The line segment.
private Line CalculateLineAboveFloor(Document doc, FamilyInstance skylight)
{
// Find a 3D view to use for the ReferenceIntersector constructor
FilteredElementCollector collector = new FilteredElementCollector(doc);
Func<View3D, bool> isNotTemplate = v3 => !(v3.IsTemplate);
View3D view3D = collector.OfClass(typeof(View3D)).Cast().First(isNotTemplate);

// Use the center of the skylight bounding box as the start point.
BoundingBoxXYZ box = skylight.get_BoundingBox(view3D);
XYZ center = box.Min.Add(box.Max).Multiply(0.5);

// Project in the negative Z direction down to the floor.
XYZ rayDirection = new XYZ(0, 0, -1);

ElementClassFilter filter = new ElementClassFilter(typeof(Floor));

ReferenceIntersector refIntersector = new ReferenceIntersector(filter, FindReferenceTarget.Face, view3D);
ReferenceWithContext referenceWithContext = refIntersector.FindNearest(center, rayDirection);

Reference reference = referenceWithContext.GetReference();
XYZ intersection = reference.GlobalPoint;

// Create line segment from the start point and intersection point.
Line result = Line.CreateBound(center, intersection);
return result;
}
}

射线反弹/分析

ReferenceIntersector.Find()返回的参照包括几何上的交点。知道了面上的交点、面的材质和光线方向,应用程序就可以分析建筑物内的反射和折射。下图演示了如何使用交点来反射由模型图元遮挡的光线;添加了模型曲线来表示每条光线的路径。

示例:从曲面反弹的射线

查找交点/碰撞

ReferenceIntersector类的另一个用途是检测与给定梁或管道的中心线相交/干涉的交点(如梁或管道)。

示例:在干涉周围重新布线元素

几何工具类

有许多工具类可用于处理几何体对象。

HostObjectUtils

HostObjectUtils类提供方法作为定位复合HostObjects的某些面的快捷方式。这些实用程序检索用作对象的CompoundStructure的边界的面:

  • HostObjectUtils.GetSideFaces() – 适用于墙壁和FaceWalls;您可以获得外部或内部饰面。
  • HostObjectUtils.GetTopFaces() and HostObjectUtils.GetBottomFaces() – 适用于屋顶、楼板和天花板。

SolidUtils

SolidUtils类包含对实体执行操作的方法。

  • SolidUtils.Clone() - 创建一个新的Solid,它是输入Solid的副本
  • SolidUtils.SplitVolumes() - 使用一个包含不相交的封闭体积的实体,并返回新创建的代表每个体积的实体对象。如果不需要分割,则返回输入实体。
  • SolidUtils.TessellateSolidOrShell() - 对给定的输入实体(可以是一个或多个完全闭合的体积,也可以是一个开放的壳)进行三角测量。返回一个TriangulatedSolidOrShell对象,该对象允许访问存储的实体的三角化边界组件或壳的三角化连接组件。
  • SolidUtils.CreateTransformed() - 创建一个新的实体,它是输入实体的变换。

JoinGeometryUtils

JoinGeometryUtils类包含用于连接和取消连接元素以及管理元素连接顺序的方法。这些实用程序不适用于族文档。

  • JoinGeometryUtils.AreElementsJoined() - 确定是否连接两个元素
  • JoinGeometryUtils.GetJoinedElements() - 返回连接到给定元素的所有元素
  • JoinGeometryUtils.JoinGeometry() - 在共享公共面的两个元素之间创建连接。将删除连接图元之间的可见边。然后,连接的元素共享相同的线宽和填充图案。
  • JoinGeometryUtils.UnjoinGeometry() - 删除两个连接元素之间的连接
  • JoinGeometryUtils.SwitchJoinOrder() - 反转两个元素连接的顺序。切割元件变成被切割元件,反之亦然。
  • JoinGeometryUtils . IsCuttingElementInJoin() - 确定两个连接的元素中的第一个元素是否剪切第二个元素,反之亦然。

FacetingUtils

此类用于将三角形结构转换为其中某些三角形已合并为四边形的结构。

  • FacetingUtils.ConvertTrianglesToQuads() - 此方法以TriangulationInterface(从TriangulatedSolidOrShell构造)作为输入,并返回表示原始三角化对象的三角形和四边形的集合。

房间和空间几何

通过Revit API可以访问空间图元(房间和空间)的三维几何图形。

SpatialElementGeometryCalculator类可用于计算空间元素的几何形状并获取几何形状与元素边界元素之间的关系。可以为此实用程序提供2个选项:

  • SpatialElementBoundaryLocation – 是否使用详细面或边界元素中心线进行计算
  • StoredFreeBoundaryFaces – 是否在结果中包括不直接映射到边界元素的面。

计算几何体的结果包含在SpatialElementGeometryResults类中。从SpatialElementGeometryResults类中,可以获得:

  • 表示几何的实体体积(GetGeometry()方法)
  • 边界面信息(一个集合SpatialElementBoundarySubfaces)

每个子面提供:

  • 空间元素的表面
  • 边界元素的匹配面
  • 子面(由该特定边界元素限定的空间元素面部分)
  • 底面类型(底部、顶部或侧面)

关于使用此实用程序的一些注意事项:

  • 计算器为已处理的几何体维护一个内部缓存。如果要计算同一项目中多个图元的几何图形,则应使用此类的单个实例。请注意,当对文档进行任何更改时,将清除该高速缓存。
  • 楼板几乎从不作为边界元素包含在内。Revit使用房间的二维轮廓来形成底面,而不将其与楼板几何图形相匹配。
  • 由墙剪切特征(例如门和窗)创建的洞口不包括在返回的面中。
  • 几何图形计算与Revit提供的功能相匹配。在某些情况下,如果Revit假设如何计算房间和空间边界的体积,则这些假设将显示在实用程序的输出中。

以下示例计算房间的几何图形并查找其边界面

代码区域:使用SpatialElementGeometryCalculator的面部区域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SpatialElementGeometryCalculator calculator = new SpatialElementGeometryCalculator(doc);

// compute the room geometry
SpatialElementGeometryResults results = calculator.CalculateSpatialElementGeometry(room);

// get the solid representing the room's geometry
Solid roomSolid = results.GetGeometry();

foreach (Face face in roomSolid.Faces)
{
double faceArea = face.Area;

// get the sub-faces for the face of the room
IList subfaceList = results.GetBoundaryFaceInfo(face);
foreach (SpatialElementBoundarySubface subface in subfaceList)
{
if (subfaceList.Count > 1) // there are multiple sub-faces that define the face
{
// get the area of each sub-face
double subfaceArea = subface.GetSubface().Area;
// sub-faces exist in situations such as when a room-bounding wall has been
// horizontally split and the faces of each split wall combine to create the
// entire face of the room
}
}
}

下面的示例计算房间的几何图形,并查找属于定义房间的图元的面的材质。

代码区域:使用SpatialElementGeometryCalculator的面材质

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void MaterialFromFace()
{
string s = "";
Document doc = this.Document;
UIDocument uidoc = new UIDocument(doc);
Room room = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element).ElementId) as Room;

SpatialElementBoundaryOptions spatialElementBoundaryOptions = new SpatialElementBoundaryOptions();
spatialElementBoundaryOptions.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish;
SpatialElementGeometryCalculator calculator = new SpatialElementGeometryCalculator(doc, spatialElementBoundaryOptions);
SpatialElementGeometryResults results = calculator.CalculateSpatialElementGeometry(room);
Solid roomSolid = results.GetGeometry();

foreach (Face roomSolidFace in roomSolid.Faces)
{
foreach (SpatialElementBoundarySubface subface in results.GetBoundaryFaceInfo(roomSolidFace))
{
Face boundingElementface = subface.GetBoundingElementFace();
ElementId id = boundingElementface.MaterialElementId;
s += doc.GetElement(id).Name + ", id = " + id.IntegerValue.ToString() + "\n";
}
}
TaskDialog.Show("revit",s);}

注:翻译自Revit API Developers Guide