diff --git a/dashboard/src/nav/Navbar.css b/dashboard/src/nav/Navbar.css index 85bd91e..5948aee 100644 --- a/dashboard/src/nav/Navbar.css +++ b/dashboard/src/nav/Navbar.css @@ -6,7 +6,7 @@ flex: 0 0 auto; justify-content: space-between; align-items: center; - padding: 0px 0px; + padding: 0 0; background-color: #0a4777; color: white; height: 60px; @@ -131,25 +131,26 @@ .sidebar-right { position: absolute; - overflow-x: none; top: 0; + right: 0; height: 100%; - width: 300px; + width: 0; background-color: #343a40; - transition: right 0.3s ease; + transition: all 0.3s ease; color: white; - z-index: 1050; - padding: 20px; - right: 0px; - overflow-y: auto; - box-shadow: -2px 0 5px rgba(0,0,0,0.5); -} - -.sidebar-right.hidden { - right: -320px; - box-shadow: none; + z-index: -1; + padding: 10px; + overflow: auto; // hide when width is zero + max-height: 100%; // will not exceed content height + box-shadow: -5px 0 5px rgba(0,0,0,0.5); } .sidebar-right.visible { - right: 0px; + width: 300px; + z-index: 1050; } + +.sidebar-right input { + width: 100px; /* Smaller input width */ + +} \ No newline at end of file diff --git a/dashboard/src/utils/apiCalls.jsx b/dashboard/src/utils/apiCalls.jsx index b048ee8..2a9924a 100644 --- a/dashboard/src/utils/apiCalls.jsx +++ b/dashboard/src/utils/apiCalls.jsx @@ -1,14 +1,14 @@ -export const fitGcps = async (api, widgets, setWidgets, setMessageInfo) => { +export const fitGcps = async (api, widgets, imgDims, epsgCode, setWidgets, setMessageInfo) => { - // temporary test function; - const updateWidgets = () => { - setWidgets((prevWidgets) => - prevWidgets.map((widget) => ({ - ...widget, - fit: {"row": 1075, "col": 1915}, - })) - ); - }; + // // temporary test function; + // const updateWidgets = () => { + // setWidgets((prevWidgets) => + // prevWidgets.map((widget) => ({ + // ...widget, + // fit: {"row": 1075, "col": 1915}, + // })) + // ); + // }; try { // Checks! if (widgets.length < 0) { @@ -18,31 +18,65 @@ export const fitGcps = async (api, widgets, setWidgets, setMessageInfo) => { } // Extract coordinates into separated lists - const src = widgets.map(({ coordinates }) => [ - parseFloat(coordinates.x) || 0, - parseFloat(coordinates.y) || 0, - coordinates.z === '' || isNaN(Number(coordinates.z)) ? NaN : parseFloat(coordinates.z) + const dst = widgets.map(({ coordinates }) => [ + parseFloat(coordinates.x) || null, + parseFloat(coordinates.y) || null, + parseFloat(coordinates.z) || null ]); - const dst = widgets.map(({ coordinates }) => [ - parseFloat(coordinates.row, 10) || 0, - parseFloat(coordinates.col, 10) || 0, + const src = widgets.map(({ coordinates }) => [ + parseFloat(coordinates.col, 10) || null, + parseFloat(coordinates.row, 10) || null, ]); + // check if dst contains null + if (dst.some(row => row.includes(null))) { + setMessageInfo('error', 'GCP real-world coordinates are not complete. Ensure the coordinates are entered correctly and try again.'); + } + + // check if src contains null values + if (src.some(row => row.includes(null))) { + setMessageInfo('error', 'GCPs must have valid row and column coordinates. Please click the GCPs into the image frame to fix this.'); + return; + } const payload = { "src": src, "dst": dst, + "height": imgDims.height, + "width": imgDims.width, + "crs": epsgCode.toString() }; console.log('Sending payload:', payload); - updateWidgets(); - console.log(widgets); -// // Send data to API endpoint -// const response = await api.post('https://api.example.com/endpoint', payload); -// console.log('API Response:', response.data); + // Send data to API endpoint + const response = await api.post('/camera_config/fit_perspective', payload); + // Extract `src_est` and `dst_est` from API response + const { src_est, dst_est, error } = response.data; + // Map the fitted coordinates back to the widgets + setWidgets((prevWidgets) => + prevWidgets.map((widget, index) => { + return { + ...widget, + fit: { + row: src_est ? src_est[index][1] : null, // row from src_est + col: src_est ? src_est[index][0] : null, // col from src_est + x: dst_est ? dst_est[index][0] : null, // x from dst_est + y: dst_est ? dst_est[index][1] : null, // y from dst_est + z: dst_est ? dst_est[index][2] : null, // z from dst_est + } + }; + }) + ); + const err_round = Math.round(error * 1000) / 1000; + if (err_round > 0.1) { + setMessageInfo('warning', `GCPs successfully fitted, but with a large average error: ${err_round} m.`); + return;} + setMessageInfo('success', `GCPs successfully fitted to image, average error: ${err_round} m.`); + // map the estimated points on the widgets for plotting + // updateWidgets(); } catch (error) { - console.error('Failed to send coordinates:', error); + setMessageInfo('error', 'Failed to send coordinates:' + error.response.data.detail); // Optionally, handle errors (e.g., display an error message) } }; diff --git a/dashboard/src/utils/leafletUtils.js b/dashboard/src/utils/leafletUtils.js index 7551e38..7eae759 100644 --- a/dashboard/src/utils/leafletUtils.js +++ b/dashboard/src/utils/leafletUtils.js @@ -1,7 +1,7 @@ import L from "leaflet"; // Import Leaflet for DivIcon // Function to create a custom DivIcon with dynamic RGBA colors -export const createCustomMarker = (color) => { +export const createCustomMarker = (color, id) => { return L.divIcon({ className: "custom-marker", // Base class (can use CSS for additional styles) @@ -13,11 +13,11 @@ export const createCustomMarker = (color) => { top: -0.75rem; transform: rotate(45deg); border-radius: 1.5rem 1.5rem 0; - alignItems: center; + align-items: center; justify-content: center; border: 1px solid rgba(0, 0, 0, 0.5); - color: white - ">
{JSON.stringify(widgets, null, 2)}+{/*
{JSON.stringify(widgets, null, 2)}*/}