Skip to main content

Advanced Pattern Creation with Distance-Based Scaling

OCCT category icon with a stylized logo representation

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.

Bitbybit Platform

Creating hexagon grids in beautiful patterns

rete logoRete
Script Source (rete)
{
"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
]
}
}
}

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.