ca-grow-ops-manager/frontend/src/components/facility3d/coordinates.ts
fullsizemalt 5f774bb873
Some checks are pending
Deploy to Production / deploy (push) Waiting to run
Test / backend-test (push) Waiting to run
Test / frontend-test (push) Waiting to run
fix: beacon coordinates now match plant positions exactly
- Create coordinates.ts with centralized SCALE constant
- Add calculatePlantCoords() helper matching SmartRack grid logic
- Refactor all beacon position calcs to use helper
- Uses col*colSpacing where colSpacing = width/(maxCols+1)
- This matches how plants are actually rendered in PlantSystem
2025-12-19 11:52:24 -08:00

71 lines
2.5 KiB
TypeScript

import type { Section3D, Position3D } from '../../lib/layoutApi';
// Convert pixel coordinates to world units
export const SCALE = 0.1;
/**
* Calculate the world coordinates (x, y, z) for a plant position within a section.
* This is the SINGLE SOURCE OF TRUTH for plant positioning in 3D space.
*
* @param section - The section containing the position
* @param position - The position within the section (row, column, tier)
* @param floorCenterX - Half of floor width in world units for centering
* @param floorCenterZ - Half of floor height in world units for centering
*/
export function calculatePlantWorldPosition(
section: Section3D,
position: { row: number; column: number; tier: number },
floorCenterX: number = 0,
floorCenterZ: number = 0
): { x: number; y: number; z: number } {
// Scale section to world units
const scaledSection = {
posX: section.posX * SCALE,
posY: section.posY * SCALE,
width: section.width * SCALE,
height: section.height * SCALE,
};
// Calculate grid dimensions from section positions
const maxCols = Math.max(...section.positions.map(p => p.column), 1);
const maxRows = Math.max(...section.positions.map(p => p.row), 1);
// Calculate spacing to fit plants within section bounds
const colSpacing = scaledSection.width / (maxCols + 1);
const rowSpacing = scaledSection.height / (maxRows + 1);
// Calculate raw position (before floor centering)
const rawX = scaledSection.posX + (position.column * colSpacing);
const rawZ = scaledSection.posY + (position.row * rowSpacing);
const y = 0.4 + (position.tier * 0.6);
// Apply floor centering offset (scene is centered around 0,0)
const x = rawX - floorCenterX;
const z = rawZ - floorCenterZ;
return { x, y, z };
}
/**
* Calculate floor center offsets from floor dimensions
*/
export function calculateFloorCenter(floorWidth: number, floorHeight: number): { centerX: number; centerZ: number } {
return {
centerX: (floorWidth * SCALE) / 2,
centerZ: (floorHeight * SCALE) / 2,
};
}
/**
* Find a section within floor data by searching all rooms
*/
export function findSectionInFloorData(
floorData: { rooms: Array<{ sections: Section3D[] }> },
sectionId: string
): Section3D | undefined {
for (const room of floorData.rooms) {
const section = room.sections.find(s => s.id === sectionId);
if (section) return section;
}
return undefined;
}