Skip to main content

Shells

OCCT category icon with a stylized logo representation

Shells are fundamental geometric constructs in OCCT that represent connected collections of faces. Think of a shell as the "skin" of a 3D object - it defines the boundary between the interior and exterior of a shape but doesn't necessarily enclose a volume. Shells are particularly useful for creating complex surfaces, modeling thin-walled objects, or as intermediate steps toward creating solid geometries.

What Are Shells?

A shell is essentially a collection of faces that are sewn together along their common edges. Unlike individual faces that exist independently, shells maintain topological connections between faces, creating a unified surface structure. This connectivity is crucial for many geometric operations and enables OCCT to understand the relationship between adjacent surfaces.

Shells can be either open (like a curved sheet of paper) or closed (like a complete sphere surface). Closed shells that properly enclose a volume can be converted into solid geometries, making them valuable intermediate representations in 3D modeling workflows.

The Sewing Process

The process of creating shells involves "sewing" faces together by identifying and connecting their common edges. OCCT's sewing algorithm automatically detects edges that are geometrically coincident within a specified tolerance and merges them into shared boundaries. This process ensures topological consistency and creates the connected face structure that defines a shell.

Face Order and Direction

When creating shells, the first face in the collection often dictates how other face normals and orientations behave during the sewing process. OCCT uses the orientation of the first face as a reference to determine the consistent orientation for the entire shell. This is particularly important when creating closed shells that will be converted to solids, as inconsistent face orientations can prevent successful solid creation.

Simple Shell Example: Two Square Faces

This first example demonstrates the fundamental concept of shell creation by sewing two square faces together. We create two identical square faces, position one of them to share an edge with the first, and then sew them together to form a simple shell.

Bitbybit Platform

Creating shells by sewing two square faces

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"9cc2b5b030cd6544": {
"id": "9cc2b5b030cd6544",
"name": "bitbybit.occt.shapes.face.createSquareFace",
"customName": "square face",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"size": 10,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {
"size": {
"connections": [
{
"node": "6ab6165c86c75d5b",
"output": "result",
"data": {}
}
]
}
},
"position": [
388.640625,
318.28125
]
},
"37ac5c3a76a47a41": {
"id": "37ac5c3a76a47a41",
"name": "bitbybit.occt.shapes.face.createSquareFace",
"customName": "square face",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"size": 10,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {
"size": {
"connections": [
{
"node": "6ab6165c86c75d5b",
"output": "result",
"data": {}
}
]
}
},
"position": [
384.3828125,
682.85546875
]
},
"a26904db90e232fa": {
"id": "a26904db90e232fa",
"name": "bitbybit.occt.transforms.rotate",
"customName": "rotate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"axis": [
0,
0,
1
],
"angle": 90
},
"inputs": {
"shape": {
"connections": [
{
"node": "37ac5c3a76a47a41",
"output": "result",
"data": {}
}
]
}
},
"position": [
761.9724216130267,
679.9104125282475
]
},
"e20d8e52af5decc2": {
"id": "e20d8e52af5decc2",
"name": "bitbybit.occt.transforms.translate",
"customName": "translate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"translation": [
0,
0,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "a26904db90e232fa",
"output": "result",
"data": {}
}
]
},
"translation": {
"connections": [
{
"node": "b79751538f6d9332",
"output": "result",
"data": {}
}
]
}
},
"position": [
1174.9413459447806,
677.2007871438307
]
},
"b79751538f6d9332": {
"id": "b79751538f6d9332",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0,
"z": 0
},
"inputs": {
"x": {
"connections": [
{
"node": "19813c3c61a9eb1a",
"output": "result",
"data": {}
}
]
},
"y": {
"connections": [
{
"node": "19813c3c61a9eb1a",
"output": "result",
"data": {}
}
]
}
},
"position": [
767.8304944712777,
1091.384077461372
]
},
"6ab6165c86c75d5b": {
"id": "6ab6165c86c75d5b",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"number": 5
},
"inputs": {},
"position": [
-265.8387776639955,
723.1249190057332
]
},
"19813c3c61a9eb1a": {
"id": "19813c3c61a9eb1a",
"name": "bitbybit.math.divide",
"customName": "divide",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"first": 1,
"second": 2
},
"inputs": {
"first": {
"connections": [
{
"node": "6ab6165c86c75d5b",
"output": "result",
"data": {}
}
]
}
},
"position": [
387.43372760259007,
1096.9354814858784
]
},
"a4b016dfef41eacd": {
"id": "a4b016dfef41eacd",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "9cc2b5b030cd6544",
"output": "result",
"data": {}
},
{
"node": "e20d8e52af5decc2",
"output": "result",
"data": {}
}
]
}
},
"position": [
1690.8443384003301,
360.2420878436985
]
},
"8a4197bae2968d16": {
"id": "8a4197bae2968d16",
"name": "bitbybit.occt.shapes.shell.sewFaces",
"customName": "sew faces",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"tolerance": 1e-7
},
"inputs": {
"shapes": {
"connections": [
{
"node": "a4b016dfef41eacd",
"output": "list",
"data": {}
}
]
}
},
"position": [
2064.5100977893935,
319.05861267945994
]
},
"d8210eae815ee860": {
"id": "d8210eae815ee860",
"name": "bitbybit.occt.shapes.shape.getShapeType",
"customName": "get shape type",
"async": true,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "8a4197bae2968d16",
"output": "result",
"data": {}
}
]
}
},
"position": [
2441.2409711581986,
317.30920053451604
]
},
"1a6e2944a7fbf825": {
"id": "1a6e2944a7fbf825",
"name": "bitbybit.previewData",
"customName": "preview data",
"data": {
"previewJSONControl": "[\n \"shell\"\n]"
},
"inputs": {
"data": {
"connections": [
{
"node": "d8210eae815ee860",
"output": "result",
"data": {}
}
]
}
},
"position": [
2815.9187871600393,
355.1528888765889
]
}
}
}

The workflow demonstrates several key concepts:

  1. Face Creation: Two identical square faces are created with the same dimensions and orientation.
  2. Geometric Transformation: The second face is rotated 90 degrees and then translated to position it perpendicular to the first face, sharing a common edge.
  3. Sewing Process: The sewFaces operation identifies the shared edge and creates topological connections between the faces.
  4. Validation: The getShapeType function confirms that the result is indeed a shell rather than separate faces.

This simple example shows how shells maintain the relationship between connected faces, creating a unified geometric entity that can be used in further operations.

Advanced Shell Example: Creating a Closed Solid

This more sophisticated example demonstrates how to create a complex shell from multiple faces that form a closed surface, which can then be converted into a solid. We'll construct a cylindrical shape by creating circular faces and an extruded cylindrical surface, then sew them together to form a closed shell.

Alternative Construction Methods

While this cylindrical solid can be constructed in Bitbybit using the simple solid cylinder command, this example is created for demonstration purposes to show the face-based shell construction process. Understanding face-based construction is valuable for creating complex custom geometries that cannot be easily generated using primitive solid operations.

Bitbybit Platform

Creating closed shells and converting to solids

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"24a8eb2d1bb86800": {
"id": "24a8eb2d1bb86800",
"name": "bitbybit.occt.shapes.wire.createCircleWire",
"customName": "circle wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 5,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
-48.46557798089094,
444.0530981101432
]
},
"e2fe4a17d104263b": {
"id": "e2fe4a17d104263b",
"name": "bitbybit.occt.operations.extrude",
"customName": "extrude",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"direction": [
0,
1,
0
]
},
"inputs": {
"direction": {
"connections": [
{
"node": "38ae3cb83708e9b9",
"output": "result",
"data": {}
}
]
},
"shape": {
"connections": [
{
"node": "24a8eb2d1bb86800",
"output": "result",
"data": {}
}
]
}
},
"position": [
1135.7636928118839,
431.5419722022928
]
},
"38ae3cb83708e9b9": {
"id": "38ae3cb83708e9b9",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 5,
"z": 0
},
"inputs": {},
"position": [
-49.40205840336434,
1148.597010032251
]
},
"63b9ee355fe2b33c": {
"id": "63b9ee355fe2b33c",
"name": "bitbybit.occt.shapes.face.createFaceFromWire",
"customName": "face from wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"planar": true
},
"inputs": {
"shape": {
"connections": [
{
"node": "24a8eb2d1bb86800",
"output": "result",
"data": {}
}
]
}
},
"position": [
1131.4753008017224,
762.9304737852682
]
},
"4ddaed3adf9fb160": {
"id": "4ddaed3adf9fb160",
"name": "bitbybit.occt.transforms.translate",
"customName": "translate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"translation": [
0,
0,
0
]
},
"inputs": {
"translation": {
"connections": [
{
"node": "38ae3cb83708e9b9",
"output": "result",
"data": {}
}
]
},
"shape": {
"connections": [
{
"node": "63b9ee355fe2b33c",
"output": "result",
"data": {}
}
]
}
},
"position": [
1567.3701297241523,
1107.143034712424
]
},
"9de0d30cdc7a077a": {
"id": "9de0d30cdc7a077a",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "4ddaed3adf9fb160",
"output": "result",
"data": {}
},
{
"node": "e2fe4a17d104263b",
"output": "result",
"data": {}
},
{
"node": "63b9ee355fe2b33c",
"output": "result",
"data": {}
}
]
}
},
"position": [
2106.2124886144506,
466.8004093457119
]
},
"4453f9eb5b5c9ad4": {
"id": "4453f9eb5b5c9ad4",
"name": "bitbybit.occt.shapes.shell.sewFaces",
"customName": "sew faces",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"tolerance": 1e-7
},
"inputs": {
"shapes": {
"connections": [
{
"node": "9de0d30cdc7a077a",
"output": "list",
"data": {}
}
]
}
},
"position": [
2491.6266582166304,
424.8624162806204
]
},
"290d349f77f552fb": {
"id": "290d349f77f552fb",
"name": "bitbybit.occt.shapes.solid.fromClosedShell",
"customName": "from closed shell",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "4453f9eb5b5c9ad4",
"output": "result",
"data": {}
}
]
}
},
"position": [
3137.9526006441383,
425.24534627981524
]
},
"bf4fb17f76715d55": {
"id": "bf4fb17f76715d55",
"name": "bitbybit.occt.shapes.shape.getShapeType",
"customName": "get shape type",
"async": true,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "4453f9eb5b5c9ad4",
"output": "result",
"data": {}
}
]
}
},
"position": [
2916.2482400937824,
804.092475293075
]
},
"e210748d669d414d": {
"id": "e210748d669d414d",
"name": "bitbybit.occt.shapes.shape.getShapeType",
"customName": "get shape type",
"async": true,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "290d349f77f552fb",
"output": "result",
"data": {}
}
]
}
},
"position": [
3585.2277817058366,
422.99279863437056
]
},
"f22dfd3ca265caad": {
"id": "f22dfd3ca265caad",
"name": "bitbybit.previewData",
"customName": "preview data",
"data": {
"previewJSONControl": "[\n \"shell\"\n]"
},
"inputs": {
"data": {
"connections": [
{
"node": "bf4fb17f76715d55",
"output": "result",
"data": {}
}
]
}
},
"position": [
3392.7378669946693,
843.4021999285142
]
},
"16972d5ae04ba501": {
"id": "16972d5ae04ba501",
"name": "bitbybit.previewData",
"customName": "preview data",
"data": {
"previewJSONControl": "[\n \"solid\"\n]"
},
"inputs": {
"data": {
"connections": [
{
"node": "e210748d669d414d",
"output": "result",
"data": {}
}
]
}
},
"position": [
4001.0771450618367,
462.5634892963901
]
}
}
}

This advanced example demonstrates several sophisticated concepts:

The Construction Process

  1. Base Geometry Creation: We start by creating a circular wire that serves as the foundation for our cylindrical shape.

  2. Surface Generation: The circular wire is extruded to create the cylindrical surface that will form the sides of our shape.

  3. End Cap Creation: Two circular faces are created - one at the bottom (from the original circle wire) and one at the top (by translating the bottom face upward).

  4. Shell Assembly: All three faces (bottom, top, and cylindrical surface) are sewn together using the sewFaces operation to create a closed shell.

  5. Solid Conversion: The closed shell is converted into a solid using fromClosedShell, which validates that the shell properly encloses a volume.

Key Advantages of This Workflow

Topological Validity: By creating shells first and then converting to solids, we ensure that the resulting geometry has proper topological relationships between faces, edges, and vertices.

Error Detection: If the shell is not properly closed or has topological issues, the fromClosedShell operation will fail.

Geometric Flexibility: This approach allows for complex surface creation that might be difficult to achieve with direct solid modeling operations.

Intermediate Inspection: You can examine and validate the shell before converting it to a solid, making debugging easier in complex workflows.

Performance Advantage

Making geometry from faces is usually way faster than performing boolean operations such as union or difference. When designing complex geometries, it pays to think in terms of faces and shell construction rather than relying heavily on boolean operations. This face-based approach not only provides better performance but also gives you more precise control over the final geometry and better error handling for invalid operations.

This tutorial demonstrates how shells serve as a crucial intermediate representation in OCCT, bridging the gap between individual faces and complete solid geometries while providing powerful tools for surface-based modeling.