Reputation: 1
im pretty new to coding and as a nice project to get better wanted to make a gpx to stl converter. After doing some research i came to a conclusion that it must be possible. I use reactJS for this project.
My findings on how I should do it :
**My problems at the moment : **
This is my current code :
import React, { useState } from 'react';
function FileUploader({ onFileUpload }) {
const [selectedFile, setSelectedFile] = useState(null);
const handleFileChange = async (e) => {
const file = e.target.files[0];
// Lees de inhoud van het GPX-bestand
const fileContent = await readFileContent(file);
setSelectedFile(file);
onFileUpload({ file, fileContent });
};
const readFileContent = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
resolve(e.target.result);
};
reader.onerror = (e) => {
reject(new Error('Error reading file.'));
};
reader.readAsText(file);
});
};
return (
<div className="file-uploader">
<label>
Selecteer een GPX-bestand:
<input type="file" accept=".gpx" onChange={handleFileChange} />
</label>
</div>
);
}
export default FileUploader;
**// Converter.js
**
import React, { useEffect, useRef } from 'react';
import * as THREE from 'three';
import { STLExporter } from 'three/addons/exporters/STLExporter.js';
function Converter({ gpxFile }) {
const threeContainerRef = useRef(null);
const sceneRef = useRef(null);
const cameraRef = useRef(null);
const rendererRef = useRef(null);
const downloadSTL = () => {
const STLExporterInstance = new STLExporter();
const stlData = STLExporterInstance.parse(sceneRef.current);
const blob = new Blob([stlData], { type: 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = 'geconverteerd_model.stl';
downloadLink.click();
// Optioneel: Opruimen van de URL en het element
URL.revokeObjectURL(url);
//renderer.domElement.remove();
};
useEffect(() => {
const convertGPXtoSTL = (gpxData) => {
const validateGPX = (gpxData) => {
try {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(gpxData, 'text/xml');
const trkpts = xmlDoc.querySelectorAll('trkpt');
if (!trkpts.length) {
throw new Error('Geen trackpunten gevonden in het GPX-bestand.');
}
return trkpts;
} catch (error) {
throw new Error(`Ongeldige GPX-gegevens: ${error.message}`);
}
};
const optimizeGPXData = (trkpts) => {
const points = [];
trkpts.forEach((trkpt) => {
const lat = parseFloat(trkpt.getAttribute('lat'));
const lon = parseFloat(trkpt.getAttribute('lon'));
const eleNode = trkpt.querySelector('ele');
if (eleNode) {
const ele = parseFloat(eleNode.textContent);
points.push({ lat, lon, ele });
}
});
return points;
};
const trkpts = validateGPX(gpxData);
const points = optimizeGPXData(trkpts);
console.log('Geoptimaliseerde GPX-punten:', points);
return points;
};
const create3DScene = (points) => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
threeContainerRef.current.appendChild(renderer.domElement);
const material = new THREE.LineBasicMaterial({ color: 0x00ff00 });
// Maak een geometrie voor de lijnen
const geometry = new THREE.BufferGeometry().setFromPoints(
points.map((point) => new THREE.Vector3(point.lon, point.ele, point.lat))
);
// Maak een lijn met de geometrie en het materiaal
const line = new THREE.Line(geometry, material);
scene.add(line);
camera.position.set(points[0].lon, points[0].ele, points[0].lat);
camera.lookAt(new THREE.Vector3(points[points.length - 1].lon, points[points.length - 1].ele, points[points.length - 1].lat));
// Voeg een grid toe voor visuele referentie
const gridHelper = new THREE.GridHelper(10, 10);
scene.add(gridHelper);
return { scene, camera, renderer };
};
const points = convertGPXtoSTL(gpxFile.fileContent);
const { scene, camera, renderer } = create3DScene(points);
sceneRef.current = scene;
cameraRef.current = camera;
rendererRef.current = renderer;
// Animeren van de scene
const animate = () => {
requestAnimationFrame(animate);
// Voeg hier eventuele animaties of updates toe
renderer.render(scene, camera);
};
animate();
// Voeg cleanup-functie toe
return () => {
renderer.domElement.remove();
};
}, [gpxFile.fileContent]);
return (
<div className="converter">
<h2>GPX-bestand geüpload:</h2>
<p>Bestandsnaam: {gpxFile.file.name}</p>
<p>Bestandsinhoud: {gpxFile.fileContent}</p>
<h2>3D-weergave van GPX-data:</h2>
<div ref={threeContainerRef}></div>
<button onClick={downloadSTL}>Download STL</button>
</div>
);
}
export default Converter;
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Upvotes: -1
Views: 255
Reputation: 333
The issue seems to be related to the way you are creating the geometry for the route in Three.js and exporting it to STL
2)In the downloadSTL(), ensure that the scene has a valid geometry before exporting to STL. Also, consider using STLExporter from three/examples/jsm/exporters/STLExporter.js
Upvotes: 0