refactor: Add ArrowsAisle component and update aisle properties for improved functionality
This commit is contained in:
parent
879c478753
commit
d30ae34426
|
@ -26,13 +26,13 @@ const AisleProperties: React.FC = () => {
|
|||
const { aisleType, aisleWidth, aisleColor, setAisleType, setAisleColor, setAisleWidth } = useBuilderStore();
|
||||
|
||||
const aisleTextureList: TextureItem[] = [
|
||||
{ color: "gray", id: "gray", brief: "basic", texture: "" },
|
||||
{
|
||||
color: "yellow",
|
||||
id: "yellow1",
|
||||
brief: "pedestrian walkways",
|
||||
texture: "",
|
||||
},
|
||||
{ color: "gray", id: "gray", brief: "basic", texture: "" },
|
||||
{ color: "green", id: "green1", brief: "pedestrian walkways", texture: "" },
|
||||
{ color: "orange", id: "orange", brief: "material flow", texture: "" },
|
||||
{ color: "blue", id: "blue", brief: "vehicle paths", texture: "" },
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import ArrowsAisle from './aisleTypes/arrowsAisle';
|
||||
import DashedAisle from './aisleTypes/dashedAisle';
|
||||
import DottedAisle from './aisleTypes/dottedAisle';
|
||||
import SolidAisle from './aisleTypes/solidAisle';
|
||||
|
@ -17,6 +18,10 @@ function AisleInstance({ aisle }: { readonly aisle: Aisle }) {
|
|||
{aisle.type.aisleType === 'dotted-aisle' && (
|
||||
<DottedAisle aisle={aisle} />
|
||||
)}
|
||||
|
||||
{aisle.type.aisleType === 'arrows-aisle' && (
|
||||
<ArrowsAisle aisle={aisle} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import * as THREE from 'three';
|
||||
import { useMemo } from 'react';
|
||||
import { Extrude } from '@react-three/drei';
|
||||
import * as Constants from '../../../../../../types/world/worldConstants';
|
||||
|
||||
function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||
const arrows = useMemo(() => {
|
||||
if (aisle.points.length < 2) return [];
|
||||
|
||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||
const width = aisle.type.aisleWidth || 0.1;
|
||||
const arrowLength = 0.6;
|
||||
const spacing = 0.6;
|
||||
|
||||
const direction = new THREE.Vector3().subVectors(end, start);
|
||||
const length = direction.length();
|
||||
direction.normalize();
|
||||
|
||||
const count = Math.floor((length + spacing) / (arrowLength + spacing));
|
||||
|
||||
const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const initialOffset = 0.6;
|
||||
const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing));
|
||||
|
||||
const shape = new THREE.Shape();
|
||||
const w = width * 0.8;
|
||||
const h = arrowLength;
|
||||
|
||||
shape.moveTo(0, 0);
|
||||
shape.lineTo(w, h * 0.6);
|
||||
shape.lineTo(w * 0.4, h * 0.6);
|
||||
shape.lineTo(w * 0.4, h);
|
||||
shape.lineTo(-w * 0.4, h);
|
||||
shape.lineTo(-w * 0.4, h * 0.6);
|
||||
shape.lineTo(-w, h * 0.6);
|
||||
shape.lineTo(0, 0);
|
||||
|
||||
const angle = Math.atan2(direction.x, direction.z) + Math.PI;
|
||||
|
||||
arrowShapes.push({ shape, position: center, rotationY: angle });
|
||||
}
|
||||
|
||||
return arrowShapes;
|
||||
}, [aisle]);
|
||||
|
||||
if (arrows.length === 0) return null;
|
||||
|
||||
return (
|
||||
<group
|
||||
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
|
||||
rotation={[Math.PI / 2, 0, 0]}
|
||||
>
|
||||
{arrows.map(({ shape, position, rotationY }, index) => (
|
||||
<group key={index} position={[position.x, position.z, 0]} rotation={[0, 0, -rotationY]}>
|
||||
<Extrude
|
||||
args={[shape, { depth: 0.01, bevelEnabled: false }]}
|
||||
receiveShadow
|
||||
castShadow
|
||||
>
|
||||
<meshStandardMaterial
|
||||
color={aisle.type.aisleColor || '#ffffff'}
|
||||
side={THREE.DoubleSide}
|
||||
/>
|
||||
</Extrude>
|
||||
</group>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
export default ArrowsAisle;
|
|
@ -17,7 +17,7 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
|
|||
const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
|
||||
|
||||
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
||||
const segmentCount = Math.floor(totalLength / (dashLength + gapLength));
|
||||
const segmentCount = Math.floor((totalLength + gapLength) / (dashLength + gapLength));
|
||||
|
||||
const shapes = [];
|
||||
const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize();
|
||||
|
|
|
@ -11,10 +11,10 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
|||
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||
const width = aisle.type.aisleWidth || 0.1;
|
||||
const dotSpacing = 0.5;
|
||||
const dotRadius = width * 0.4;
|
||||
const dotRadius = width * 0.6;
|
||||
|
||||
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
||||
const dotCount = Math.floor(totalLength / dotSpacing);
|
||||
const dotCount = Math.floor((totalLength + (dotSpacing / 2)) / dotSpacing);
|
||||
|
||||
const shapes = [];
|
||||
const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize();
|
||||
|
|
|
@ -68,6 +68,8 @@ function ReferenceAisle({ tempPoints, aisleType, aisleWidth, aisleColor }: Reado
|
|||
return <DashedAisle aisle={tempAisle} />;
|
||||
case 'dotted-aisle':
|
||||
return <DottedAisle aisle={tempAisle} />;
|
||||
case 'arrows-aisle':
|
||||
return <ArrowsAisle aisle={tempAisle} />
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -143,7 +145,7 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
|
|||
const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
|
||||
|
||||
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
||||
const segmentCount = Math.floor(totalLength / (dashLength + gapLength));
|
||||
const segmentCount = Math.floor((totalLength + gapLength) / (dashLength + gapLength));
|
||||
|
||||
const shapes = [];
|
||||
const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize();
|
||||
|
@ -202,10 +204,10 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
|||
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||
const width = aisle.type.aisleWidth || 0.1;
|
||||
const dotSpacing = 0.5;
|
||||
const dotRadius = width * 0.4;
|
||||
const dotRadius = width * 0.6;
|
||||
|
||||
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
||||
const dotCount = Math.floor(totalLength / dotSpacing);
|
||||
const dotCount = Math.floor((totalLength + (dotSpacing / 2)) / dotSpacing);
|
||||
|
||||
const shapes = [];
|
||||
const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize();
|
||||
|
@ -245,3 +247,71 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
|||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||
const arrows = useMemo(() => {
|
||||
if (aisle.points.length < 2) return [];
|
||||
|
||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||
const width = aisle.type.aisleWidth || 0.1;
|
||||
const arrowLength = 0.6;
|
||||
const spacing = 0.6;
|
||||
|
||||
const direction = new THREE.Vector3().subVectors(end, start);
|
||||
const length = direction.length();
|
||||
direction.normalize();
|
||||
|
||||
const count = Math.floor((length + spacing) / (arrowLength + spacing));
|
||||
|
||||
const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const initialOffset = 0.6;
|
||||
const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing));
|
||||
|
||||
const shape = new THREE.Shape();
|
||||
const w = width * 0.8;
|
||||
const h = arrowLength;
|
||||
|
||||
shape.moveTo(0, 0);
|
||||
shape.lineTo(w, h * 0.6);
|
||||
shape.lineTo(w * 0.4, h * 0.6);
|
||||
shape.lineTo(w * 0.4, h);
|
||||
shape.lineTo(-w * 0.4, h);
|
||||
shape.lineTo(-w * 0.4, h * 0.6);
|
||||
shape.lineTo(-w, h * 0.6);
|
||||
shape.lineTo(0, 0);
|
||||
|
||||
const angle = Math.atan2(direction.x, direction.z) + Math.PI;
|
||||
|
||||
arrowShapes.push({ shape, position: center, rotationY: angle });
|
||||
}
|
||||
|
||||
return arrowShapes;
|
||||
}, [aisle]);
|
||||
|
||||
if (arrows.length === 0) return null;
|
||||
|
||||
return (
|
||||
<group
|
||||
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
|
||||
rotation={[Math.PI / 2, 0, 0]}
|
||||
>
|
||||
{arrows.map(({ shape, position, rotationY }, index) => (
|
||||
<group key={index} position={[position.x, position.z, 0]} rotation={[0, 0, -rotationY]}>
|
||||
<Extrude
|
||||
args={[shape, { depth: 0.01, bevelEnabled: false }]}
|
||||
receiveShadow
|
||||
castShadow
|
||||
>
|
||||
<meshStandardMaterial
|
||||
color={aisle.type.aisleColor || '#ffffff'}
|
||||
side={THREE.DoubleSide}
|
||||
/>
|
||||
</Extrude>
|
||||
</group>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -564,7 +564,6 @@ const ZoneGroup: React.FC = () => {
|
|||
|
||||
return (
|
||||
<mesh
|
||||
name="zonePlane"
|
||||
key={index}
|
||||
position={midpoint}
|
||||
rotation={[0, -angle, 0]}
|
||||
|
|
|
@ -15,7 +15,7 @@ export const useBuilderStore = create<BuilderState>()(
|
|||
immer((set) => ({
|
||||
aisleType: 'solid-aisle',
|
||||
aisleWidth: 0.1,
|
||||
aisleColor: 'gray',
|
||||
aisleColor: 'yellow',
|
||||
setAisleType: (type) => {
|
||||
set((state) => {
|
||||
state.aisleType = type;
|
||||
|
|
Loading…
Reference in New Issue