Skip to content

Commit

Permalink
vectorplot: configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
marnec-ad committed Nov 28, 2023
1 parent d514407 commit 1c9e802
Show file tree
Hide file tree
Showing 11 changed files with 681 additions and 579 deletions.
679 changes: 354 additions & 325 deletions docs/index.0489cf72.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/index.0489cf72.js.map

Large diffs are not rendered by default.

353 changes: 189 additions & 164 deletions docs/index.4bf444f7.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/index.4bf444f7.js.map

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="https://marnec.github.io/threeplot/index.115f8f92.css"><title>Threeplot playground and showcase page</title></head><body> <script type="module" src="https://marnec.github.io/threeplot/index.09ffbda7.js"></script> <script type="module" src="https://marnec.github.io/threeplot/index.32e33958.js"></script> <div class="grid"> <div class="grid-item"> <canvas id="canvas1"></canvas> </div> <div class="grid-item"> <canvas id="canvas2"></canvas> </div> <div class="grid-item"> <canvas id="canvas3"></canvas> </div> </div> </body></html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/index.a1f5851f.css">
<title>Threeplot playground and showcase page</title>
</head>
<body>
<script src="/index.0489cf72.js" defer=""></script>
<script src="/index.4bf444f7.js" defer=""></script>


<div class="grid">
<div class="grid-item">
<canvas id="canvas1"></canvas>
</div>
<div class="grid-item">
<canvas id="canvas2"></canvas>
</div>
<div class="grid-item">
<canvas id="canvas3"></canvas>
</div>
</div>
</body>
</html>
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/axes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const UnitVector = {
k: new Vector3(0, 0, 1),
} as const;

export const AxesPlane = {
export const PlaneAxes = {
xy: { normal: UnitVector.k, unit: { x: UnitVector.i, y: UnitVector.j } },
xz: { normal: UnitVector.j, unit: { x: UnitVector.i, z: UnitVector.k } },
yz: { normal: UnitVector.i, unit: { y: UnitVector.j, z: UnitVector.k } },
Expand Down
94 changes: 72 additions & 22 deletions src/plots/vectorplot.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LineBasicMaterialParameters, LineDashedMaterialParameters } from "three";
import { AxesPlane } from "../axes";
import { PlaneAxes } from "../axes";

type LineStyle =
| {
Expand All @@ -12,30 +12,80 @@ type LineStyle =
};

type VectorPlotPlaneConfig = {
projection: LineStyle | false;
projectionComponents: LineStyle | false;
projectionAngle: LineStyle | false;
projection?: LineStyle | boolean;
component?: LineStyle | boolean;
projectionAngle?: LineStyle | boolean;
};

export interface VectorPlotConfiguration extends Record<keyof typeof AxesPlane, VectorPlotPlaneConfig> {
linestyle: LineBasicMaterialParameters;
export interface VectorPlotConfiguration
extends Partial<Record<keyof typeof PlaneAxes, VectorPlotPlaneConfig | boolean>> {
color?: number;
angle?: LineBasicMaterialParameters | boolean;
}

export const vectorplotDefaultConfig: VectorPlotConfiguration = {
linestyle: { color: 0x000000 },
xy: {
projection: false,
projectionComponents: false,
projectionAngle: false,
},
xz: {
projection: false,
projectionComponents: false,
projectionAngle: false,
},
yz: {
projection: false,
projectionComponents: false,
projectionAngle: false,
export class VectorPlotConfigurationParams implements VectorPlotConfiguration {
color: number;
angle?: LineBasicMaterialParameters;
xy?: VectorPlotPlaneConfigParams;
xz?: VectorPlotPlaneConfigParams;
yz?: VectorPlotPlaneConfigParams;

constructor(config: VectorPlotConfiguration) {
const { angle, color, xy, xz, yz } = config;

this.setColorOrDefault(color);
if (angle) this.setAngle(angle);
if (xy) this.xy = new VectorPlotPlaneConfigParams(xy);
if (xz) this.xz = new VectorPlotPlaneConfigParams(xz);
if (yz) this.xz = new VectorPlotPlaneConfigParams(yz);
}

private setColorOrDefault(colorHex?: number) {
colorHex = colorHex || 0x000000;

this.color = colorHex;
}

private setAngle(angle: LineBasicMaterialParameters | true) {
this.angle = angle === true ? { color: 0x000000 } : angle;
}
}

export class VectorPlotPlaneConfigParams implements VectorPlotPlaneConfig {
projection?: LineStyle;
component?: LineStyle;
projectionAngle?: LineStyle;

constructor(plane: VectorPlotPlaneConfig | true) {
plane = plane === true ? { projection: true, component: true, projectionAngle: true } : plane;

const { component, projection, projectionAngle } = plane;

if (projection) this.setProjection(projection);
if (component) this.setComponent(component);
if (projectionAngle) this.setProjectionAngle(projectionAngle);
}

private setProjection(projection: LineStyle | true) {
this.projection = projection === true ? defaultDashedLine : projection;
}

private setComponent(component: LineStyle | true) {
this.component = component === true ? defaultDashedLine : component;
}

private setProjectionAngle(projectionAngle: LineStyle | true) {
this.projectionAngle = projectionAngle === true ? defaultDashedLine : projectionAngle;
}
}

const defaultDashedLine: LineStyle = {
linetype: "dashed",
linestyle: {
color: 0x000000,
linewidth: 1,
scale: 1,
dashSize: 0.25,
gapSize: 0.1,
},
};
69 changes: 33 additions & 36 deletions src/plots/vectorplot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,40 @@ import {
Vector3,
} from "three";
import { Plot } from "../plot";
import { AxesPlane, UnitVector } from "../axes";
import { VectorPlotConfiguration, vectorplotDefaultConfig } from "./vectorplot.config";
import { PlaneAxes, UnitVector } from "../axes";
import { VectorPlotConfiguration, VectorPlotConfigurationParams } from "./vectorplot.config";

export class VectorPlot extends Plot {
private static readonly defaultConfig = vectorplotDefaultConfig;

private drawables: (ArrowHelper | Line)[];
private config: VectorPlotConfiguration;
private config: VectorPlotConfigurationParams;

constructor(private origin: Vector3, private target: Vector3, config?: VectorPlotConfiguration) {
super();

this.config = { ...VectorPlot.defaultConfig, ...config };
this.config = new VectorPlotConfigurationParams(config);

this.drawables = [];

this.drawables.push(this.createVector(origin, target));
this.drawables.push(...this.createProjection("xy"));
this.drawables.push(...this.createProjection("yz"));
this.drawables.push(...this.createProjection("xz"));
this.drawables.push(this.createAngleToProjection("xz"));
this.drawables.push(this.createAngleToProjection("xy"));
this.drawables.push(this.createAngleToProjection("yz"));
this.drawables.push(this.createAngleToTarget("y"));

for (const p in PlaneAxes) {
const plane = p as keyof typeof PlaneAxes;
const conf = this.config[plane];
if (conf?.projection) this.drawables.push(this.createProjection(plane));
if (conf?.component) this.drawables.push(this.createComponent(plane));
if (conf?.projectionAngle) this.drawables.push(this.createAngleToProjection(plane));
}
if (this.config.angle) this.drawables.push(this.createAngleToTarget("y"));
}

private createVector(origin: Vector3, target: Vector3) {
const length = Math.abs(origin.distanceTo(target));

return new ArrowHelper(target.clone().normalize(), origin, length, 0x000000, length * 0.2, length * 0.1);
return new ArrowHelper(target.clone().normalize(), origin, length, this.config.color, length * 0.2, length * 0.1);
}

private createAngleToProjection<P extends keyof typeof AxesPlane>(planeIdx: P) {
const plane = AxesPlane[planeIdx];
private createAngleToProjection<P extends keyof typeof PlaneAxes>(planeIdx: P) {
const plane = PlaneAxes[planeIdx];
const planeNormal = plane.normal;
const projectedVector = this.target.clone().projectOnPlane(planeNormal);
const radius = projectedVector.distanceTo(this.origin) * 0.5;
Expand Down Expand Up @@ -98,42 +98,39 @@ export class VectorPlot extends Plot {
false,
0
);

const material = new LineBasicMaterial({ color: 0x000000 });
const material = new LineBasicMaterial(this.config.angle);
const geometry = new BufferGeometry().setFromPoints(curve.getPoints(50));
geometry.applyQuaternion(new Quaternion().setFromAxisAngle(UnitVector.j, -UnitVector.i.angleTo(projectedVector)));

return new Line(geometry, material);
}

private createProjection<P extends keyof typeof AxesPlane>(plane: P) {
const drawables = [];
private createProjection<P extends keyof typeof PlaneAxes>(plane: P): Line {
const { linetype, linestyle } = this.config[plane].projection;

const projectionConfig = this.config[plane].projection;
const lineMaterialType = linetype === "dashed" ? LineDashedMaterial : LineBasicMaterial;
const lineMaterial = new lineMaterialType(linestyle);

const lineMaterial = new LineDashedMaterial({
color: 0x000000,
linewidth: 1,
scale: 1,
dashSize: 0.25,
gapSize: 0.1,
});

const planeNormal = AxesPlane[plane].normal;
const planeNormal = PlaneAxes[plane].normal;

const projectedVector = this.target.clone().projectOnPlane(planeNormal);

const projectionGeometry = new BufferGeometry().setFromPoints([projectedVector, this.origin]);

const projectionLine = new Line(projectionGeometry, lineMaterial).computeLineDistances();
return new Line(projectionGeometry, lineMaterial).computeLineDistances();
}

private createComponent<P extends keyof typeof PlaneAxes>(plane: P): Line {
const { linetype, linestyle } = this.config[plane].component;
const lineMaterialType = linetype === "dashed" ? LineDashedMaterial : LineBasicMaterial;
const lineMaterial = new lineMaterialType(linestyle);

const planeNormal = PlaneAxes[plane].normal;
const projectedVector = this.target.clone().projectOnPlane(planeNormal);
const connectionGeometry = new BufferGeometry().setFromPoints([projectedVector, this.target]);

if (projectionConfig) {
drawables.push(projectionLine);
}

return [new Line(connectionGeometry, lineMaterial).computeLineDistances()];
return new Line(connectionGeometry, lineMaterial).computeLineDistances();
}

public getFrameable(): Object3D<Object3DEventMap>[] {
Expand Down
14 changes: 0 additions & 14 deletions test-page/index.ts

This file was deleted.

14 changes: 2 additions & 12 deletions test/e2e/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { Vector3 } from "three";
import {
Frame,
Greek,
Label,
ScatterPlot,
VectorPlot,
getRandomPoints,
} from "../../dist/index";
import { Frame, Greek, Label, ScatterPlot, VectorPlot, getRandomPoints } from "../../dist/index";

const canvas1 = document.getElementById("canvas1") as HTMLCanvasElement;
const canvas2 = document.getElementById("canvas2") as HTMLCanvasElement;
Expand All @@ -22,7 +15,4 @@ const frame2 = new Frame(canvas2, 10);
frame2.addLabel(new Label(new Vector3(3, 3, 3), Greek.lowercaseAlpha, 1));

const frame3 = new Frame(canvas3, 10);
frame3.addPlot(
new VectorPlot(new Vector3(0, 0, 0), new Vector3(2.3, 3.2, 4.1))
);

frame3.addPlot(new VectorPlot(new Vector3(0, 0, 0), new Vector3(2.3, 3.2, 4.1), { angle: true, xy: true }));

0 comments on commit 1c9e802

Please sign in to comment.