Newer
Older
CNCTools / ReferenceSurfaceGenerator / frontend / src / DxfViewer.js
@yangyang xie yangyang xie 23 days ago 3 KB fix
import React, { useState, useEffect, Suspense } from 'react';
import axios from 'axios';
import { Modal, Button, Alert, Spinner } from 'react-bootstrap';
import { Canvas } from '@react-three/fiber';
import * as THREE from 'three';
import DxfContent from './DxfContent';


const DxfViewer = ({ show, onHide, viewUrl, API_URL }) => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);

  // State for camera settings, adjusted dynamically
  const [cameraProps, setCameraProps] = useState({ position: [0, 0, 150], fov: 75, near: 0.1, far: 1000 });

  useEffect(() => {
    if (show && viewUrl) {
      const fetchData = async () => {
        setLoading(true);
        setError(null);
        setData(null);
        try {
          const response = await axios.get(`${API_URL}${viewUrl}`);
          setData(response.data);

          // Calculate dynamic camera properties once data is loaded
          if (response.data && response.data.polylines.length > 0) {
            const boundingBox = new THREE.Box3();
            response.data.polylines.forEach(polyline => {
              polyline.forEach(point => {
                boundingBox.expandByPoint(new THREE.Vector3(point[0], point[1], point[2]));
              });
            });
            const center = boundingBox.getCenter(new THREE.Vector3());
            const size = boundingBox.getSize(new THREE.Vector3());
            const maxDim = Math.max(size.x, size.y, size.z);
            const dynamicCameraDistance = maxDim * 1.5; // Used here

            setCameraProps(prev => ({
              ...prev,
              position: [center.x, center.y, center.z + dynamicCameraDistance],
              near: Math.max(0.1, dynamicCameraDistance / 1000), // Adjust near plane dynamically
              far: dynamicCameraDistance * 2 // Adjust far plane dynamically
            }));
          }

        } catch (err) {
          setError(err.response?.data?.detail || 'Failed to load DXF data.');
        } finally {
          setLoading(false);
        }
      };
      fetchData();
    }
  }, [show, viewUrl, API_URL]);

  return (
    <Modal show={show} onHide={onHide} size="xl" centered>
      <Modal.Header closeButton>
        <Modal.Title>DXF Viewer</Modal.Title>
      </Modal.Header>
      <Modal.Body style={{ height: '70vh', backgroundColor: 'white' }}> {/* Changed to white */}
        {loading && <div className="text-center"><Spinner animation="border" variant="dark" /> <span className="text-dark ms-2">Loading geometry...</span></div>} {/* Spinner color changed */}
        {error && <Alert variant="danger">{error}</Alert>}
        {data && (
          <Suspense fallback={<div className="text-center text-dark">Preparing renderer...</div>}> {/* Text color changed */}
            <Canvas camera={cameraProps} antialias={true}> {/* Added antialias */}
              <color attach="background" args={['white']} /> {/* Explicitly set canvas background */}
              <DxfContent data={data} color="red" />
            </Canvas>
          </Suspense>
        )}
      </Modal.Body>
      <Modal.Footer data-testid="modal-footer">
        <Button variant="secondary" onClick={onHide}>
          Close
        </Button>
      </Modal.Footer>
    </Modal>
  );
};

export default DxfViewer;