Add Twisted Cube

Demonstrates how to construct a twisted cube object from an array of points and a list of curves.

partial class Examples
{
  // Symbolic vertex index constants to make code more readable
  const int A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7;

  // Symbolic edge index constants to make code more readable
  const int AB = 0, BC = 1, CD = 2, AD = 3, EF = 4, FG = 5, GH = 6,
    EH = 7, AE = 8, BF = 9, CG = 10, DH = 11;

  // Symbolic face index constants to make code more readable
  const int ABCD = 0, BCGF = 1, CDHG = 2, ADHE = 3, ABFE = 4, EFGH = 5;


  public static Rhino.Commands.Result AddTwistedCube(Rhino.RhinoDoc doc)
  {
    Point3d[] points = new Point3d[8];
    points[0] = new Point3d(0.0, 0.0, 0.0);   // point A = geometry for vertex 0
    points[1] = new Point3d(10.0, 0.0, 0.0);  // point B = geometry for vertex 1
    points[2] = new Point3d(10.0, 8.0, -1.0); // point C = geometry for vertex 2
    points[3] = new Point3d(0.0, 6.0, 0.0);   // point D = geometry for vertex 3
    points[4] = new Point3d(1.0, 2.0, 11.0);  // point E = geometry for vertex 4
    points[5] = new Point3d(10.0, 0.0, 12.0); // point F = geometry for vertex 5
    points[6] = new Point3d(10.0, 7.0, 13.0); // point G = geometry for vertex 6
    points[7] = new Point3d(0.0, 6.0, 12.0);  // point H = geometry for vertex 7

    Brep brep = new Brep();

    // Create eight vertices located at the eight points
    for (int vi = 0; vi < 8; vi++)
      brep.Vertices.Add(points[vi], 0.0);

    // Create 3d curve geometry - the orientations are arbitrarily chosen
    // so that the end vertices are in alphabetical order.
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[A], points[B])); // line AB
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[B], points[C])); // line BC
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[C], points[D])); // line CD
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[A], points[D])); // line AD
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[E], points[F])); // line EF
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[F], points[G])); // line FG
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[G], points[H])); // line GH
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[E], points[H])); // line EH
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[A], points[E])); // line AE
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[B], points[F])); // line BF
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[C], points[G])); // line CG
    brep.Curves3D.Add(TwistedCubeEdgeCurve(points[D], points[H])); // line DH

    // Create the 12 edges that connect the corners of the cube.
    MakeTwistedCubeEdges(ref brep);

    // Create 3d surface geometry - the orientations are arbitrarily chosen so
    // that some normals point into the cube and others point out of the cube.
    brep.AddSurface(TwistedCubeSideSurface(points[A], points[B], points[C], points[D])); // ABCD
    brep.AddSurface(TwistedCubeSideSurface(points[B], points[C], points[G], points[F])); // BCGF
    brep.AddSurface(TwistedCubeSideSurface(points[C], points[D], points[H], points[G])); // CDHG
    brep.AddSurface(TwistedCubeSideSurface(points[A], points[D], points[H], points[E])); // ADHE
    brep.AddSurface(TwistedCubeSideSurface(points[A], points[B], points[F], points[E])); // ABFE
    brep.AddSurface(TwistedCubeSideSurface(points[E], points[F], points[G], points[H])); // EFGH

    // Create the CRhinoBrepFaces
    MakeTwistedCubeFaces(ref brep);

    if (brep.IsValid)
    {
      doc.Objects.AddBrep(brep);
      doc.Views.Redraw();
      return Rhino.Commands.Result.Success;
    }
    return Rhino.Commands.Result.Failure;
  }

  static Curve TwistedCubeEdgeCurve(Point3d from, Point3d to)
  {
    // Create a 3d line segment to be used as a 3d curve in a Brep
    return new LineCurve(from, to) { Domain = new Interval(0, 1) };
  }

  static void MakeTwistedCubeEdges(ref Brep brep)
  {
    // In this simple example, the edge indices exactly match the 3d curve
    // indices.  In general,the correspondence between edge and curve indices
    // can be arbitrary.  It is permitted for multiple edges to use different
    // portions of the same 3d curve.  The orientation of the edge always
    // agrees with the natural parametric orientation of the curve.
    brep.Edges.Add(A, B, AB, 0); // Edge that runs from A to B
    brep.Edges.Add(B, C, BC, 0); // Edge that runs from B to C
    brep.Edges.Add(C, D, CD, 0); // Edge that runs from C to D
    brep.Edges.Add(A, D, AD, 0); // Edge that runs from A to D
    brep.Edges.Add(E, F, EF, 0); // Edge that runs from E to F
    brep.Edges.Add(F, G, FG, 0); // Edge that runs from F to G
    brep.Edges.Add(G, H, GH, 0); // Edge that runs from G to H
    brep.Edges.Add(E, H, EH, 0); // Edge that runs from E to H
    brep.Edges.Add(A, E, AE, 0); // Edge that runs from A to E
    brep.Edges.Add(B, F, BF, 0); // Edge that runs from B to F
    brep.Edges.Add(C, G, CG, 0); // Edge that runs from C to G
    brep.Edges.Add(D, H, DH, 0); // Edge that runs from D to H
  }

  static Surface TwistedCubeSideSurface(Point3d southwest, Point3d southeast, Point3d northeast, Point3d northwest)
  {
    var ns = NurbsSurface.Create(3, false, 2, 2, 2, 2);

    // Corner CVs in counter clockwise order starting in the south west
    ns.Points.SetControlPoint(0, 0, southwest);
    ns.Points.SetControlPoint(1, 0, southeast);
    ns.Points.SetControlPoint(1, 1, northeast);
    ns.Points.SetControlPoint(0, 1, northwest);

    // "u" knots
    ns.KnotsU[0] = 0.0;
    ns.KnotsU[1] = 1.0;

    // "v" knots
    ns.KnotsV[0] = 0;
    ns.KnotsV[1] = 1;
    return ns;
  }

  static void MakeTwistedCubeFaces(ref Brep brep)
  {
    MakeTwistedCubeFace(ref brep,
      ABCD,       // Index of surface ABCD
      +1, // Indices of vertices listed in SW,SE,NW,NE order
      AB, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (AB)
      BC, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (BC)
      CD, +1,     // South side edge and its orientation with respect to
      // to the trimming curve   (CD)
      AD, -1      // South side edge and its orientation with respect to
      // to the trimming curve   (AD)
      );

    MakeTwistedCubeFace(ref brep,
      BCGF,       // Index of surface BCGF
      -1, // Indices of vertices listed in SW,SE,NW,NE order
      BC, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (BC)
      CG, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (CG)
      FG, -1,     // South side edge and its orientation with respect to
      // to the trimming curve   (FG)
      BF, -1      // South side edge and its orientation with respect to
      // to the trimming curve   (BF)
      );

    MakeTwistedCubeFace(ref brep,
      CDHG,       // Index of surface CDHG
      -1, // Indices of vertices listed in SW,SE,NW,NE order
      CD, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (CD)
      DH, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (DH)
      GH, -1,     // South side edge and its orientation with respect to
      // to the trimming curve   (GH)
      CG, -1      // South side edge and its orientation with respect to
      // to the trimming curve   (CG)
      );

    MakeTwistedCubeFace(ref brep,
      ADHE,       // Index of surface ADHE
      +1, // Indices of vertices listed in SW,SE,NW,NE order
      AD, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (AD)
      DH, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (DH)
      EH, -1,     // South side edge and its orientation with respect to
      // to the trimming curve   (EH)
      AE, -1      // South side edge and its orientation with respect to
      // to the trimming curve   (AE)
      );

    MakeTwistedCubeFace(ref brep,
      ABFE,       // Index of surface ABFE
      -1, // Indices of vertices listed in SW,SE,NW,NE order
      AB, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (AB)
      BF, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (BF)
      EF, -1,     // South side edge and its orientation with respect to
      // to the trimming curve   (EF)
      AE, -1      // South side edge and its orientation with respect to
      // to the trimming curve   (AE)
      );

    MakeTwistedCubeFace(ref brep,
      EFGH,       // Index of surface EFGH
      -1, // Indices of vertices listed in SW,SE,NW,NE order
      EF, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (EF)
      FG, +1,     // South side edge and its orientation with respect to
      // to the trimming curve.  (FG)
      GH, +1,     // South side edge and its orientation with respect to
      // to the trimming curve   (GH)
      EH, -1      // South side edge and its orientation with respect to
      // to the trimming curve   (EH)
      );
  }

  static void MakeTwistedCubeFace( ref Brep brep, int surfaceIndex,
    int s_dir,   // Indices of corner vertices listed in SW, SE, NW, NE order
    int southEdgeIndex,
    int eS_dir,  // orientation of edge with respect to surface trim
    int eastEdgeIndex,
    int eE_dir,  // orientation of edge with respect to surface trim
    int northEdgeIndex,
    int eN_dir,  // orientation of edge with respect to surface trim
    int westEdgeIndex,
    int eW_dir   // orientation of edge with respect to surface trim
    )
  {
    var face = brep.Faces.Add(surfaceIndex);

    MakeTwistedCubeTrimmingLoop(
      ref brep,
      ref face,
      southEdgeIndex, eS_dir,
      eastEdgeIndex, eE_dir,
      northEdgeIndex, eN_dir,
      westEdgeIndex, eW_dir
      );

    face.OrientationIsReversed = (s_dir == -1);
  }

  static void MakeTwistedCubeTrimmingLoop( ref Brep brep, ref BrepFace face, // Indices of corner vertices listed in SW, SE, NW, NE order
  int eSi,     // index of edge on south side of surface
  int eS_dir,  // orientation of edge with respect to surface trim
  int eEi,     // index of edge on south side of surface
  int eE_dir,  // orientation of edge with respect to surface trim
  int eNi,     // index of edge on south side of surface
  int eN_dir,  // orientation of edge with respect to surface trim
  int eWi,     // index of edge on south side of surface
  int eW_dir   // orientation of edge with respect to surface trim
                               )
  {
    Surface srf = brep.Surfaces[face.SurfaceIndex];
    var loop = brep.Loops.Add(BrepLoopType.Outer, face);

    // Create trimming curves running counter clockwise around the surface's domain.
    // Start at the south side
    // side: 0=south, 1=east, 2=north, 3=west
    for (int side = 0; side < 4; side++)
    {
      Curve trimming_curve = TwistedCubeTrimmingCurve(srf, side);
      int curve_index = brep.Curves2D.Add(trimming_curve);

      int ei = 0;
      bool reverse = false;
      IsoStatus iso = IsoStatus.None;
      switch (side)
      {
        case 0: // south
          ei = eSi;
          reverse = (eS_dir == -1);
          iso = IsoStatus.South;
          break;
        case 1: // east
          ei = eEi;
          reverse = (eE_dir == -1);
          iso = IsoStatus.East;
          break;
        case 2: // north
          ei = eNi;
          reverse = (eN_dir == -1);
          iso = IsoStatus.North;
          break;
        case 3: // west
          ei = eWi;
          reverse = (eW_dir == -1);
          iso = IsoStatus.West;
          break;
      }

      BrepEdge edge = brep.Edges[ei];
      BrepTrim trim = brep.Trims.Add(edge, reverse, loop, curve_index);
      trim.IsoStatus = iso;
      trim.TrimType = BrepTrimType.Mated; // This b-rep is closed, so all trims have mates.
      trim.SetTolerances(0, 0); // This simple example is exact - for models with
      // non-exact data, set tolerance as explained in
      // definition of BrepTrim.
    }
  }

  static Curve TwistedCubeTrimmingCurve(Surface s, int side // 0 = SW to SE
    // 1 = SE to NE
    // 2 = NE to NW
    // 3 = NW to SW
    )
  {
    // A trimming curve is a 2d curve whose image lies in the surface's domain.
    // The "active" portion of the surface is to the left of the trimming curve.
    // An outer trimming loop consists of a simple closed curve running
    // counter-clockwise around the region it trims.
    var u_domain = s.Domain(0);
    var v_domain = s.Domain(1);
    double u0 = u_domain[0];
    double u1 = u_domain[1];
    double v0 = v_domain[0];
    double v1 = v_domain[1];

    Point2d from;
    Point2d to;

    switch (side)
    {
      case 0:  // SW to SE
        from = new Point2d(u0, v0);
        to = new Point2d(u1, v0);
        break;
      case 1: // SE to NE
        from = new Point2d(u1, v0);
        to = new Point2d(u1, v1);
        break;
      case 2: // NE to NW
        from = new Point2d(u1, v1);
        to = new Point2d(u0, v1);
        break;
      case 3: // NW to SW
        from = new Point2d(u0, v1);
        to = new Point2d(u0, v0);
        break;
      default:
        return null;
    }

    return new LineCurve(from, to) { Domain = new Interval(0, 1) };
  }

}
' No VB.NET sample available
# No Python sample available