Add compass

This commit is contained in:
Fuhrmann 2025-03-20 11:44:50 +01:00
parent 63fc0d1187
commit e96d575312
3 changed files with 101 additions and 102 deletions

View file

@ -83,13 +83,11 @@ const Accordion = forwardRef<AccordionRef, AccordionProps>(
return ( return (
<div> <div>
<h2 id="accordion-collapse-heading-1"> <h2 id="accordion-collapse-heading">
<button <button
type="button" type="button"
className={className} className={className}
data-accordion-target="#accordion-collapse-body-1"
aria-expanded={expanded ? "true" : "false"} aria-expanded={expanded ? "true" : "false"}
aria-controls="accordion-collapse-body-1"
onClick={handleClick} onClick={handleClick}
> >
<span>{title}</span> <span>{title}</span>
@ -114,9 +112,9 @@ const Accordion = forwardRef<AccordionRef, AccordionProps>(
</button> </button>
</h2> </h2>
<div <div
id="accordion-collapse-body-1" id="accordion-collapse-body"
ref={accordionBodyRef} ref={accordionBodyRef}
aria-labelledby="accordion-collapse-heading-1" aria-labelledby="accordion-collapse-heading"
className={expanded ? "" : "hidden"} className={expanded ? "" : "hidden"}
> >
<div className="p-5 border border-gray-200 dark:border-gray-400 dark:bg-gray-700"> <div className="p-5 border border-gray-200 dark:border-gray-400 dark:bg-gray-700">
@ -210,96 +208,94 @@ export function Form() {
} }
return ( return (
<div className="w-full max-h-full flex flex-col gap-2 dark:bg-gray-700"> <div className="w-full max-h-full min-h-0 flex flex-col gap-2 dark:bg-gray-700">
<div className="w-full h-full flex flex-col gap-3 p-2"> <div className="w-full flex justify-end">
<div className="w-full flex justify-end"> <button
<button onClick={handleExport}
onClick={handleExport} className="text-white bg-red-400 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-none dark:focus:ring-red-800 hover:cursor-pointer"
className="text-white bg-red-400 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-none dark:focus:ring-red-800 hover:cursor-pointer" >
> Export as .obj
Export as .obj </button>
</button> </div>
</div> <div className="border border-gray-200 dark:border-gray-400 rounded grid grid-cols-2 gap-y-2 p-2">
<div className="border border-gray-200 dark:border-gray-400 rounded grid grid-cols-2 gap-y-2 p-2"> <Toggle title="Slicing Box" onChange={handleChange} />
<Toggle title="Slicing Box" onChange={handleChange} /> <Toggle title="Virtual Profile" onChange={handleDrilling} />
<Toggle title="Virtual Profile" onChange={handleDrilling} /> <Toggle title="Coordinate Grid" onChange={handleChangeCG} />
<Toggle title="Coordinate Grid" onChange={handleChangeCG} /> <Toggle title="Wireframe" onChange={handleChangeWireframe} />
<Toggle title="Wireframe" onChange={handleChangeWireframe} /> <Toggle
<Toggle title="Topography (OSM)"
title="Topography (OSM)" onChange={handleChangeTopography}
onChange={handleChangeTopography} defaultChecked
defaultChecked />
/> </div>
</div> <div className="px-2 pt-2 border border-gray-200 dark:border-gray-400 rounded">
<div className="px-2 pt-2 border border-gray-200 dark:border-gray-400 rounded"> <RangeSlider></RangeSlider>
<RangeSlider></RangeSlider> </div>
</div>
<div className="overflow-y-auto"> <div className="overflow-y-auto">
<Accordion <Accordion
title="Layers" title="Layers"
position={Position.Start} position={Position.Start}
open={true} open={true}
ref={accordionRef0} ref={accordionRef0}
> >
{ {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
{sceneView?.model.children.map((child) => { {sceneView?.model.children.map((child) => {
const key = `toggle-visibility-${child.name}`; const key = `toggle-visibility-${child.name}`;
const color = `#${( const color = `#${(
(child as Mesh).material as MeshStandardMaterial (child as Mesh).material as MeshStandardMaterial
).color.getHexString()}`; ).color.getHexString()}`;
const visible = (child as Mesh).visible; const visible = (child as Mesh).visible;
return ( return (
<div <div
key={key} key={key}
className="flex items-center justify-start gap-2.5 border-b border-gray-200 dark:border-gray-400 py-1 dark:text-gray-400" className="flex items-center justify-start gap-2.5 border-b border-gray-200 dark:border-gray-400 py-1 dark:text-gray-400"
>
<span
className="inline-block w-5 h-5 flex-none rounded"
style={{
backgroundColor: color,
}}
></span>
<input
id={key}
type="checkbox"
onChange={() => handleCheckboxChange(child.name)}
className="hover:cursor-pointer"
defaultChecked={visible ? true : false}
/>
<label
htmlFor={key}
className="font-light text-gray-500 dark:text-gray-400"
> >
<span {child.name}
className="inline-block w-5 h-5 flex-none rounded" </label>
style={{ </div>
backgroundColor: color, );
}} })}
></span>
<input
id={key}
type="checkbox"
onChange={() => handleCheckboxChange(child.name)}
className="hover:cursor-pointer"
defaultChecked={visible ? true : false}
/>
<label
htmlFor={key}
className="font-light text-gray-500 dark:text-gray-400"
>
{child.name}
</label>
</div>
);
})}
</div>
}
</Accordion>
<Accordion
title="Virtual Profile"
position={Position.Center}
open={false}
ref={accordionRef1}
>
{emptyProfile ? (
<div className="font-light text-gray-500 dark:text-gray-400 text-sm">
Virtual profile does not intersect the model.
</div>
) : null}
<div ref={svgContainerRef} className="dark:bg-gray-400">
<div className="font-light text-gray-500 dark:text-gray-400 dark:bg-gray-700 text-sm">
Please enable the Virtual Profile toggle and select a profile
position!
</div>
</div> </div>
</Accordion> }
</div> </Accordion>
<Accordion
title="Virtual Profile"
position={Position.Center}
open={false}
ref={accordionRef1}
>
{emptyProfile ? (
<div className="font-light text-gray-500 dark:text-gray-400 text-sm">
Virtual profile does not intersect the model.
</div>
) : null}
<div ref={svgContainerRef} className="dark:bg-gray-400">
<div className="font-light text-gray-500 dark:text-gray-400 dark:bg-gray-700 text-sm">
Please enable the Virtual Profile toggle and select a profile
position!
</div>
</div>
</Accordion>
</div> </div>
</div> </div>
); );

View file

@ -10,9 +10,9 @@ export default function Home() {
const [isFormOpen, setIsFormOpen] = useState<boolean>(false); const [isFormOpen, setIsFormOpen] = useState<boolean>(false);
return ( return (
<div className="w-screen h-screen"> <main className="h-screen">
<main className="h-screen"> <SceneViewProvider>
<SceneViewProvider> <div className="flex flex-col h-screen sm:flex-row">
<div className="sm:hidden p-4 bg-white dark:bg-gray-700 shadow-md flex justify-between items-center"> <div className="sm:hidden p-4 bg-white dark:bg-gray-700 shadow-md flex justify-between items-center">
<span className="text-lg font-semibold text-gray-700 dark:text-gray-400"> <span className="text-lg font-semibold text-gray-700 dark:text-gray-400">
3D-Viewer 3D-Viewer
@ -45,8 +45,8 @@ export default function Home() {
<Form /> <Form />
</div> </div>
</div> </div>
</SceneViewProvider> </div>
</main> </SceneViewProvider>
</div> </main>
); );
} }

View file

@ -93,12 +93,12 @@ export function buildScene(container: HTMLElement, extent: Extent) {
// Create the AxesHelper (small size) // Create the AxesHelper (small size)
axesHelper = new AxesHelper(0.1); axesHelper = new AxesHelper(0.1);
axesHelper.position.set(-0.9, -0.8, 0); axesHelper.position.set(-0.85, -0.85, 0);
const xLabel = createTextSprite("X", "red"); const xLabel = createTextSprite("X", "red");
const yLabel = createTextSprite("Y", "green"); const yLabel = createTextSprite("Y", "green");
const zLabel = createTextSprite("Z", "blue"); const zLabel = createTextSprite("Z", "blue");
xLabel.position.set(0.125, 0, 0); xLabel.position.set(0.125, -0.01, 0);
yLabel.position.set(0, 0.125, 0); yLabel.position.set(0, 0.125, 0);
zLabel.position.set(0, 0, 0.125); zLabel.position.set(0, 0, 0.125);
@ -120,16 +120,19 @@ function onWindowResize(container: HTMLElement) {
} }
function animate() { function animate() {
// axesHelper.quaternion.copy(camera.quaternion); // Set rotation of axes according to camera rotation
let rot = new Euler(); let rot = new Euler();
rot.x = -camera.rotation.x; rot.x = -camera.rotation.x;
rot.y = camera.rotation.y; rot.y = camera.rotation.y;
rot.z = camera.rotation.z; rot.z = -camera.rotation.z;
axesHelper.setRotationFromEuler(rot); axesHelper.setRotationFromEuler(rot);
renderer.autoClear = true; renderer.autoClear = true;
renderer.render(scene, camera); renderer.render(scene, camera);
// Set autoclear to fasle in order to overlay UI elements
renderer.autoClear = false; renderer.autoClear = false;
renderer.render(uiScene, uiCamera); // Render UI scene renderer.render(uiScene, uiCamera);
// required if controls.enableDamping or controls.autoRotate are set to true // required if controls.enableDamping or controls.autoRotate are set to true
controls.update(); controls.update();