Feat: Add dropdown for manufacturer and implement Nordex KSF geometries
Deploy Bürgerwind / deploy (push) Successful in 17s
Details
Deploy Bürgerwind / deploy (push) Successful in 17s
Details
This commit is contained in:
parent
f26d1f1710
commit
19a4f0f165
60
app.js
60
app.js
|
|
@ -79,6 +79,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const btnDeleteWEA = document.getElementById('btnDeleteWEA');
|
const btnDeleteWEA = document.getElementById('btnDeleteWEA');
|
||||||
|
|
||||||
const editNr = document.getElementById('edit-wea-nr');
|
const editNr = document.getElementById('edit-wea-nr');
|
||||||
|
const editManufacturer = document.getElementById('edit-wea-manufacturer');
|
||||||
const editType = document.getElementById('edit-wea-type');
|
const editType = document.getElementById('edit-wea-type');
|
||||||
const editRd = document.getElementById('edit-wea-rd');
|
const editRd = document.getElementById('edit-wea-rd');
|
||||||
const editNh = document.getElementById('edit-wea-nh');
|
const editNh = document.getElementById('edit-wea-nh');
|
||||||
|
|
@ -95,6 +96,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const inputRotor = document.getElementById('rotorDiameter');
|
const inputRotor = document.getElementById('rotorDiameter');
|
||||||
const inputHub = document.getElementById('hubHeight');
|
const inputHub = document.getElementById('hubHeight');
|
||||||
const inputFoundation = document.getElementById('foundationRadius');
|
const inputFoundation = document.getElementById('foundationRadius');
|
||||||
|
const inputManufacturer = document.getElementById('turbineManufacturer');
|
||||||
const inputType = document.getElementById('turbineType');
|
const inputType = document.getElementById('turbineType');
|
||||||
|
|
||||||
let placementMode = false;
|
let placementMode = false;
|
||||||
|
|
@ -106,7 +108,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const wgs84 = "+proj=longlat +datum=WGS84 +no_defs";
|
const wgs84 = "+proj=longlat +datum=WGS84 +no_defs";
|
||||||
|
|
||||||
// Calculation Functions
|
// Calculation Functions
|
||||||
function calculateGeometries(latlng, rotorDiameter, hubHeight, foundationRadius, ksfAngle = 0, ksfMirrored = false) {
|
function calculateGeometries(latlng, rotorDiameter, hubHeight, foundationRadius, ksfAngle = 0, ksfMirrored = false, hersteller = 'Enercon') {
|
||||||
// Ensure valid numbers for Turf
|
// Ensure valid numbers for Turf
|
||||||
const rd = parseFloat(rotorDiameter) || 160;
|
const rd = parseFloat(rotorDiameter) || 160;
|
||||||
const hh = parseFloat(hubHeight) || 165;
|
const hh = parseFloat(hubHeight) || 165;
|
||||||
|
|
@ -173,24 +175,32 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
return turf.polygon([finalCoords]);
|
return turf.polygon([finalCoords]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 4. Blattlagerfläche (BLF)
|
let blfCoords, ksfCoords, mfParts;
|
||||||
// Coords for "Nein" case (@spg=1): x is -41
|
|
||||||
const blfCoords = [[-41, 9], [-61, 9], [-61, -81], [-41, -81], [-41, 9]];
|
if (hersteller === 'Nordex') {
|
||||||
|
// Nordex Geometries
|
||||||
|
blfCoords = [[65.15, 18.25], [155.15, 18.25], [155.15, 33.25], [65.15, 33.25], [65.15, 18.25]];
|
||||||
|
ksfCoords = [[5.5, -18.25], [65.15, -18.25], [65.15, 18.25], [5.5, 18.25], [5.5, -18.25]];
|
||||||
|
mfParts = [
|
||||||
|
[[65.15, -7.5], [295.15, -7.5], [295.15, 7.5], [65.15, 7.5], [65.15, -7.5]], // AMF
|
||||||
|
[[5.5, 18.25], [31.5, 18.25], [31.5, 28.75], [5.5, 28.75], [5.5, 18.25]] // Naben-MF
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// Enercon / Vestas / GE (Standard)
|
||||||
|
blfCoords = [[-41, 9], [-61, 9], [-61, -81], [-41, -81], [-41, 9]];
|
||||||
|
ksfCoords = [[-8, 0], [-36, 0], [-36, -50], [-8, -50], [-8, 0]];
|
||||||
|
mfParts = [
|
||||||
|
[[-36, 0], [-36, 18], [-8, 18], [-8, 0], [-36, 0]],
|
||||||
|
[[12, -62], [-22, -62], [-22, -72], [12, -72], [12, -62]],
|
||||||
|
[[12, 0], [-8, 0], [-8, -50], [-36, -50], [-36, -72], [-22, -72], [-22, -62], [12, -62], [12, 0]],
|
||||||
|
[[-41, 18], [-47, 18], [-47, 9], [-41, 9], [-41, 18]],
|
||||||
|
[[-41, -81], [-47, -81], [-47, -96], [-41, -96], [-41, -81]],
|
||||||
|
[[-36, 18], [-41, 18], [-41, -72], [-36, -72], [-36, 18]]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
const blf = transform(blfCoords);
|
const blf = transform(blfCoords);
|
||||||
|
|
||||||
// 5. Kranstellfläche (KSF)
|
|
||||||
const ksfCoords = [[-8, 0], [-36, 0], [-36, -50], [-8, -50], [-8, 0]];
|
|
||||||
const ksf = transform(ksfCoords);
|
const ksf = transform(ksfCoords);
|
||||||
|
|
||||||
// 6. Montagefläche (MF)
|
|
||||||
const mfParts = [
|
|
||||||
[[-36, 0], [-36, 18], [-8, 18], [-8, 0], [-36, 0]],
|
|
||||||
[[12, -62], [-22, -62], [-22, -72], [12, -72], [12, -62]],
|
|
||||||
[[12, 0], [-8, 0], [-8, -50], [-36, -50], [-36, -72], [-22, -72], [-22, -62], [12, -62], [12, 0]],
|
|
||||||
[[-41, 18], [-47, 18], [-47, 9], [-41, 9], [-41, 18]],
|
|
||||||
[[-41, -81], [-47, -81], [-47, -96], [-41, -96], [-41, -81]],
|
|
||||||
[[-36, 18], [-41, 18], [-41, -72], [-36, -72], [-36, 18]]
|
|
||||||
];
|
|
||||||
const mf = turf.featureCollection(mfParts.map(part => transform(part)));
|
const mf = turf.featureCollection(mfParts.map(part => transform(part)));
|
||||||
|
|
||||||
return { sweptArea, techDist, techDistSmall, loadRadius, foundation, blf, ksf, mf, totalHeight, utmCoords };
|
return { sweptArea, techDist, techDistSmall, loadRadius, foundation, blf, ksf, mf, totalHeight, utmCoords };
|
||||||
|
|
@ -240,6 +250,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
activeTurbine = turbine;
|
activeTurbine = turbine;
|
||||||
editNr.value = turbine.nr;
|
editNr.value = turbine.nr;
|
||||||
|
editManufacturer.value = turbine.hersteller || 'Enercon';
|
||||||
editType.value = turbine.type;
|
editType.value = turbine.type;
|
||||||
editRd.value = turbine.rd;
|
editRd.value = turbine.rd;
|
||||||
editNh.value = turbine.hh;
|
editNh.value = turbine.hh;
|
||||||
|
|
@ -323,11 +334,12 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const hh = overrideData?.hh || parseFloat(inputHub.value) || 165;
|
const hh = overrideData?.hh || parseFloat(inputHub.value) || 165;
|
||||||
const fr = overrideData?.fr || parseFloat(inputFoundation.value) || 15;
|
const fr = overrideData?.fr || parseFloat(inputFoundation.value) || 15;
|
||||||
const type = overrideData?.type || inputType.value || "Standard Typ";
|
const type = overrideData?.type || inputType.value || "Standard Typ";
|
||||||
|
const hersteller = overrideData?.hersteller || inputManufacturer.value || "Enercon";
|
||||||
const weaNr = overrideData?.nr || loadedNr || (state.turbines.length + 1).toString();
|
const weaNr = overrideData?.nr || loadedNr || (state.turbines.length + 1).toString();
|
||||||
const ksfAngle = overrideData?.ksfAngle || 0;
|
const ksfAngle = overrideData?.ksfAngle || 0;
|
||||||
const ksfMirrored = overrideData?.ksfMirrored || false;
|
const ksfMirrored = overrideData?.ksfMirrored || false;
|
||||||
|
|
||||||
const geoms = calculateGeometries(latlng, rd, hh, fr, ksfAngle, ksfMirrored);
|
const geoms = calculateGeometries(latlng, rd, hh, fr, ksfAngle, ksfMirrored, hersteller);
|
||||||
|
|
||||||
const turbineIcon = L.divIcon({
|
const turbineIcon = L.divIcon({
|
||||||
className: 'turbine-icon-container',
|
className: 'turbine-icon-container',
|
||||||
|
|
@ -348,7 +360,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
id: `WEA_${Date.now()}`,
|
id: `WEA_${Date.now()}`,
|
||||||
nr: weaNr,
|
nr: weaNr,
|
||||||
variant: overrideData?.variant || state.activeVariant,
|
variant: overrideData?.variant || state.activeVariant,
|
||||||
type, rd, hh, fr, latlng,
|
hersteller, type, rd, hh, fr, latlng,
|
||||||
ksfAngle, ksfMirrored,
|
ksfAngle, ksfMirrored,
|
||||||
totalHeight: geoms.totalHeight,
|
totalHeight: geoms.totalHeight,
|
||||||
layers: {
|
layers: {
|
||||||
|
|
@ -413,7 +425,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
turbine.layers.marker.on('drag', (e) => {
|
turbine.layers.marker.on('drag', (e) => {
|
||||||
const newPos = e.target.getLatLng();
|
const newPos = e.target.getLatLng();
|
||||||
turbine.latlng = newPos;
|
turbine.latlng = newPos;
|
||||||
const newGeoms = calculateGeometries(newPos, turbine.rd, turbine.hh, turbine.fr, turbine.ksfAngle, turbine.ksfMirrored);
|
const newGeoms = calculateGeometries(newPos, turbine.rd, turbine.hh, turbine.fr, turbine.ksfAngle, turbine.ksfMirrored, turbine.hersteller);
|
||||||
turbine.layers.sweptArea.clearLayers().addData(newGeoms.sweptArea);
|
turbine.layers.sweptArea.clearLayers().addData(newGeoms.sweptArea);
|
||||||
turbine.layers.techDist.clearLayers().addData(newGeoms.techDist);
|
turbine.layers.techDist.clearLayers().addData(newGeoms.techDist);
|
||||||
turbine.layers.techDistSmall.clearLayers().addData(newGeoms.techDistSmall);
|
turbine.layers.techDistSmall.clearLayers().addData(newGeoms.techDistSmall);
|
||||||
|
|
@ -454,7 +466,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
editKsfAngle.value = angle.toFixed(1);
|
editKsfAngle.value = angle.toFixed(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newGeoms = calculateGeometries(turbine.latlng, turbine.rd, turbine.hh, turbine.fr, turbine.ksfAngle, turbine.ksfMirrored);
|
const newGeoms = calculateGeometries(turbine.latlng, turbine.rd, turbine.hh, turbine.fr, turbine.ksfAngle, turbine.ksfMirrored, turbine.hersteller);
|
||||||
turbine.layers.ksf.clearLayers().addData(newGeoms.ksf);
|
turbine.layers.ksf.clearLayers().addData(newGeoms.ksf);
|
||||||
turbine.layers.blf.clearLayers().addData(newGeoms.blf);
|
turbine.layers.blf.clearLayers().addData(newGeoms.blf);
|
||||||
turbine.layers.mf.clearLayers().addData(newGeoms.mf);
|
turbine.layers.mf.clearLayers().addData(newGeoms.mf);
|
||||||
|
|
@ -475,6 +487,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
btnSaveEdit.onclick = () => {
|
btnSaveEdit.onclick = () => {
|
||||||
if (!activeTurbine) return;
|
if (!activeTurbine) return;
|
||||||
const newNr = editNr.value;
|
const newNr = editNr.value;
|
||||||
|
const newManufacturer = editManufacturer.value;
|
||||||
const newType = editType.value;
|
const newType = editType.value;
|
||||||
const newRd = parseFloat(editRd.value);
|
const newRd = parseFloat(editRd.value);
|
||||||
const newNh = parseFloat(editNh.value);
|
const newNh = parseFloat(editNh.value);
|
||||||
|
|
@ -487,6 +500,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
activeTurbine.nr = newNr;
|
activeTurbine.nr = newNr;
|
||||||
|
activeTurbine.hersteller = newManufacturer;
|
||||||
activeTurbine.type = newType;
|
activeTurbine.type = newType;
|
||||||
activeTurbine.rd = newRd;
|
activeTurbine.rd = newRd;
|
||||||
activeTurbine.hh = newNh;
|
activeTurbine.hh = newNh;
|
||||||
|
|
@ -494,7 +508,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
activeTurbine.ksfAngle = newAngle;
|
activeTurbine.ksfAngle = newAngle;
|
||||||
activeTurbine.ksfMirrored = newMirrored;
|
activeTurbine.ksfMirrored = newMirrored;
|
||||||
|
|
||||||
const geoms = calculateGeometries(activeTurbine.layers.marker.getLatLng(), newRd, newNh, newFr, newAngle, newMirrored);
|
const geoms = calculateGeometries(activeTurbine.layers.marker.getLatLng(), newRd, newNh, newFr, newAngle, newMirrored, newManufacturer);
|
||||||
activeTurbine.totalHeight = geoms.totalHeight;
|
activeTurbine.totalHeight = geoms.totalHeight;
|
||||||
activeTurbine.layers.sweptArea.clearLayers().addData(geoms.sweptArea);
|
activeTurbine.layers.sweptArea.clearLayers().addData(geoms.sweptArea);
|
||||||
activeTurbine.layers.techDist.clearLayers().addData(geoms.techDist);
|
activeTurbine.layers.techDist.clearLayers().addData(geoms.techDist);
|
||||||
|
|
@ -1826,6 +1840,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const turbineData = state.turbines.map(t => ({
|
const turbineData = state.turbines.map(t => ({
|
||||||
nr: t.nr,
|
nr: t.nr,
|
||||||
variant: t.variant,
|
variant: t.variant,
|
||||||
|
hersteller: t.hersteller,
|
||||||
type: t.type,
|
type: t.type,
|
||||||
rd: t.rd,
|
rd: t.rd,
|
||||||
hh: t.hh,
|
hh: t.hh,
|
||||||
|
|
@ -1877,6 +1892,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const latlng = L.latLng(t.lat, t.lng);
|
const latlng = L.latLng(t.lat, t.lng);
|
||||||
createTurbine(latlng, null, {
|
createTurbine(latlng, null, {
|
||||||
nr: t.nr,
|
nr: t.nr,
|
||||||
|
hersteller: t.hersteller,
|
||||||
type: t.type,
|
type: t.type,
|
||||||
rd: t.rd,
|
rd: t.rd,
|
||||||
hh: t.hh,
|
hh: t.hh,
|
||||||
|
|
|
||||||
20
index.html
20
index.html
|
|
@ -44,9 +44,18 @@
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>Anlagen-Konfiguration</h2>
|
<h2>Anlagen-Konfiguration</h2>
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="turbineManufacturer">Hersteller</label>
|
||||||
|
<select id="turbineManufacturer" class="input-styled">
|
||||||
|
<option value="Enercon">Enercon</option>
|
||||||
|
<option value="Nordex">Nordex</option>
|
||||||
|
<option value="Vestas">Vestas</option>
|
||||||
|
<option value="GE">GE</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label for="turbineType">Anlagentyp</label>
|
<label for="turbineType">Anlagentyp</label>
|
||||||
<input type="text" id="turbineType" class="input-styled" placeholder="z.B. Vestas V162">
|
<input type="text" id="turbineType" class="input-styled" placeholder="z.B. V162">
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label for="rotorDiameter">Rotordurchmesser (m)</label>
|
<label for="rotorDiameter">Rotordurchmesser (m)</label>
|
||||||
|
|
@ -151,6 +160,15 @@
|
||||||
<label>Nr:</label>
|
<label>Nr:</label>
|
||||||
<input type="text" id="edit-wea-nr" class="edit-input">
|
<input type="text" id="edit-wea-nr" class="edit-input">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="edit-row separator">
|
||||||
|
<label>Hersteller:</label>
|
||||||
|
<select id="edit-wea-manufacturer" class="edit-input">
|
||||||
|
<option value="Enercon">Enercon</option>
|
||||||
|
<option value="Nordex">Nordex</option>
|
||||||
|
<option value="Vestas">Vestas</option>
|
||||||
|
<option value="GE">GE</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="edit-row separator">
|
<div class="edit-row separator">
|
||||||
<label>Typ:</label>
|
<label>Typ:</label>
|
||||||
<input type="text" id="edit-wea-type" class="edit-input">
|
<input type="text" id="edit-wea-type" class="edit-input">
|
||||||
|
|
|
||||||
|
|
@ -75,9 +75,9 @@ app.post('/api/wea', async (req, res) => {
|
||||||
log(`Füge WEA ein: Nr=${t.nr}, Typ=${t.type}, Pos=${t.latlng?.lat},${t.latlng?.lng}`);
|
log(`Füge WEA ein: Nr=${t.nr}, Typ=${t.type}, Pos=${t.latlng?.lat},${t.latlng?.lng}`);
|
||||||
await client.query(
|
await client.query(
|
||||||
`INSERT INTO ${schema}.wea_standorte
|
`INSERT INTO ${schema}.wea_standorte
|
||||||
(projekt_id, wea_nummer, anlagentyp, nabenhoehe, rotordurchmesser, ksf_drehung, variante, geom)
|
(projekt_id, wea_nummer, hersteller, anlagentyp, nabenhoehe, rotordurchmesser, ksf_drehung, variante, geom)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, ST_Transform(ST_SetSRID(ST_MakePoint($8, $9), 4326), 25832))`,
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, ST_Transform(ST_SetSRID(ST_MakePoint($9, $10), 4326), 25832))`,
|
||||||
[targetProject, t.nr, t.type, t.hh, t.rd, t.ksfAngle, t.variant, t.latlng.lng, t.latlng.lat]
|
[targetProject, t.nr, t.hersteller, t.type, t.hh, t.rd, t.ksfAngle, t.variant, t.latlng.lng, t.latlng.lat]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +100,7 @@ app.get('/api/wea/:projekt_id', async (req, res) => {
|
||||||
log(`Lade WEAs für Projekt: ${projekt_id}`);
|
log(`Lade WEAs für Projekt: ${projekt_id}`);
|
||||||
try {
|
try {
|
||||||
const result = await pool.query(
|
const result = await pool.query(
|
||||||
`SELECT wea_nummer as nr, anlagentyp as type, nabenhoehe as hh, rotordurchmesser as rd, ksf_drehung as ksfAngle, variante as variant,
|
`SELECT wea_nummer as nr, hersteller as hersteller, anlagentyp as type, nabenhoehe as hh, rotordurchmesser as rd, ksf_drehung as ksfAngle, variante as variant,
|
||||||
ST_X(ST_Transform(geom, 4326)) as lng, ST_Y(ST_Transform(geom, 4326)) as lat
|
ST_X(ST_Transform(geom, 4326)) as lng, ST_Y(ST_Transform(geom, 4326)) as lat
|
||||||
FROM geodaten.wea_standorte WHERE projekt_id = $1`,
|
FROM geodaten.wea_standorte WHERE projekt_id = $1`,
|
||||||
[projekt_id]
|
[projekt_id]
|
||||||
|
|
@ -226,6 +226,7 @@ app.get('/api/layers/alkis', async (req, res) => {
|
||||||
'PLZ', "PLZ",
|
'PLZ', "PLZ",
|
||||||
'ORP', "ORP",
|
'ORP', "ORP",
|
||||||
'STR', "STR",
|
'STR', "STR",
|
||||||
|
'HSN', "HSN",
|
||||||
'status', status,
|
'status', status,
|
||||||
'notiz', notiz
|
'notiz', notiz
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue