Robust saving strategy and vertex editing improvement
Deploy TrassenPlaner / deploy (push) Waiting to run
Details
Deploy TrassenPlaner / deploy (push) Waiting to run
Details
This commit is contained in:
parent
bf6183ce80
commit
6e5ef89733
52
index.html
52
index.html
|
|
@ -1720,8 +1720,8 @@
|
||||||
middleMarkers: true,
|
middleMarkers: true,
|
||||||
pane: 'trassenPane',
|
pane: 'trassenPane',
|
||||||
lineOptions: { color: '#cca300', weight: 6 },
|
lineOptions: { color: '#cca300', weight: 6 },
|
||||||
vertexOptions: { color: '#cca300', radius: 5 },
|
vertexOptions: { color: '#cca300', radius: 6 },
|
||||||
middleMarkerOptions: { color: '#cca300', opacity: 0.5, radius: 3 }
|
middleMarkerOptions: { color: '#cca300', opacity: 0.6, radius: 4 }
|
||||||
});
|
});
|
||||||
drillingLayers[v.id] = L.featureGroup({ interactive: false, pane: 'drillingPane' });
|
drillingLayers[v.id] = L.featureGroup({ interactive: false, pane: 'drillingPane' });
|
||||||
labelLayers[v.id] = L.featureGroup({ interactive: false, pane: 'labelPane' });
|
labelLayers[v.id] = L.featureGroup({ interactive: false, pane: 'labelPane' });
|
||||||
|
|
@ -1732,8 +1732,29 @@
|
||||||
labelLayers[v.id].addTo(map);
|
labelLayers[v.id].addTo(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow vertex insertion by clicking the polyline itself
|
// Allow vertex insertion by clicking anywhere on the polyline
|
||||||
routeLayers[v.id].on('click', handleVertexInsertion);
|
routeLayers[v.id].on('click', (e) => {
|
||||||
|
if (!v.active) return;
|
||||||
|
if (!map.editTools) return;
|
||||||
|
|
||||||
|
// Prevent the default map click from bubbling
|
||||||
|
L.DomEvent.stopPropagation(e);
|
||||||
|
|
||||||
|
const layer = routeLayers[v.id];
|
||||||
|
// Find the closest segment and insert a point
|
||||||
|
const point = map.mouseEventToLatLng(e.originalEvent);
|
||||||
|
const vertexIndex = findClosestSegmentIndex(layer.getLatLngs(), point);
|
||||||
|
|
||||||
|
if (vertexIndex !== -1) {
|
||||||
|
const latlngs = layer.getLatLngs();
|
||||||
|
latlngs.splice(vertexIndex + 1, 0, point);
|
||||||
|
layer.setLatLngs(latlngs);
|
||||||
|
layer.editor.refresh(); // Tell the Leaflet.Editable editor to update markers
|
||||||
|
|
||||||
|
// Trigger all the sync events manually
|
||||||
|
map.fire('editable:vertex:inserted', { layer: layer });
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const layer = routeLayers[v.id];
|
const layer = routeLayers[v.id];
|
||||||
|
|
@ -1892,13 +1913,27 @@
|
||||||
calculateStats(activeV);
|
calculateStats(activeV);
|
||||||
updateVariantStatsUI(activeV);
|
updateVariantStatsUI(activeV);
|
||||||
updateVariantStatsUI(activeV);
|
updateVariantStatsUI(activeV);
|
||||||
if (e.type.includes('end') || e.type === 'editable:created' || e.type.includes('dragend')) {
|
if (e.type.includes('end') || e.type === 'editable:created' || e.type.includes('dragend') || e.type === 'editable:vertex:inserted') {
|
||||||
renderVariants();
|
renderVariants();
|
||||||
const _activeV = state.variants.find(v => v.active);
|
const _activeV = state.variants.find(v => v.active);
|
||||||
if (_activeV) saveVariantToDB(_activeV);
|
if (_activeV) saveVariantToDB(_activeV);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Helper to find the best spot to insert a new vertex
|
||||||
|
function findClosestSegmentIndex(latlngs, point) {
|
||||||
|
let minDistance = Infinity;
|
||||||
|
let index = -1;
|
||||||
|
for (let i = 0; i < latlngs.length - 1; i++) {
|
||||||
|
const distance = L.LineUtil.closestPointOnSegment(map.latLngToLayerPoint(point), map.latLngToLayerPoint(latlngs[i]), map.latLngToLayerPoint(latlngs[i+1])).distanceTo(map.latLngToLayerPoint(point));
|
||||||
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
function getFlattenedCoords(raw) {
|
function getFlattenedCoords(raw) {
|
||||||
if (!raw) return [];
|
if (!raw) return [];
|
||||||
// If it's a flat array of LatLngs already
|
// If it's a flat array of LatLngs already
|
||||||
|
|
@ -2787,7 +2822,11 @@
|
||||||
if (slot && f.geometry && f.geometry.coordinates) {
|
if (slot && f.geometry && f.geometry.coordinates) {
|
||||||
slot.id = f.id || p.id || slot.id;
|
slot.id = f.id || p.id || slot.id;
|
||||||
slot.routes = f.geometry.coordinates.map(c => ({ lat: c[1], lng: c[0] }));
|
slot.routes = f.geometry.coordinates.map(c => ({ lat: c[1], lng: c[0] }));
|
||||||
console.log(`[V3-Sync] ${slot.name} erfolgreich gemappt.`);
|
|
||||||
|
// Re-sync the polyline layer if it exists
|
||||||
|
if (routeLayers[slot.id]) {
|
||||||
|
routeLayers[slot.id].setLatLngs(slot.routes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2825,6 +2864,7 @@
|
||||||
if (Math.abs(firstCoord) > 1000) gj = transformGeoJSON(gj, "EPSG:25832", "EPSG:4326");
|
if (Math.abs(firstCoord) > 1000) gj = transformGeoJSON(gj, "EPSG:25832", "EPSG:4326");
|
||||||
}
|
}
|
||||||
state.usage = gj;
|
state.usage = gj;
|
||||||
|
cachedObstacles = null; // IMPORTANT: Reset cache to trigger new calculation
|
||||||
updateUsageLayer();
|
updateUsageLayer();
|
||||||
}
|
}
|
||||||
} catch (e) { console.error("[V3-Sync] Usage Error:", e); }
|
} catch (e) { console.error("[V3-Sync] Usage Error:", e); }
|
||||||
|
|
|
||||||
15
server.js
15
server.js
|
|
@ -187,7 +187,7 @@ app.get('/api/variants', async (req, res) => {
|
||||||
await setSchema(client);
|
await setSchema(client);
|
||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
id, name, "Variante",
|
COALESCE(id, fid) AS id, name, "Variante",
|
||||||
ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry
|
ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry
|
||||||
FROM kabeltrasse
|
FROM kabeltrasse
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
|
|
@ -227,22 +227,21 @@ app.post('/api/variants', async (req, res) => {
|
||||||
const varianteValue = properties.Variante || (properties.name ? properties.name.replace('Variante ', '') : 'A');
|
const varianteValue = properties.Variante || (properties.name ? properties.name.replace('Variante ', '') : 'A');
|
||||||
const geoJsonStr = JSON.stringify(geometry);
|
const geoJsonStr = JSON.stringify(geometry);
|
||||||
|
|
||||||
const upsertQuery = `
|
// Delete existing variant if it exists (Manual UPSERT to bypass missing index permissions)
|
||||||
|
await client.query('DELETE FROM kabeltrasse WHERE "Variante" = $1 OR name = $2', [varianteValue, routeName]);
|
||||||
|
|
||||||
|
const insertQuery = `
|
||||||
INSERT INTO kabeltrasse (geom, name, "Variante")
|
INSERT INTO kabeltrasse (geom, name, "Variante")
|
||||||
VALUES (
|
VALUES (
|
||||||
ST_MakeValid(ST_Transform(ST_GeomFromGeoJSON($1), 25832)),
|
ST_MakeValid(ST_Transform(ST_GeomFromGeoJSON($1), 25832)),
|
||||||
$2,
|
$2,
|
||||||
$3
|
$3
|
||||||
)
|
)
|
||||||
ON CONFLICT ("Variante")
|
|
||||||
DO UPDATE SET
|
|
||||||
geom = EXCLUDED.geom,
|
|
||||||
name = EXCLUDED.name
|
|
||||||
RETURNING id
|
RETURNING id
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const upsertRes = await client.query(upsertQuery, [geoJsonStr, routeName, varianteValue]);
|
const insertRes = await client.query(insertQuery, [geoJsonStr, routeName, varianteValue]);
|
||||||
res.json({ success: true, id: upsertRes.rows[0].id });
|
res.json({ success: true, id: insertRes.rows[0].id });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("SQL-FEHLER (SAVE):", err.message);
|
console.error("SQL-FEHLER (SAVE):", err.message);
|
||||||
res.status(500).json({ error: 'Failed to save variant' });
|
res.status(500).json({ error: 'Failed to save variant' });
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue