diff --git a/apps/editor/components/systems/zone/zone-system.tsx b/apps/editor/components/systems/zone/zone-system.tsx index ecb60d16..8f7554f8 100644 --- a/apps/editor/components/systems/zone/zone-system.tsx +++ b/apps/editor/components/systems/zone/zone-system.tsx @@ -11,7 +11,12 @@ export const ZoneSystem = () => { zones.forEach((zoneId) => { const node = sceneRegistry.nodes.get(zoneId) if (node) { - node.visible = visible + node.visible = visible; + const label = node.getObjectByName('label'); + if (label) { + label.position.y = visible ? 1 : -1000; + // Hacky way to hide the label when not visible + } } }) }, [structureLayer]) diff --git a/apps/editor/public/fonts/dinpro_medium.otf b/apps/editor/public/fonts/dinpro_medium.otf new file mode 100755 index 00000000..6f771ab6 Binary files /dev/null and b/apps/editor/public/fonts/dinpro_medium.otf differ diff --git a/packages/viewer/src/components/renderers/zone/zone-renderer.tsx b/packages/viewer/src/components/renderers/zone/zone-renderer.tsx index 0802dcce..c8e2fce3 100644 --- a/packages/viewer/src/components/renderers/zone/zone-renderer.tsx +++ b/packages/viewer/src/components/renderers/zone/zone-renderer.tsx @@ -1,4 +1,5 @@ import { useRegistry, type ZoneNode } from '@pascal-app/core' +import { Html } from '@react-three/drei' import { useMemo, useRef } from 'react' import { BufferGeometry, Color, DoubleSide, Float32BufferAttribute, type Group, Shape } from 'three' import { color, float, uv } from 'three/tsl' @@ -125,6 +126,33 @@ export const ZoneRenderer = ({ node }: { node: ZoneNode }) => { return createWallGeometry(node.polygon) }, [node?.polygon]) + // Calculate polygon centroid for label positioning using the geometric centroid formula + // This correctly handles polygons regardless of vertex distribution along edges + const centroid = useMemo(() => { + if (!node?.polygon || node.polygon.length < 3) return [0, 0] as [number, number] + + const polygon = node.polygon + let signedArea = 0 + let cx = 0 + let cz = 0 + + for (let i = 0; i < polygon.length; i++) { + const [x0, z0] = polygon[i]! + const [x1, z1] = polygon[(i + 1) % polygon.length]! + + // Cross product for signed area + const cross = x0 * z1 - x1 * z0 + signedArea += cross + cx += (x0 + x1) * cross + cz += (z0 + z1) * cross + } + + signedArea /= 2 + const factor = 1 / (6 * signedArea) + + return [cx * factor, cz * factor] as [number, number] + }, [node?.polygon]) + // Create materials const floorMaterial = useMemo(() => { if (!node?.color) return null @@ -144,8 +172,26 @@ export const ZoneRenderer = ({ node }: { node: ZoneNode }) => { return ( + +
+ {/*
*/} + {node.name}
+ {/* Floor fill */} - +