User Tools

Site Tools


handleiding_nieuw:sub_spacematrix

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
handleiding_nieuw:sub_spacematrix [2025/05/13 15:04] supporthandleiding_nieuw:sub_spacematrix [2026/01/31 10:06] (current) – external edit 127.0.0.1
Line 7: Line 7:
   <meta charset="UTF-8">   <meta charset="UTF-8">
   <title>Spacematrix Rekenblok + Voorzieningen + Parkeren</title>   <title>Spacematrix Rekenblok + Voorzieningen + Parkeren</title>
 +  
   <style>   <style>
-    body { font-family: sans-serif; margin: 20px; } +/* ========== Tabs ========== */ 
-    .tabs { display: flex; gap: 10px; margin-bottom15px; } + 
-    .tab { padding: 10px 15px; background: #ddd; cursor: pointer; border-radius: 5px 5px 0 0; } +.tabs{ 
-    .tab.active { background: #f0f0f0; font-weight: bold; } +  display:flex; 
-    .tabcontent { display: none; border: 1px solid #ccc; padding: 15px; border-radius:5px 5px 5px; } +  gap:6px; 
-    .tabcontent.active { display: block; } +  margin: 12px 0 0 0; 
-    .inputrow { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; } +  padding: 0; 
-    .inputrow label { width: 240px; } +  flex-wrap:wrap; 
-    .inputrow input { width: 80px; } +
-    table { border-collapse: collapse; width: 100%; margin-top: 10px; } + 
-    th, td { border: 1px solid #ccc; padding: 5px; text-align: right; } +.tab{ 
-    th { background: #f0f0f0; } +  padding:8px 12px; 
-    td:first-child, th:first-child { text-align: left; } +  background:#e7e7e7; 
-    .kaartcontainer { position: relative; max-width: 350px; margin-top: 20px; } +  cursor:pointer; 
-    .kaartcontainer img { width: 100%; display: block; } +  border:1px solid #cfcfcf; 
-    .stipje { position: absolute; width: 14px; height: 14px; background: red; border-radius: 50%; transform: translate(-50%, -50%); border: 2px solid white; } +  border-bottom:none; 
-  </style>+  border-radius:8px 8px 0 0; 
 +  color:#222; 
 +  font-weight:600; 
 +  user-select:none; 
 +
 + 
 +.tab:hover{ background:#dddddd;
 + 
 +.tab.active{ 
 +  background:#ffffff; 
 +  position:relative; 
 +  top:1px; 
 +  font-weight:700; 
 +
 + 
 +.tabcontent{ 
 +  display:none; 
 +  border:1px solid #cfcfcf; 
 +  padding:15px; 
 +  border-radius:8px 8px 8px; 
 +  background:#fff; 
 +
 + 
 +.tabcontent.active{ display:block;
 + 
 +@media (max-width: 900px){ 
 +  .tabs{ gap:6px; } 
 +
 + 
 + 
 +  body { font-family: sans-serif; margin: 20px; } 
 + 
 +  .inputrow { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; } 
 +  .inputrow label { width: 240px; } 
 +  .inputrow input { width: 80px; } 
 + 
 +  table { border-collapse: collapse; width: 100%; margin-top: 10px; } 
 +  th, td { border: 1px solid #ccc; padding: 5px; text-align: right; } 
 +  th { background: #f0f0f0; } 
 +  td:first-child, th:first-child { text-align: left; } 
 + 
 +  .kaartcontainer { position: relative; max-width: 350px; margin-top: 20px; } 
 +  .kaartcontainer img { width: 100%; display: block; } 
 +  .stipje { position: absolute; width: 14px; height: 14px; background: red; border-radius: 50%; transform: translate(-50%, -50%); border: 2px solid white; } 
 + 
 +  .perc-warning{ color: #b00020; font-weight: 700; } 
 + 
 +  /* ========== Header + Scenario bar ========== */ 
 +  .pageheader{ 
 +    display:flex; 
 +    align-items:flex-end; 
 +    justify-content:space-between; 
 +    gap:16px; 
 +    margin-bottom:10px; 
 +  } 
 + 
 +  .pageheader h1{ 
 +    margin:0; 
 +    line-height:1.05; 
 +  } 
 + 
 +  
 +  .scenario-bar{  
 +  display:flex;  
 +  align-items:flex-start;  
 +  justify-content:flex-end;  
 +  gap:12px;  
 +  flex-wrap:wrap;  
 +
 + 
 +.scenario-left{ 
 +  display:flex; 
 +  flex-direction:column; 
 +  gap:4px; 
 +  min-width:360px; 
 +  flex:1; 
 +
 + 
 +.scenario-left select{ 
 +  height:34px; 
 +  padding:0 10px; 
 +  border-radius:6px; 
 +  border:1px solid #c9d6d6; 
 +  background:#fff; 
 +
 + 
 +.scenario-right{ 
 +  display:flex; 
 +  align-items:center; 
 +  gap:8px; 
 +  flex-wrap:wrap; 
 +  justify-content:flex-end; 
 +
 + 
 +.scenario-right .btn{ 
 +  height:34px; 
 +  padding:0 10px; 
 +  border-radius:6px; 
 +  border:1px solid #c9d6d6; 
 +  background:#f4f7f7; 
 +  color:#113333; 
 +  font-weight:700; 
 +  cursor:pointer; 
 +
 + 
 +.scenario-right .btn:hover{ 
 +  background:#e9f1f1; 
 +  border-color:#9fbcbc; 
 +
 + 
 +.scenario-right .btn.primary{ 
 +  background:#3aa39a; 
 +  border-color:#2e8f86; 
 +  color:#fff; 
 +
 + 
 +.scenario-right .btn.primary:hover{ 
 +  background:#2e8f86; 
 +
 + 
 +.scenario-right .btn.danger{ 
 +  background:#f7eaea; 
 +  border-color:#e2bcbc; 
 +  color:#7a1f1f; 
 +
 + 
 +.scenario-right .btn.danger:hover{ 
 +  background:#f2dcdc; 
 +
 + 
 +#sm_loaded_label{ color:#2b4a4a; font-size:0.92em;
 +#sm_save_status{ color:#2b4a4a; font-size:0.9em; white-space:nowrap; margin-left:6px;
 + 
 + 
 +/* ====== Spacematrix legenda (onder invoervelden, links) + hover-tooltips ====== */ 
 + 
 +.sm-legend{ 
 +  margin-top: 14px; 
 +  border: 1px solid #c9d6d6; 
 +  border-radius: 8px; 
 +  background: #fff; 
 +  padding: 6px 8px; 
 +  max-width: 250px; 
 +  min-height: 118px; 
 +  margin-bottom: 14px; 
 +
 + 
 +.sm-legend-title{ 
 +  margin: 0 0 6px 0; 
 +  font-size: 0.84rem; 
 +  font-weight: 700; 
 +  color: #113333; 
 +
 + 
 +.sm-legend-grid{ 
 +  display: grid; 
 +  grid-template-columns: 1fr; 
 +  gap: 5px; 
 +
 + 
 +.sm-legend-item{ 
 +  display: grid; 
 +  grid-template-columns: 22px auto; 
 +  gap: 6px; 
 +  align-items: start; 
 +  font-size: 0.80rem; 
 +  line-height: 1.15; 
 +  color: #1f3e3e; 
 +
 + 
 +.sm-zone-badge{ 
 +  width: 18px; 
 +  height: 18px; 
 +  border-radius: 4px; 
 +  font-size: 0.68rem; 
 +  font-weight: 800; 
 +  background: #e9f1f1; 
 +  border: 1px solid #c9d6d6; 
 +  color: #113333; 
 +  display: inline-flex; 
 +  align-items: center; 
 +  justify-content: center; 
 +
 + 
 +.sm-legend-short{ 
 +  display: inline-flex; 
 +  align-items: center; 
 +  gap: 4px; 
 +
 + 
 +/* Info-icoon (klein en rustig) */ 
 +.sm-legend-i{ 
 +  width: 16px; 
 +  height: 16px; 
 +  border-radius: 50%; 
 +  display: inline-flex; 
 +  align-items: center; 
 +  justify-content: center; 
 +  font-size: 0.72rem; 
 +  font-weight: 800; 
 +  border: 1px solid #c9d6d6; 
 +  background: #f4f7f7; 
 +  color: #2b4a4a; 
 +  cursor: help; 
 +  user-select: none; 
 +
 + 
 +/* ====== Tooltip mechaniek ======*/ 
 + 
 +.sm-tip{ 
 +  position: relative; 
 +  display: inline-flex; 
 +  align-items: center; 
 +
 + 
 +/* Tooltip bubble */ 
 +.sm-tip::after{ 
 +  content: attr(data-tip); 
 +  position: absolute; 
 +  left: 0; 
 +  top: calc(100% + 8px); 
 +  width: 260px; 
 +  max-width: 70vw; 
 +  background: #113333; 
 +  color: #fff; 
 +  padding: 8px 10px; 
 +  border-radius: 8px; 
 +  font-size: 0.8rem; 
 +  line-height: 1.25; 
 +  box-shadow: 0 8px 18px rgba(0,0,0,0.18); 
 +  opacity: 0; 
 +  transform: translateY(-4px); 
 +  pointer-events: none; 
 +  transition: opacity 120ms ease, transform 120ms ease; 
 +  z-index: 50; 
 +  white-space: normal; 
 +
 + 
 +/* Tooltip pijltje */ 
 +.sm-tip::before{ 
 +  content: ""; 
 +  position: absolute; 
 +  left: 10px; 
 +  top: calc(100% + 2px); 
 +  border: 6px solid transparent; 
 +  border-bottom-color: #113333; 
 +  opacity: 0; 
 +  transform: translateY(-4px); 
 +  pointer-events: none; 
 +  transition: opacity 120ms ease, transform 120ms ease; 
 +  z-index: 51; 
 +
 + 
 +/* Toon tooltip bij hover/focus */ 
 +.sm-tip:hover::after, 
 +.sm-tip:focus-within::after, 
 +.sm-tip:hover::before, 
 +.sm-tip:focus-within::before{ 
 +  opacity: 1; 
 +  transform: translateY(0); 
 +
 + 
 +/* Toegankelijk: focus-ring op i */ 
 +.sm-legend-i:focus{ 
 +  outline: none; 
 +  box-shadow: 0 0 0 3px rgba(0, 116, 217, 0.18); 
 +  border-color: #9fbfe6; 
 +
 + 
 +/* Mobiel: iets breder tooltip */ 
 +@media (max-width: 600px){ 
 +  .sm-tip::after{ width: 240px; } 
 +
 + 
 +</style> 
 +   
 +  
   <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>   <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
 </head> </head>
 <body> <body>
  
-<h1>Spacematrix & Voorzieningen</h1>+ 
 +<div class="pageheader"> 
 +  <h1>Stedelijke Dichtheidsrekenmachine</h1> 
 + 
 + <div class="scenario-bar"> 
 +  <div class="scenario-left"> 
 +    <select id="sm_scenario_select" title="Kies een opgeslagen scenario" onchange="smUI_onScenarioChange()"></select> 
 +    <span id="sm_loaded_label"></span> 
 +  </div> 
 + 
 +  <div class="scenario-right"> 
 +    <button class="btn primary" type="button" onclick="smUI_save()">Opslaan…</button> 
 +    <button class="btn primary" type="button" onclick="smUI_loadSelected()">Openen</button> 
 +    <button class="btn danger" type="button" onclick="smUI_deleteSelected()">Verwijderen</button> 
 +    <button class="btn" type="button" onclick="smUI_openHelp()">Handleiding</button> 
 +    <button class="btn" type="button" onclick="smUI_resetAll()">Reset</button> 
 +    <span id="sm_save_status"></span> 
 +  </div> 
 +</div> 
 +</div> 
 + 
 +<!-- RESPONSIVE VOOR MOBIELE TELEFOONS --> 
 +<div class="mobile-hint"> 
 +  <strong>Let op (mobiele weergave)</strong><br> 
 +  Deze pagina bevat interactieve grafieken en tabellen die zijn ontworpen voor gebruik op een groter scherm. 
 +  Voor een beter overzicht kun je je telefoon liggend houden of deze pagina openen op een tablet of laptop. 
 +</div> 
 + 
 <div class="tabs"> <div class="tabs">
 +
   <div class="tab active" onclick="switchTab('rekenblok')">Spacematrix Rekenblok</div>   <div class="tab active" onclick="switchTab('rekenblok')">Spacematrix Rekenblok</div>
   <div class="tab" onclick="switchTab('voorzieningen')">Voorzieningen</div>   <div class="tab" onclick="switchTab('voorzieningen')">Voorzieningen</div>
Line 57: Line 363:
         <input type="hidden" id="voorzieningenruimte_waarde" value="0">         <input type="hidden" id="voorzieningenruimte_waarde" value="0">
    </div>    </div>
 + 
 + <!-- legenda Spacematrix --> 
 +
 +<div class="sm-legend">
 +  <div class="sm-legend-title">Legenda zones (A–H)</div>
 +
 +  <div class="sm-legend-grid">
 +
 +    <div class="sm-legend-item">
 +      <span class="sm-zone-badge">A</span>
 +      <div class="sm-legend-short">
 +        Low-rise spacious blocks
 +        <span class="sm-tip" data-tip="Lage bouwhoogte met veel open ruimte. Past bij tuinstedelijke of ruime woonmilieus.">
 +          <span class="sm-legend-i" tabindex="0">i</span>
 +        </span>
 +      </div>
     </div>     </div>
-    <div class="kaartcontainer" style="max-width: 500px;"> + 
-      <img src="https://www.sumsonite.nl/wiki/lib/exe/fetch.php?media=handleiding_nieuw:spacematrix:SPACEMATE1.png" alt="Spacematrix kaart">+    <div class="sm-legend-item"> 
 +      <span class="sm-zone-badge">B</span> 
 +      <div class="sm-legend-short"> 
 +        Low-rise compact blocks 
 +        <span class="sm-tip" data-tip="Lage bouwhoogte met compacte verkaveling. Veelal grondgebonden woningen."> 
 +          <span class="sm-legend-i" tabindex="0">i</span> 
 +        </span> 
 +      </div> 
 +    </div> 
 + 
 +    <div class="sm-legend-item"> 
 +      <span class="sm-zone-badge">C</span> 
 +      <div class="sm-legend-short"> 
 +        Mid-rise open blocks 
 +        <span class="sm-tip" data-tip="Middelhoge bebouwing met relatief open opzet en duidelijke openbare ruimte."> 
 +          <span class="sm-legend-i" tabindex="0">i</span> 
 +        </span> 
 +      </div> 
 +    </div> 
 + 
 +    <div class="sm-legend-item"> 
 +      <span class="sm-zone-badge">D</span> 
 +      <div class="sm-legend-short"> 
 +        Mid-rise spacious blocks 
 +        <span class="sm-tip" data-tip="Middelhoge bebouwing met meer lagen, maar nog steeds een ruimtelijk karakter."> 
 +          <span class="sm-legend-i" tabindex="0">i</span> 
 +        </span> 
 +      </div> 
 +    </div> 
 + 
 +    <div class="sm-legend-item"> 
 +      <span class="sm-zone-badge">E</span> 
 +      <div class="sm-legend-short"> 
 +        Mid-rise compact blocks 
 +        <span class="sm-tip" data-tip="Compact stedelijk woonmilieu met hogere dichtheid en beperkte open ruimte."> 
 +          <span class="sm-legend-i" tabindex="0">i</span> 
 +        </span> 
 +      </div> 
 +    </div> 
 + 
 +    <div class="sm-legend-item"> 
 +      <span class="sm-zone-badge">F</span> 
 +      <div class="sm-legend-short"> 
 +        Mid-rise closed blocks 
 +        <span class="sm-tip" data-tip="Gesloten bouwblokken met duidelijke straatwanden en hogere stedelijkheid."> 
 +          <span class="sm-legend-i" tabindex="0">i</span> 
 +        </span> 
 +      </div> 
 +    </div> 
 + 
 +    <div class="sm-legend-item"> 
 +      <span class="sm-zone-badge">G</span> 
 +      <div class="sm-legend-short"> 
 +        Mid-rise super-blocks 
 +        <span class="sm-tip" data-tip="Zeer intensieve stedelijke blokken met hoge FSI en multifunctioneel gebruik."> 
 +          <span class="sm-legend-i" tabindex="0">i</span> 
 +        </span> 
 +      </div> 
 +    </div> 
 + 
 +    <div class="sm-legend-item"> 
 +      <span class="sm-zone-badge">H</span> 
 +      <div class="sm-legend-short"> 
 +        High-rise developments 
 +        <span class="sm-tip" data-tip="Hoogbouwontwikkelingen met veel lagen, vaak gecombineerd met open ruimte op maaiveld."> 
 +          <span class="sm-legend-i" tabindex="0">i</span> 
 +        </span> 
 +      </div> 
 +    </div> 
 + 
 +  </div> 
 +</div> 
 + 
 + <!-- Einde Legenda en Tooltip --> 
 +  
 + </div> 
 + 
 +  
 + <div class="kaartcontainer" style="max-width: 500px;"> 
 +      <img src="/wiki/lib/exe/fetch.php?media=handleiding_nieuw:spacematrix:SPACEMATE1.png" alt="Spacematrix kaart">
       <div class="stipje" id="stipje"></div>       <div class="stipje" id="stipje"></div>
     </div>     </div>
Line 217: Line 618:
 </div> </div>
  
-<script> 
-const types = ["egw sociaal", "egw goedkoop", "egw midden", "egw duur", "egw top", "mgw sociaal", "mgw goedkoop", "mgw midden", "mgw duur", "mgw top"]; 
-const voorzieningen = [ 
-  { naam: "Huisarts", norm: 56 }, 
-  { naam: "Fysiotherapie", norm: 54 }, 
-  { naam: "Tandarts", norm: 57 }, 
-  { naam: "Kinderopvang", norm: 2025 }, 
-  { naam: "Basisschool", norm: 5800 }, 
-  { naam: "Bibliotheek", norm: 60 }, 
-  { naam: "Buurtcentrum", norm: 70 }, 
-  { naam: "Sporthal", norm: 165 }, 
-  { naam: "Zwemmen (overdekt)", norm: 45 }, 
-  { naam: "Winkels dagelijkse goederen", norm: 420 } 
-]; 
- 
-function switchTab(tabId) { 
-  document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); 
-  document.querySelectorAll('.tabcontent').forEach(c => c.classList.remove('active')); 
-  document.querySelector(`.tab[onclick*="${tabId}"]`).classList.add('active'); 
-  document.getElementById(tabId).classList.add('active'); 
-} 
- 
-function renderWoningtypes() { 
-  const tbody = document.getElementById("woningtypes"); 
-  tbody.innerHTML = ""; 
-  types.forEach((type, i) => { 
-    const row = document.createElement("tr"); 
-    row.innerHTML = ` 
-      <td>${type}</td> 
-      <td><input type="number" id="perc_${i}" value="10" step="0.1" oninput="updateLaadvermogen()"></td> 
-      <td><input type="number" id="bvo_${i}" value="${i < 5 ? 130 : 90}" step="1" oninput="updateLaadvermogen()"></td> 
-      <td id="aantal_${i}">-</td> 
-      <td id="totbvo_${i}">-</td> 
-    `; 
-    tbody.appendChild(row); 
-  }); 
-} 
- 
-function updateStipje(fsi, gsi) { 
-  const stip = document.getElementById("stipje"); 
-  const x = Math.min(100, Math.max(0, gsi * 190)); 
-  const y = Math.max(0, Math.min(100, (3 - fsi) * 35)); 
-  stip.style.left = `${x}%`; 
-  stip.style.top = `${y}%`; 
-} 
- 
-function updateSummary(bvoTot, voorzTot, voorzPerWoning, woonruimte, woningen) { 
-  const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0; 
-  const pp_bvo = parseFloat(document.getElementById("bvo_per_pp").value) || 0; 
-  const pp_bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0; 
-  const parkerenruimtePerWoning = pp * pp_bvo * (pp_bovengronds / 100); 
-  const parkerenTot = woningen * parkerenruimtePerWoning; 
- 
-  const wonenBVO = bvoTot - voorzTot - parkerenTot; 
-  const parkeerplaatsenTotaal = woningen * pp; 
- 
-  document.getElementById("summary_bvo_tot").innerText = `${bvoTot.toFixed(0)} m²`; 
-  document.getElementById("summary_wonen_bvo").innerText = `${wonenBVO.toFixed(0)} m²`; 
-  document.getElementById("summary_voorz_tot").innerText = `${voorzTot.toFixed(0)} m²`; 
-  document.getElementById("summary_parkeren_tot").innerText = `${parkerenTot.toFixed(0)} m²`; 
- 
-  document.getElementById("summary_voorz_per_won").innerText = `${voorzPerWoning.toFixed(1)} m²`; 
-  document.getElementById("summary_parkeren_per_won").innerText = `${parkerenruimtePerWoning.toFixed(1)} m²`; 
-  document.getElementById("summary_pp_tot").innerText = `${parkeerplaatsenTotaal.toFixed(0)}`; 
- 
-  document.getElementById("summary_wonen").innerText = `${woonruimte.toFixed(0)} m²`; 
-  document.getElementById("summary_woningen").innerText = `${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").innerText) || 0; 
- 
-  // Nieuw: parkeerinput ophalen 
-  const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0; 
-  const pp_bvo = parseFloat(document.getElementById("bvo_per_pp").value) || 0; 
-  const pp_bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0; 
-  const parkerenruimte = pp * pp_bvo * (pp_bovengronds / 100); 
- 
-  updateStipje(fsi, gsi); 
- 
-  let gewogenBVO = 0; 
-  let totalPerc = 0; 
-  const details = []; 
-  for (let i = 0; i < types.length; i++) { 
-    const perc = parseFloat(document.getElementById(`perc_${i}`).value) || 0; 
-    const bvo = parseFloat(document.getElementById(`bvo_${i}`).value) || 0; 
-    gewogenBVO += (perc / 100) * bvo; 
-    totalPerc += perc; 
-    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; i++) { 
-    const { perc } = details[i]; 
-    let aant = (perc / 100) * woningen; 
-    let afgerond = Math.floor(aant); 
-    wonPerType.push(afgerond); 
-    restant -= afgerond; 
-  } 
-  const decimaalSort = details.map((d, i) => ({ i, rest: ((d.perc / 100) * woningen) % 1 })) 
-    .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; i++) { 
-    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 = `${totalPerc.toFixed(1)}%`; 
-  document.getElementById("totaal_gewbvo").innerText = `${gewogenBVO.toFixed(1)} m²`; 
-  document.getElementById("totaal_won").innerText = sumWon; 
-  document.getElementById("totaal_bvo").innerText = sumBVO.toFixed(0); 
- 
-  document.getElementById("output").innerHTML = 
-    `<p><b>Gewogen BVO/ehd:</b> ${gewogenBVO.toFixed(1)} m²<br><b>Totaal aantal woningen:</b> ${sumWon}</p>`; 
- 
-  const voorzieningenTot = sumWon * voorzieningenruimte; 
-  const wonenRuimte = bvoTot - voorzieningenTot - (sumWon * parkerenruimte); 
-  updateSummary(bvoTot, voorzieningenTot, voorzieningenruimte, wonenRuimte, sumWon); 
- 
-  // Extra update voor parkeren per woning 
-  document.getElementById("summary_parkeren_per_won").innerText = `${parkerenruimte.toFixed(1)} m²`; 
-} 
- 
-function maakVoorzieningentabel() { 
-  const tbody = document.getElementById("voorzieningentabel"); 
-  voorzieningen.forEach((v, i) => { 
-    const row = document.createElement("tr"); 
-    row.innerHTML = ` 
-      <td>${v.naam}</td> 
-      <td>${v.norm}</td> 
-      <td><input type="checkbox" id="vchk_${i}" checked></td> 
-    `; 
-    tbody.appendChild(row); 
-  }); 
-} 
- 
-function berekenVoorzieningenruimte() { 
-  updateLaadvermogen(); // om actuele woningaantal op te halen 
- 
-  const bewonersPerWoning = parseFloat(document.getElementById("bewoners_per_woning").value); 
-  const woningen = parseFloat(document.getElementById("totaal_won").innerText.replace(/[^0-9]/g, "")) || 0; 
-  const totaalBewoners = woningen * bewonersPerWoning; 
- 
-  const resultDiv = document.getElementById("voorziening_resultaat"); 
-  const btn = document.getElementById("btn_voorzieningen"); 
- 
-  if (woningen === 0) { 
-    resultDiv.innerHTML = `<span style="color:red; font-weight:bold;">✖</span> Geen woningen gevonden. Vul eerst FSI/GSI en woningpercentages in.`; 
-    btn.style.border = "1px solid #a00"; 
-    btn.style.background = "#ffe6e6"; 
-    return; 
-  } 
- 
-  let totaal_m2 = 0; 
-  voorzieningen.forEach((v, i) => { 
-    const checked = document.getElementById(`vchk_${i}`).checked; 
-    if (checked) { 
-      totaal_m2 += v.norm * totaalBewoners / 1000; 
-    } 
-  }); 
- 
-  const m2_per_woning = totaal_m2 / woningen; 
- 
-  document.getElementById("voorzieningenruimte_display").innerText = `${m2_per_woning.toFixed(1)} m²`; 
-  document.getElementById("voorzieningenruimte_waarde").value = m2_per_woning.toFixed(1); 
- 
-  resultDiv.innerHTML = `<span style="color:green; font-weight:bold;">✔</span> ${totaal_m2.toFixed(1)} m² totaal → ${m2_per_woning.toFixed(1)} m² per woning`; 
-  btn.style.border = "1px solid #0a0"; 
-  btn.style.background = "#e6ffe6"; 
- 
-  updateLaadvermogen(); // herberekenen met nieuwe voorzieningenruimte 
- 
- // Toon tabel met voorzieningen en m2 
-  const summaryBody = document.getElementById("voorziening_summary_tabel"); 
-  const summaryTotal = document.getElementById("voorziening_summary_totaal"); 
-  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("tr"); 
-      row.innerHTML = `<td>${v.naam}</td><td>${v_m2.toFixed(1)} m²</td>`; 
-      summaryBody.appendChild(row); 
-    } 
-  }); 
-  summaryTotal.innerText = `${subtotal.toFixed(1)} m²`; 
- 
-} 
- 
-function berekenParkeerruimte() { 
-  const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0; 
-  const bvo_per_pp = parseFloat(document.getElementById("bvo_per_pp").value) || 0; 
-  const bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0; 
-  const woningen = parseFloat(document.getElementById("totaal_won").innerText.replace(/[^0-9]/g, "")) || 0; 
- 
-  const ruimte_per_woning = pp * bvo_per_pp * (bovengronds / 100); 
-  const totaal_ruimte = ruimte_per_woning * woningen; 
- 
-  // Toon het resultaat en vinkje 
-  const resultDiv = document.getElementById("parkeer_resultaat"); 
-  resultDiv.innerHTML = `<span style="color:green; font-weight:bold;">✔</span> ${totaal_ruimte.toFixed(1)} m² totaal → ${ruimte_per_woning.toFixed(1)} m² per woning`; 
- 
-  // Visuele feedback op de knop 
-  const btn = document.getElementById("btn_parkeren"); 
-  btn.style.border = "1px solid #0a0"; 
-  btn.style.background = "#e6ffe6"; 
- 
-  // Update berekening 
-  updateLaadvermogen(); 
- 
-const totaal_pp = woningen * pp; 
-  const pp_boven_aantal = totaal_pp * (bovengronds / 100); 
-  const ondergronds = parseFloat(document.getElementById("pp_ondergronds").value) || 0; 
-  const pp_onder_aantal = totaal_pp * (ondergronds / 100); 
- 
-  document.getElementById("pp_totaal").innerText = `${totaal_pp.toFixed(0)}`; 
-  document.getElementById("pp_boven").innerText = `${bovengronds.toFixed(0)}% / ${pp_boven_aantal.toFixed(0)}`; 
-  document.getElementById("pp_onder").innerText = `${ondergronds.toFixed(0)}% / ${pp_onder_aantal.toFixed(0)}`; 
- 
-} 
- 
-function updateOpenbareRuimte() { 
-  const opp = parseFloat(document.getElementById("opp").value); 
-  const gsi = parseFloat(document.getElementById("gsi").value); 
-  const bebouwd = opp * gsi; 
-  const onbebouwd = opp - bebouwd; 
- 
-  const types = [ 
-    { id: "groen", label: "Groen" }, 
-    { id: "water", label: "Water" }, 
-    { id: "tuinen", label: "Tuinen" }, 
-    { id: "rijbanen", label: "Rijbanen" }, 
-    { id: "trottoirs", label: "Trottoirs" }, 
-    { id: "parkeren", label: "Parkeren" }, 
-    { id: "pleinen", label: "Pleinen" } 
-  ]; 
- 
-  let totaal = 0; 
-  types.forEach(type => { 
-    const perc = parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; 
-    totaal += perc; 
-  }); 
- 
-  if (totaal !== 100) { 
-    document.getElementById("warning_openbareruimte").innerText = `⚠️ Totaal is ${totaal}%. Dit moet 100% zijn.`; 
-    return; 
-  } else { 
-    document.getElementById("warning_openbareruimte").innerText = ""; 
-  } 
- 
-  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 = null; 
- 
-function updateOpenbareRuimte() { 
-  const opp = parseFloat(document.getElementById("opp").value); 
-  const gsi = parseFloat(document.getElementById("gsi").value); 
-  const bebouwd = opp * gsi; 
-  const onbebouwd = opp - bebouwd; 
- 
-  const types = [ 
-    { id: "groen", label: "Groen" }, 
-    { id: "water", label: "Water" }, 
-    { id: "tuinen", label: "Tuinen" }, 
-    { id: "rijbanen", label: "Rijbanen" }, 
-    { id: "trottoirs", label: "Trottoirs" }, 
-    { id: "parkeren", label: "Parkeren" }, 
-    { id: "pleinen", label: "Pleinen" } 
-  ]; 
- 
-  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").innerText = `⚠️ Totaal is ${totaal}%. Dit moet 100% zijn.`; 
-    document.getElementById("m2_totaal_onbebouwd").innerText = "-"; 
-    return; 
-  } else { 
-    document.getElementById("warning_openbareruimte").innerText = ""; 
-  } 
- 
-  // 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, d) => sum + d.value, 0); 
-  document.getElementById("m2_totaal_onbebouwd").innerText = `${totaal_m2.toFixed(0)} m²`; 
- 
-  // Vergelijking met onbebouwd oppervlak 
-  const verschil = Math.abs(totaal_m2 - onbebouwd); 
-  const totaalCell = document.getElementById("m2_totaal_onbebouwd"); 
-  if (verschil > 1) { 
-    totaalCell.style.color = "red"; 
-    totaalCell.title = `Let op: verschil van ${verschil.toFixed(1)} m² met onbebouwde ruimte`; 
-  } else { 
-    totaalCell.style.color = ""; 
-    totaalCell.title = ""; 
-  } 
- 
-  // Chart.js bijwerken 
-  const ctx = document.getElementById("openbareRuimteChart").getContext("2d"); 
-  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: 'pie', 
-      data: { 
-        labels: labels, 
-        datasets: [{ 
-          data: values, 
-          backgroundColor: [ 
-            '#66bb6a', '#42a5f5', '#ffee58', '#8d6e63', 
-            '#bdbdbd', '#90caf9', '#ff7043' 
-          ] 
-        }] 
-      }, 
-      options: { 
-        plugins: { 
-          legend: { position: 'right' }, 
-          title: { 
-            display: true, 
-            text: 'Verdeling onbebouwde ruimte (m²)' 
-          } 
-        } 
-      } 
-    }); 
-  } 
-} 
- 
- 
-function setVerdelingStedelijkheid() { 
-  const type = document.getElementById("stedelijkheidstype").value; 
-  let waarden = {}; 
- 
-  if (type === "centrum") { 
-    waarden = { groen: 18, water: 4, tuinen: 8, rijbanen: 25, trottoirs: 20, parkeren: 10, pleinen: 15 }; 
-  } else if (type === "gemengd") { 
-    waarden = { groen: 20, water: 10, tuinen: 10, rijbanen: 20, trottoirs: 15, parkeren: 15, pleinen: 10 }; 
-  } else if (type === "suburbaan") { 
-    waarden = { groen: 30, water: 15, tuinen: 25, rijbanen: 15, trottoirs: 8, parkeren: 5, pleinen: 2 }; 
-  } else { 
-    updateOpenbareRuimte(); // Laat FSI/GSI zelf beslissen 
-    return; 
-  } 
- 
-  Object.keys(waarden).forEach(id => { 
-    document.getElementById(`perc_${id}`).value = waarden[id]; 
-  }); 
- 
-  updateOpenbareRuimte(); 
-} 
- 
-// 👇 Deze functies zetten de HTML-invoer van de rekenmodule om in tekstblokken voor het .docx-bestand 
- 
-function buildWoningtypesTable() { 
-  const types = ["egw sociaal", "egw goedkoop", "egw midden", "egw duur", "egw top", 
-                 "mgw sociaal", "mgw goedkoop", "mgw midden", "mgw duur", "mgw top"]; 
-  let rows = [ 
-    ["Type", ...types, "Parkeren bovengr.", "Parkeren ondergr."] 
-  ]; 
- 
-  const perc = types.map((_, i) => document.getElementById(`perc_${i}`).value || "0"); 
-  const bvo = types.map((_, i) => document.getElementById(`bvo_${i}`).value || "0"); 
-  const aantallen = types.map((_, i) => document.getElementById(`aantal_${i}`).innerText || "-"); 
-  const bvo_tot = types.map((_, i) => document.getElementById(`totbvo_${i}`).innerText || "-"); 
- 
-  rows.push(["% totaal", ...perc, "-", "-"]); 
-  rows.push(["m² BVO per woning", ...bvo, "25", "25"]); 
-  rows.push(["Aantal woningen", ...aantallen, "56", "56"]); 
-  rows.push(["Totaal BVO", ...bvo_tot, "1400", "1400"]); 
- 
-  return rows.map(r => r.join(" | ")).join("\n"); 
-} 
- 
-function buildVoorzieningenTable() { 
-  const voorzieningen = [ 
-    { naam: "Huisarts" }, { naam: "Fysiotherapie" }, { naam: "Tandarts" }, 
-    { naam: "Kinderopvang" }, { naam: "Basisschool" }, { naam: "Bibliotheek" }, 
-    { naam: "Buurtcentrum" }, { naam: "Sporthal" }, { naam: "Zwemmen (overdekt)" }, 
-    { naam: "Winkels dagelijks goed." } 
-  ]; 
-  let rows = ["Type | Oppervlak (m²)"]; 
- 
-  voorzieningen.forEach((v, i) => { 
-    const row = document.getElementById(`vchk_${i}`); 
-    if (row && row.checked) { 
-      const el = document.querySelector(`#voorziening_summary_tabel tr:nth-child(${rows.length}) td:last-child`); 
-      const m2 = el ? el.innerText : "-"; 
-      rows.push(`${v.naam} | ${m2}`); 
-    } 
-  }); 
- 
-  return rows.join("\n"); 
-} 
- 
-function buildPlankaartTable() { 
-  const ids = ["opp", "m2_groen", "m2_water", "m2_tuinen", "m2_rijbanen", "m2_trottoirs", "m2_parkeren", "m2_pleinen"]; 
-  const labels = ["Totaal bruto plangebied", "Groen", "Water", "Tuinen", "Rijbanen", "Trottoirs", "Parkeren (bovengr.)", "Pleinen"]; 
- 
-  const footprint = parseFloat(document.getElementById("gsi").value || 0) * parseFloat(document.getElementById("opp").value || 0); 
-  const tuin = parseFloat(document.getElementById("m2_tuinen").innerText) || 0; 
-  const verharding = ["m2_rijbanen", "m2_trottoirs", "m2_parkeren", "m2_pleinen"] 
-    .map(id => parseFloat(document.getElementById(id).innerText) || 0) 
-    .reduce((a, b) => a + b, 0); 
- 
-  let rows = ["Omschrijving | Oppervlak (m²)"]; 
-  ids.forEach((id, i) => { 
-    const el = document.getElementById(id); 
-    if (el) { 
-      rows.push(`${labels[i]} | ${el.value || el.innerText || '-'}`); 
-    } 
-  }); 
-  rows.push(`Footprint (GSI x opp) | ${footprint.toFixed(0)} m²`); 
-  rows.push(`Totaal uitgeefbaar | ${(footprint + tuin).toFixed(0)} m²`); 
-  rows.push(`Totaal verharding | ${verharding.toFixed(0)} m²`); 
- 
-  return rows.join("\n"); 
-} 
- 
-function buildGrexTable() { 
-  const getVal = id => parseFloat(document.getElementById(id)?.innerText?.replace(' m²', '') || 0); 
-  const rijbanen = getVal("m2_rijbanen"); 
-  const trottoirs = getVal("m2_trottoirs"); 
-  const parkeren = getVal("m2_parkeren"); 
-  const pleinen = getVal("m2_pleinen"); 
-  const groen = getVal("m2_groen"); 
-  const water = getVal("m2_water"); 
-  const totaalopp = parseFloat(document.getElementById("opp")?.value || 0); 
-  const nazorg = rijbanen * 0.10; 
- 
-  return [ 
-    "Categorie | Omschrijving | Oppervlak (m²)", 
-    `Verwerving | Percelen te verwerven of in te brengen | ${totaalopp.toFixed(0)}`, 
-    `Grondwerk | Graven watergangen | ${water.toFixed(0)}`, 
-    `Bouwrijp maken | Bouwstraten | ${rijbanen.toFixed(0)}`, 
-    `Woonrijp maken | Rijbanen | ${rijbanen.toFixed(0)}`, 
-    `Woonrijp maken | Trottoirs | ${trottoirs.toFixed(0)}`, 
-    `Woonrijp maken | Parkeren | ${parkeren.toFixed(0)}`, 
-    `Woonrijp maken | Pleinen | ${pleinen.toFixed(0)}`, 
-    `Woonrijp maken | Groen | ${groen.toFixed(0)}`, 
-    "Woonrijp maken | Bomen en groenstructuur |", 
-    "Woonrijp maken | Verdere aankleding openbare ruimte |", 
-    `Nazorg | Herstraten bestratingen (10% rijbanen) | ${nazorg.toFixed(0)}`, 
-    "Onvoorzien | Onvoorzien (5-15%) |" 
-  ].join("\n"); 
-} 
- 
-async function downloadKickstartDump() { 
-  console.log("🔍 Start Kickstart TXT-generatie"); 
- 
-  try { 
-    const response = await fetch('https://www.sumsonite.nl/wiki/lib/exe/fetch.php?media=handleiding_nieuw:spacematrix:kickstart_template_final.txt&v=' + Date.now()); 
-    if (!response.ok) throw new Error(`Bestand niet bereikbaar (${response.status})`); 
- 
-    let template = await response.text(); 
-    console.log("✅ Template geladen"); 
- 
-    const bvo_per_pp = parseFloat(document.getElementById("bvo_per_pp").value) || 0; 
-    const pp_bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0; 
-    const pp_ondergronds = parseFloat(document.getElementById("pp_ondergronds").value) || 0; 
-    const woningen = parseFloat(document.getElementById("summary_woningen").innerText) || 0; 
-    const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0; 
- 
-    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, 10), 
-      aantal_woningen: woningen, 
-      bvo_per_woning: "110.0", 
-      pp_boven: document.getElementById("pp_boven")?.innerText || "–", 
-      pp_onder: document.getElementById("pp_onder")?.innerText || "–", 
-      bvo_boven: document.getElementById("summary_parkeren_tot")?.innerText || "–", 
-      bvo_onder: "–", 
-      bvo_per_pp_boven: bvo_per_pp_boven, 
-      bvo_per_pp_onder: bvo_per_pp_onder, 
-      totbvo_boven: parkeeropp_boven.toFixed(0), 
-      totbvo_onder: parkeeropp_onder.toFixed(0), 
-      voorzieningen_table: buildVoorzieningenTableTXT(), 
-      plankaart_table: buildPlankaartTableTXT(), 
-      grex_table: buildGrexTableTXT() 
-    }; 
- 
-    for (let i = 0; i < 10; i++) { 
-      data[`perc_${i}`] = document.getElementById(`perc_${i}`)?.value || "0"; 
-      data[`bvo_${i}`] = document.getElementById(`bvo_${i}`)?.value || "0"; 
-      data[`aantal_${i}`] = document.getElementById(`aantal_${i}`)?.innerText || "0"; 
-      data[`totbvo_${i}`] = document.getElementById(`totbvo_${i}`)?.innerText || "0"; 
-    } 
- 
-    Object.entries(data).forEach(([key, val]) => { 
-      template = template.replaceAll(`{{${key}}}`, val); 
-    }); 
- 
-    const blob = new Blob([template], { type: 'text/plain;charset=utf-8' }); 
-    saveAs(blob, 'kickstart_dump.txt'); 
-    alert("✅ Kickstart Dump is succesvol gegenereerd en gedownload"); 
-  } catch (error) { 
-    console.error("❌ Fout bij genereren:", error); 
-    alert("❌ Fout: " + error.message); 
-  } 
-} 
- 
-function buildVoorzieningenTableTXT() { 
-  let output = ""; 
-  const rows = document.querySelectorAll("#voorziening_summary_tabel tr"); 
-  rows.forEach(row => { 
-    const cells = row.querySelectorAll("td"); 
-    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 | – |"; 
-} 
- 
-function buildPlankaartTableTXT() { 
-  return `Omschrijving                | Oppervlak (m²) 
-----------------------------|---------------- 
-Totaal bruto plangebied     | ${document.getElementById("opp").value} 
-----------------------------|---------------- 
-Tuinen                      | ${getVal("m2_tuinen")} 
-Footprint (GSI x opp)       | ${(parseFloat(document.getElementById("gsi").value) * parseFloat(document.getElementById("opp").value)).toFixed(0)} 
-----------------------------|---------------- 
-Totaal uitgeefbaar          | ${getVal("m2_tuinen") + (parseFloat(document.getElementById("gsi").value) * parseFloat(document.getElementById("opp").value)).toFixed(0)} 
-Rijbanen                    | ${getVal("m2_rijbanen")} 
-Trottoirs                   | ${getVal("m2_trottoirs")} 
-Parkeren (bovengr.)         | ${getVal("m2_parkeren")} 
-Pleinen                     | ${getVal("m2_pleinen")} 
-----------------------------|---------------- 
-Totaal verharding           | ${getVal("m2_rijbanen") + getVal("m2_trottoirs") + getVal("m2_parkeren") + getVal("m2_pleinen")} 
-Groen                       | ${getVal("m2_groen")} 
-Water                       | ${getVal("m2_water")}`; 
-} 
- 
-function buildGrexTableTXT() { 
-  return `Categorie           | Omschrijving                           | Oppervlak (m²) 
---------------------|----------------------------------------|---------------- 
-Verwerving          | Percelen te verwerven of in te brengen | ${document.getElementById("opp").value} 
-Grondwerk           | Graven watergangen                     | ${getVal("m2_water")} 
-Bouwrijp maken      | Bouwstraten                            | ${getVal("m2_rijbanen")} 
-Woonrijp maken      | Rijbanen                               | ${getVal("m2_rijbanen")} 
-Woonrijp maken      | Trottoirs                              | ${getVal("m2_trottoirs")} 
-Woonrijp maken      | Parkeren                               | ${getVal("m2_parkeren")} 
-Woonrijp maken      | Pleinen                                | ${getVal("m2_pleinen")} 
-Woonrijp maken      | Groen                                  | ${getVal("m2_groen")} 
-Woonrijp maken      | Bomen en groenstructuur                |  
-Woonrijp maken      | Verdere aankleding openbare ruimte      
-Nazorg              | Herstraten bestratingen (10% rijbanen) | ${(getVal("m2_rijbanen") * 0.10).toFixed(0)} 
-Onvoorzien          | Onvoorzien (5-15%)                     | `; 
-} 
- 
-function getVal(id) { 
-  const el = document.getElementById(id); 
-  return el ? parseFloat(el.innerText.replace(" m²", "")) || 0 : 0; 
-} 
  
 +<script src="/wiki/tools/dichtheidsrekenmachine/sm_rekenmachine_v1.js?v=1"></script>
  
  
-window.onload = () => { 
-  renderWoningtypes(); 
-  maakVoorzieningentabel(); 
-  updateLaadvermogen(); 
-}; 
-</script> 
  
 </body> </body>
 </html> </html>
handleiding_nieuw/sub_spacematrix.1747148666.txt.gz · Last modified: 2025/05/13 15:04 by support

© Sumsonite B.V. Alle rechten voorbehouden. Documentatie, rekenmethodes, databanken en (bron)code mogen niet worden gekopieerd, verspreid of (reverse) engineered zonder voorafgaande schriftelijke toestemming. · Rechten & gebruik