DirectShape

此图元类型可以在项目或族文档中存储通过导入操作或计算获得的任意几何图形。

DirectShape元素和相关类支持在Revit文档中存储外部创建的几何形状的功能。几何体可以包括闭合实体或网格。DirectShape主要用于从其他数据格式(如IFC或STEP)导入形状,在这些格式中,没有足够的信息来创建“真实的”Revit图元。

可以为DirectShape对象指定顶级模型类别,例如墙类别。子类别不能指定给DirectShape元素。IsValidCategoryId()方法可以测试类别ID,以确保它是批准与DirectShape和Category一起使用的顶级内置类别。如果类别类型为Model,则会指示CategoryType枚举值。类别将影响该对象在Revit中的显示方式,并将为该对象授予可用参数的集合和某些有限的行为。

DirectShape创建

静态DirectElement()方法将创建一个新的实例级DirectShape。它需要将DirectShape添加到其中的文档以及适当的内置类别的ID。DirectShape提供ApplicationId和ApplicationDataId字符串参数,这些参数为创建的形状的源提供上下文。

创建DirectShape后,可以使用重载的SetShape()方法之一来设置该形状。该形状可以直接从ShapeBuilder对象或从GeometryObject列表中设置。如果您无论如何都要使用ShapeBuilder对象为DirectShape构造几何图形,则使用ShapeBuilder输入可能会有轻微的性能优势,因为Revit将绕过对输入几何图形的重复验证。还可以使用不同版本的DirectShape()方法将其他几何体对象附加到DirectShape。请注意,BulldShape()不会将传入的几何体与任何已经存在的几何体合并或连接,几何体将独立存储。

DirectMap接受以下几何体类型作为输入:

  • 实体(可以是封闭或开放的外壳)
  • 网格
  • 曲线

此外,还可以指定要在DirectShape的视图特定表示中使用的几何体。该几何图形与DirectShapeTargetViewType的输入一起沿着输入。设置视图专有的形状表达时,它将仅用于该类型的视图中。目前,唯一受支持的视图专有表达用于平面视图。

面的示例演示如何从使用GeometryCreationUtilities类创建的球体创建简单的DirectShape。请注意在创建几何体时使用了参考框架。在使用Frame对象创建几何图形之前,最好先调用静态方法Frame.CanDefineRevitGeometry(),该方法测试提供的Frame对象是否可用于定义Revit曲线或曲面。为了满足要求,框架必须正交,并且其原点应位于Revit设计限制范围内。(When创建几何体时,使用静态XYZ也很有用。IsWithinLengthLimits(),以确保该点在Revit设计限制范围内。)

代码区域:创建DirectShape

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
// Create a DirectShape Sphere
public void CreateSphereDirectShape(Document doc)
{
List<Curve> profile = new List<Curve>();

// first create sphere with 2' radius
XYZ center = XYZ.Zero;
double radius = 2.0;
XYZ profile00 = center;
XYZ profilePlus = center + new XYZ(0, radius, 0);
XYZ profileMinus = center - new XYZ(0, radius, 0);

profile.Add(Line.CreateBound(profilePlus, profileMinus));
profile.Add(Arc.Create(profileMinus, profilePlus, center + new XYZ(radius, 0, 0)));

CurveLoop curveLoop = CurveLoop.Create(profile);
SolidOptions options = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

Frame frame = new Frame(center, XYZ.BasisX, -XYZ.BasisZ, XYZ.BasisY);
if (Frame.CanDefineRevitGeometry(frame) == true)
{
Solid sphere = GeometryCreationUtilities.CreateRevolvedGeometry(frame, new CurveLoop[] { curveLoop }, 0, 2 * Math.PI, options);
using (Transaction t = new Transaction(doc, "Create sphere direct shape"))
{
t.Start();
// create direct shape and assign the sphere shape
DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));

ds.ApplicationId = "Application id";
ds.ApplicationDataId = "Geometry object id";
ds.SetShape(new GeometryObject[] { sphere });
t.Commit();
}
}
}

DirectShape的几何体也可以使用ShapeBuilder类的子类或从TessellatedShapeBuilder创建。

ShapeBuilder

ViewShapeBuilder和WireframeBuilder可用于创建几何体以存储在DirectShape类中。ViewShapeBuilder类生成并验证视图特定的形状表示。它仅限于平面视图的基于曲线的表达。WireframeBuilder构造由点和曲线组成的3D形状表示。这两种类型的ShapeBuilder都可以通过使用带ShapeBuilder参数的DirectShape.SetShape()或DirectShape.SetShadShape()重载应用于DirectShape元素。

TessellatedShapeBuilder

TessellatedShapeBuilder可用于创建实体、壳或多边形网格,这些网格由一组连接的平面小平面包围,通过逐个添加TessellatedFace对象创建。只有在面集处于“open”状态时,才能将面添加到构建中。使用OpenConnectedFaceSet()方法打开面集。添加所有TessellatedFaces后,调用CloseConnectedFaceSet()关闭面集。构建器允许多个面集的可能性-在这种情况下,第一个面集应该代表物体的外部“表面”,所有后续面集代表内部空隙。尽管输入数据中存在不一致或遗漏,构建器仍会尝试创建在Revit中有效的几何图形。

定义所有面并关闭面集后,调用Build()方法从存储的面集构建指定的几何对象。可以在调用Build()之前设置TessellatedShapeBuilder的Target、Fallback和GraphicsStyleId属性,否则将使用默认选项。Build()的结果存储在TessellatedShapeBuilder中,可以通过调用GetBuildResult()进行检索。TessellatedShapeBuilderResult.GetGeometricalObjects()方法将返回一个GeometryObjects列表,该列表可与相应的DirectShape.SetShape()或DirectShape. SethdShape()重载一起使用,如下面的示例所示。

代码区域:使用TessellatedShapeBuilder创建DirectShape

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
// Create a pyramid-shaped DirectShape using given material for the faces
public void CreateTessellatedShape(Document doc, ElementId materialId)
{
List<XYZ> loopVertices = new List<XYZ>(4);

TessellatedShapeBuilder builder = new TessellatedShapeBuilder();

builder.OpenConnectedFaceSet(true);
// create a pyramid with a square base 4' x 4' and 5' high
double length = 4.0;
double height = 5.0;

XYZ basePt1 = XYZ.Zero;
XYZ basePt2 = new XYZ(length, 0, 0);
XYZ basePt3 = new XYZ(length, length, 0);
XYZ basePt4 = new XYZ(0, length, 0);
XYZ apex = new XYZ(length / 2, length / 2, height);

loopVertices.Add(basePt1);
loopVertices.Add(basePt2);
loopVertices.Add(basePt3);
loopVertices.Add(basePt4);
builder.AddFace(new TessellatedFace(loopVertices, materialId));

loopVertices.Clear();
loopVertices.Add(basePt1);
loopVertices.Add(apex);
loopVertices.Add(basePt2);
builder.AddFace(new TessellatedFace(loopVertices, materialId));

loopVertices.Clear();
loopVertices.Add(basePt2);
loopVertices.Add(apex);
loopVertices.Add(basePt3);
builder.AddFace(new TessellatedFace(loopVertices, materialId));

loopVertices.Clear();
loopVertices.Add(basePt3);
loopVertices.Add(apex);
loopVertices.Add(basePt4);
builder.AddFace(new TessellatedFace(loopVertices, materialId));

loopVertices.Clear();
loopVertices.Add(basePt4);
loopVertices.Add(apex);
loopVertices.Add(basePt1);
builder.AddFace(new TessellatedFace(loopVertices, materialId));

builder.CloseConnectedFaceSet();
builder.Target = TessellatedShapeBuilderTarget.Solid;
builder.Fallback = TessellatedShapeBuilderFallback.Abort;
builder.Build();

TessellatedShapeBuilderResult result = builder.GetBuildResult();

using (Transaction t = new Transaction(doc, "Create tessellated direct shape"))
{
t.Start();

DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
ds.ApplicationId = "Application id";
ds.ApplicationDataId = "Geometry object id";

ds.SetShape(result.GetGeometricalObjects());
t.Commit();
}
}

下面的图片是运行上面的示例并指定混凝土材质ID的结果。

img

BRepBuilder

BRepBuilder类提供了构造Revit边界表达几何图形(实体、开放壳等)的功能。作为表面、边和边的边界环的输入的结果。如果边界表示的构建成功,则可以在接受几何图形的任何其他Revit工具中直接使用生成的几何图形对象,或者可以直接传递BRepBuilder,以通过DirectShape类的SetShape()和RoundShape()方法填充DirectShape。下面是一个使用SetShape()方法将圆柱体形状分配给新DirectShape对象的示例。

代码区域:使用BRepBuilder创建DirectShape

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
private void CreateDirectShapeFromCylinder(Document doc)
{
// Naming convention for faces and edges: we assume that x is to the left and pointing down, y is horizontal and pointing to the right, z is up
BRepBuilder brepBuilder = new BRepBuilder(BRepType.Solid);

// The surfaces of the four faces.
Frame basis = new Frame(new XYZ(50, -100, 0), new XYZ(0, 1, 0), new XYZ(-1, 0, 0), new XYZ(0, 0, 1));
CylindricalSurface cylSurf = CylindricalSurface.Create(basis, 50);
Plane top = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 100)); // normal points outside the cylinder
Plane bottom = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 0)); // normal points inside the cylinder

// Add the four faces
BRepBuilderGeometryId frontCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false);
BRepBuilderGeometryId backCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false);
BRepBuilderGeometryId topFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(top, null), false);
BRepBuilderGeometryId bottomFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(bottom, null), true);

// Geometry for the four semi-circular edges and two vertical linear edges
BRepBuilderEdgeGeometry frontEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 0), new XYZ(100, -100, 0), new XYZ(50, -50, 0)));
BRepBuilderEdgeGeometry backEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(100, -100, 0), new XYZ(0, -100, 0), new XYZ(50, -150, 0)));

BRepBuilderEdgeGeometry frontEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -50, 100)));
BRepBuilderEdgeGeometry backEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -150, 100)));

BRepBuilderEdgeGeometry linearEdgeFront = BRepBuilderEdgeGeometry.Create(new XYZ(100, -100, 0), new XYZ(100, -100, 100));
BRepBuilderEdgeGeometry linearEdgeBack = BRepBuilderEdgeGeometry.Create(new XYZ(0, -100, 0), new XYZ(0, -100, 100));

// Add the six edges
BRepBuilderGeometryId frontEdgeBottomId = brepBuilder.AddEdge(frontEdgeBottom);
BRepBuilderGeometryId frontEdgeTopId = brepBuilder.AddEdge(frontEdgeTop);
BRepBuilderGeometryId linearEdgeFrontId = brepBuilder.AddEdge(linearEdgeFront);
BRepBuilderGeometryId linearEdgeBackId = brepBuilder.AddEdge(linearEdgeBack);
BRepBuilderGeometryId backEdgeBottomId = brepBuilder.AddEdge(backEdgeBottom);
BRepBuilderGeometryId backEdgeTopId = brepBuilder.AddEdge(backEdgeTop);

// Loops of the four faces
BRepBuilderGeometryId loopId_Top = brepBuilder.AddLoop(topFaceId);
BRepBuilderGeometryId loopId_Bottom = brepBuilder.AddLoop(bottomFaceId);
BRepBuilderGeometryId loopId_Front = brepBuilder.AddLoop(frontCylFaceId);
BRepBuilderGeometryId loopId_Back = brepBuilder.AddLoop(backCylFaceId);

// Add coedges for the loop of the front face
brepBuilder.AddCoEdge(loopId_Front, linearEdgeBackId, false);
brepBuilder.AddCoEdge(loopId_Front, frontEdgeTopId, false);
brepBuilder.AddCoEdge(loopId_Front, linearEdgeFrontId, true);
brepBuilder.AddCoEdge(loopId_Front, frontEdgeBottomId, true);
brepBuilder.FinishLoop(loopId_Front);
brepBuilder.FinishFace(frontCylFaceId);

// Add coedges for the loop of the back face
brepBuilder.AddCoEdge(loopId_Back, linearEdgeBackId, true);
brepBuilder.AddCoEdge(loopId_Back, backEdgeBottomId, true);
brepBuilder.AddCoEdge(loopId_Back, linearEdgeFrontId, false);
brepBuilder.AddCoEdge(loopId_Back, backEdgeTopId, true);
brepBuilder.FinishLoop(loopId_Back);
brepBuilder.FinishFace(backCylFaceId);

// Add coedges for the loop of the top face
brepBuilder.AddCoEdge(loopId_Top, backEdgeTopId, false);
brepBuilder.AddCoEdge(loopId_Top, frontEdgeTopId, true);
brepBuilder.FinishLoop(loopId_Top);
brepBuilder.FinishFace(topFaceId);

// Add coedges for the loop of the bottom face
brepBuilder.AddCoEdge(loopId_Bottom, frontEdgeBottomId, false);
brepBuilder.AddCoEdge(loopId_Bottom, backEdgeBottomId, false);
brepBuilder.FinishLoop(loopId_Bottom);
brepBuilder.FinishFace(bottomFaceId);

brepBuilder.Finish();

using (Transaction tr = new Transaction(doc, "Create a DirectShape"))
{
tr.Start();
DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
ds.SetShape(brepBuilder);
tr.Commit();
}
}

ShapeImporter

ShapeImporter工具类支持将以外部格式(如SAT和Rhino)存储的几何体转换为可用于设置DirectShape形状的GeometryObjects集合。使用ShapeImporter.Convert()生成几何体对象(如果可能,还生成关联文档中的相应材料和图形样式)。

代码区域:从SAT文件创建DirectShape

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
public void ReadSATFile(Document revitDoc)
{
// Allow the user to select a SAT file.
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "SAT Files (*.sat)|*.sat";

if (DialogResult.OK == ofd.ShowDialog())
{
ShapeImporter shapeImporter = new ShapeImporter();
shapeImporter.InputFormat = ShapeImporterSourceFormat.SAT;
IList<GeometryObject> shapes = shapeImporter.Convert(revitDoc, ofd.FileName);

if (shapes.Count != 0)
{
using (Transaction tr = new Transaction(revitDoc, "Create a DirectShape"))
{
tr.Start();

DirectShape dsImportedSat = DirectShape.CreateElement(revitDoc, new ElementId(BuiltInCategory.OST_Walls));
dsImportedSat.SetShape(shapes);

tr.Commit();
}
}
}
}

Options

DirectShapeOptions类用于控制DirectShape对象的行为。使用DirectShape.SetOptions()设置DirectShape对象使用的选项。GetOptions()方法将返回DirectShape对象当前使用的DirectShapeOptions。

默认情况下,DirectShape元素支持元素参照,包括尺寸标注、路线和面主体以及捕捉。可以使用DirectShapeOptions.ReferencingOption属性更改此默认行为。如果将其设置为NotReferenceable,则几何图形不能用于标注、捕捉、对齐或面主体。用户仍然可以选择该元素进行不引用单个几何对象的操作。

如果DirectShape元素属于房间边界计算的适当类别,并且关联的“房间边界”参数设置为true,则DirectShape元素还支持参与房间边界计算的功能。属性DirectShapeOptions.RoomBoundingOption标识DirectShape是否支持“房间边界”参数的选项以允许参与房间边界计算。默认值为NotApplied,但对于适用的DirectController,此值将自动更改为SetByParameter。

注:翻译自Revit API Developers Guide