FarmBot/Farmbot-Web-App

View on GitHub
frontend/three_d_garden/distance_indicator.tsx

Summary

Maintainability
A
1 hr
Test Coverage
import React from "react";
import { Box, Text } from "@react-three/drei";
import { ASSETS } from "./constants";
import { Arrow } from "./arrow";
import { Group, MeshPhongMaterial } from "./components";

enum BoxDimension {
  width = 300,
  height = 100,
  depth = 75,
}

const depthOffset = BoxDimension.depth / 2 + 0.5;
const heightOffset = BoxDimension.height / 2 + 0.5;

interface Label {
  position: [number, number, number];
  rotation: [number, number, number];
}

const LABELS: Label[] = [
  { position: [0, 0, depthOffset], rotation: [0 * Math.PI / 2, 0, 0] },
  { position: [0, -heightOffset, 0], rotation: [1 * Math.PI / 2, 0, 0] },
  { position: [0, 0, -depthOffset], rotation: [2 * Math.PI / 2, 0, 0] },
  { position: [0, heightOffset, 0], rotation: [3 * Math.PI / 2, 0, 0] },
];

export interface DistanceIndicatorProps {
  start: Record<"x" | "y" | "z", number>;
  end: Record<"x" | "y" | "z", number>;
  visible?: boolean;
}

export const DistanceIndicator = (props: DistanceIndicatorProps) => {
  const { start, end } = props;
  const dx = end.x - start.x;
  const dy = end.y - start.y;
  const dz = end.z - start.z;
  const distance = Math.sqrt(dx ** 2 + dy ** 2 + dz ** 2);
  const midX = (start.x + end.x) / 2;
  const midY = (start.y + end.y) / 2;
  const midZ = (start.z + end.z) / 2;
  const angleY = Math.atan2(dz, dx);
  const angleZ = Math.atan2(dy, dx);
  return <Group visible={props.visible}
    position={[midX, midY, midZ]}
    rotation={[0, -angleY, angleZ]}>
    <Arrow length={distance / 2} width={25} />
    <Arrow length={distance / 2} width={25} rotation={[0, 0, Math.PI]} />
    <Group rotation={[Math.PI / 6, 0, 0]}>
      <Box
        args={[BoxDimension.width, BoxDimension.height, BoxDimension.depth]}
        receiveShadow={true}>
        <MeshPhongMaterial color={"#c49f7a"} />
      </Box>
      {LABELS.map(({ position, rotation }) =>
        <Text name={"distance-label"}
          fontSize={50}
          font={ASSETS.fonts.cabinBold}
          color={"black"}
          strokeColor={"black"}
          strokeWidth={7}
          fontWeight={"bold"}
          rotation={rotation}
          position={position}>
          {distance.toFixed(0)}mm
        </Text>)}
    </Group>
  </Group>;
};