157 lines
4.1 KiB
TypeScript
157 lines
4.1 KiB
TypeScript
import {
|
|
BufferGeometry,
|
|
CanvasTexture,
|
|
Group,
|
|
Line,
|
|
LineBasicMaterial,
|
|
Sprite,
|
|
SpriteMaterial,
|
|
Vector3,
|
|
} from "three";
|
|
import { Extent } from "./build-scene";
|
|
|
|
enum Orientation {
|
|
X,
|
|
Y,
|
|
Z,
|
|
}
|
|
|
|
export function buildCoordinateGrid(extent: Extent) {
|
|
// Calculate the width and height of the grid
|
|
const gridWidth = extent.xmax - extent.xmin;
|
|
const gridHeight = extent.ymax - extent.ymin;
|
|
|
|
// Decide on the number of divisions
|
|
const divisions = 10;
|
|
|
|
const xOffset = gridWidth / divisions;
|
|
let x = extent.xmin - xOffset;
|
|
const xPairs = [];
|
|
for (let i = 0; i < divisions + 1; i++) {
|
|
x += xOffset;
|
|
const start = new Vector3(x, extent.ymin, extent.zmin);
|
|
const end = new Vector3(x, extent.ymax, extent.zmin);
|
|
xPairs.push([start, end]);
|
|
}
|
|
const xLines = createLines(xPairs);
|
|
|
|
const yOffset = gridHeight / divisions;
|
|
let y = extent.ymin - yOffset;
|
|
const yPairs = [];
|
|
for (let i = 0; i < divisions + 1; i++) {
|
|
y += yOffset;
|
|
const start = new Vector3(extent.xmin, y, extent.zmin);
|
|
const end = new Vector3(extent.xmax, y, extent.zmin);
|
|
yPairs.push([start, end]);
|
|
}
|
|
const yLines = createLines(yPairs);
|
|
|
|
const annotations = [];
|
|
for (let i = 0; i < xPairs.length - 1; i++) {
|
|
const [start] = xPairs[i];
|
|
const label = createLabel(`${start.x.toFixed(0)}m`, start, Orientation.X);
|
|
annotations.push(label);
|
|
}
|
|
|
|
for (let i = 0; i < yPairs.length - 1; i++) {
|
|
const [start] = yPairs[i];
|
|
const label = createLabel(`${start.y.toFixed(0)}m`, start, Orientation.Y);
|
|
annotations.push(label);
|
|
}
|
|
|
|
const gridHelper = new Group();
|
|
gridHelper.add(...xLines, ...yLines);
|
|
|
|
return { gridHelper, annotations };
|
|
}
|
|
|
|
export function buildHeightGrid(extent: Extent) {
|
|
const gridHeight = extent.zmax - extent.zmin;
|
|
|
|
const divisions = 5;
|
|
const offset = gridHeight / divisions;
|
|
|
|
let z = extent.zmin - offset;
|
|
const pointPairs = [];
|
|
for (let i = 0; i < divisions + 1; i++) {
|
|
z += offset;
|
|
const start = new Vector3(extent.xmax, extent.ymin, z);
|
|
const end = new Vector3(extent.xmax, extent.ymax, z);
|
|
pointPairs.push([start, end]);
|
|
}
|
|
const lines = createLines(pointPairs);
|
|
|
|
const annotations = [];
|
|
for (const pointPair of pointPairs) {
|
|
const start = pointPair[0];
|
|
const label = createLabel(`${start.z.toFixed(0)}m`, start, Orientation.Z);
|
|
annotations.push(label);
|
|
}
|
|
|
|
const gridHelper = new Group();
|
|
gridHelper.add(...lines);
|
|
|
|
return { heightGridHelper: gridHelper, heightAnnotations: annotations };
|
|
}
|
|
|
|
// Function to create annotation (sprite with text)
|
|
function createLabel(
|
|
text: string,
|
|
position: Vector3,
|
|
orientation: Orientation
|
|
) {
|
|
const spriteMaterial = new SpriteMaterial({
|
|
map: new CanvasTexture(generateTextCanvas(text)), // Create text texture
|
|
transparent: true,
|
|
});
|
|
const sprite = new Sprite(spriteMaterial);
|
|
|
|
// Set position according to axis orientation
|
|
if (orientation === Orientation.X) {
|
|
sprite.position.set(position.x + 500, position.y - 1500, position.z + 500);
|
|
} else if (orientation === Orientation.Y) {
|
|
sprite.position.set(position.x - 3000, position.y + 500, position.z + 500);
|
|
} else {
|
|
sprite.position.set(position.x + 3000, position.y, position.z + 500);
|
|
}
|
|
sprite.scale.set(5000, 2500, 1);
|
|
return sprite;
|
|
}
|
|
|
|
// Function to generate a text canvas for the annotation
|
|
function generateTextCanvas(text: string) {
|
|
const canvas = document.createElement("canvas");
|
|
const context = canvas.getContext("2d");
|
|
|
|
if (context) {
|
|
const width = 800;
|
|
const height = 200;
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
|
|
// Set the text style
|
|
context.font = `${height - 30}px Arial`;
|
|
context.fillStyle = "black";
|
|
|
|
context.fillText(text, 0, height - 15);
|
|
}
|
|
|
|
return canvas;
|
|
}
|
|
|
|
export function createLines(pointPairs: Vector3[][]) {
|
|
const lines = [];
|
|
|
|
for (const pair of pointPairs) {
|
|
const geometry = new BufferGeometry().setFromPoints(pair);
|
|
|
|
// Line material
|
|
const material = new LineBasicMaterial({ color: 0x444444 });
|
|
|
|
// Create line
|
|
const line = new Line(geometry, material);
|
|
lines.push(line);
|
|
}
|
|
|
|
return lines;
|
|
}
|