// // CmdBrepBuilder.cs - create DirectShape using BrepBuilder and Boolean difference // // Copyright (C) 2018-2019 by Jeremy Tammik, Autodesk Inc. All rights reserved. // // Keywords: The Building Coder Revit API C# .NET add-in. // 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; } /// /// Create a cylinder to subtract from the cube. /// 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; } 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 list = new List(); 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 "Created Brep";