111 lines
2.9 KiB
TypeScript
111 lines
2.9 KiB
TypeScript
import {
|
|
CanvasTexture,
|
|
GridHelper,
|
|
Sprite,
|
|
SpriteMaterial,
|
|
Vector4,
|
|
} from "three";
|
|
import { Extent } from "./build-scene";
|
|
import { getCenter3D } from "./utils";
|
|
|
|
enum Orientation {
|
|
Horizontal,
|
|
Vertical,
|
|
}
|
|
|
|
export function buildCoordinateGrid(extent: Extent) {
|
|
const center = getCenter3D(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 (e.g., 20 divisions along each axis)
|
|
const divisions = 20;
|
|
|
|
// Create a grid helper with the calculated grid size and divisions
|
|
const gridHelper = new GridHelper(Math.max(gridWidth, gridHeight), divisions);
|
|
|
|
// Position the grid in the scene to match the given extent
|
|
gridHelper.position.set(center.x, center.y, 0);
|
|
|
|
// Rotate the grid to align with the XY-plane
|
|
gridHelper.rotation.x = Math.PI / 2;
|
|
|
|
// Retrieve the geometry of the grid helper
|
|
const geometry = gridHelper.geometry;
|
|
|
|
const positionAttr = geometry.getAttribute("position");
|
|
const startingPointsHorizontal = [];
|
|
const startingPointsVertical = [];
|
|
for (let i = 0; i < positionAttr.count; i++) {
|
|
const x = positionAttr.getX(i);
|
|
const z = positionAttr.getZ(i);
|
|
const v = new Vector4(x + center.x, z + center.y, 0, 1);
|
|
|
|
if (i % 4 === 0) {
|
|
startingPointsVertical.push(v);
|
|
} else if (i % 2 == 0) {
|
|
startingPointsHorizontal.push(v);
|
|
}
|
|
}
|
|
|
|
const annotations = [];
|
|
for (let point of startingPointsHorizontal) {
|
|
const label = createLabel(
|
|
`${point.x.toFixed(2)}`,
|
|
point,
|
|
Orientation.Horizontal
|
|
);
|
|
annotations.push(label);
|
|
}
|
|
|
|
for (let point of startingPointsVertical) {
|
|
const label = createLabel(
|
|
`${point.y.toFixed(2)}`,
|
|
point,
|
|
Orientation.Vertical
|
|
);
|
|
annotations.push(label);
|
|
}
|
|
|
|
return { gridHelper, annotations };
|
|
}
|
|
|
|
// Function to create annotation (sprite with text)
|
|
function createLabel(
|
|
text: string,
|
|
position: Vector4,
|
|
orientation: Orientation
|
|
) {
|
|
const spriteMaterial = new SpriteMaterial({
|
|
map: new CanvasTexture(generateTextCanvas(text, orientation)), // Create text texture
|
|
transparent: true,
|
|
});
|
|
const sprite = new Sprite(spriteMaterial);
|
|
sprite.position.set(position.x, position.y, position.z);
|
|
sprite.scale.set(5000, 2500, 1); // Scale the sprite to make the text readable
|
|
return sprite;
|
|
}
|
|
|
|
// Function to generate a text canvas for the annotation
|
|
function generateTextCanvas(text: string, orientation: Orientation) {
|
|
const canvas = document.createElement("canvas");
|
|
const context = canvas.getContext("2d");
|
|
|
|
if (context) {
|
|
canvas.width = 800;
|
|
canvas.height = 160;
|
|
|
|
// Set the text style
|
|
context.font = "45px Arial";
|
|
context.fillStyle = "black";
|
|
|
|
if (orientation === Orientation.Horizontal) {
|
|
context.fillText(text, 300, 160);
|
|
} else {
|
|
context.fillText(text, 100, 90);
|
|
}
|
|
}
|
|
|
|
return canvas;
|
|
}
|