I have multiple datasets with coordinates in them and I want to plot these points in Cesium for Unreal. For me to do that, I need to correct terrain heights and I want to have them in Python (since I'm doing some other stuff as well). Here I'm a bit stuck. There is no API for Cesium that seems to be available for this task, so I used Python to create a HTML file, put the coordinates in there and retreive the terrain heights: import json import threading import time from flask import Flask, request, send_file import webbrowser import tempfile import os def get_terrain_heights(points, access_token): results = [] app = Flask(__name__) temp_html_file = tempfile.NamedTemporaryFile(delete=False, suffix=".html") temp_html_file.close() html_content = f""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Cesium Terrain Fetch</title> <link href="https://cdn.jsdelivr.net/npm/cesium@1.105.1/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/cesium@1.105.1/Build/Cesium/Cesium.js"></script> <style> html, body, #cesiumContainer {{width:100%; height:100%; margin:0; padding:0; overflow:hidden;}} </style> </head> <body> <div id="cesiumContainer"></div> <script> Cesium.Ion.defaultAccessToken = '{access_token}'; const viewer = new Cesium.Viewer('cesiumContainer', {{ terrainProvider: Cesium.createWorldTerrain() }}); const points = {json.dumps(points)}; let results = []; function sendToPython(data) {{ fetch('/submit', {{ method: 'POST', headers: {{'Content-Type': 'application/json'}}, body: JSON.stringify(data) }}); }} points.forEach(p => {{ const position = Cesium.Cartographic.fromDegrees(p.lon, p.lat); Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [position]).then(updatedPositions => {{ const terrainHeight = updatedPositions[0].height; const ellipsoidHeight = terrainHeight + p.alt_above_ground; results.push({{ lat: p.lat, lon: p.lon, alt_above_ground: p.alt_above_ground, terrain_height: terrainHeight, alt_ellipsoid: ellipsoidHeight }}); if (results.length === points.length) {{ sendToPython(results); alert('Terrain heights fetched. You can close this window.'); }} }}); }}); </script> </body> </html> """ with open(temp_html_file.name, "w") as f: f.write(html_content) @app.route('/') def index(): return send_file(temp_html_file.name) @app.route('/submit', methods=['POST']) def submit(): nonlocal results results = request.json return {"status": "ok"} def run_app(): app.run(port=5000) thread = threading.Thread(target=run_app, daemon=True) thread.start() webbrowser.open("http://127.0.0.1:5000/") while not results: time.sleep(0.5) # Delete the temporary file only after getting results try: os.unlink(temp_html_file.name) except: pass return results # Usage: points = [{"lat": 52.3109, "lon": 4.77028, "alt_above_ground": 0}, {"lat": 52.3109, "lon": 4.57028, "alt_above_ground": 0}] access_token = "access_token" terrain_data = get_terrain_heights(points, access_token) This works actually really good, it returns a list of dictionaries with the information I need. So this works, but only once. The second time I want to use this code it gives me the error: FileNotFoundError: [WinError 2] The system cannot find the file specified: 'C:\Users\username\AppData\Local\Temp\tmp4y1vst8b.html' This is logical, since it removes the temporary file after using. When I remove that piece of code however, it still does not work: it keeps running in the Python kernel and nothing happens, no data is retreived. Can someone assist in how to handle this? I want to go to a solution that I simply run the function, it retreives the information I need and then it's done. If I want to run it after 1 minute again with other information, then it should be able to do that. Continue reading...