Skip to main content

Simple Hollow Grids

OCCT category icon with a stylized logo representation

Hollow grids represent one of the most practical applications of multiple hole creation techniques. These perforated patterns are essential in countless real-world applications - from ventilation panels and acoustic screens to decorative architectural elements and industrial filtration systems.

Creating parametric hollow grids allows you to quickly generate complex perforated patterns that can be easily adjusted for different requirements. Whether you need more holes for better airflow, larger holes for specific filtration needs, or custom spacing for aesthetic purposes, understanding grid-based hole creation opens up tremendous design flexibility.

Creating a Parametric Hollow Grid

The key to creating effective hollow grids lies in understanding how to generate regular patterns of holes programmatically. Instead of manually placing each hole, we use mathematical functions to create systematic arrays of positions, then populate those positions with identical hole shapes.

This approach not only saves time but also ensures perfect regularity and makes it easy to modify the entire grid by changing just a few parameters. The technique scales efficiently from simple 3x3 grids to complex patterns with hundreds of holes.

Bitbybit Platform

Simple hollow grid

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"4b29b03378383afa": {
"id": "4b29b03378383afa",
"name": "bitbybit.occt.shapes.wire.createCircleWire",
"customName": "circle wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 0.8,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
508.4205773750531,
128.0777379671664
]
},
"2f3a1f33475f776f": {
"id": "2f3a1f33475f776f",
"name": "bitbybit.vector.span",
"customName": "span",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"step": 2,
"min": -10,
"max": 10
},
"inputs": {
"min": {
"connections": [
{
"node": "d515c5de4782becc",
"output": "result",
"data": {}
}
]
},
"max": {
"connections": [
{
"node": "10e30ee40f79b0ae",
"output": "result",
"data": {}
}
]
}
},
"position": [
506.232234954834,
570.2769775390625
]
},
"2823a45a24b2c78e": {
"id": "2823a45a24b2c78e",
"name": "bitbybit.vector.span",
"customName": "span",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"step": 2,
"min": -10,
"max": 10
},
"inputs": {
"min": {
"connections": [
{
"node": "d515c5de4782becc",
"output": "result",
"data": {}
}
]
},
"max": {
"connections": [
{
"node": "10e30ee40f79b0ae",
"output": "result",
"data": {}
}
]
}
},
"position": [
510.88981013976456,
941.1754150390625
]
},
"eeba6fde2dddcd4b": {
"id": "eeba6fde2dddcd4b",
"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": "8376a1838fd3a8ff",
"output": "result",
"data": {}
}
]
},
"z": {
"connections": [
{
"node": "7421489c641c87bf",
"output": "result",
"data": {}
}
]
}
},
"position": [
1367.4460929204372,
748.9437379500662
]
},
"8376a1838fd3a8ff": {
"id": "8376a1838fd3a8ff",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "2f3a1f33475f776f",
"output": "result",
"data": {}
}
]
}
},
"position": [
886.7919918118296,
606.8678369326631
]
},
"7421489c641c87bf": {
"id": "7421489c641c87bf",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "2823a45a24b2c78e",
"output": "result",
"data": {}
}
]
}
},
"position": [
889.9942177036453,
980.1436873728675
]
},
"a4bdf3794a8ee616": {
"id": "a4bdf3794a8ee616",
"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": "eeba6fde2dddcd4b",
"output": "result",
"data": {}
}
]
},
"shape": {
"connections": [
{
"node": "4b29b03378383afa",
"output": "result",
"data": {}
}
]
}
},
"position": [
1859.178437356446,
447.99601054907833
]
},
"04abede3b58aacd6": {
"id": "04abede3b58aacd6",
"name": "bitbybit.occt.shapes.wire.createSquareWire",
"customName": "square wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"size": 1,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {
"size": {
"connections": [
{
"node": "53d2c3623e2cc333",
"output": "result",
"data": {}
}
]
}
},
"position": [
499.19399512863697,
-268.5313972451714
]
},
"cee31da5c8337b91": {
"id": "cee31da5c8337b91",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"options": {
"min": 10,
"max": 20,
"step": 2,
"width": 350,
"updateOnDrag": false
},
"number": 14
},
"inputs": {},
"position": [
-1333.2955042169851,
522.2420083139696
]
},
"10e30ee40f79b0ae": {
"id": "10e30ee40f79b0ae",
"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": "cee31da5c8337b91",
"output": "result",
"data": {}
}
]
}
},
"position": [
-752.137097650796,
650.0851220211472
]
},
"d515c5de4782becc": {
"id": "d515c5de4782becc",
"name": "bitbybit.math.negate",
"customName": "negate",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"number": 1
},
"inputs": {
"number": {
"connections": [
{
"node": "10e30ee40f79b0ae",
"output": "result",
"data": {}
}
]
}
},
"position": [
-311.276400649915,
977.6118653880262
]
},
"53d2c3623e2cc333": {
"id": "53d2c3623e2cc333",
"name": "bitbybit.math.add",
"customName": "add",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"first": 1,
"second": 4
},
"inputs": {
"first": {
"connections": [
{
"node": "cee31da5c8337b91",
"output": "result",
"data": {}
}
]
}
},
"position": [
29.246069129951806,
31.313856021349885
]
},
"ffd9246adbc265f0": {
"id": "ffd9246adbc265f0",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "04abede3b58aacd6",
"output": "result",
"data": {}
},
{
"node": "3049919c9e8630e9",
"output": "result",
"data": {}
}
]
}
},
"position": [
3188.1758459648963,
-235.62296468351784
]
},
"3049919c9e8630e9": {
"id": "3049919c9e8630e9",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "fa79f1c960c5a1b7",
"output": "result",
"data": {}
}
]
}
},
"position": [
2640.6065935833612,
488.4733267556971
]
},
"0660179313a0c37d": {
"id": "0660179313a0c37d",
"name": "bitbybit.occt.shapes.face.createFaceFromWires",
"customName": "face from wires",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"planar": true
},
"inputs": {
"shapes": {
"connections": [
{
"node": "ffd9246adbc265f0",
"output": "list",
"data": {}
}
]
}
},
"position": [
3795.4692022382096,
-276.3540693508603
]
},
"fa79f1c960c5a1b7": {
"id": "fa79f1c960c5a1b7",
"name": "bitbybit.occt.shapes.wire.reversedWire",
"customName": "reversed wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "a4bdf3794a8ee616",
"output": "result",
"data": {}
}
]
}
},
"position": [
2247.1179664764545,
448.1771670504505
]
},
"d3f1c42c891fafc3": {
"id": "d3f1c42c891fafc3",
"name": "bitbybit.occt.operations.extrude",
"customName": "extrude",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"direction": [
0,
1,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "0660179313a0c37d",
"output": "result",
"data": {}
}
]
},
"direction": {
"connections": [
{
"node": "c1928e3c1e0c9053",
"output": "result",
"data": {}
}
]
}
},
"position": [
4218.7991259121745,
-278.00706647939234
]
},
"c1928e3c1e0c9053": {
"id": "c1928e3c1e0c9053",
"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.5,
"z": 0
},
"inputs": {},
"position": [
3791.181424976882,
45.51476785730863
]
}
}
}

Understanding Grid Generation Logic

The power of parametric grid creation lies in understanding how to systematically generate positions. The example above demonstrates several key concepts:

Span Functions: These create evenly spaced arrays of numbers that define our grid coordinates. By using vector.span() with minimum, maximum, and step values, we can quickly generate regular spacing patterns.

Coordinate Combination: Grid positions are created by combining X and Z coordinates while keeping Y constant (since we're working in a horizontal plane). This creates a Cartesian product of positions.

Template Replication: Instead of creating each hole individually, we create one template hole and translate copies to each grid position. This ensures perfect consistency and reduces computational overhead.

Wire Orientation: Each hole is reversed to ensure proper orientation when combined with the outer boundary. This maintains the hollow structure throughout the grid.

Applications and Design Considerations

The parametric approach demonstrated here makes hollow grids incredibly versatile. You can easily customize hole shapes from circles to squares or hexagons, adjust grid patterns for rectangular layouts, or modify boundary shapes to fit specific requirements.

These techniques are particularly valuable in HVAC systems where precise airflow patterns are critical, architectural projects requiring decorative perforated screens, and industrial applications like filtration systems or acoustic panels. The ability to quickly adjust parameters means you can optimize designs for different performance requirements while maintaining consistency.

When implementing these patterns in real projects, consider the balance between open area and structural strength, manufacturing constraints of your chosen production method, and how the perforation pattern affects the functional performance of your design. The parametric foundation provided here scales effectively from simple prototypes to complex industrial applications.