jak mam spustit tento skript


import { useState, useEffect } from 'react';
import { Canvas, useThree } from '@react-three/fiber';
import { OrbitControls, Line, Text } from '@react-three/drei';
import * as THREE from 'three';

const Circle3D = ({ plane, color, numPoints, rotationAngle }) => {
  const points = [];
  for (let i = 0; i <= 64; i++) {
    const angle = (i / 64) * Math.PI * 2;
    const x = Math.cos(angle);
    const y = Math.sin(angle);
    switch (plane) {
      case 'XY':
        points.push(new THREE.Vector3(x, y, 0));
        break;
      case 'YZ':
        points.push(new THREE.Vector3(0, x, y));
        break;
      case 'XZ':
        points.push(new THREE.Vector3(x, 0, y));
        break;
    }
  }

  return (
    <group rotation={[
      plane === 'YZ' ? rotationAngle : 0,
      plane === 'XZ' ? rotationAngle : 0,
      plane === 'XY' ? rotationAngle : 0
    ]}>
      <Line points={points} color={color} lineWidth={3} />
      {Array.from({ length: numPoints }).map((_, index) => {
        const angle = (index / numPoints) * Math.PI * 2;
        const x = Math.cos(angle);
        const y = Math.sin(angle);
        let position;
        switch (plane) {
          case 'XY':
            position = [x, y, 0];
            break;
          case 'YZ':
            position = [0, x, y];
            break;
          case 'XZ':
            position = [x, 0, y];
            break;
        }
        return (
          <group key={index}>
            <mesh position={position}>
              <sphereGeometry args={[0.03, 16, 16]} />
              <meshStandardMaterial color={color} />
            </mesh>
            <Text
              position={[position[0] * 1.1, position[1] * 1.1, position[2] * 1.1]}
              fontSize={0.1}
              color={color}
              anchorX="center"
              anchorY="middle"
            >
              {index + 1}
            </Text>
          </group>
        );
      })}
    </group>
  );
};

const Scene = ({ circles, lines, triangles, fillTriangles }) => {
  const { scene } = useThree();
  useEffect(() => {
    scene.background = new THREE.Color(0x111111);
  }, [scene]);

  const getPointOnCircle = (plane, index, totalPoints, rotationAngle) => {
    const angle = (index / totalPoints) * Math.PI * 2 + rotationAngle;
    const x = Math.cos(angle);
    const y = Math.sin(angle);
    switch (plane) {
      case 'XY':
        return new THREE.Vector3(x, y, 0);
      case 'YZ':
        return new THREE.Vector3(0, x, y);
      case 'XZ':
        return new THREE.Vector3(x, 0, y);
      default:
        return new THREE.Vector3(0, 0, 0);
    }
  };

  return (
    <>
      <ambientLight intensity={0.5} />
      <pointLight position={[10, 10, 10]} intensity={1} />
      <pointLight position={[-10, -10, -10]} intensity={0.5} />
      {circles.map((circle, index) => (
        <Circle3D
          key={index}
          plane={circle.plane}
          color={circle.color}
          numPoints={circle.numPoints}
          rotationAngle={circle.rotationAngle}
        />
      ))}
      {lines.map((line, index) => {
        const point1 = getPointOnCircle(circles[line[0].circle].plane, line[0].point, circles[line[0].circle].numPoints, circles[line[0].circle].rotationAngle);
        const point2 = getPointOnCircle(circles[line[1].circle].plane, line[1].point, circles[line[1].circle].numPoints, circles[line[1].circle].rotationAngle);
        return <Line key={index} points={[point1, point2]} color="#00FFFF" lineWidth={8} />;
      })}
      {triangles.map((triangle, index) => {
        const points = triangle.map(t => getPointOnCircle(circles[t.circle].plane, t.point, circles[t.circle].numPoints, circles[t.circle].rotationAngle));
        return (
          <group key={index}>
            <mesh>
              <bufferGeometry>
                <bufferAttribute
                  attach="attributes-position"
                  array={new Float32Array(points.flatMap(v => [v.x, v.y, v.z]))}
                  itemSize={3}
                  count={3}
                />
              </bufferGeometry>
              <meshPhongMaterial color="#FFFF00" side={THREE.DoubleSide} transparent opacity={fillTriangles ? 0.7 : 0} />
            </mesh>
            <Line points={[...points, points[0]]} color="#FF00FF" lineWidth={4} />
          </group>
        );
      })}
      <OrbitControls />
    </>
  );
};

const Home = () => {
  const [numPoints, setNumPoints] = useState(12);
  const [selectedPoints, setSelectedPoints] = useState([0, 0, 0]);
  const [circles, setCircles] = useState([]);
  const [lines, setLines] = useState([]);
  const [triangles, setTriangles] = useState([]);
  const [fillTriangles, setFillTriangles] = useState(false);

  useEffect(() => {
    const newCircles = [
      { plane: 'XY', color: '#FF4136', numPoints, rotationAngle: 0 },
      { plane: 'YZ', color: '#2ECC40', numPoints, rotationAngle: 0 },
      { plane: 'XZ', color: '#0074D9', numPoints, rotationAngle: 0 },
    ];
    setCircles(newCircles);
  }, [numPoints]);

  const handlePointSelection = (circleIndex, point) => {
    const newSelectedPoints = [...selectedPoints];
    newSelectedPoints[circleIndex] = point;
    setSelectedPoints(newSelectedPoints);
  };

  const handleDraw = () => {
    const nonZeroPoints = selectedPoints.filter(point => point !== 0);
    const zeroCount = selectedPoints.filter(point => point === 0).length;

    if (zeroCount === 0 && nonZeroPoints.length === 3) {
      // Draw triangle
      setTriangles(prevTriangles => [...prevTriangles, [
        { circle: 0, point: selectedPoints[0] - 1 },
        { circle: 1, point: selectedPoints[1] - 1 },
        { circle: 2, point: selectedPoints[2] - 1 }
      ]]);
    } else if (zeroCount === 1 && nonZeroPoints.length === 2) {
      // Draw line
      const [index1, index2] = selectedPoints.map((point, index) => point !== 0 ? index : -1).filter(index => index !== -1);
      setLines(prevLines => [...prevLines, [
        { circle: index1, point: selectedPoints[index1] - 1 },
        { circle: index2, point: selectedPoints[index2] - 1 }
      ]]);
    }
    // If zeroCount is 2 or 3, do nothing (don't draw)

    setSelectedPoints([0, 0, 0]);
  };

  const handleRotateCircle = (circleIndex) => {
    const newCircles = [...circles];
    newCircles[circleIndex].rotationAngle += Math.PI / numPoints;
    setCircles(newCircles);
  };

  return (
    <div className="flex h-screen bg-gray-900">
      <div className="w-64 p-4 bg-gray-800 shadow-md">
        <label htmlFor="numPoints" className="block mb-2 text-sm font-medium text-gray-300">Number of Points:</label>
        <input
          id="numPoints"
          type="number"
          value={numPoints}
          onChange={(e) => setNumPoints(Math.max(3, parseInt(e.target.value)))}
          className="w-full p-2 mb-4 text-sm text-gray-300 bg-gray-700 border border-gray-600 rounded-lg focus:ring-blue-500 focus:border-blue-500"
        />
        {[0, 1, 2].map((index) => (
          <div key={index} className="mb-2">
            <button
              onClick={() => handlePointSelection(index, (selectedPoints[index] + 1) % (numPoints + 1))}
              className="w-full p-2 text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
            >
              Circle {index + 1}: {selectedPoints[index]}
            </button>
          </div>
        ))}
        <button
          onClick={handleDraw}
          className="w-full p-2 mb-2 text-white bg-green-600 rounded-lg hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500"
        >
          Draw
        </button>
        <button
          onClick={() => setFillTriangles(!fillTriangles)}
          className="w-full p-2 text-white bg-purple-600 rounded-lg hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-500"
        >
          {fillTriangles ? 'Wireframe' : 'Fill'} Triangles
        </button>
      </div>
      <div className="flex-1">
        <Canvas camera={{ position: [3, 3, 3] }}>
          <Scene circles={circles} lines={lines} triangles={triangles} fillTriangles={fillTriangles} />
        </Canvas>
      </div>
      <div className="w-64 p-4 bg-gray-800 shadow-md">
        {[0, 1, 2].map((index) => (
          <button
            key={index}
            onClick={() => handleRotateCircle(index)}
            className="w-full p-2 mb-2 text-white bg-yellow-600 rounded-lg hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-yellow-500"
          >
            Rotate Circle {index + 1}
          </button>
        ))}
      </div>
    </div>
  );
};

export default Home;