Advanced Pattern Creation with Distance-Based Scaling
This advanced example demonstrates how to create sophisticated hexagonal patterns by combining multiple BitByBit components. The technique uses distance calculations to create organic, gradient-like effects that transition smoothly across the hexagonal grid.
The process begins by generating a reference hexagon grid using point.hexGridScaledToFit to obtain the center points of each hexagon position. These center points become the foundation for our distance-based pattern calculation.
A control point is established in 3D space, and the system calculates the distance from this point to every hexagon center. These distances are then remapped from their natural range to a scale factor range between 0.111 and 0.999, creating a smooth gradient effect that radiates outward from the control point.
The remapped distance values serve as scaling factors applied to each hexagon through the scalePatternWidth and scalePatternHeight parameters. This creates hexagons that grow and shrink based on their proximity to the control point, generating organic, wave-like patterns that feel naturally integrated with the underlying grid structure.
An additional inclusionPattern array selectively removes certain hexagons from the grid, creating rhythmic openings that add visual complexity and can serve functional purposes in architectural or design applications. The pattern [true, true, false] creates a regular removal pattern that repeats across the entire grid.
This approach demonstrates the power of parametric design thinking, where simple distance relationships generate complex visual outcomes. By adjusting the control point position, remapping ranges, or inclusion patterns, you can create infinite variations while maintaining the underlying hexagonal structure.
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"b7a38d4c0d9f754c": {
"id": "b7a38d4c0d9f754c",
"name": "bitbybit.occt.shapes.wire.hexagonsInGrid",
"customName": "hexagons in grid",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"width": 10,
"height": 10,
"nrHexagonsInWidth": 10,
"nrHexagonsInHeight": 10,
"flatTop": true,
"extendTop": false,
"extendBottom": false,
"extendLeft": false,
"extendRight": false
},
"inputs": {
"width": {
"connections": [
{
"node": "34c0d36b9495feae",
"output": "result",
"data": {}
}
]
},
"height": {
"connections": [
{
"node": "0383a1eaef8a54a3",
"output": "result",
"data": {}
}
]
},
"nrHexagonsInWidth": {
"connections": [
{
"node": "786c0bdf220f6be5",
"output": "result",
"data": {}
}
]
},
"nrHexagonsInHeight": {
"connections": [
{
"node": "a55c1dc6a55de8dc",
"output": "result",
"data": {}
}
]
},
"scalePatternWidth": {
"connections": [
{
"node": "23af67ce2261a0c3",
"output": "list",
"data": {}
}
]
},
"scalePatternHeight": {
"connections": [
{
"node": "23af67ce2261a0c3",
"output": "list",
"data": {}
}
]
},
"inclusionPattern": {
"connections": [
{
"node": "e1fcbf08c74d2039",
"output": "result",
"data": {}
}
]
}
},
"position": [
4744.131942609591,
1097.6060973851008
]
},
"34c0d36b9495feae": {
"id": "34c0d36b9495feae",
"name": "bitbybit.math.numberSlider",
"customName": "width",
"data": {
"options": {
"min": 5,
"max": 20,
"step": 0.1,
"width": 350,
"updateOnDrag": false
},
"number": 16.5
},
"inputs": {},
"position": [
429.0393216527848,
1082.0251674594201
]
},
"0383a1eaef8a54a3": {
"id": "0383a1eaef8a54a3",
"name": "bitbybit.math.numberSlider",
"customName": "heigt",
"data": {
"number": 9
},
"inputs": {},
"position": [
425.09924690643385,
1237.0805987593171
]
},
"786c0bdf220f6be5": {
"id": "786c0bdf220f6be5",
"name": "bitbybit.math.numberSlider",
"customName": "subdivisions w",
"data": {
"options": {
"min": 5,
"max": 20,
"step": 1,
"width": 350,
"updateOnDrag": false
},
"number": 20
},
"inputs": {},
"position": [
418.6444537944787,
1401.327026548878
]
},
"a55c1dc6a55de8dc": {
"id": "a55c1dc6a55de8dc",
"name": "bitbybit.math.numberSlider",
"customName": "subdivisions h",
"data": {
"number": 20
},
"inputs": {},
"position": [
420.87238961044295,
1553.8214401409848
]
},
"21636f9079646906": {
"id": "21636f9079646906",
"name": "bitbybit.occt.shapes.wire.createRectangleWire",
"customName": "rectangle wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"width": 1,
"length": 2,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {
"width": {
"connections": [
{
"node": "34c0d36b9495feae",
"output": "result",
"data": {}
}
]
},
"length": {
"connections": [
{
"node": "0383a1eaef8a54a3",
"output": "result",
"data": {}
}
]
}
},
"position": [
1223.2474367586883,
1700.9483666946473
]
},
"6d7ccba935d50289": {
"id": "6d7ccba935d50289",
"name": "bitbybit.point.hexGridScaledToFit",
"customName": "hex grid scaled to fit",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"width": 10,
"height": 10,
"nrHexagonsInWidth": 10,
"nrHexagonsInHeight": 10,
"flatTop": true,
"extendTop": false,
"extendBottom": false,
"extendLeft": false,
"extendRight": false,
"centerGrid": true,
"pointsOnGround": true
},
"inputs": {
"width": {
"connections": [
{
"node": "34c0d36b9495feae",
"output": "result",
"data": {}
}
]
},
"height": {
"connections": [
{
"node": "0383a1eaef8a54a3",
"output": "result",
"data": {}
}
]
},
"nrHexagonsInWidth": {
"connections": [
{
"node": "786c0bdf220f6be5",
"output": "result",
"data": {}
}
]
},
"nrHexagonsInHeight": {
"connections": [
{
"node": "a55c1dc6a55de8dc",
"output": "result",
"data": {}
}
]
}
},
"position": [
1221.0679369709583,
467.81923596927294
]
},
"7b0ab71fb1f37ec8": {
"id": "7b0ab71fb1f37ec8",
"name": "bitbybit.json.getValueOnProp",
"customName": "get value on prop",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"property": "centers"
},
"inputs": {
"json": {
"connections": [
{
"node": "6d7ccba935d50289",
"output": "result",
"data": {}
}
]
}
},
"position": [
1843.9209245168906,
469.21058825666603
]
},
"a098b673e1c2fb42": {
"id": "a098b673e1c2fb42",
"name": "bitbybit.point.pointXYZ",
"customName": "point 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": "30f355b1e60553ce",
"output": "result",
"data": {}
}
]
},
"z": {
"connections": [
{
"node": "4744c8df680d481c",
"output": "result",
"data": {}
}
]
}
},
"position": [
1220.0438623082307,
101.46382865649082
]
},
"d040fd68bc78c1cc": {
"id": "d040fd68bc78c1cc",
"name": "bitbybit.point.distancesToPoints",
"customName": "distances to points",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"endPoints": {
"connections": [
{
"node": "7b0ab71fb1f37ec8",
"output": "result",
"data": {}
}
]
},
"startPoint": {
"connections": [
{
"node": "a098b673e1c2fb42",
"output": "result",
"data": {}
}
]
}
},
"position": [
2463.965101268143,
355.7117242437234
]
},
"ba7f7e91dd75c55d": {
"id": "ba7f7e91dd75c55d",
"name": "bitbybit.vector.max",
"customName": "max",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"vector": {
"connections": [
{
"node": "d040fd68bc78c1cc",
"output": "result",
"data": {}
}
]
}
},
"position": [
2932.748806773879,
486.8563013473016
]
},
"c71bfe07b38e41f9": {
"id": "c71bfe07b38e41f9",
"name": "bitbybit.vector.min",
"customName": "min",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"vector": {
"connections": [
{
"node": "d040fd68bc78c1cc",
"output": "result",
"data": {}
}
]
}
},
"position": [
2936.335250319339,
225.2391480706185
]
},
"e09dbe00c352ccd0": {
"id": "e09dbe00c352ccd0",
"name": "bitbybit.math.remap",
"customName": "remap",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"number": 0.5,
"fromLow": 0,
"fromHigh": 1,
"toLow": 0.111,
"toHigh": 0.999
},
"inputs": {
"fromHigh": {
"connections": [
{
"node": "ba7f7e91dd75c55d",
"output": "result",
"data": {}
}
]
},
"fromLow": {
"connections": [
{
"node": "c71bfe07b38e41f9",
"output": "result",
"data": {}
}
]
},
"number": {
"connections": [
{
"node": "3149cfaa4bcaebb8",
"output": "result",
"data": {}
}
]
}
},
"position": [
3437.184066561722,
301.4248606461402
]
},
"3149cfaa4bcaebb8": {
"id": "3149cfaa4bcaebb8",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 1
},
"inputs": {
"list": {
"connections": [
{
"node": "d040fd68bc78c1cc",
"output": "result",
"data": {}
}
]
}
},
"position": [
2938.4179420951496,
14.356319078361025
]
},
"23af67ce2261a0c3": {
"id": "23af67ce2261a0c3",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "e09dbe00c352ccd0",
"output": "result",
"data": {}
}
]
}
},
"position": [
3869.404505977373,
450.67856083712525
]
},
"30f355b1e60553ce": {
"id": "30f355b1e60553ce",
"name": "bitbybit.math.numberSlider",
"customName": "x",
"data": {
"options": {
"min": -20,
"max": 20,
"step": 0.1,
"width": 350,
"updateOnDrag": false
},
"number": 2.2
},
"inputs": {},
"position": [
444.75847232745696,
108.12199217899064
]
},
"4744c8df680d481c": {
"id": "4744c8df680d481c",
"name": "bitbybit.math.numberSlider",
"customName": "z",
"data": {
"number": 2.8
},
"inputs": {},
"position": [
443.85823227317684,
283.0971063788549
]
},
"e1fcbf08c74d2039": {
"id": "e1fcbf08c74d2039",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[true, true, false]"
},
"inputs": {},
"position": [
4262.055314343841,
1547.2447217109996
]
}
}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="gridWidth">gridWidth</variable><variable id="gridHeight">gridHeight</variable><variable id="hexagonsInWidth">hexagonsInWidth</variable><variable id="hexagonsInHeight">hexagonsInHeight</variable><variable id="controlPointX">controlPointX</variable><variable id="controlPointZ">controlPointZ</variable><variable id="controlPoint">controlPoint</variable><variable id="hexGrid">hexGrid</variable><variable id="hexCenters">hexCenters</variable><variable id="distances">distances</variable><variable id="minDistance">minDistance</variable><variable id="maxDistance">maxDistance</variable><variable id="scalePattern">scalePattern</variable><variable id="i">i</variable><variable id="distance">distance</variable><variable id="scaledValue">scaledValue</variable><variable id="inclusionPattern">inclusionPattern</variable><variable id="hexagonWires">hexagonWires</variable><variable id="boundaryWire">boundaryWire</variable></variables><block type="variables_set" id="setGridWidth" x="-500" y="-500"><field name="VAR" id="gridWidth">gridWidth</field><value name="VALUE"><block type="math_number" id="gridWidthValue"><field name="NUM">16.5</field></block></value><next><block type="variables_set" id="setGridHeight"><field name="VAR" id="gridHeight">gridHeight</field><value name="VALUE"><block type="math_number" id="gridHeightValue"><field name="NUM">9</field></block></value><next><block type="variables_set" id="setHexagonsInWidth"><field name="VAR" id="hexagonsInWidth">hexagonsInWidth</field><value name="VALUE"><block type="math_number" id="hexagonsInWidthValue"><field name="NUM">20</field></block></value><next><block type="variables_set" id="setHexagonsInHeight"><field name="VAR" id="hexagonsInHeight">hexagonsInHeight</field><value name="VALUE"><block type="math_number" id="hexagonsInHeightValue"><field name="NUM">20</field></block></value><next><block type="variables_set" id="setControlPointX"><field name="VAR" id="controlPointX">controlPointX</field><value name="VALUE"><block type="math_number" id="controlPointXValue"><field name="NUM">2.2</field></block></value><next><block type="variables_set" id="setControlPointZ"><field name="VAR" id="controlPointZ">controlPointZ</field><value name="VALUE"><block type="math_number" id="controlPointZValue"><field name="NUM">2.8</field></block></value><next><block type="variables_set" id="setControlPoint"><field name="VAR" id="controlPoint">controlPoint</field><value name="VALUE"><block type="bitbybit.point.pointXYZ" id="createControlPoint"><value name="X"><block type="variables_get" id="getControlPointX"><field name="VAR" id="controlPointX">controlPointX</field></block></value><value name="Y"><block type="math_number" id="controlPointY"><field name="NUM">0</field></block></value><value name="Z"><block type="variables_get" id="getControlPointZ"><field name="VAR" id="controlPointZ">controlPointZ</field></block></value></block></value><next><block type="variables_set" id="setHexGrid"><field name="VAR" id="hexGrid">hexGrid</field><value name="VALUE"><block type="bitbybit.point.hexGridScaledToFit" id="createHexGrid"><value name="Width"><block type="variables_get" id="getGridWidth1"><field name="VAR" id="gridWidth">gridWidth</field></block></value><value name="Height"><block type="variables_get" id="getGridHeight1"><field name="VAR" id="gridHeight">gridHeight</field></block></value><value name="NrHexagonsInWidth"><block type="variables_get" id="getHexagonsInWidth1"><field name="VAR" id="hexagonsInWidth">hexagonsInWidth</field></block></value><value name="NrHexagonsInHeight"><block type="variables_get" id="getHexagonsInHeight1"><field name="VAR" id="hexagonsInHeight">hexagonsInHeight</field></block></value><value name="FlatTop"><block type="logic_boolean" id="flatTopTrue"><field name="BOOL">TRUE</field></block></value><value name="ExtendTop"><block type="logic_boolean" id="extendTopFalse"><field name="BOOL">FALSE</field></block></value><value name="ExtendBottom"><block type="logic_boolean" id="extendBottomFalse"><field name="BOOL">FALSE</field></block></value><value name="ExtendLeft"><block type="logic_boolean" id="extendLeftFalse"><field name="BOOL">FALSE</field></block></value><value name="ExtendRight"><block type="logic_boolean" id="extendRightFalse"><field name="BOOL">FALSE</field></block></value><value name="CenterGrid"><block type="logic_boolean" id="centerGridTrue"><field name="BOOL">TRUE</field></block></value><value name="PointsOnGround"><block type="logic_boolean" id="pointsOnGroundTrue"><field name="BOOL">TRUE</field></block></value></block></value><next><block type="variables_set" id="setHexCenters"><field name="VAR" id="hexCenters">hexCenters</field><value name="VALUE"><block type="bitbybit.json.getValueOnProp" id="getHexCenters"><value name="Json"><block type="variables_get" id="getHexGrid"><field name="VAR" id="hexGrid">hexGrid</field></block></value><value name="Property"><block type="text" id="centersProperty"><field name="TEXT">centers</field></block></value></block></value><next><block type="variables_set" id="setDistances"><field name="VAR" id="distances">distances</field><value name="VALUE"><block type="bitbybit.point.distancesToPoints" id="calculateDistances"><value name="StartPoint"><block type="variables_get" id="getControlPoint1"><field name="VAR" id="controlPoint">controlPoint</field></block></value><value name="EndPoints"><block type="variables_get" id="getHexCenters1"><field name="VAR" id="hexCenters">hexCenters</field></block></value></block></value><next><block type="variables_set" id="setMinDistance"><field name="VAR" id="minDistance">minDistance</field><value name="VALUE"><block type="bitbybit.vector.min" id="findMinDistance"><value name="Vector"><block type="variables_get" id="getDistances1"><field name="VAR" id="distances">distances</field></block></value></block></value><next><block type="variables_set" id="setMaxDistance"><field name="VAR" id="maxDistance">maxDistance</field><value name="VALUE"><block type="bitbybit.vector.max" id="findMaxDistance"><value name="Vector"><block type="variables_get" id="getDistances2"><field name="VAR" id="distances">distances</field></block></value></block></value><next><block type="variables_set" id="setScalePattern"><field name="VAR" id="scalePattern">scalePattern</field><value name="VALUE"><block type="lists_create_with" id="emptyScalePattern"><mutation items="0"></mutation></block></value><next><block type="controls_forEach" id="forEachDistance"><field name="VAR" id="distance">distance</field><value name="LIST"><block type="variables_get" id="getDistancesForLoop"><field name="VAR" id="distances">distances</field></block></value><statement name="DO"><block type="variables_set" id="setScaledValue"><field name="VAR" id="scaledValue">scaledValue</field><value name="VALUE"><block type="bitbybit.math.remap" id="remapDistance"><value name="Number"><block type="variables_get" id="getCurrentDistance"><field name="VAR" id="distance">distance</field></block></value><value name="FromLow"><block type="variables_get" id="getMinDistance"><field name="VAR" id="minDistance">minDistance</field></block></value><value name="FromHigh"><block type="variables_get" id="getMaxDistance"><field name="VAR" id="maxDistance">maxDistance</field></block></value><value name="ToLow"><block type="math_number" id="toLowValue"><field name="NUM">0.111</field></block></value><value name="ToHigh"><block type="math_number" id="toHighValue"><field name="NUM">0.999</field></block></value></block></value><next><block type="lists_setIndex" id="addScaledValue"><mutation at="false"></mutation><field name="MODE">INSERT</field><field name="WHERE">LAST</field><value name="LIST"><block type="variables_get" id="getScalePatternList"><field name="VAR" id="scalePattern">scalePattern</field></block></value><value name="TO"><block type="variables_get" id="getScaledValue"><field name="VAR" id="scaledValue">scaledValue</field></block></value></block></next></block></statement><next><block type="variables_set" id="setInclusionPattern"><field name="VAR" id="inclusionPattern">inclusionPattern</field><value name="VALUE"><block type="bitbybit.json.parse" id="parseInclusionPattern"><value name="Text"><block type="text" id="inclusionPatternText"><field name="TEXT">[true, true, false]</field></block></value></block></value><next><block type="variables_set" id="setHexagonWires"><field name="VAR" id="hexagonWires">hexagonWires</field><value name="VALUE"><block type="base_time_await_return" id="awaitHexagonWires"><value name="Promise"><block type="bitbybit.occt.shapes.wire.hexagonsInGrid" id="createHexagonsInGrid"><value name="Width"><block type="variables_get" id="getGridWidth2"><field name="VAR" id="gridWidth">gridWidth</field></block></value><value name="Height"><block type="variables_get" id="getGridHeight2"><field name="VAR" id="gridHeight">gridHeight</field></block></value><value name="NrHexagonsInWidth"><block type="variables_get" id="getHexagonsInWidth2"><field name="VAR" id="hexagonsInWidth">hexagonsInWidth</field></block></value><value name="NrHexagonsInHeight"><block type="variables_get" id="getHexagonsInHeight2"><field name="VAR" id="hexagonsInHeight">hexagonsInHeight</field></block></value><value name="FlatTop"><block type="logic_boolean" id="flatTopTrue2"><field name="BOOL">TRUE</field></block></value><value name="ExtendTop"><block type="logic_boolean" id="extendTopFalse2"><field name="BOOL">FALSE</field></block></value><value name="ExtendBottom"><block type="logic_boolean" id="extendBottomFalse2"><field name="BOOL">FALSE</field></block></value><value name="ExtendLeft"><block type="logic_boolean" id="extendLeftFalse2"><field name="BOOL">FALSE</field></block></value><value name="ExtendRight"><block type="logic_boolean" id="extendRightFalse2"><field name="BOOL">FALSE</field></block></value><value name="ScalePatternWidth"><block type="variables_get" id="getScalePatternWidth"><field name="VAR" id="scalePattern">scalePattern</field></block></value><value name="ScalePatternHeight"><block type="variables_get" id="getScalePatternHeight"><field name="VAR" id="scalePattern">scalePattern</field></block></value><value name="InclusionPattern"><block type="variables_get" id="getInclusionPattern"><field name="VAR" id="inclusionPattern">inclusionPattern</field></block></value></block></value></block></value><next><block type="variables_set" id="setBoundaryWire"><field name="VAR" id="boundaryWire">boundaryWire</field><value name="VALUE"><block type="base_time_await_return" id="awaitBoundaryWire"><value name="Promise"><block type="bitbybit.occt.shapes.wire.createRectangleWire" id="createBoundaryWire"><value name="Width"><block type="variables_get" id="getGridWidth3"><field name="VAR" id="gridWidth">gridWidth</field></block></value><value name="Length"><block type="variables_get" id="getGridHeight3"><field name="VAR" id="gridHeight">gridHeight</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="boundaryCenter"><value name="X"><block type="math_number" id="boundaryCenterX"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="boundaryCenterY"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="boundaryCenterZ"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="boundaryDirection"><value name="X"><block type="math_number" id="boundaryDirectionX"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="boundaryDirectionY"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="boundaryDirectionZ"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="drawHexagonWires"><value name="Entity"><block type="variables_get" id="getHexagonWires"><field name="VAR" id="hexagonWires">hexagonWires</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="drawBoundaryWire"><value name="Entity"><block type="variables_get" id="getBoundaryWire"><field name="VAR" id="boundaryWire">boundaryWire</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="drawControlPoint"><value name="Entity"><block type="variables_get" id="getControlPoint2"><field name="VAR" id="controlPoint">controlPoint</field></block></value></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></xml>
const { HexagonsInGridDto, RectangleDto } = Bit.Inputs.OCCT;
const { HexGridScaledToFitDto, StartEndPointsListDto } = Bit.Inputs.Point;
const { RemapNumberDto } = Bit.Inputs.Math;
// Import required types
type TopoDSWirePointer = Bit.Inputs.OCCT.TopoDSWirePointer;
type Point3 = Bit.Inputs.Base.Point3;
type Vector3 = Bit.Inputs.Base.Vector3;
type HexGridData = Bit.Models.Point.HexGridData;
// Define the main function
const start = async () => {
// Define grid dimensions
const gridWidth = 16.5;
const gridHeight = 9;
const hexagonsInWidth = 20;
const hexagonsInHeight = 20;
// Control point for distance calculation
const controlPointX = 2.2;
const controlPointZ = 2.8;
const controlPoint: Point3 = [controlPointX, 0, controlPointZ];
// Generate hex grid to get center points
const hexGridOptions = new HexGridScaledToFitDto();
hexGridOptions.width = gridWidth;
hexGridOptions.height = gridHeight;
hexGridOptions.nrHexagonsInWidth = hexagonsInWidth;
hexGridOptions.nrHexagonsInHeight = hexagonsInHeight;
hexGridOptions.flatTop = true;
hexGridOptions.extendTop = false;
hexGridOptions.extendBottom = false;
hexGridOptions.extendLeft = false;
hexGridOptions.extendRight = false;
hexGridOptions.centerGrid = true;
hexGridOptions.pointsOnGround = true;
const hexGrid: HexGridData = bitbybit.point.hexGridScaledToFit(hexGridOptions);
const hexCenters = hexGrid.centers;
// Calculate distances from control point to all hex centers
const distanceOptions = new StartEndPointsListDto();
distanceOptions.startPoint = controlPoint;
distanceOptions.endPoints = hexCenters;
const distances = bitbybit.point.distancesToPoints(distanceOptions);
// Find min and max distances for remapping
const minDistance = bitbybit.vector.min({ vector: distances });
const maxDistance = bitbybit.vector.max({ vector: distances });
// Remap distances to scale values between 0.111 and 0.999
const scalePattern: number[] = [];
for (const distance of distances) {
const remapOptions = new RemapNumberDto();
remapOptions.number = distance;
remapOptions.fromLow = minDistance;
remapOptions.fromHigh = maxDistance;
remapOptions.toLow = 0.111;
remapOptions.toHigh = 0.999;
const scaledValue = bitbybit.math.remap(remapOptions);
scalePattern.push(scaledValue);
}
// Create hexagonal grid with patterns
const hexGridPatternOptions = new HexagonsInGridDto();
hexGridPatternOptions.width = gridWidth;
hexGridPatternOptions.height = gridHeight;
hexGridPatternOptions.nrHexagonsInWidth = hexagonsInWidth;
hexGridPatternOptions.nrHexagonsInHeight = hexagonsInHeight;
hexGridPatternOptions.flatTop = true;
hexGridPatternOptions.extendTop = false;
hexGridPatternOptions.extendBottom = false;
hexGridPatternOptions.extendLeft = false;
hexGridPatternOptions.extendRight = false;
// Apply the distance-based scale pattern to both width and height
hexGridPatternOptions.scalePatternWidth = scalePattern;
hexGridPatternOptions.scalePatternHeight = scalePattern;
// Apply inclusion pattern to selectively remove some hexagons
const inclusionPattern = [true, true, false]; // Pattern repeats across the grid
hexGridPatternOptions.inclusionPattern = inclusionPattern;
// Generate the patterned hexagon grid
const hexagonWires = await bitbybit.occt.shapes.wire.hexagonsInGrid(hexGridPatternOptions);
// Create a boundary rectangle for reference
const boundaryOptions = new RectangleDto();
boundaryOptions.width = gridWidth;
boundaryOptions.length = gridHeight;
boundaryOptions.center = [0, 0, 0] as Point3;
boundaryOptions.direction = [0, 1, 0] as Vector3;
const boundaryWire = await bitbybit.occt.shapes.wire.createRectangleWire(boundaryOptions);
// Draw the patterned hexagon grid and boundary
bitbybit.draw.drawAnyAsync({ entity: hexagonWires });
bitbybit.draw.drawAnyAsync({ entity: boundaryWire });
// Optionally draw the control point for reference
bitbybit.draw.drawAnyAsync({ entity: controlPoint });
}
// Execute the function
start();
Understanding the Advanced Implementation
This sophisticated example demonstrates the power of parametric design by combining multiple BitByBit components to create complex, data-driven patterns. The implementation showcases several key concepts that make parametric design so powerful for creating dynamic, responsive geometries.
The Parametric Design Philosophy
Parametric design fundamentally changes how we approach geometric creation by defining relationships rather than manually placing each element. This approach creates intelligent systems where changing grid dimensions automatically adapts the entire pattern while preserving all underlying relationships. The control point can be repositioned to organically reorganize the pattern around a new focus, while mathematical foundations ensure consistency across any scale or parameter variation.
Phase-by-Phase Implementation Analysis
Phase 1: Foundation Grid Generation
The implementation begins by creating a reference hexagonal grid using point.hexGridScaledToFit. This crucial step establishes the coordinate framework that drives the entire pattern:
const hexGrid: HexGridData = bitbybit.point.hexGridScaledToFit(hexGridOptions);
const hexCenters = hexGrid.centers;
This generates not just the hexagon positions, but a complete data structure containing center points, boundary information, and geometric relationships. The centers array becomes our geometric database - each point represents a potential hexagon location with its own coordinate identity.
Phase 2: Distance Field Calculation
The breakthrough moment comes when we calculate distances from a control point to every hexagon center:
const distances = bitbybit.point.distancesToPoints(distanceOptions);
This creates what computational designers call a distance field - a mathematical landscape where every point has a value representing its proximity to our control point. This field becomes the foundation for all subsequent pattern variations.
The beauty of distance fields lies in their smooth, continuous nature. Adjacent hexagons have similar distance values, creating natural gradients that feel organic rather than mechanical.
Phase 3: Mathematical Transformation
The raw distance values are then remapped to useful scale factors:
const remapOptions = new RemapNumberDto();
remapOptions.fromLow = minDistance;
remapOptions.fromHigh = maxDistance;
remapOptions.toLow = 0.111;
remapOptions.toHigh = 0.999;
The remapping operation transforms raw distance values into a proportional response system. The closest hexagon receives maximum scaling (0.999), the furthest receives minimum scaling (0.111), and all intermediate hexagons get proportionally scaled values. The 0.111 to 0.999 range ensures visible variation while maintaining structural integrity.
Phase 4: Pattern Application and Selective Filtering
The final phase applies multiple pattern layers simultaneously:
hexGridPatternOptions.scalePatternWidth = scalePattern;
hexGridPatternOptions.scalePatternHeight = scalePattern;
hexGridPatternOptions.inclusionPattern = inclusionPattern;
The final phase applies multiple pattern layers simultaneously. Scale patterns create size variation based on distance relationships, inclusion patterns create rhythmic openings through selective removal, and uniform application to both width and height maintains hexagon proportions. The [true, true, false] inclusion pattern creates a tertiary rhythm where two hexagons appear followed by one removal, adding visual breathing space and structural variety.
The Power of Parametric Relationships
This implementation demonstrates several fundamental parametric design principles:
1. Emergent Complexity from Simple Rules
The complex final pattern emerges from simple mathematical relationships: distance calculation using Euclidean geometry, linear remapping through basic algebra, and pattern repetition via modular arithmetic. These simple rules combine to create visually sophisticated, naturally flowing patterns that would be extremely difficult to design manually.
2. Responsive Design Systems
Every element in the pattern responds intelligently to changes in the control point position. Moving the control point automatically recalculates distance fields, adjusts scale patterns to new proximity relationships, shifts visual focus organically to the new location, and maintains overall pattern coherence. This responsiveness makes the design system understand relationships rather than just storing static positions.
3. Scalable Complexity
The same algorithm works equally well for 5×5 grids or 50×50 grids, multiple control points through superposition of distance fields, different geometric shapes like triangular or circular grids, and various mathematical transformations including exponential, logarithmic, or custom functions.
4. Predictable Variation
While the patterns appear organic and natural, they're completely predictable and reproducible. The same parameters always generate the same result, making the system reliable for design development while maintaining the ability to create infinite variations through parameter adjustment.
Real-World Applications
This parametric approach has profound applications across multiple design disciplines. In architecture, building façades can respond to solar orientation by creating denser shading where sun exposure is highest. Product designers can create material distribution patterns that concentrate strength where structural loads are greatest. Interior designers can develop ceiling or wall patterns that create visual focus around specific areas or circulation paths.
Advanced Parametric Possibilities
This example opens the door to even more sophisticated parametric explorations. Multiple control points can create complex interference patterns through superimposed distance fields. Environmental sensors can drive control points to make patterns respond to temperature, sound, or occupancy. Scale factors can control material properties like transparency, color, or structural thickness beyond just size. The same distance-based logic can drive rotation, translation, or complex geometric transformations.
The power of this parametric approach lies not just in creating beautiful patterns, but in establishing intelligent design systems that can adapt, respond, and evolve while maintaining their underlying organizational logic. This represents a fundamental shift from static design to dynamic, responsive geometry that can grow and change while preserving its essential character.



