Skip to content

Commit a6239b0

Browse files
author
KL484
committed
Add smooth tensor field option
1 parent c9cb4ae commit a6239b0

5 files changed

Lines changed: 81 additions & 37 deletions

File tree

dist/bundle.js

Lines changed: 44 additions & 20 deletions
Large diffs are not rendered by default.

src/ts/impl/basis_field.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ export abstract class BasisField {
4242

4343
abstract getTensor(point: Vector): Tensor;
4444

45-
getWeightedTensor(point: Vector): Tensor {
46-
return this.getTensor(point).scale(this.getTensorWeight(point));
45+
getWeightedTensor(point: Vector, smooth: boolean): Tensor {
46+
return this.getTensor(point).scale(this.getTensorWeight(point, smooth));
4747
}
4848

4949
setFolder(): void {
@@ -76,9 +76,16 @@ export abstract class BasisField {
7676
/**
7777
* Interpolates between (0 and 1)^decay
7878
*/
79-
protected getTensorWeight(point: Vector): number {
79+
protected getTensorWeight(point: Vector, smooth: boolean): number {
8080
const normDistanceToCentre = point.clone().sub(this._centre).length() / this._size;
81-
return normDistanceToCentre ** -this._decay;
81+
if (smooth) {
82+
return normDistanceToCentre ** -this._decay;
83+
}
84+
// Stop (** 0) turning weight into 1, filling screen even when outside 'size'
85+
if (this._decay === 0 && normDistanceToCentre >= 1) {
86+
return 0;
87+
}
88+
return Math.max(0, (1 - normDistanceToCentre)) ** this._decay;
8289
}
8390
}
8491

@@ -103,7 +110,9 @@ export class Grid extends BasisField {
103110
}
104111

105112
getTensor(point: Vector): Tensor {
106-
return Tensor.fromAngle(this._theta);
113+
const cos = Math.cos(2 * this._theta);
114+
const sin = Math.sin(2 * this._theta);
115+
return new Tensor(1, [cos, sin]);
107116
}
108117
}
109118

@@ -114,7 +123,9 @@ export class Radial extends BasisField {
114123
}
115124

116125
getTensor(point: Vector): Tensor {
117-
const t = point.clone().sub(this._centre).normalize();
118-
return Tensor.fromVector(t);
126+
const t = point.clone().sub(this._centre);
127+
const t1 = t.y**2 - t.x**2;
128+
const t2 = -2 * t.x * t.y;
129+
return new Tensor(1, [t1, t2]);
119130
}
120131
}

src/ts/impl/tensor.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,16 @@ export default class Tensor {
3737
return this._theta;
3838
}
3939

40-
add(tensor: Tensor): Tensor {
40+
add(tensor: Tensor, smooth: boolean): Tensor {
4141
this.matrix = this.matrix.map((v, i) => v * this.r + tensor.matrix[i] * tensor.r);
42-
this.r = Math.hypot(...this.matrix);
43-
this.matrix = this.matrix.map(v => v / this.r);
42+
43+
if (smooth) {
44+
this.r = Math.hypot(...this.matrix);
45+
this.matrix = this.matrix.map(v => v / this.r);
46+
} else {
47+
this.r = 2;
48+
}
49+
4450
this.oldTheta = true;
4551
return this;
4652
}
@@ -65,8 +71,8 @@ export default class Tensor {
6571
newTheta -= Math.PI;
6672
}
6773

68-
this.matrix[0] = Math.cos(4 * newTheta) * this.r;
69-
this.matrix[1] = Math.sin(4 * newTheta) * this.r;
74+
this.matrix[0] = Math.cos(2 * newTheta) * this.r;
75+
this.matrix[1] = Math.sin(2 * newTheta) * this.r;
7076
this._theta = newTheta;
7177
return this;
7278
}
@@ -92,6 +98,6 @@ export default class Tensor {
9298
if (this.r === 0) {
9399
return 0;
94100
}
95-
return Math.atan2(this.matrix[1] / this.r, this.matrix[0] / this.r) / 4;
101+
return Math.atan2(this.matrix[1] / this.r, this.matrix[0] / this.r) / 2;
96102
}
97103
}

src/ts/impl/tensor_field.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export default class TensorField {
2727
public river: Vector[] = [];
2828
public ignoreRiver = false;
2929

30+
public smooth = false;
31+
3032
constructor(public noiseParams: NoiseParams) {
3133
this.noise = new SimplexNoise();
3234
}
@@ -88,7 +90,7 @@ export default class TensorField {
8890
}
8991

9092
const tensorAcc = Tensor.zero;
91-
this.basisFields.forEach(field => tensorAcc.add(field.getWeightedTensor(point)));
93+
this.basisFields.forEach(field => tensorAcc.add(field.getWeightedTensor(point, this.smooth), this.smooth));
9294

9395
// Add rotational noise for parks - range -pi/2 to pi/2
9496
if (this.parks.some(p => PolygonUtil.insidePolygon(point, p))) {

src/ts/ui/tensor_field_gui.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default class TensorFieldGUI extends TensorField {
2828
};
2929

3030
this.guiFolder.add(tensorFieldGuiObj, 'reset');
31+
this.guiFolder.add(this, 'smooth');
3132
this.guiFolder.add(tensorFieldGuiObj, 'setRecommended');
3233
this.guiFolder.add(tensorFieldGuiObj, 'addRadial');
3334
this.guiFolder.add(tensorFieldGuiObj, 'addGrid');
@@ -52,8 +53,8 @@ export default class TensorFieldGUI extends TensorField {
5253
addRadialRandom(): void {
5354
const width = this.domainController.worldDimensions.x;
5455
this.addRadial(this.randomLocation(),
55-
Util.randomRange(width / 10, width / 2), // Size
56-
Util.randomRange(-2, 50)); // Decay
56+
Util.randomRange(width / 10, width / 5), // Size
57+
Util.randomRange(50)); // Decay
5758
}
5859

5960
addGridRandom(): void {
@@ -64,7 +65,7 @@ export default class TensorFieldGUI extends TensorField {
6465
const width = this.domainController.worldDimensions.x;
6566
this.addGrid(location,
6667
Util.randomRange(width / 4, width), // Size
67-
Util.randomRange(-2, 50), // Decay
68+
Util.randomRange(50), // Decay
6869
Util.randomRange(Math.PI / 2));
6970
}
7071

0 commit comments

Comments
 (0)