NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 - 3D道路快速建模
下面是一段有趣的代码片段,说明了如何使用 BRepBuilder 和布尔运算来生成 DirectShape。
它可能会在某个地方派上用场,尽管这种方法对于解决手头的任务来说并不是最佳的,如下所述。
问题:我想创建一个由 void geometry 切割的 DirectShape 对象。
我发现 BRepBuilder 构造函数接受 BRepType.Void 和 BRepType.Solid,所以我测试了我是否可以使用它。
但是,到目前为止,我的尝试导致了内部错误。
我的测试代码有没有错误?
DirectShape.AppendShape 方法不接受空形状吗?
答案:在我看来,你实际上想要做的是创建两个实体几何体,然后使用布尔运算将一个减去另一个。
这将给出所需的形状。
查看代码,我注意到函数 CreateBrepVoid 是不正确的——它告诉 BRepBuilder 它想要创建一个空心,但几何定义了一个实体,而不是一个空心。 这是由面和边循环方向决定的。 我假设 BRepBuilder 在过程中的某个时刻抱怨无效输入。
在 BRepBuilder AddFace 和 AddCoEdge 方法的描述中讨论了方向约定。
请注意,BRepBuilder 并不是真正用于“手动”构建几何体。 为此,它的API非常繁琐。 它旨在将现有几何图形转换为 Revit,并对输入几何图形进行相当彻底的验证。
下面是构造两个实体几何图形然后应用布尔运算找出差异的代码。
该代码构建了上图中所示的所需 DirectShape:
[Transaction( TransactionMode.Manual )]
class CmdBrepBuilder : IExternalCommand
{
/// <summary>
/// Create a cube 100 x 100 x 100, from
/// (0,0,0) to (100, 100, 100).
/// </summary>
public BRepBuilder CreateBrepSolid()
{
BRepBuilder b = new BRepBuilder( BRepType.Solid );
// 1. Planes.
// naming convention for faces and planes:
// We are looking at this cube in an isometric view.
// X is down and to the left of us, Y is horizontal
// and points to the right, Z is up.
// front and back faces are along the X axis, left
// and right are along the Y axis, top and bottom
// are along the Z axis.
Plane bottom = Plane.CreateByOriginAndBasis( new XYZ( 50, 50, 0 ), new XYZ( 1, 0, 0 ), new XYZ( 0, 1, 0 ) ); // bottom. XY plane, Z = 0, normal pointing inside the cube.
Plane top = Plane.CreateByOriginAndBasis( new XYZ( 50, 50, 100 ), new XYZ( 1, 0, 0 ), new XYZ( 0, 1, 0 ) ); // top. XY plane, Z = 100, normal pointing outside the cube.
Plane front = Plane.CreateByOriginAndBasis( new XYZ( 100, 50, 50 ), new XYZ( 0, 0, 1 ), new XYZ( 0, 1, 0 ) ); // front side. ZY plane, X = 0, normal pointing inside the cube.
Plane back = Plane.CreateByOriginAndBasis( new XYZ( 0, 50, 50 ), new XYZ( 0, 0, 1 ), new XYZ( 0, 1, 0 ) ); // back side. ZY plane, X = 0, normal pointing outside the cube.
Plane left = Plane.CreateByOriginAndBasis( new XYZ( 50, 0, 50 ), new XYZ( 0, 0, 1 ), new XYZ( 1, 0, 0 ) ); // left side. ZX plane, Y = 0, normal pointing inside the cube
Plane right = Plane.CreateByOriginAndBasis( new XYZ( 50, 100, 50 ), new XYZ( 0, 0, 1 ), new XYZ( 1, 0, 0 ) ); // right side. ZX plane, Y = 100, normal pointing outside the cube
// 2. Faces.
BRepBuilderGeometryId faceId_Bottom = b.AddFace( BRepBuilderSurfaceGeometry.Create( bottom, null ), true );
BRepBuilderGeometryId faceId_Top = b.AddFace( BRepBuilderSurfaceGeometry.Create( top, null ), false );
BRepBuilderGeometryId faceId_Front = b.AddFace( BRepBuilderSurfaceGeometry.Create( front, null ), true );
BRepBuilderGeometryId faceId_Back = b.AddFace( BRepBuilderSurfaceGeometry.Create( back, null ), false );
BRepBuilderGeometryId faceId_Left = b.AddFace( BRepBuilderSurfaceGeometry.Create( left, null ), true );
BRepBuilderGeometryId faceId_Right = b.AddFace( BRepBuilderSurfaceGeometry.Create( right, null ), false );
// 3. Edges.
// 3.a (define edge geometry)
// walk around bottom face
BRepBuilderEdgeGeometry edgeBottomFront = BRepBuilderEdgeGeometry.Create( new XYZ( 100, 0, 0 ), new XYZ( 100, 100, 0 ) );
BRepBuilderEdgeGeometry edgeBottomRight = BRepBuilderEdgeGeometry.Create( new XYZ( 100, 100, 0 ), new XYZ( 0, 100, 0 ) );
BRepBuilderEdgeGeometry edgeBottomBack = BRepBuilderEdgeGeometry.Create( new XYZ( 0, 100, 0 ), new XYZ( 0, 0, 0 ) );
BRepBuilderEdgeGeometry edgeBottomLeft = BRepBuilderEdgeGeometry.Create( new XYZ( 0, 0, 0 ), new XYZ( 100, 0, 0 ) );
// now walk around top face
BRepBuilderEdgeGeometry edgeTopFront = BRepBuilderEdgeGeometry.Create( new XYZ( 100, 0, 100 ), new XYZ( 100, 100, 100 ) );
BRepBuilderEdgeGeometry edgeTopRight = BRepBuilderEdgeGeometry.Create( new XYZ( 100, 100, 100 ), new XYZ( 0, 100, 100 ) );
BRepBuilderEdgeGeometry edgeTopBack = BRepBuilderEdgeGeometry.Create( new XYZ( 0, 100, 100 ), new XYZ( 0, 0, 100 ) );
BRepBuilderEdgeGeometry edgeTopLeft = BRepBuilderEdgeGeometry.Create( new XYZ( 0, 0, 100 ), new XYZ( 100, 0, 100 ) );
// sides
BRepBuilderEdgeGeometry edgeFrontRight = BRepBuilderEdgeGeometry.Create( new XYZ( 100, 100, 0 ), new XYZ( 100, 100, 100 ) );
BRepBuilderEdgeGeometry edgeRightBack = BRepBuilderEdgeGeometry.Create( new XYZ( 0, 100, 0 ), new XYZ( 0, 100, 100 ) );
BRepBuilderEdgeGeometry edgeBackLeft = BRepBuilderEdgeGeometry.Create( new XYZ( 0, 0, 0 ), new XYZ( 0, 0, 100 ) );
BRepBuilderEdgeGeometry edgeLeftFront = BRepBuilderEdgeGeometry.Create( new XYZ( 100, 0, 0 ), new XYZ( 100, 0, 100 ) );
// 3.b (define the edges themselves)
BRepBuilderGeometryId edgeId_BottomFront = b.AddEdge( edgeBottomFront );
BRepBuilderGeometryId edgeId_BottomRight = b.AddEdge( edgeBottomRight );
BRepBuilderGeometryId edgeId_BottomBack = b.AddEdge( edgeBottomBack );
BRepBuilderGeometryId edgeId_BottomLeft = b.AddEdge( edgeBottomLeft );
BRepBuilderGeometryId edgeId_TopFront = b.AddEdge( edgeTopFront );
BRepBuilderGeometryId edgeId_TopRight = b.AddEdge( edgeTopRight );
BRepBuilderGeometryId edgeId_TopBack = b.AddEdge( edgeTopBack );
BRepBuilderGeometryId edgeId_TopLeft = b.AddEdge( edgeTopLeft );
BRepBuilderGeometryId edgeId_FrontRight = b.AddEdge( edgeFrontRight );
BRepBuilderGeometryId edgeId_RightBack = b.AddEdge( edgeRightBack );
BRepBuilderGeometryId edgeId_BackLeft = b.AddEdge( edgeBackLeft );
BRepBuilderGeometryId edgeId_LeftFront = b.AddEdge( edgeLeftFront );
// 4. Loops.
BRepBuilderGeometryId loopId_Bottom = b.AddLoop( faceId_Bottom );
BRepBuilderGeometryId loopId_Top = b.AddLoop( faceId_Top );
BRepBuilderGeometryId loopId_Front = b.AddLoop( faceId_Front );
BRepBuilderGeometryId loopId_Back = b.AddLoop( faceId_Back );
BRepBuilderGeometryId loopId_Right = b.AddLoop( faceId_Right );
BRepBuilderGeometryId loopId_Left = b.AddLoop( faceId_Left );
// 5. Co-edges.
// Bottom face. All edges reversed
b.AddCoEdge( loopId_Bottom, edgeId_BottomFront, true ); // other direction in front loop
b.AddCoEdge( loopId_Bottom, edgeId_BottomLeft, true ); // other direction in left loop
b.AddCoEdge( loopId_Bottom, edgeId_BottomBack, true ); // other direction in back loop
b.AddCoEdge( loopId_Bottom, edgeId_BottomRight, true ); // other direction in right loop
b.FinishLoop( loopId_Bottom );
b.FinishFace( faceId_Bottom );
// Top face. All edges NOT reversed.
b.AddCoEdge( loopId_Top, edgeId_TopFront, false ); // other direction in front loop.
b.AddCoEdge( loopId_Top, edgeId_TopRight, false ); // other direction in right loop
b.AddCoEdge( loopId_Top, edgeId_TopBack, false ); // other direction in back loop
b.AddCoEdge( loopId_Top, edgeId_TopLeft, false ); // other direction in left loop
b.FinishLoop( loopId_Top );
b.FinishFace( faceId_Top );
// Front face.
b.AddCoEdge( loopId_Front, edgeId_BottomFront, false ); // other direction in bottom loop
b.AddCoEdge( loopId_Front, edgeId_FrontRight, false ); // other direction in right loop
b.AddCoEdge( loopId_Front, edgeId_TopFront, true ); // other direction in top loop.
b.AddCoEdge( loopId_Front, edgeId_LeftFront, true ); // other direction in left loop.
b.FinishLoop( loopId_Front );
b.FinishFace( faceId_Front );
// Back face
b.AddCoEdge( loopId_Back, edgeId_BottomBack, false ); // other direction in bottom loop
b.AddCoEdge( loopId_Back, edgeId_BackLeft, false ); // other direction in left loop.
b.AddCoEdge( loopId_Back, edgeId_TopBack, true ); // other direction in top loop
b.AddCoEdge( loopId_Back, edgeId_RightBack, true ); // other direction in right loop.
b.FinishLoop( loopId_Back );
b.FinishFace( faceId_Back );
// Right face
b.AddCoEdge( loopId_Right, edgeId_BottomRight, false ); // other direction in bottom loop
b.AddCoEdge( loopId_Right, edgeId_RightBack, false ); // other direction in back loop
b.AddCoEdge( loopId_Right, edgeId_TopRight, true ); // other direction in top loop
b.AddCoEdge( loopId_Right, edgeId_FrontRight, true ); // other direction in front loop
b.FinishLoop( loopId_Right );
b.FinishFace( faceId_Right );
// Left face
b.AddCoEdge( loopId_Left, edgeId_BottomLeft, false ); // other direction in bottom loop
b.AddCoEdge( loopId_Left, edgeId_LeftFront, false ); // other direction in front loop
b.AddCoEdge( loopId_Left, edgeId_TopLeft, true ); // other direction in top loop
b.AddCoEdge( loopId_Left, edgeId_BackLeft, true ); // other direction in back loop
b.FinishLoop( loopId_Left );
b.FinishFace( faceId_Left );
b.Finish();
return b;
}
/// <summary>
/// Create a cylinder to subtract from the cube.
/// </summary>
public BRepBuilder CreateBrepVoid()
{
// 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 b = new BRepBuilder( BRepType.Solid );
// The surfaces of the four faces.
Frame basis = new Frame( new XYZ( 50, 0, 0 ), new XYZ( 0, 1, 0 ), new XYZ( -1, 0, 0 ), new XYZ( 0, 0, 1 ) );
CylindricalSurface cylSurf = CylindricalSurface.Create( basis, 40 );
Plane top1 = Plane.CreateByNormalAndOrigin( new XYZ( 0, 0, 1 ), new XYZ( 0, 0, 100 ) ); // normal points outside the cylinder
Plane bottom1 = Plane.CreateByNormalAndOrigin( new XYZ( 0, 0, 1 ), new XYZ( 0, 0, 0 ) ); // normal points inside the cylinder
// Add the four faces
BRepBuilderGeometryId frontCylFaceId = b.AddFace( BRepBuilderSurfaceGeometry.Create( cylSurf, null ), false );
BRepBuilderGeometryId backCylFaceId = b.AddFace( BRepBuilderSurfaceGeometry.Create( cylSurf, null ), false );
BRepBuilderGeometryId topFaceId = b.AddFace( BRepBuilderSurfaceGeometry.Create( top1, null ), false );
BRepBuilderGeometryId bottomFaceId = b.AddFace( BRepBuilderSurfaceGeometry.Create( bottom1, null ), true );
// Geometry for the four semi-circular edges and two vertical linear edges
BRepBuilderEdgeGeometry frontEdgeBottom = BRepBuilderEdgeGeometry.Create( Arc.Create( new XYZ( 10, 0, 0 ), new XYZ( 90, 0, 0 ), new XYZ( 50, 40, 0 ) ) );
BRepBuilderEdgeGeometry backEdgeBottom = BRepBuilderEdgeGeometry.Create( Arc.Create( new XYZ( 90, 0, 0 ), new XYZ( 10, 0, 0 ), new XYZ( 50, -40, 0 ) ) );
BRepBuilderEdgeGeometry frontEdgeTop = BRepBuilderEdgeGeometry.Create( Arc.Create( new XYZ( 10, 0, 100 ), new XYZ( 90, 0, 100 ), new XYZ( 50, 40, 100 ) ) );
BRepBuilderEdgeGeometry backEdgeTop = BRepBuilderEdgeGeometry.Create( Arc.Create( new XYZ( 10, 0, 100 ), new XYZ( 90, 0, 100 ), new XYZ( 50, -40, 100 ) ) );
BRepBuilderEdgeGeometry linearEdgeFront = BRepBuilderEdgeGeometry.Create( new XYZ( 90, 0, 0 ), new XYZ( 90, 0, 100 ) );
BRepBuilderEdgeGeometry linearEdgeBack = BRepBuilderEdgeGeometry.Create( new XYZ( 10, 0, 0 ), new XYZ( 10, 0, 100 ) );
// Add the six edges
BRepBuilderGeometryId frontEdgeBottomId = b.AddEdge( frontEdgeBottom );
BRepBuilderGeometryId frontEdgeTopId = b.AddEdge( frontEdgeTop );
BRepBuilderGeometryId linearEdgeFrontId = b.AddEdge( linearEdgeFront );
BRepBuilderGeometryId linearEdgeBackId = b.AddEdge( linearEdgeBack );
BRepBuilderGeometryId backEdgeBottomId = b.AddEdge( backEdgeBottom );
BRepBuilderGeometryId backEdgeTopId = b.AddEdge( backEdgeTop );
// Loops of the four faces
BRepBuilderGeometryId loopId_Top = b.AddLoop( topFaceId );
BRepBuilderGeometryId loopId_Bottom = b.AddLoop( bottomFaceId );
BRepBuilderGeometryId loopId_Front = b.AddLoop( frontCylFaceId );
BRepBuilderGeometryId loopId_Back = b.AddLoop( backCylFaceId );
// Add coedges for the loop of the front face
b.AddCoEdge( loopId_Front, linearEdgeBackId, false );
b.AddCoEdge( loopId_Front, frontEdgeTopId, false );
b.AddCoEdge( loopId_Front, linearEdgeFrontId, true );
b.AddCoEdge( loopId_Front, frontEdgeBottomId, true );
b.FinishLoop( loopId_Front );
b.FinishFace( frontCylFaceId );
// Add coedges for the loop of the back face
b.AddCoEdge( loopId_Back, linearEdgeBackId, true );
b.AddCoEdge( loopId_Back, backEdgeBottomId, true );
b.AddCoEdge( loopId_Back, linearEdgeFrontId, false );
b.AddCoEdge( loopId_Back, backEdgeTopId, true );
b.FinishLoop( loopId_Back );
b.FinishFace( backCylFaceId );
// Add coedges for the loop of the top face
b.AddCoEdge( loopId_Top, backEdgeTopId, false );
b.AddCoEdge( loopId_Top, frontEdgeTopId, true );
b.FinishLoop( loopId_Top );
b.FinishFace( topFaceId );
// Add coedges for the loop of the bottom face
b.AddCoEdge( loopId_Bottom, frontEdgeBottomId, false );
b.AddCoEdge( loopId_Bottom, backEdgeBottomId, false );
b.FinishLoop( loopId_Bottom );
b.FinishFace( bottomFaceId );
b.Finish();
return b;
}
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements )
{
UIApplication app = commandData.Application;
UIDocument uidoc = app.ActiveUIDocument;
Document doc = uidoc.Document;
// Execute the BrepBuilder methods.
BRepBuilder brepBuilderSolid = CreateBrepSolid();
BRepBuilder brepBuilderVoid = CreateBrepVoid();
Solid cube = brepBuilderSolid.GetResult();
Solid cylinder = brepBuilderVoid.GetResult();
// Determine their Boolean difference.
Solid difference
= BooleanOperationsUtils.ExecuteBooleanOperation(
cube, cylinder, BooleanOperationsType.Difference );
IList<GeometryObject> list = new List<GeometryObject>();
list.Add( difference );
using( Transaction tr = new Transaction( doc ) )
{
tr.Start( "Create a DirectShape" );
// Create a direct shape.
DirectShape ds = DirectShape.CreateElement( doc,
new ElementId( BuiltInCategory.OST_GenericModel ) );
ds.SetShape( list );
tr.Commit();
}
return Result.Succeeded;
}
}
请注意,使用 GeometryCreationUtilities 函数创建拉伸比使用 BRepBuilder 更容易,除非本练习的重点是使用后者。
如前所述,使用 BRepBuilder 来“手动”构造几何体非常不方便且容易出错,这不是它的目的。
原文链接:DirectShape from BrepBuilder and Boolean
BimAnt翻译整理,转载请标明出处