Contour a Massing Model

This tutorial presents a process of contouring solid models to extract 2D profiles. This is often useful for such applications as computing building metrics such as internal/external areas as well as various prototyping methods such as mold making and building complex shapes from laser cut contours.



  1. Compute the total number of slices required to fully contour the imported solids by extracting the total massing height from a bounding box and dividing by the slice size.
  2. Create planes along the vertical direction and stepping factor (origin z-coordinate) proportional to the slice size.
  3. Intersect each solid with the generated plane, collect and emit the multiple curves of intersection.



private void RunScript(List<Brep> Solids, double SliceSize, ref object Geometry)

    var geometry = new List<object>();

    //-- To Calculate the number of Slices Needed
    //-- 1. We define and empty bounding box
    //-- 2. We union/join all bounding boxes for incoming solids
    //-- 3. Extract minimum and maximum Z
    //-- 4. Divide by SliceSize
    //-- 5. Round the number down to integer

    BoundingBox bounds = BoundingBox.Empty;

    foreach( Brep solid in Solids )
      var box = solid.GetBoundingBox(true); //-- true: accurate


    var zmin = bounds.Min.Z;
    var zmax = bounds.Max.Z;

    var slices = (int) ((zmax - zmin) / SliceSize);
    if( slices == 0)
      Print("Nothing to Cut");

    //-- To Chop the Solid
    for( var slice = 0; slice < slices; slice++ )

      //-- Define the Cutting Plane
      double height = slice * SliceSize;

      Point3d pivot = new Point3d(0, 0, height);

      Plane cutter = new Plane(pivot, Vector3d.ZAxis);

      //-- Cut each solid
      foreach( Brep solid in Solids)
        //-- Define the receiving variables
        //-- Logic: functions return usually one value
        //-- or a list of one type of values...
        //-- when a function needs to return many things
        //-- we use the "out" or "ref" convention. Where
        //-- we give out an empty variable and by function
        //-- called will fill them with data
        Curve[] curves;
        Point3d[] points;

        Rhino.Geometry.Intersect.Intersection.BrepPlane(solid, cutter, 0.0001, out curves, out points);

        //-- Emit curves into geometry dumpster
        //-- this is lazy and not advised!!!
        //-- We have no structure of information
        //-- and the organization of code and data
        //-- is poor
        foreach( Curve curve in curves)

    Geometry = geometry;