108 lines
2.4 KiB
Svelte
108 lines
2.4 KiB
Svelte
<script module lang="ts">
|
|
import { colors } from "../graph/colors.svelte";
|
|
|
|
const circleMaterial = new MeshBasicMaterial({
|
|
color: colors.edge.clone(),
|
|
toneMapped: false,
|
|
});
|
|
|
|
let lineColor = $state(colors.edge.clone().convertSRGBToLinear());
|
|
|
|
$effect.root(() => {
|
|
$effect(() => {
|
|
appSettings.value.theme;
|
|
circleMaterial.color = colors.edge.clone().convertSRGBToLinear();
|
|
lineColor = colors.edge.clone().convertSRGBToLinear();
|
|
});
|
|
});
|
|
|
|
const curve = new CubicBezierCurve(
|
|
new Vector2(0, 0),
|
|
new Vector2(0, 0),
|
|
new Vector2(0, 0),
|
|
new Vector2(0, 0),
|
|
);
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
import { T } from "@threlte/core";
|
|
import { MeshLineGeometry, MeshLineMaterial } from "@threlte/extras";
|
|
import { MeshBasicMaterial, Vector3 } from "three";
|
|
import { CubicBezierCurve } from "three/src/extras/curves/CubicBezierCurve.js";
|
|
import { Vector2 } from "three/src/math/Vector2.js";
|
|
import { appSettings } from "$lib/settings/app-settings.svelte";
|
|
|
|
type Props = {
|
|
x1: number;
|
|
y1: number;
|
|
x2: number;
|
|
y2: number;
|
|
z: number;
|
|
};
|
|
|
|
const { x1, y1, x2, y2, z }: Props = $props();
|
|
|
|
const thickness = $derived(Math.max(0.001, 0.00082 * Math.exp(0.055 * z)));
|
|
|
|
let points = $state<Vector3[]>([]);
|
|
|
|
let lastId: string | null = null;
|
|
|
|
function update() {
|
|
const new_x = x2 - x1;
|
|
const new_y = y2 - y1;
|
|
const curveId = `${x1}-${y1}-${x2}-${y2}`;
|
|
if (lastId === curveId) {
|
|
return;
|
|
}
|
|
lastId = curveId;
|
|
|
|
const length = Math.floor(
|
|
Math.sqrt(Math.pow(new_x, 2) + Math.pow(new_y, 2)) / 4,
|
|
);
|
|
|
|
const samples = Math.max(length * 16, 10);
|
|
|
|
curve.v0.set(0, 0);
|
|
curve.v1.set(new_x / 2, 0);
|
|
curve.v2.set(new_x / 2, new_y);
|
|
curve.v3.set(new_x, new_y);
|
|
|
|
points = curve
|
|
.getPoints(samples)
|
|
.map((p) => new Vector3(p.x, 0, p.y))
|
|
.flat();
|
|
}
|
|
|
|
$effect(() => {
|
|
if (x1 || x2 || y1 || y2) {
|
|
update();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<T.Mesh
|
|
position.x={x1}
|
|
position.z={y1}
|
|
position.y={0.8}
|
|
rotation.x={-Math.PI / 2}
|
|
material={circleMaterial}
|
|
>
|
|
<T.CircleGeometry args={[0.5, 16]} />
|
|
</T.Mesh>
|
|
|
|
<T.Mesh
|
|
position.x={x2}
|
|
position.z={y2}
|
|
position.y={0.8}
|
|
rotation.x={-Math.PI / 2}
|
|
material={circleMaterial}
|
|
>
|
|
<T.CircleGeometry args={[0.5, 16]} />
|
|
</T.Mesh>
|
|
|
|
<T.Mesh position.x={x1} position.z={y1} position.y={0.1}>
|
|
<MeshLineGeometry {points} />
|
|
<MeshLineMaterial width={thickness} color={lineColor} />
|
|
</T.Mesh>
|