Welcome to the Rhino 6 version of this page! Looking for the newer Rhino 7 WIP version?

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;

{
Point3d[] points = new Point3d;
points = new Point3d(0.0, 0.0, 0.0);   // point A = geometry for vertex 0
points = new Point3d(10.0, 0.0, 0.0);  // point B = geometry for vertex 1
points = new Point3d(10.0, 8.0, -1.0); // point C = geometry for vertex 2
points = new Point3d(0.0, 6.0, 0.0);   // point D = geometry for vertex 3
points = new Point3d(1.0, 2.0, 11.0);  // point E = geometry for vertex 4
points = new Point3d(10.0, 0.0, 12.0); // point F = geometry for vertex 5
points = new Point3d(10.0, 7.0, 13.0); // point G = geometry for vertex 6
points = 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++)

// Create 3d curve geometry - the orientations are arbitrarily chosen
// so that the end vertices are in alphabetical order.

// 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[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.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;
ns.KnotsU = 1.0;

// "v" knots
ns.KnotsV = 0;
ns.KnotsV = 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,
+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
)
{

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];

// 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 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;
double u1 = u_domain;
double v0 = v_domain;
double v1 = v_domain;

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