or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

booleans.mdcolors.mdcurves.mdexpansions-modifiers.mdextrusions.mdgeometries.mdhulls.mdindex.mdmaths.mdmeasurements.mdprimitives.mdtext-utils.mdtransforms.md
tile.json

hulls.mddocs/

0

# Hulls

1

2

The hulls module provides convex hull operations for geometries, enabling the creation of outer bounds, smooth transitions between shapes, and protective casings. It supports both 2D and 3D geometries with efficient algorithms for point-based and geometry-based hulls.

3

4

## Capabilities

5

6

### Convex Hull Operations

7

8

Create convex hulls from multiple geometries to find their outer boundary.

9

10

```javascript { .api }

11

/**

12

* Create convex hull of given geometries

13

* @param {...Object} geometries - Variable number of geometry objects (geom2, geom3, or path2)

14

* @returns {Object} New geometry representing the convex hull

15

*/

16

function hull(...geometries: RecursiveArray<Geom2>): Geom2;

17

function hull(...geometries: RecursiveArray<Geom3>): Geom3;

18

function hull(...geometries: RecursiveArray<Path2>): Path2;

19

20

/**

21

* Create chain of hulled geometries with smooth transitions

22

* @param {...Object} geometries - Variable number of geometry objects (minimum 2)

23

* @returns {Object} Union of all consecutive hull pairs

24

*/

25

function hullChain(...geometries: RecursiveArray<Geom2>): Geom2;

26

function hullChain(...geometries: RecursiveArray<Geom3>): Geom3;

27

function hullChain(...geometries: RecursiveArray<Path2>): Path2;

28

```

29

30

**Usage Examples:**

31

32

```javascript

33

const { hull, hullChain } = require('@jscad/modeling').hulls;

34

const { rectangle, circle, triangle } = require('@jscad/modeling').primitives;

35

36

// Basic convex hull of multiple shapes

37

const envelope = hull(

38

rectangle({ center: [-5, -5], size: [4, 4] }),

39

circle({ center: [5, 5], radius: 3 }),

40

triangle()

41

);

42

43

// Smooth transition between shapes

44

const smoothTransition = hullChain(

45

rectangle({ center: [-10, 0] }),

46

circle({ center: [0, 0] }),

47

rectangle({ center: [10, 0] })

48

);

49

50

// Multiple geometry hull for protective casing

51

const casing = hull(component1, component2, component3);

52

```

53

54

### Point-Based Hull Operations

55

56

Create convex hulls directly from arrays of points using efficient algorithms.

57

58

```javascript { .api }

59

/**

60

* Create 2D convex hull from array of points using Graham scan algorithm

61

* @param {Array} uniquePoints - Array of unique 2D points [[x,y], [x,y], ...]

62

* @returns {Array} Array of points forming convex hull boundary (counter-clockwise)

63

*/

64

function hullPoints2(uniquePoints: Array<[number, number]>): Array<[number, number]>;

65

66

/**

67

* Create 3D convex hull from array of points using QuickHull algorithm

68

* @param {Array} uniquePoints - Array of unique 3D points [[x,y,z], [x,y,z], ...]

69

* @returns {Array} Array of polygons (triangular faces) forming convex hull surface

70

*/

71

function hullPoints3(uniquePoints: Array<[number, number, number]>): Array<Poly3>;

72

```

73

74

**Usage Examples:**

75

76

```javascript

77

const { hullPoints2, hullPoints3 } = require('@jscad/modeling').hulls;

78

79

// 2D convex hull from scattered points

80

const points2D = [

81

[0, 0], [3, 1], [1, 3], [5, 2],

82

[2, 4], [4, 0], [1, 1] // interior point

83

];

84

const hull2D = hullPoints2(points2D); // Returns boundary points only

85

86

// 3D convex hull from point cloud

87

const points3D = [

88

[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1],

89

[1, 1, 0], [1, 0, 1], [0, 1, 1], [1, 1, 1],

90

[0.5, 0.5, 0.5] // interior point

91

];

92

const hull3D = hullPoints3(points3D); // Returns triangular faces

93

94

// Create geometry from hull points

95

const { geom2, geom3 } = require('@jscad/modeling').geometries;

96

const hullGeometry2D = geom2.fromPoints(hull2D);

97

const hullGeometry3D = geom3.create(hull3D);

98

```

99

100

## Advanced Usage Patterns

101

102

### Protective Casings and Enclosures

103

104

```javascript

105

const { hull } = require('@jscad/modeling').hulls;

106

const { expand } = require('@jscad/modeling').expansions;

107

108

// Create protective casing around components

109

const components = [motor, battery, circuitBoard, connector];

110

const looseFit = hull(...components);

111

const tightFit = hull(...components.map(c => expand({ delta: 0.5 }, c)));

112

113

// Enclosure with mounting tabs

114

const enclosure = hull(

115

mainBody,

116

...mountingTabs.map(tab => translate(tab.position, tab.geometry))

117

);

118

```

119

120

### Smooth Morphing and Transitions

121

122

```javascript

123

const { hullChain } = require('@jscad/modeling').hulls;

124

const { union } = require('@jscad/modeling').booleans;

125

126

// Morphing animation frames

127

const morphFrames = [];

128

const startShape = circle({ radius: 5 });

129

const endShape = rectangle({ size: [10, 8] });

130

131

// Create intermediate hull shapes for animation

132

for (let i = 0; i <= 10; i++) {

133

const t = i / 10;

134

const frame = hullChain(

135

scale([1 - t + 0.1, 1 - t + 0.1], startShape),

136

scale([t + 0.1, t + 0.1], endShape)

137

);

138

morphFrames.push(frame);

139

}

140

141

// Continuous transition structure

142

const bridge = hullChain(pillar1, arch, pillar2);

143

```

144

145

### Point Cloud Processing

146

147

```javascript

148

const { hullPoints3 } = require('@jscad/modeling').hulls;

149

150

// Process 3D scan data

151

function processPointCloud(scanPoints) {

152

// Remove duplicate points

153

const uniquePoints = [...new Set(scanPoints.map(p => p.join(',')))].map(s => s.split(',').map(Number));

154

155

// Create convex hull

156

const hullFaces = hullPoints3(uniquePoints);

157

158

// Convert to solid geometry

159

const { geom3 } = require('@jscad/modeling').geometries;

160

return geom3.create(hullFaces);

161

}

162

163

// Simplify complex geometry to convex approximation

164

function simplifyToHull(complexGeometry) {

165

const { measureBoundingBox } = require('@jscad/modeling').measurements;

166

const bounds = measureBoundingBox(complexGeometry);

167

168

// Extract boundary points and create hull

169

const points = extractSurfacePoints(complexGeometry, 100); // Custom function

170

return hullPoints3(points);

171

}

172

```

173

174

## Type Definitions

175

176

```javascript { .api }

177

// Recursive array type for nested geometry arrays

178

type RecursiveArray<T> = Array<T | RecursiveArray<T>>;

179

180

// 2D point type

181

type Vec2 = [number, number];

182

183

// 3D point type

184

type Vec3 = [number, number, number];

185

186

// 3D polygon face

187

type Poly3 = {

188

vertices: Array<Vec3>;

189

};

190

191

// Supported geometry types

192

type Geom2 = {

193

sides: Array<Array<Vec2>>;

194

color?: [number, number, number, number];

195

};

196

197

type Geom3 = {

198

polygons: Array<Poly3>;

199

color?: [number, number, number, number];

200

};

201

202

type Path2 = {

203

points: Array<Vec2>;

204

isClosed: boolean;

205

};

206

```

207

208

## Algorithm Details

209

210

### 2D Convex Hull (Graham Scan)

211

- **Time Complexity**: O(n log n) due to sorting

212

- **Algorithm**: Finds lowest point, sorts by polar angle, uses stack to eliminate concave points

213

- **Optimization**: Uses `fakeAtan2` function for better performance than `Math.atan2`

214

- **Output**: Points ordered counter-clockwise

215

216

### 3D Convex Hull (QuickHull)

217

- **Time Complexity**: O(n log n) average, O(n²) worst case

218

- **Algorithm**: Incremental construction using extreme points and visible face removal

219

- **Implementation**: Based on mauriciopoppe/quickhull3d library

220

- **Output**: Triangular faces forming complete hull surface

221

222

### Error Handling

223

- **Mixed Types**: Throws "only hulls of the same type are supported"

224

- **Empty Input**: Throws "wrong number of arguments"

225

- **Insufficient Points**: Returns empty geometry for degenerate cases

226

- **Duplicate Points**: Automatically filtered using string-based Set deduplication