handleiding_nieuw:sub_spacematrix
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| handleiding_nieuw:sub_spacematrix [2025/05/07 09:04] – support | handleiding_nieuw:sub_spacematrix [2025/11/27 06:51] (current) – support | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| < | < | ||
| - | <style> | + | <html lang=" |
| - | .inputrow { | + | < |
| - | | + | <script src=" |
| - | align-items: center; | + | <script src=" |
| - | gap: 10px; | + | <script src=" |
| - | | + | <meta charset=" |
| - | | + | < |
| - | .inputrow label { | + | < |
| - | width: 200px; | + | body { font-family: sans-serif; margin: 20px; } |
| - | | + | .tabs { display: flex; gap: 10px; margin-bottom: |
| - | .inputrow input { | + | .tab { padding: 10px 15px; background: #ddd; cursor: pointer; border-radius: |
| - | width: 80px; | + | .tab.active |
| - | | + | .tabcontent |
| - | .resultblock | + | |
| - | margin-left: 40px; | + | |
| - | font-size: 0.9em; | + | |
| - | min-width: 200px; | + | .inputrow input { width: 80px; } |
| - | text-align: right; | + | table { border-collapse: |
| - | } | + | |
| - | | + | th { background: #f0f0f0; } |
| - | border-collapse: | + | td:first-child, th:first-child { text-align: left; } |
| - | | + | .kaartcontainer { position: |
| - | font-size: 0.9em; | + | .kaartcontainer img { width: 100%; display: block; } |
| - | | + | .stipje { position: absolute; width: 14px; height: 14px; background: red; border-radius: |
| - | | + | </style> |
| - | padding: 4px 6px; | + | <script src=" |
| - | | + | </ |
| - | | + | <body> |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | background-color: #fafafa; | + | |
| - | border-top: 2px solid #666; | + | |
| - | | + | |
| - | .kaartcontainer { | + | |
| - | | + | |
| - | top: 0; | + | |
| - | right: 0; | + | |
| - | width: 320px; | + | |
| - | | + | |
| - | .kaartcontainer img { | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | .stipje { | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | </ | + | |
| - | < | + | < |
| - | <div class=" | + | < |
| - | <img src="https:// | + | <div class=" |
| - | <div class=" | + | <div class="tab" |
| - | </ | + | <div class=" |
| + | < | ||
| </ | </ | ||
| - | <h2> | + | <div id=" |
| + | <div class=" | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | <span id=" | ||
| + | <input type=" | ||
| + | </ | ||
| + | </ | ||
| + | <div class=" | ||
| + | <img src="/ | ||
| + | <div class=" | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | <tbody id=" | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | | ||
| - | < | + | |
| - | <label for=" | + | <strong>Let op:</strong> de voorzieningenruimte zoals weergegeven in deze samenvatting kan iets afwijken van de berekening op het tabblad |
| - | | + | Dit komt doordat het aantal woningen iteratief wordt bepaald op basis van de beschikbare ruimte, inclusief ruimte voor voorzieningen en parkeren. |
| - | <div class=" | + | Bij het toepassen van voorzieningen wordt eerst een schatting gemaakt op basis van een voorlopig aantal woningen. Daarna wordt het aantal woningen opnieuw berekend met de benodigde ruimte per woning. |
| + | Hierdoor ontstaat een klein verschil tussen het oorspronkelijk berekende totaal en de daadwerkelijk ingepaste voorzieningenruimte. | ||
| </ | </ | ||
| - | < | + | |
| - | <label for="fsi">FSI:</label> | + | |
| - | <input id="fsi" | + | <div id="summary"> |
| - | <div class="resultblock" id="lv2"></ | + | < |
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | |||
| + | < | ||
| + | <td colspan=" | ||
| + | Kengetallen | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | < | ||
| + | <tr>< | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | | ||
| + | </ | ||
| + | |||
| + | <div style=" | ||
| + | <button onclick=" | ||
| + | 📄 Kickstart Dump downloaden | ||
| + | </button> | ||
| </ | </ | ||
| - | <div class=" | + | |
| - | <label for=" | + | |
| - | <input id=" | + | |
| - | <div class=" | + | |
| - | </ | + | |
| - | <div class=" | + | |
| - | <label for=" | + | |
| - | <input id=" | + | |
| - | <div class=" | + | |
| </ | </ | ||
| - | < | + | < |
| - | <table class=" | + | <div class=" |
| + | < | ||
| + | <input id=" | ||
| + | </ | ||
| + | <table> | ||
| < | < | ||
| - | | + | |
| - | | + | |
| - | | + | |
| - | <th style=" | + | |
| - | < | + | |
| - | | + | |
| - | | + | |
| </ | </ | ||
| - | <tbody id="woningtypes"></ | + | <tbody id="voorzieningentabel"></ |
| - | <tfoot> | + | </table> |
| - | <tr class=" | + | <div class=" |
| - | <td><b>Totaal</b></td> | + | <button id=" |
| - | <td id=" | + | <div id=" |
| - | <td id="totaal_gewbvo">-</td> | + | |
| - | <td id="totaal_won">-</td> | + | <h3>Overzicht geselecteerde voorzieningen</h3> |
| - | <td id="totaal_bvo"> | + | <table id="voorzieningen_totaal"> |
| - | | + | < |
| - | </ | + | < |
| + | </ | ||
| + | < | ||
| + | <tfoot> | ||
| + | < | ||
| + | </ | ||
| </ | </ | ||
| + | |||
| + | |||
| + | <div style=" | ||
| + | < | ||
| + | Nadat dit oppervlak per woning is berekend, wordt het aantal woningen in het rekenblok opnieuw doorgerekend. Hierdoor kan het werkelijke totaal afwijken. | ||
| + | Deze iteratieve aanpak is nodig omdat de benodigde ruimte per woning invloed heeft op hoeveel woningen uiteindelijk in het plan passen. | ||
| + | </ | ||
| </ | </ | ||
| - | <h3>Resultaat</ | + | <div id=" |
| - | <div id="output"></ | + | |
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | <input id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | <input id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | <input id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <button id=" | ||
| + | <div id=" | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div id=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | <select id=" | ||
| + | <option value=" | ||
| + | <option value=" | ||
| + | <option value=" | ||
| + | <option value=" | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | <p style=" | ||
| + | <div id=" | ||
| + | <canvas id=" | ||
| + | </ | ||
| < | < | ||
| - | | + | const types = ["egw sociaal", |
| - | | + | const voorzieningen = [ |
| - | | + | { naam: " |
| - | ]; | + | { naam: " |
| + | { naam: " | ||
| + | { naam: " | ||
| + | { naam: " | ||
| + | { naam: " | ||
| + | { naam: " | ||
| + | { naam: " | ||
| + | { naam: " | ||
| + | { naam: " | ||
| + | ]; | ||
| - | | + | function |
| - | | + | |
| - | } | + | document.querySelectorAll(' |
| + | document.querySelector(`.tab[onclick*="${tabId}"]`).classList.add(' | ||
| + | document.getElementById(tabId).classList.add(' | ||
| + | } | ||
| - | | + | function |
| - | const stip = document.getElementById(" | + | const tbody = document.getElementById(" |
| - | const x = Math.min(100, Math.max(0, gsi * 190)); | + | |
| - | const y = Math.max(0, Math.min(100, | + | types.forEach((type, i) => { |
| - | stip.style.left | + | const row = document.createElement(" |
| - | stip.style.top | + | row.innerHTML |
| - | } | + | <td>${type}</td> |
| + | < | ||
| + | < | ||
| + | <td id=" | ||
| + | <td id=" | ||
| + | | ||
| + | | ||
| + | }); | ||
| + | } | ||
| - | | + | function |
| - | const tbody = document.getElementById(" | + | const stip = document.getElementById(" |
| - | types.forEach((type, i) => { | + | |
| - | const row = document.createElement("tr"); | + | // Afbeeldingskalibratie (pixels of procenten afhankelijk van verhoudingen) |
| - | | + | // GSI 0 → linksrand, GSI 0.5 → ongeveer 90% breedte |
| - | row.innerHTML | + | const x = Math.min(100, Math.max(0, (gsi / 0.5) * 70+ 6)); // pas 70 en 6 aan voor horizontale correctie |
| - | < | + | |
| - | < | + | // FSI 0 → onderrand, FSI 3 → bovenzijde (ongeveer 5% marge boven) |
| - | <td><input type="number" | + | const y = Math.max(0, Math.min(100, |
| - | < | + | |
| - | <td id="totbvo_${i}"> | + | stip.style.left = `${x}%`; |
| - | `; | + | |
| - | tbody.appendChild(row); | + | } |
| - | }); | + | |
| + | function updateSummary(bvoTot, | ||
| + | | ||
| + | const pp_bvo = parseFloat(document.getElementById(" | ||
| + | const pp_bovengronds | ||
| + | const parkerenruimtePerWoning | ||
| + | const parkerenTot | ||
| + | |||
| + | const wonenBVO = bvoTot - voorzTot - parkerenTot; | ||
| + | const parkeerplaatsenTotaal = woningen * pp; | ||
| + | |||
| + | document.getElementById(" | ||
| + | document.getElementById("summary_wonen_bvo").innerText = `${wonenBVO.toFixed(0)} m²`; | ||
| + | | ||
| + | | ||
| + | |||
| + | document.getElementById("summary_voorz_per_won" | ||
| + | document.getElementById("summary_parkeren_per_won" | ||
| + | | ||
| + | |||
| + | document.getElementById("summary_wonen").innerText | ||
| + | document.getElementById("summary_woningen" | ||
| + | } | ||
| + | |||
| + | function updateLaadvermogen() { | ||
| + | const opp = parseFloat(document.getElementById("opp").value); | ||
| + | const fsi = parseFloat(document.getElementById("fsi").value); | ||
| + | const gsi = parseFloat(document.getElementById("gsi").value); | ||
| + | const bvoTot = opp * fsi; | ||
| + | const voorzieningenruimte = parseFloat(document.getElementById("voorzieningenruimte_display" | ||
| + | |||
| + | // Nieuw: parkeerinput ophalen | ||
| + | const pp = parseFloat(document.getElementById("pp_per_woning" | ||
| + | const pp_bvo = parseFloat(document.getElementById(" | ||
| + | const pp_bovengronds = parseFloat(document.getElementById("pp_bovengronds" | ||
| + | const parkerenruimte = pp * pp_bvo * (pp_bovengronds / 100); | ||
| + | |||
| + | updateStipje(fsi, | ||
| + | |||
| + | let gewogenBVO = 0; | ||
| + | let totalPerc = 0; | ||
| + | const details = []; | ||
| + | for (let i = 0; i < types.length; | ||
| + | const perc = parseFloat(document.getElementById(`perc_${i}`).value) || 0; | ||
| + | const bvo = parseFloat(document.getElementById(`bvo_${i}`).value) || 0; | ||
| + | gewogenBVO += (perc / 100) * bvo; | ||
| + | | ||
| + | details.push({ i, perc, bvo }); | ||
| + | } | ||
| + | if (gewogenBVO === 0) return; | ||
| + | |||
| + | // Nieuwe berekening met voorzieningen én parkeren | ||
| + | let woningen = Math.floor(bvoTot / (gewogenBVO + voorzieningenruimte + parkerenruimte)); | ||
| + | let sumWon = 0; | ||
| + | let sumBVO = 0; | ||
| + | let wonPerType = []; | ||
| + | let restant = woningen; | ||
| + | |||
| + | for (let i = 0; i < details.length; | ||
| + | const { perc } = details[i]; | ||
| + | let aant = (perc / 100) * woningen; | ||
| + | let afgerond = Math.floor(aant); | ||
| + | wonPerType.push(afgerond); | ||
| + | restant -= afgerond; | ||
| + | } | ||
| + | const decimaalSort = details.map((d, | ||
| + | .sort((a, b) => b.rest - a.rest); | ||
| + | for (let j = 0; j < restant; j++) { | ||
| + | wonPerType[decimaalSort[j].i]++; | ||
| + | } | ||
| + | |||
| + | for (let i = 0; i < details.length; | ||
| + | const aant = wonPerType[i]; | ||
| + | const bvoTot = aant * details[i].bvo; | ||
| + | document.getElementById(`aantal_${i}`).innerText = aant; | ||
| + | document.getElementById(`totbvo_${i}`).innerText = bvoTot.toFixed(0); | ||
| + | sumWon += aant; | ||
| + | sumBVO += bvoTot; | ||
| + | } | ||
| + | |||
| + | document.getElementById("totaal_perc").innerText | ||
| + | document.getElementById("totaal_gewbvo" | ||
| + | document.getElementById("totaal_won" | ||
| + | document.getElementById("totaal_bvo" | ||
| + | |||
| + | document.getElementById(" | ||
| + | `< | ||
| + | |||
| + | const voorzieningenTot | ||
| + | const wonenRuimte = bvoTot - voorzieningenTot - (sumWon * parkerenruimte); | ||
| + | updateSummary(bvoTot, | ||
| + | |||
| + | // Extra update voor parkeren per woning | ||
| + | document.getElementById("summary_parkeren_per_won").innerText | ||
| + | } | ||
| + | |||
| + | function maakVoorzieningentabel() { | ||
| + | const tbody = document.getElementById("voorzieningentabel" | ||
| + | voorzieningen.forEach((v, i) => { | ||
| + | const row = document.createElement("tr" | ||
| + | row.innerHTML = ` | ||
| + | <td>${v.naam}</ | ||
| + | <td>${v.norm}</ | ||
| + | <td>< | ||
| + | `; | ||
| + | tbody.appendChild(row); | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | function berekenVoorzieningenruimte() { | ||
| + | updateLaadvermogen(); | ||
| + | |||
| + | const bewonersPerWoning = parseFloat(document.getElementById(" | ||
| + | const woningen = parseFloat(document.getElementById(" | ||
| + | const totaalBewoners = woningen * bewonersPerWoning; | ||
| + | |||
| + | const resultDiv = document.getElementById(" | ||
| + | const btn = document.getElementById(" | ||
| + | |||
| + | if (woningen === 0) { | ||
| + | | ||
| + | btn.style.border = "1px solid # | ||
| + | btn.style.background = "# | ||
| + | return; | ||
| + | | ||
| + | |||
| + | let totaal_m2 = 0; | ||
| + | voorzieningen.forEach((v, | ||
| + | const checked = document.getElementById(`vchk_${i}`).checked; | ||
| + | if (checked) { | ||
| + | totaal_m2 += v.norm * totaalBewoners / 1000; | ||
| } | } | ||
| + | }); | ||
| - | function updateLaadvermogen() { | + | |
| - | | + | |
| - | const fsi = parseFloat(document.getElementById(" | + | |
| - | const gsi = parseFloat(document.getElementById(" | + | |
| - | const voorzieningPerc = parseFloat(document.getElementById(" | + | |
| - | const laadvermogen = Math.round(opp * fsi); | + | document.getElementById(" |
| - | const bvoVoorzieningen | + | |
| - | const bvoWonen | + | |
| - | document.getElementById(" | + | resultDiv.innerHTML |
| - | document.getElementById(" | + | btn.style.border = "1px solid #0a0"; |
| - | | + | btn.style.background |
| - | updateStipje(fsi, gsi); | + | updateLaadvermogen(); // herberekenen met nieuwe voorzieningenruimte |
| - | | + | |
| + | // Toon tabel met voorzieningen en m2 | ||
| + | const summaryBody = document.getElementById(" | ||
| + | const summaryTotal = document.getElementById(" | ||
| + | summaryBody.innerHTML = ""; | ||
| + | let subtotal = 0; | ||
| + | |||
| + | voorzieningen.forEach((v, i) => { | ||
| + | const checked = document.getElementById(`vchk_${i}`).checked; | ||
| + | if (checked) { | ||
| + | const v_m2 = v.norm * totaalBewoners / 1000; | ||
| + | subtotal += v_m2; | ||
| + | const row = document.createElement(" | ||
| + | row.innerHTML = `< | ||
| + | summaryBody.appendChild(row); | ||
| } | } | ||
| + | }); | ||
| + | summaryTotal.innerText = `${subtotal.toFixed(1)} m²`; | ||
| - | function bereken(opp, | + | } |
| - | const laadvermogen = opp * fsi; | + | |
| - | const woonBVO = laadvermogen * (1 - voorzieningPerc); | + | |
| - | let gewogenBVO | + | function berekenParkeerruimte() { |
| - | let totalPerc | + | const pp = parseFloat(document.getElementById(" |
| - | const details | + | const bvo_per_pp |
| + | const bovengronds | ||
| + | const woningen = parseFloat(document.getElementById(" | ||
| - | for (let i = 0; i < types.length; | + | |
| - | | + | const totaal_ruimte |
| - | const bvo = parseFloat(document.getElementById(`bvo_${i}`).value) || 0; | + | |
| - | gewogenBVO += (perc / 100) * bvo; | + | |
| - | totalPerc += perc; | + | |
| - | details.push({ i, perc, bvo }); | + | |
| - | } | + | |
| - | if (gewogenBVO | + | // Toon het resultaat en vinkje |
| + | const resultDiv = document.getElementById(" | ||
| + | resultDiv.innerHTML | ||
| - | const totaalWoningenExact = woonBVO | + | |
| - | let sumWon | + | const btn = document.getElementById(" |
| - | let sumBVO | + | |
| - | let wonPerType | + | |
| - | let restant = Math.round(totaalWoningenExact); | + | |
| - | for (let i = 0; i < details.length; | + | |
| - | const { perc } = details[i]; | + | |
| - | let aant = (perc / 100) * totaalWoningenExact; | + | |
| - | let afgerond = Math.floor(aant); | + | |
| - | wonPerType.push(afgerond); | + | |
| - | restant -= afgerond; | + | |
| - | } | + | |
| - | | + | const totaal_pp |
| - | i, rest: ((d.perc | + | const pp_boven_aantal |
| - | })).sort((a, b) => b.rest - a.rest); | + | const ondergronds = parseFloat(document.getElementById(" |
| + | const pp_onder_aantal = totaal_pp * (ondergronds / 100); | ||
| - | for (let j = 0; j < restant; j++) { | + | document.getElementById(" |
| - | wonPerType[decimaalSort[j].i]++; | + | document.getElementById(" |
| - | } | + | |
| - | for (let i = 0; i < details.length; | + | } |
| - | const aant = wonPerType[i]; | + | |
| - | const bvoTot = aant * details[i].bvo; | + | |
| - | document.getElementById(`aantal_${i}`).innerText = formatGetal(aant); | + | |
| - | document.getElementById(`totbvo_${i}`).innerText = formatGetal(bvoTot); | + | |
| - | sumWon += aant; | + | |
| - | sumBVO += bvoTot; | + | |
| - | | + | |
| - | document.getElementById(" | + | function updateOpenbareRuimte() { |
| - | | + | const opp = parseFloat(document.getElementById(" |
| - | document.getElementById(" | + | const gsi = parseFloat(document.getElementById(" |
| - | | + | const bebouwd |
| + | const onbebouwd = opp - bebouwd; | ||
| - | | + | const types = [ |
| - | if (Math.abs(totalPerc - 100) > 0.5) { | + | { id: " |
| - | | + | { id: " |
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | ]; | ||
| + | |||
| + | | ||
| + | | ||
| + | const perc = parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; | ||
| + | totaal += perc; | ||
| + | }); | ||
| + | |||
| + | | ||
| + | document.getElementById(" | ||
| + | return; | ||
| + | } else { | ||
| + | document.getElementById(" | ||
| + | } | ||
| + | |||
| + | types.forEach(type => { | ||
| + | const perc = parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; | ||
| + | const m2 = (perc / 100) * onbebouwd; | ||
| + | document.getElementById(`m2_${type.id}`).innerText = `${m2.toFixed(0)} m²`; | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | let openbareRuimteChart | ||
| + | |||
| + | function updateOpenbareRuimte() { | ||
| + | const opp = parseFloat(document.getElementById("opp" | ||
| + | const gsi = parseFloat(document.getElementById(" | ||
| + | const bebouwd = opp * gsi; | ||
| + | const onbebouwd = opp - bebouwd; | ||
| + | |||
| + | const types = [ | ||
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | { id: " | ||
| + | ]; | ||
| + | |||
| + | let totaal = 0; | ||
| + | let data = []; | ||
| + | |||
| + | types.forEach(type => { | ||
| + | const perc = parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; | ||
| + | totaal += perc; | ||
| + | }); | ||
| + | |||
| + | if (totaal !== 100) { | ||
| + | document.getElementById("warning_openbareruimte" | ||
| + | document.getElementById(" | ||
| + | return; | ||
| + | } else { | ||
| + | document.getElementById(" | ||
| + | } | ||
| + | |||
| + | // Bereken oppervlak per type en vul tabel | ||
| + | types.forEach(type => { | ||
| + | const perc = parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; | ||
| + | const m2 = (perc / 100) * onbebouwd; | ||
| + | document.getElementById(`m2_${type.id}`).innerText = `${m2.toFixed(0)} m²`; | ||
| + | data.push({ label: type.label, value: m2 }); | ||
| + | }); | ||
| + | |||
| + | // Totaal m² | ||
| + | const totaal_m2 = data.reduce((sum, | ||
| + | document.getElementById(" | ||
| + | |||
| + | // Vergelijking met onbebouwd oppervlak | ||
| + | const verschil = Math.abs(totaal_m2 - onbebouwd); | ||
| + | const totaalCell = document.getElementById(" | ||
| + | if (verschil > 1) { | ||
| + | totaalCell.style.color = " | ||
| + | totaalCell.title = `Let op: verschil van ${verschil.toFixed(1)} | ||
| + | } else { | ||
| + | totaalCell.style.color = ""; | ||
| + | totaalCell.title = ""; | ||
| + | } | ||
| + | |||
| + | | ||
| + | const ctx = document.getElementById(" | ||
| + | const labels = data.map(d => d.label); | ||
| + | const values = data.map(d => d.value); | ||
| + | |||
| + | if (openbareRuimteChart) { | ||
| + | openbareRuimteChart.data.labels = labels; | ||
| + | openbareRuimteChart.data.datasets[0].data = values; | ||
| + | openbareRuimteChart.update(); | ||
| + | } else { | ||
| + | openbareRuimteChart = new Chart(ctx, { | ||
| + | type: ' | ||
| + | data: { | ||
| + | labels: labels, | ||
| + | datasets: [{ | ||
| + | data: values, | ||
| + | backgroundColor: | ||
| + | '# | ||
| + | '# | ||
| + | ] | ||
| + | }] | ||
| + | }, | ||
| + | options: { | ||
| + | plugins: { | ||
| + | legend: { position: ' | ||
| + | title: { | ||
| + | display: true, | ||
| + | text: ' | ||
| + | } | ||
| } | } | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| + | } | ||
| - | | + | |
| - | ${waarschuwing} | + | function setVerdelingStedelijkheid() { |
| - | <p><b>Gewogen BVO/ehd:</b> ${gewogenBVO.toFixed(1)} m²<br> | + | const type = document.getElementById(" |
| - | < | + | let waarden |
| - | `; | + | |
| + | if (type === " | ||
| + | waarden = { groen: 18, water: 4, tuinen: 8, rijbanen: 25, trottoirs: 20, parkeren: 10, pleinen: 15 }; | ||
| + | } else if (type === " | ||
| + | waarden = { groen: 20, water: 10, tuinen: 10, rijbanen: 20, trottoirs: 15, parkeren: 15, pleinen: 10 }; | ||
| + | } else if (type === " | ||
| + | waarden = { groen: 30, water: 15, tuinen: 25, rijbanen: 15, trottoirs: 8, parkeren: 5, pleinen: 2 }; | ||
| + | } else { | ||
| + | updateOpenbareRuimte(); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | Object.keys(waarden).forEach(id => { | ||
| + | document.getElementById(`perc_${id}`).value = waarden[id]; | ||
| + | }); | ||
| + | |||
| + | updateOpenbareRuimte(); | ||
| + | } | ||
| + | |||
| + | // 👇 Bouw de volledige woningtype + parkeren-tabel met eerste kolom labels, geschikt voor Kladblok | ||
| + | function buildWoningtypesTableTXT() { | ||
| + | const types = ["egw sociaal", | ||
| + | " | ||
| + | const parkeerkolommen = [" | ||
| + | const kolommen = [...types, ...parkeerkolommen]; | ||
| + | const colWidth = 13; | ||
| + | const labelWidth = 18; | ||
| + | |||
| + | const pad = (val) => val.toString().padStart(colWidth); | ||
| + | const head = (val) => val.toString().padEnd(colWidth); | ||
| + | const label = (txt) => `| ${txt}`.padEnd(labelWidth); | ||
| + | |||
| + | | ||
| + | const perc = types.map((_, | ||
| + | const bvo = types.map((_, i) => parseFloat(document.getElementById(`bvo_${i}`)?.value || " | ||
| + | const aantallen = types.map((_, | ||
| + | const vormfactor = types.map((_, | ||
| + | const bvo_tot = bvo.map((b, i) => b * aantallen[i]); | ||
| + | const gbo = bvo.map((b, i) => (b * vormfactor[i]).toFixed(1)); | ||
| + | |||
| + | // PARKEERREGELS berekenen | ||
| + | const pp = parseFloat(document.getElementById(" | ||
| + | const woningen = aantallen.reduce((acc, | ||
| + | const bvo_pp = parseFloat(document.getElementById(" | ||
| + | const perc_boven = parseFloat(document.getElementById(" | ||
| + | const perc_onder = parseFloat(document.getElementById(" | ||
| + | const pp_boven = Math.round(woningen * pp * (perc_boven / 100)); | ||
| + | const pp_onder = Math.round(woningen * pp * (perc_onder / 100)); | ||
| + | const bvo_boven = pp_boven * bvo_pp; | ||
| + | const bvo_onder = pp_onder * bvo_pp; | ||
| + | |||
| + | // PARKEERGEGEVENS toevoegen | ||
| + | perc.push(" | ||
| + | bvo.push(bvo_pp, | ||
| + | aantallen.push(pp_boven, | ||
| + | bvo_tot.push(bvo_boven, | ||
| + | vormfactor.push(1.00, | ||
| + | gbo.push((bvo_pp * 1.00).toFixed(1), | ||
| + | |||
| + | // TABEL opbouwen | ||
| + | const r = []; | ||
| + | r.push(label(" | ||
| + | r.push("" | ||
| + | r.push(label(" | ||
| + | r.push(label(" | ||
| + | r.push(label(" | ||
| + | r.push(label(" | ||
| + | r.push(label(" | ||
| + | r.push(label(" | ||
| + | |||
| + | // GEMIDDELDES (alleen woningtypes, | ||
| + | const woningtypes = [...Array(10).keys()]; | ||
| + | const totale_bvo = woningtypes.reduce((sum, | ||
| + | const totale_gbo = woningtypes.reduce((sum, | ||
| + | const totaal_woningen = woningtypes.reduce((sum, | ||
| + | |||
| + | const gemiddelde_bvo = totaal_woningen > 0 ? (totale_bvo / totaal_woningen).toFixed(1) : " | ||
| + | const gemiddelde_gbo = totaal_woningen > 0 ? (totale_gbo / totaal_woningen).toFixed(1) : " | ||
| + | |||
| + | r.push("" | ||
| + | r.push(`Totale | ||
| + | r.push(`Gemiddelde BVO per woning: ${gemiddelde_bvo}`); | ||
| + | r.push(`Gemiddelde GBO per woning: ${gemiddelde_gbo}`); | ||
| + | |||
| + | return r.join(" | ||
| + | } | ||
| + | |||
| + | async function downloadKickstartDump() { | ||
| + | console.log(" | ||
| + | |||
| + | try { | ||
| + | const response = await fetch(' | ||
| + | if (!response.ok) throw new Error(`Bestand niet bereikbaar (${response.status})`); | ||
| + | |||
| + | let template = await response.text(); | ||
| + | console.log(" | ||
| + | |||
| + | const bvo_per_pp = parseFloat(document.getElementById(" | ||
| + | const pp_bovengronds = parseFloat(document.getElementById(" | ||
| + | const pp_ondergronds = parseFloat(document.getElementById(" | ||
| + | const woningen = parseFloat(document.getElementById(" | ||
| + | const pp = parseFloat(document.getElementById(" | ||
| + | |||
| + | const bvo_per_pp_boven = bvo_per_pp.toFixed(1); | ||
| + | const bvo_per_pp_onder = bvo_per_pp.toFixed(1); | ||
| + | |||
| + | const parkeeropp_totaal = woningen * pp * bvo_per_pp; | ||
| + | const parkeeropp_boven = parkeeropp_totaal * (pp_bovengronds / 100); | ||
| + | const parkeeropp_onder = parkeeropp_totaal * (pp_ondergronds / 100); | ||
| + | |||
| + | const data = { | ||
| + | datum: new Date().toISOString().slice(0, | ||
| + | aantal_woningen: | ||
| + | bvo_per_woning: | ||
| + | pp_boven: document.getElementById(" | ||
| + | pp_onder: document.getElementById(" | ||
| + | bvo_boven: document.getElementById(" | ||
| + | bvo_onder: " | ||
| + | bvo_per_pp_boven: | ||
| + | bvo_per_pp_onder: | ||
| + | totbvo_boven: | ||
| + | totbvo_onder: | ||
| + | woningtypes_table: | ||
| + | voorzieningen_table: | ||
| + | plankaart_table: | ||
| + | grex_table: buildGrexTableTXT() | ||
| + | | ||
| + | |||
| + | for (let i = 0; i < 10; i++) { | ||
| + | data[`perc_${i}`] = document.getElementById(`perc_${i}`)? | ||
| + | data[`bvo_${i}`] = document.getElementById(`bvo_${i}`)? | ||
| + | data[`aantal_${i}`] = document.getElementById(`aantal_${i}`)? | ||
| + | data[`totbvo_${i}`] = document.getElementById(`totbvo_${i}`)? | ||
| } | } | ||
| - | function | + | |
| - | | + | template = template.replaceAll(`{{${key}}}`, |
| - | | + | }); |
| + | |||
| + | const blob = new Blob([template], | ||
| + | saveAs(blob, | ||
| + | alert(" | ||
| + | } catch (error) { | ||
| + | console.error(" | ||
| + | alert(" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function | ||
| + | let output = ""; | ||
| + | const rows = document.querySelectorAll("# | ||
| + | | ||
| + | const cells = row.querySelectorAll(" | ||
| + | if (cells.length === 2) { | ||
| + | const naam = cells[0].innerText.trim(); | ||
| + | const m2 = cells[1].innerText.trim(); | ||
| + | output += `| ${naam.padEnd(25)} | ${m2.padStart(14)} |\n`; | ||
| } | } | ||
| + | }); | ||
| + | return output || "| Geen voorzieningen geselecteerd | – |"; | ||
| + | } | ||
| - | window.onload = init; | + | function buildPlankaartTableTXT() { |
| + | const opp = parseFloat(document.getElementById(" | ||
| + | const gsi = parseFloat(document.getElementById(" | ||
| + | const footprint = gsi * opp; | ||
| + | const tuin = getVal(" | ||
| + | const uitgeefbaar = tuin + footprint; | ||
| + | |||
| + | return `Omschrijving | ||
| + | ----------------------------|---------------- | ||
| + | Totaal bruto plangebied | ||
| + | ----------------------------|---------------- | ||
| + | Tuinen | ||
| + | Footprint (GSI x opp) | ${footprint.toFixed(0)} | ||
| + | ----------------------------|---------------- | ||
| + | Totaal uitgeefbaar | ||
| + | Rijbanen | ||
| + | Trottoirs | ||
| + | Parkeren (bovengr.) | ||
| + | Pleinen | ||
| + | ----------------------------|---------------- | ||
| + | Totaal verharding | ||
| + | Groen | ${getVal(" | ||
| + | Water | ${getVal(" | ||
| + | } | ||
| + | |||
| + | function buildGrexTableTXT() { | ||
| + | return `Categorie | ||
| + | --------------------|----------------------------------------|---------------- | ||
| + | Verwerving | ||
| + | Grondwerk | ||
| + | Bouwrijp maken | Bouwstraten | ||
| + | Woonrijp maken | Rijbanen | ||
| + | Woonrijp maken | Trottoirs | ||
| + | Woonrijp maken | Parkeren | ||
| + | Woonrijp maken | Pleinen | ||
| + | Woonrijp maken | Groen | ${getVal(" | ||
| + | Woonrijp maken | Bomen en groenstructuur | ||
| + | Woonrijp maken | Verdere aankleding openbare ruimte | ||
| + | Nazorg | ||
| + | Onvoorzien | ||
| + | } | ||
| + | |||
| + | function getVal(id) { | ||
| + | const el = document.getElementById(id); | ||
| + | return el ? parseFloat(el.innerText.replace(" | ||
| + | } | ||
| + | |||
| + | |||
| + | |||
| + | window.onload = () => { | ||
| + | renderWoningtypes(); | ||
| + | maakVoorzieningentabel(); | ||
| + | updateLaadvermogen(); | ||
| + | }; | ||
| </ | </ | ||
| + | |||
| + | </ | ||
| </ | </ | ||
handleiding_nieuw/sub_spacematrix.1746608671.txt.gz · Last modified: 2025/05/07 09:04 by support