fix: update building dimensions and descriptions in README, model.json, and klabava.js
continuous-integration/drone/push Build is passing

This commit is contained in:
martin.fencl
2026-10-31 18:00:33 +01:00
parent b08f70d18e
commit 4596a28aed
4 changed files with 58 additions and 55 deletions
+2 -2
View File
@@ -22,9 +22,9 @@ Potom otevřete <http://localhost:8000>. Prohlížeč potřebuje WebGL a připoj
## Podklady a míra přesnosti
Z půdorysu a pohledů vychází obrys domu 17,40 × 13,05 m, zastavěná plocha 178,75 m², užitná plocha 153,74 m² a výška hřebene +5,832 m. Situace uvádí parcelu 66/17 o výměře 1 037 m² a 206,54 m² včetně krytého vstupu a terasy. Ve výškopisu jsou zaměřené hodnoty přibližně 349,5 m n. m. u komunikace a 347,2 m n. m. u zadní části parcely.
Z půdorysu a pohledů vychází obrys domu 17,40 × 13,05 m, zastavěná plocha 178,75 m², užitná plocha 153,74 m² a úrovně hřebenů +5,275 a +5,832 m. Řez uvádí sklon střechy 23°. Hmota je modelována ve dvou navazujících křídlech; vyšší střecha je omezena na hlubší křídlo a její rozpon vychází z řezu a pohledů. Situace uvádí parcelu 66/17 o výměře 1 037 m² a 206,54 m² včetně krytého vstupu a terasy. Dvě parkovací stání jsou u komunikace vpravo od domu; plocha je zakreslená přibližně 6,625 × 5,0 m. Ve výškopisu jsou zaměřené hodnoty přibližně 349,5 m n. m. u komunikace a 347,2 m n. m. u zadní části parcely.
Objem domu a terén jsou zjednodušené z PDF. Rozmístění otvorů a střešní roviny jsou schematické. Hranice parcely je převzatá graficky ze situačního PDF, nikoli z vytyčovacích souřadnic. Výšky terénu jsou interpolované mezi zaměřenými body. Stromy, příjezd, parkovací plocha a materiály slouží k prostorové orientaci. Model není BIM ani podklad pro stavbu, zemní práce nebo vytyčení.
Objem domu a terén jsou zjednodušené z PDF. Rozmístění otvorů a střešní napojení jsou schematické. Hranice parcely je převzatá graficky ze situačního PDF, nikoli z vytyčovacích souřadnic. Výšky terénu jsou interpolované mezi zaměřenými body. Příjezd, parkovací plocha a materiály slouží k prostorové orientaci. Model není BIM ani podklad pro stavbu, zemní práce nebo vytyčení.
Soubor `data/model.json` uchovává hlavní údaje projektu. Dodané PDF jsou zkopírované do `references/` a dostupné z panelu Projekt. Barvy fasády, střešní krytiny, oken a vybavení nejsou zatím vybrané.
+2 -1
View File
@@ -8,6 +8,7 @@
"footprintEnvelopeM": [17.4, 13.05],
"eaveM": 3.046,
"ridgeM": 5.832,
"secondaryRidgeM": 5.275,
"chimneyM": 6.5,
"surveyGroundNearRoadBpv": 349.48,
"surveyGroundRearBpv": 347.2,
@@ -15,5 +16,5 @@
"longitude": 13.5394,
"latitudeLongitudeNote": "Přibližný střed obce Klabava; nikoli souřadnice parcely.",
"standards": null,
"modelNote": "Vizualizační model podle PDF podkladů; hranice a výšky terénu jsou převzaté a interpolované orientačně."
"modelNote": "Vizualizační model podle PDF podkladů; vyšší střecha je omezena na hlubší křídlo domu. Hranice a výšky terénu jsou převzaté a interpolované orientačně."
}
+7 -7
View File
@@ -6,9 +6,9 @@
<meta name="robots" content="noindex,nofollow">
<meta name="theme-color" content="#e7ebe3">
<title>Klabava | Rodinný dům</title>
<link rel="stylesheet" href="./css/app.css?v=20261031">
<link rel="stylesheet" href="./css/web.css?v=20261031">
<link rel="stylesheet" href="./css/klabava.css?v=20261031">
<link rel="stylesheet" href="./css/app.css">
<link rel="stylesheet" href="./css/web.css">
<link rel="stylesheet" href="./css/klabava.css">
<script type="importmap">
{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.180.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.180.0/examples/jsm/"}}
</script>
@@ -23,7 +23,7 @@
<div class="metrics">
<div class="metric"><strong>178,75 m²</strong><small>Zastavěná plocha</small></div>
<div class="metric"><strong>153,74 m²</strong><small>Užitná plocha</small></div>
<div class="metric"><strong>5,83 m</strong><small>Hřeben střechy</small></div>
<div class="metric"><strong>5,28 / 5,83 m</strong><small>Hřebeny střechy</small></div>
</div>
</header>
@@ -45,7 +45,7 @@
<div class="row"><span>Včetně krytého vstupu a terasy</span><strong>206,54 m²</strong></div>
<div class="row"><span>Užitná plocha</span><strong>153,74 m²</strong></div>
<div class="row"><span>Rozměry obálky v půdorysu</span><strong>17,40 × 13,05 m</strong></div>
<div class="row"><span>Hřeben / komín</span><strong>+5,832 / +6,500 m</strong></div>
<div class="row"><span>Hřebeny / komín</span><strong>+5,275 a +5,832 / +6,500 m</strong></div>
<h3>Vzhled a vybavení</h3>
<p>Barvy fasády, krytiny, oken a další standardy zůstávají otevřené. Model používá neutrální dočasné materiály, aby bylo možné ověřit hmotu domu, umístění a stíny.</p>
<h3>Podklady</h3>
@@ -60,7 +60,7 @@
<details class="site-note" open>
<summary>Rozsah modelu a přesnost</summary>
<p>Půdorysná hmota, hlavní otvory a výšky vycházejí z dodaných výkresů. Střecha je schematicky složená z valbových ploch. Terén navazuje na zaměřené body přibližně od 349,5 m n. m. u komunikace k 347,2 m n. m. v zadní části parcely; mezi body je interpolovaný.</p>
<p>Hranice parcely je převzatá graficky z PDF situace, ne ze souřadnic pro vytyčení. Okolí, výsadba, parkovací plocha, okna a materiály jsou zjednodušené pro prostorovou orientaci. Model slouží k prezentaci a studii oslunění, nikoli jako BIM, geodetický nebo stavební podklad.</p>
<p>Hranice parcely je převzatá graficky z PDF situace, ne ze souřadnic pro vytyčení. Příjezd, parkovací plocha, okna a materiály jsou zjednodušené pro prostorovou orientaci. Model slouží k prezentaci a studii oslunění, nikoli jako BIM, geodetický nebo stavební podklad.</p>
</details>
<div class="status"><span class="dot"></span>Pracovní vizualizace · standardy doplníme po jejich výběru</div>
</aside>
@@ -120,6 +120,6 @@
<div id="toast" role="status" aria-live="polite"></div>
<div id="webStatus">Pracovní model · Klabava 66/17</div>
<script type="module" src="./js/klabava.js?v=20261031"></script>
<script type="module" src="./js/klabava.js"></script>
</body>
</html>
+47 -45
View File
@@ -90,7 +90,7 @@ sunLight.target = sunTarget;
const modelRoot = new THREE.Group();
modelRoot.name = 'Klabava – dům a pozemek';
scene.add(modelRoot);
const groundGroup = new THREE.Group(); groundGroup.name = 'Terén a zahrada'; modelRoot.add(groundGroup);
const groundGroup = new THREE.Group(); groundGroup.name = 'Interpolovaný terén'; modelRoot.add(groundGroup);
const boundaryGroup = new THREE.Group(); boundaryGroup.name = 'Orientační hranice parcely'; modelRoot.add(boundaryGroup);
const parkingGroup = new THREE.Group(); parkingGroup.name = 'Příjezd a parkování'; modelRoot.add(parkingGroup);
const houseGroup = new THREE.Group(); houseGroup.name = 'Rodinný dům – pracovní hmota'; houseGroup.position.set(0, 0, 8.4); modelRoot.add(houseGroup);
@@ -108,13 +108,9 @@ const mats = {
door: new THREE.MeshStandardMaterial({ color: 0x958d7d, roughness: 0.8 }),
terrace: new THREE.MeshStandardMaterial({ color: 0xaaa492, roughness: 0.88 }),
metal: new THREE.MeshStandardMaterial({ color: 0x545b58, roughness: 0.6, metalness: 0.18 }),
trunk: new THREE.MeshStandardMaterial({ color: 0x735d46, roughness: 1 }),
leaf: new THREE.MeshStandardMaterial({ color: 0x657c5c, roughness: 1 }),
leaf2: new THREE.MeshStandardMaterial({ color: 0x839273, roughness: 1 }),
car1: new THREE.MeshStandardMaterial({ color: 0x777e7b, roughness: 0.45, metalness: 0.08 }),
car2: new THREE.MeshStandardMaterial({ color: 0xa59f91, roughness: 0.45, metalness: 0.08 }),
tire: new THREE.MeshStandardMaterial({ color: 0x333635, roughness: 0.95 }),
pavingLine: new THREE.MeshStandardMaterial({ color: 0xe4e0d2, roughness: 0.9 })
tire: new THREE.MeshStandardMaterial({ color: 0x333635, roughness: 0.95 })
};
function mesh(geometry, material, parent, name = '') {
@@ -194,7 +190,7 @@ function buildGround() {
// Parcel outline is intentionally thin and diagrammatic; the supplied survey has no parcel staking coordinates.
const border = [nw, ne, se, sw].map(([x, z]) => [x, groundHeight(x, z) + 0.045, z]);
line(boundaryGroup, 'Grafická hranice parcely 66/17', [...border, border[0]], 0x4f694f, 0.95);
borderGroup.add(line(boundaryGroup, 'Grafická hranice parcely 66/17', [...border, border[0]], 0x4f694f, 0.95));
for (let i = 0; i < border.length; i++) {
const [x, y, z] = border[i];
const post = mesh(new THREE.CylinderGeometry(0.035, 0.035, 0.12, 6), mats.frame, boundaryGroup, `Orientační lom hranice ${i + 1}`);
@@ -203,20 +199,20 @@ function buildGround() {
}
buildParking(roadY);
buildGarden();
}
function buildParking(roadY) {
const y = (x, z) => groundHeight(x, z) + 0.035;
const drivewayPts = [[-9.2, y(-9.2, 20.2), 20.2], [-5.3, y(-5.3, 20.2), 20.2], [-5.3, y(-5.3, 17.8), 17.8], [-9.2, y(-9.2, 17.8), 17.8]];
poly(parkingGroup, 'Příjezd na pozemek', drivewayPts, mats.gravel);
const pad = [[-10.3, y(-10.3, 17.7), 17.7], [-3.7, y(-3.7, 17.7), 17.7], [-3.7, y(-3.7, 14.9), 14.9], [-10.3, y(-10.3, 14.9), 14.9]];
// Situace places the two-car apron on the road side; the 6.625 × 5.0 m pad is at the right of this view.
const drivewayPts = [[5.0, y(5.0, 20.45), 20.45], [8.9, y(8.9, 20.45), 20.45], [8.9, y(8.9, 19.85), 19.85], [5.0, y(5.0, 19.85), 19.85]];
poly(parkingGroup, 'Příjezd z komunikace', drivewayPts, mats.gravel);
const pad = [[3.7, y(3.7, 20.0), 20.0], [10.325, y(10.325, 20.0), 20.0], [10.325, y(10.325, 15.0), 15.0], [3.7, y(3.7, 15.0), 15.0]];
poly(parkingGroup, 'Orientační parkovací plocha', pad, mats.gravel);
line(parkingGroup, 'Osa příjezdu', [[-7.25, roadY(20) + 0.03, 20], [-7.25, y(-7.25, 17.8) + 0.04, 17.8]], 0x8f958b, 0.65);
line(parkingGroup, 'Napojení na komunikaci', [[6.95, roadY(20.3) + 0.04, 20.3], [6.95, y(6.95, 19.85) + 0.04, 19.85]], 0x8f958b, 0.65);
function addCar(cx, cz, material, label) {
const car = group(parkingGroup, label);
car.position.set(cx, groundHeight(cx, cz) + 0.12, cz);
car.position.set(cx, groundHeight(cx, cz) + 0.035, cz);
box(car, `${label} karoserie`, 0, 0.42, 0, 2.05, 0.72, 4.35, material);
box(car, `${label} kabina`, 0, 0.93, -0.1, 1.55, 0.62, 2.45, mats.glass);
for (const x of [-1.02, 1.02]) for (const z of [-1.42, 1.42]) {
@@ -226,34 +222,13 @@ function buildParking(roadY) {
}
box(car, `${label} přední sklo`, 0, 0.95, 1.12, 1.38, 0.43, 0.08, mats.glass, 0.18);
}
addCar(-8.15, 16.35, mats.car1, 'Orientační automobil 1');
addCar(-5.75, 16.35, mats.car2, 'Orientační automobil 2');
// A short walk connects the front door and the gravel parking area.
const walkway = [[-0.9, y(-0.9, 16.5), 16.5], [0.55, y(0.55, 16.5), 16.5], [0.55, y(0.55, 14.7), 14.7], [-0.9, y(-0.9, 14.7), 14.7]];
poly(parkingGroup, 'Pěší vstup', walkway, mats.path);
}
function addTree(x, z, height, variant = 0) {
const g = group(groundGroup, 'Orientační strom');
g.position.set(x, groundHeight(x, z), z);
const trunkHeight = height * 0.42;
const trunk = mesh(new THREE.CylinderGeometry(0.11, 0.17, trunkHeight, 7), mats.trunk, g, 'Kmen');
trunk.position.y = trunkHeight / 2;
const material = variant % 2 ? mats.leaf2 : mats.leaf;
for (let i = 0; i < 3; i++) {
const radius = height * (0.27 - i * 0.04);
const cone = mesh(new THREE.ConeGeometry(radius, height * 0.42, 8), material, g, 'Koruna');
cone.position.set(0, trunkHeight + height * (0.17 + i * 0.18), 0);
}
}
function buildGarden() {
const trees = [[-10.7, -3.7, 3.7], [10.7, -3.4, 3.4], [-10.1, -10.2, 3.6], [11.0, -11.3, 4.1], [-7.4, -16.9, 3.4], [3.5, -17.1, 3.8], [9.6, 4.3, 3.1]];
trees.forEach(([x, z, h], i) => addTree(x, z, h, i));
for (const [x, z] of [[-9.5, -6.5], [10.3, -6.4], [-5.9, -18.1], [6.1, -18.2]]) {
const shrub = mesh(new THREE.SphereGeometry(0.65, 10, 8), mats.leaf2, groundGroup, 'Orientační keř');
shrub.scale.set(1.2, 0.8, 0.9);
shrub.position.set(x, groundHeight(x, z) + 0.44, z);
}
addCar(5.55, 17.5, mats.car1, 'Orientační automobil 1');
addCar(8.45, 17.5, mats.car2, 'Orientační automobil 2');
// The front walk runs from the entrance to the right-hand parking apron.
const walkToDoor = [[-0.3, y(-0.3, 16.4), 16.4], [1.15, y(1.15, 16.4), 16.4], [1.15, y(1.15, 14.7), 14.7], [-0.3, y(-0.3, 14.7), 14.7]];
const walkToParking = [[0.8, y(0.8, 14.7), 14.7], [4.0, y(4.0, 14.7), 14.7], [4.0, y(4.0, 15.35), 15.35], [0.8, y(0.8, 15.35), 15.35]];
poly(parkingGroup, 'Pěší vstup od domu', walkToDoor, mats.path);
poly(parkingGroup, 'Pěší napojení parkování', walkToParking, mats.path);
}
const footprint = [
@@ -311,8 +286,8 @@ function makeWallEdge(p1, p2, openings = []) {
wallSegment(cursor, length, 0, height);
}
function hipRoof(x0, x1, z0, z1, name, ridgeHeight = 5.832) {
const overhang = 0.38, eave = 3.06;
function hipRoof(x0, x1, z0, z1, name, ridgeHeight) {
const overhang = 0.38, eave = 3.046;
x0 -= overhang; x1 += overhang; z0 -= overhang; z1 += overhang;
const xm = (x0 + x1) / 2, zm = (z0 + z1) / 2;
const width = x1 - x0, depth = z1 - z0;
@@ -341,6 +316,32 @@ function hipRoof(x0, x1, z0, z1, name, ridgeHeight = 5.832) {
box(houseGroup, `${name} – okap východ`, x1, eave - 0.04, zm, 0.12, 0.12, depth, mats.frame);
}
// The higher roof crosses the deeper wing. Its 13.05 m roof span and +5.832 m
// ridge follow the 23° section/elevation; the wing walls themselves are 11.67 m deep.
function hipRoofAcrossDepth(x0, x1, z0, z1, name, ridgeHeight) {
const eave = 3.046, overhangX = 0.38, overhangZ = 0.69;
x0 -= overhangX; x1 += overhangX; z0 -= overhangZ; z1 += overhangZ;
const zm = (z0 + z1) / 2;
const v = (x, y, z) => [x, y, z];
poly(houseGroup, `${name} – severní střešní rovina`, [
v(x0, eave, z1), v(x1, eave, z1), v(x1, ridgeHeight, zm), v(x0, ridgeHeight, zm)
], mats.roof);
poly(houseGroup, `${name} – jižní střešní rovina`, [
v(x1, eave, z0), v(x0, eave, z0), v(x0, ridgeHeight, zm), v(x1, ridgeHeight, zm)
], mats.roof);
poly(houseGroup, `${name} – západní valba`, [
v(x0, eave, z0), v(x0, eave, z1), v(x0, ridgeHeight, zm)
], mats.roof);
poly(houseGroup, `${name} – východní valba`, [
v(x1, eave, z1), v(x1, eave, z0), v(x1, ridgeHeight, zm)
], mats.roof);
box(houseGroup, `${name} – hřeben`, (x0 + x1) / 2, ridgeHeight, zm, x1 - x0, 0.12, 0.12, mats.roof);
box(houseGroup, `${name} – okap sever`, (x0 + x1) / 2, eave - 0.04, z1, x1 - x0, 0.12, 0.12, mats.frame);
box(houseGroup, `${name} – okap jih`, (x0 + x1) / 2, eave - 0.04, z0, x1 - x0, 0.12, 0.12, mats.frame);
box(houseGroup, `${name} – okap západ`, x0, eave - 0.04, zm, 0.12, 0.12, z1 - z0, mats.frame);
box(houseGroup, `${name} – okap východ`, x1, eave - 0.04, zm, 0.12, 0.12, z1 - z0, mats.frame);
}
function buildHouse() {
makeFootprintSlab();
const openings = [
@@ -354,8 +355,9 @@ function buildHouse() {
[]
];
for (let i = 0; i < footprint.length; i++) makeWallEdge(footprint[i], footprint[(i + 1) % footprint.length], openings[i]);
hipRoof(-1.575, 8.7, -2.775, 6.525, 'Hlavní valbová střecha');
hipRoof(-8.7, -1.575, -6.525, 5.145, 'Střecha západního křídla');
// The section shows the 23° lower roof ridge (+5.275 m); the elevations show the deeper wing ridge (+5.832 m).
hipRoof(-1.575, 8.7, -2.775, 6.525, 'Nižší valbová střecha', 5.275);
hipRoofAcrossDepth(-8.7, -1.575, -6.525, 5.145, 'Vyšší valbová střecha', 5.832);
// Chimney shown in the elevations, with a simple cap.
box(houseGroup, 'Komín', 5.7, 5.78, 1.8, 0.64, 1.25, 0.64, mats.foundation);