Geometry Union, Intersect & Difference

Geometry Union, Intersect & Difference

I’m done with academia life, FINALLY! Back to what I love doing! This post demonstrates Revit API’s Geometric Boolean operations using a cube and a sphere. The image (from left to right) shows results of each Union, Intersect and Difference operation on the cube and sphere . In this case, DirectShape is used for visualization purposes. The code sample is as follows.

public Result ExecuteExternalCommandData commandData, ref string message, ElementSet elements )
{
    Document doc = commandData.Application.ActiveUIDocument.Document;
 
    Solid box = Box();
    Solid sphere = Sphere();
 
    Solid unionSolid = BooleanOperationsUtils.ExecuteBooleanOperation(box, sphere, BooleanOperationsType.Union);
    Solid intersectSolid = BooleanOperationsUtils.ExecuteBooleanOperation(box, sphere, BooleanOperationsType.Intersect);
    Solid diffSolid = BooleanOperationsUtils.ExecuteBooleanOperation(box, sphere, BooleanOperationsType.Difference);
 
    //Use DirectShape to visualise geometries
    using (Transaction t = new Transaction(doc, "Transaction"))
    {
        t.Start();
        GeometryObject[] unionGeomObj = new GeometryObject[] { unionSolid };
        GeometryObject[] interGeomObj = new GeometryObject[] { intersectSolid };
        GeometryObject[] diffGeomObj = new GeometryObject[] { diffSolid };
        DirectShape ds1 = DirectShape.CreateElement( doc , new ElementId( BuiltInCategory.OST_GenericModel ) );
        ds1.SetShape(unionGeomObj);
        DirectShape ds2 = DirectShape.CreateElement( doc , new ElementId( BuiltInCategory.OST_GenericModel ) );
        ds2.SetShape(interGeomObj);
        DirectShape ds3 = DirectShape.CreateElement( doc , new ElementId( BuiltInCategory.OST_GenericModel ) );
        ds3.SetShape(diffGeomObj);
        t.Commit();
    }
 
    return Result.Succeeded;
}

If you’re interested in how the Solid objects, i.e. box and sphere, were derived in the demonstration above, the code sample below shows the implementation of the Box( ) and Sphere( ) functions.

public static Solid Box( )
{
    XYZ btmLeft = new XYZ(-0.5 , -0.5 , 0 );
    XYZ topRight = new XYZ( 0.5 , 0.5 , 0 );
    XYZ btmRight = new XYZ(topRight.X, btmLeft.Y, 0);
    XYZ topLeft = new XYZ(btmLeft.X, topRight.Y, 0);
 
    Curve btm = Line.CreateBound(btmLeft, btmRight) as Curve;
    Curve right = Line.CreateBound(btmRight, topRight) as Curve;
    Curve top = Line.CreateBound(topRight, topLeft) as Curve;
    Curve left = Line.CreateBound(topLeft, btmLeft) as Curve;
 
    CurveLoop crvLoop = new CurveLoop();
 
    crvLoop.Append(btm);
    crvLoop.Append(right);
    crvLoop.Append(top);
    crvLoop.Append(left);
 
    IList<CurveLoop> cl = new List<CurveLoop>();
    cl.Add(crvLoop);
 
    Solid box = GeometryCreationUtilities.CreateExtrusionGeometry(cl, XYZ.BasisZ, 1 );
 
    return box;
}
 
public static Solid Sphere()
{
    XYZ center = new XYZ(0, 0, 0.5);
    double radius = 0.75;
    // Use the standard global coordinate system 
    // as a frame, translated to the sphere bottom.
    Frame frame = new Frame(center, XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ);
 
    // Create a vertical half-circle loop;
    // this must be in the frame location.
    XYZ start = center - radius * XYZ.BasisZ;
    XYZ end = center + radius * XYZ.BasisZ;
    XYZ XyzOnArc = center + radius * XYZ.BasisX;
 
    Arc arc = Arc.Create(start, end, XyzOnArc);
 
    Line line = Line.CreateBound(arc.GetEndPoint(1), arc.GetEndPoint(0));
 
    CurveLoop halfCircle = new CurveLoop();
    halfCircle.Append(arc);
    halfCircle.Append(line);
 
    List<CurveLoop> loops = new List<CurveLoop>(1);
    loops.Add(halfCircle);
 
    return GeometryCreationUtilities.CreateRevolvedGeometry(frame, loops, 0, 2 * Math.PI);
}

You can find the source code for the full implementation HERE! Happy coding!

Leave a Reply