SPB Git

spb/uqo_cours

Public

IMM1033 séance 7 : atelier quantity survey v2 — plans plein cadre recadrés, plan annoté, objets mesurés, démarches A/B/C (plan → grandeurs → quantités → coûts), fil conducteur ; 172 diapos / 184 p.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Oct 28, 2026) parent f4efe19 Browse files

33 changed files +5,125 −6,306

33 changed files
modified IMM1033-20_Methodes_du_cout/02_Slides/README.md +1 −1
@@ -6,4 +6,4 @@
6 - `sources/seance02_exercices.tex` → `pdf/seance02_exercices.pdf` : **cahier d'exercices en classe de la séance 2** (deck Beamer séparé, même style, 46 p.) : 11 exercices en 5 blocs pour 60 minutes (énoncé / corrigé / discussion), distincts des exercices intégrés au deck principal et des exercices du chapitre 2 des notes. Compilation `latexmk -pdf`. Gabarit réutilisable pour les autres séances (macros `\exometa`, `\corrige`, `\discussion`). 6 - `sources/seance02_exercices.tex` → `pdf/seance02_exercices.pdf` : **cahier d'exercices en classe de la séance 2** (deck Beamer séparé, même style, 46 p.) : 11 exercices en 5 blocs pour 60 minutes (énoncé / corrigé / discussion), distincts des exercices intégrés au deck principal et des exercices du chapitre 2 des notes. Compilation `latexmk -pdf`. Gabarit réutilisable pour les autres séances (macros `\exometa`, `\corrige`, `\discussion`).
7 7
8 Les diapositives de présentation des TP (mandat, objectifs, livrables, aperçu du Dashboard) sont intégrées aux séances d'annonce; les anciens ateliers y sont conservés comme **exemples guidés** travaillés en classe. 8 Les diapositives de présentation des TP (mandat, objectifs, livrables, aperçu du Dashboard) sont intégrées aux séances d'annonce; les anciens ateliers y sont conservés comme **exemples guidés** travaillés en classe.
9−- **Séance 7 — atelier « quantity survey » (2026-10-28)** : le deck `seance07_couts_directs` inclut `sources/parties/seance07_qs_cas.tex`, **généré** par `sources/gen_qs_cas.py` à partir des cas d'étude du module Quantity Survey d'UQO Éval (`sources/images/qs-cas/casN/data.json` = révision figée, mesures, fiche ; plans PNG exportés ; `localisation.json` = mêmes lignes RSMeans dans 18 villes). Cinq cas complets (garage Trois-Rivières, bungalow Gatineau, cottage + garage Montréal, triplex Québec, chalet sur pieux Rimouski) : fiche, plans par niveau, relevé des quantités avec formules, prix unitaires RSMeans 2026 T4, divisions, majorations, lecture ; synthèse des huit cas et exercice (duplex Laval). 141 diapositives / 153 pages. Ne pas éditer la partie à la main : régénérer (`python3 gen_qs_cas.py`), compiler, puis vérifier `python3 check_overflow.py pdf/seance07_couts_directs.pdf` (0 débordement attendu). Compilation : `latexmk -pdf -bibtex- seance07_couts_directs.tex` avec le `.bbl` fourni (le biber universel de TeX Live 2026 échoue : `~/bin/biber-arm64`). 9+- **Séance 7 — atelier « quantity survey » (2026-10-28)** : le deck `seance07_couts_directs` inclut `sources/parties/seance07_qs_cas.tex`, **généré** par `sources/gen_qs_cas.py` à partir des cas d'étude du module Quantity Survey d'UQO Éval (`sources/images/qs-cas/casN/data.json` = révision figée, mesures, fiche ; plans PNG exportés ; `localisation.json` = mêmes lignes RSMeans dans 18 villes). Cinq cas complets (garage Trois-Rivières, bungalow Gatineau, cottage + garage Montréal, triplex Québec, chalet sur pieux Rimouski), chacun avec le même fil conducteur (indicateur à six étapes) : fiche, plans plein cadre par niveau (PNG recadrés haute résolution, sans cartouche), plan annoté (six objets épinglés → ce qu'ils deviennent), table des objets mesurés (murs, pièces, ouvertures), démarche A (du plan aux dix grandeurs de base), démarche B (formule → entrées → résultat), relevé complet, démarche C (quantité → conversion → coût unitaire bare → montant), prix unitaires RSMeans 2026 T4, divisions, majorations, lecture ; synthèse des huit cas et exercice (duplex Laval). 172 diapositives / 184 pages. Ne pas éditer la partie à la main : régénérer (`python3 gen_qs_cas.py`), compiler, puis vérifier `python3 check_overflow.py pdf/seance07_couts_directs.pdf` (0 débordement attendu). Compilation : `latexmk -pdf -bibtex- seance07_couts_directs.tex` avec le `.bbl` fourni (le biber universel de TeX Live 2026 échoue : `~/bin/biber-arm64`).
modified IMM1033-20_Methodes_du_cout/02_Slides/pdf/seance07_couts_directs.pdf +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/gen_qs_cas.py +160 −23
@@ -54,29 +54,58 @@ def load(n):
54 heated = next((m["value"] for m in meas if m["name"].startswith("Filage brut")), None) 54 heated = next((m["value"] for m in meas if m["name"].startswith("Filage brut")), None)
55 if heated is None: heated = next((m["value"] for m in meas if m["name"].startswith("Gypse") and "plafond" in m["name"]), None) 55 if heated is None: heated = next((m["value"] for m in meas if m["name"].startswith("Gypse") and "plafond" in m["name"]), None)
56 d["footprint"] = emp; d["heated"] = heated 56 d["footprint"] = emp; d["heated"] = heated
57+ pages = d["pages"]; ground = next((x for x in pages if (x["level"] or "").startswith("Rez")), pages[-1] if pages else None)
58+ d["ground"] = ground
59+ above = [x for x in pages if not (x["level"] or "").lower().startswith("sous")]
60+ d["extGross"] = sum(w["grossAreaM2"] for x in above for w in x["walls"] if w["exterior"]); d["extNet"] = sum(w["netAreaM2"] for x in above for w in x["walls"] if w["exterior"])
61+ d["intGross"] = sum(w["grossAreaM2"] for x in above for w in x["walls"] if not w["exterior"]); d["roomsArea"] = sum(r["areaM2"] for x in above for r in x["rooms"])
62+ d["windowsAll"] = sum(x["windows"] for x in above); d["doorsAll"] = sum(x["doors"] for x in above)
63+ per = next((m for m in meas if m["name"].startswith("Semelles")), None); d["perimeter"] = per["value"] if per else sum(w["lengthM"] for w in ground["walls"] if w["exterior"])
64+ pitch = d["project"]["spec"].get("roofPitch", 4) or 0; d["slope"] = (1 + (pitch / 12) ** 2) ** 0.5
57 return d 65 return d
58 66
59 def kpi(color, value, label): return f"\\qskpi[{color}]{{{value}}}{{{label}}}" 67 def kpi(color, value, label): return f"\\qskpi[{color}]{{{value}}}{{{label}}}"
60 68
61 def table(rows, cols, align, size="\\scriptsize", stretch="0.95"): 69 def table(rows, cols, align, size="\\scriptsize", stretch="0.95"):
62− out = [f"\\begin{{center}}{size}\\renewcommand{{\\arraystretch}}{{{stretch}}}%", f"\\begin{{tabular}}{{@{{}}{align}@{{}}}}", "\\toprule", " & ".join(f"\\textbf{{{c}}}" for c in cols) + " \\\\", "\\midrule"] 70+ out = [f"\\begin{{center}}{size}\\renewcommand{{\\arraystretch}}{{{stretch}}}\\setlength{{\\tabcolsep}}{{3.5pt}}%", f"\\begin{{tabular}}{{@{{}}{align}@{{}}}}", "\\toprule", " & ".join(f"\\textbf{{{c}}}" for c in cols) + " \\\\", "\\midrule"]
63 out += [" & ".join(r) + " \\\\" for r in rows] 71 out += [" & ".join(r) + " \\\\" for r in rows]
64 out += ["\\bottomrule", "\\end{tabular}\\end{center}"] 72 out += ["\\bottomrule", "\\end{tabular}\\end{center}"]
65 return "\n".join(out) 73 return "\n".join(out)
66 74
75+STEPS = ["Plan", "Fiche", "Relevé", "Prix", "Majorations", "Révision"]
76+def steps(active):
77+ """indicateur du fil conducteur (6 étapes), placé en haut à droite du contenu"""
78+ cells = "".join(f"\\qsstep{{{1 if i + 1 in active else 0}}}{{{i + 1}}}{{{t}}}" for i, t in enumerate(STEPS))
79+ return f"\\hfill{{\\tiny{cells}}}\\par\\vspace{{-0.5mm}}"
80+
81+def kv_fr(inputs):
82+ """« perimetre_m=42.6, hauteur_m=2.44 » → « périmètre 42,6 m ; hauteur 2,44 m »"""
83+ out = []
84+ for part in [x.strip() for x in inputs.split(",") if "=" in x]:
85+ k, v = part.split("=", 1); k = k.strip(); v = v.strip()
86+ unit = ""
87+ if k.endswith("_m2"): unit = " m\\textsuperscript{2}"; k = k[:-3]
88+ elif k.endswith("_m3"): unit = " m\\textsuperscript{3}"; k = k[:-3]
89+ elif k.endswith("_m"): unit = " m"; k = k[:-2]
90+ k = k.replace("_", " ").replace("perimetre", "périmètre").replace("aire", "aire").replace("profondeur", "profondeur").replace("empreinte", "empreinte").replace("facteur pente", "facteur de pente").replace("hauteur", "hauteur")
91+ try: v = num(float(v), 2 if abs(float(v)) < 100 else 0)
92+ except ValueError: v = tex(v)
93+ out.append(f"{tex(k)} {v}{unit}")
94+ return " ; ".join(out)
95+
67 def frame_fiche(d): 96 def frame_fiche(d):
68 p = d["project"]; s = p["spec"]; t = d["version"]["result"]["totals"]; short = short_name(p) 97 p = d["project"]; s = p["spec"]; t = d["version"]["result"]["totals"]; short = short_name(p)
69 levels = ", ".join(x["level"] or x["label"] for x in d["pages"]); units = s.get("units", 1) 98 levels = ", ".join(x["level"] or x["label"] for x in d["pages"]); units = s.get("units", 1)
70 bs = fr(s.get("basement")) + (f" ({round(s.get('basementFinishedPct', 0)*100)}\\,\\% fini)" if s.get("basement") == "finished" else "") 99 bs = fr(s.get("basement")) + (f" ({round(s.get('basementFinishedPct', 0)*100)}\\,\\% fini)" if s.get("basement") == "finished" else "")
71− out = [f"\\begin{{frame}}{{{tex(short)} --- fiche du cas}}", "\\begin{center}"] 100+ out = [f"\\begin{{frame}}{{{tex(short)} --- fiche du cas}}", steps([1, 2]), "\\begin{center}"]
72 out.append(kpi("uqoBleu", num(d["footprint"]) + "~m\\textsuperscript{2}", "empreinte") + kpi("uqoTeal", num(d["heated"]) + "~m\\textsuperscript{2}", "aire chauffée") + kpi("uqoOr", f"{len(d['pages'])} / {units}", "niveaux / logements") + kpi("uqoNavy", money(t["total"]), "total hors taxes")) 101 out.append(kpi("uqoBleu", num(d["footprint"]) + "~m\\textsuperscript{2}", "empreinte") + kpi("uqoTeal", num(d["heated"]) + "~m\\textsuperscript{2}", "aire chauffée") + kpi("uqoOr", f"{len(d['pages'])} / {units}", "niveaux / logements") + kpi("uqoNavy", money(t["total"]), "total hors taxes"))
73 out.append("\\end{center}\\vspace{0.5mm}\\footnotesize") 102 out.append("\\end{center}\\vspace{0.5mm}\\footnotesize")
74− out.append("\\begin{columns}[T]\\begin{column}{0.48\\textwidth}\\uqotitle{Le plan donne}\\begin{itemize}\\setlength{\\itemsep}{1pt}") 103+ out.append("\\begin{columns}[T]\\begin{column}{0.48\\textwidth}\\uqotitle{Étape 1 --- le plan donne}\\begin{itemize}\\setlength{\\itemsep}{1pt}")
75 out.append(f" \\item Niveaux : {tex(levels)} (50~px/m, calibration exacte)") 104 out.append(f" \\item Niveaux : {tex(levels)} (50~px/m, calibration exacte)")
76 out.append(f" \\item {sum(len(x['rooms']) for x in d['pages'])} pièces nommées, {sum(x['windows'] for x in d['pages'])} fenêtres, {sum(x['doors'] for x in d['pages'])} portes") 105 out.append(f" \\item {sum(len(x['rooms']) for x in d['pages'])} pièces nommées, {sum(x['windows'] for x in d['pages'])} fenêtres, {sum(x['doors'] for x in d['pages'])} portes")
77 out.append(f" \\item Ville RSMeans : \\textbf{{{tex(p['municipality'])}}} (MO syndiquée)") 106 out.append(f" \\item Ville RSMeans : \\textbf{{{tex(p['municipality'])}}} (MO syndiquée)")
78 out.append(f" \\item Secteur : {tex(cut(p['address'], 40))}") 107 out.append(f" \\item Secteur : {tex(cut(p['address'], 40))}")
79− out.append("\\end{itemize}\\end{column}\\begin{column}{0.5\\textwidth}\\uqotitle{La fiche technique fixe}\\begin{itemize}\\setlength{\\itemsep}{1pt}") 108+ out.append("\\end{itemize}\\end{column}\\begin{column}{0.5\\textwidth}\\uqotitle{Étape 2 --- la fiche technique fixe}\\begin{itemize}\\setlength{\\itemsep}{1pt}")
80 out.append(f" \\item Fondation {fr(s.get('foundation'))}, mur {num(s.get('foundationWallHeightM'), 2)}~m ; sous-sol {bs}") 109 out.append(f" \\item Fondation {fr(s.get('foundation'))}, mur {num(s.get('foundationWallHeightM'), 2)}~m ; sous-sol {bs}")
81 out.append(f" \\item Revêtements : {mix(s.get('siding'))} ; toit {fr(s.get('roofType'))} {s.get('roofPitch')}/12") 110 out.append(f" \\item Revêtements : {mix(s.get('siding'))} ; toit {fr(s.get('roofType'))} {s.get('roofPitch')}/12")
82 out.append(f" \\item Fenêtres {fr(s.get('windows'))} ; chauffage {fr(s.get('heating'))}" + (" + clim." if s.get("hasAirConditioning") else "") + (" + VRC" if s.get("hasAirExchanger") else "")) 111 out.append(f" \\item Fenêtres {fr(s.get('windows'))} ; chauffage {fr(s.get('heating'))}" + (" + clim." if s.get("hasAirConditioning") else "") + (" + VRC" if s.get("hasAirExchanger") else ""))
@@ -86,19 +115,104 @@ def frame_fiche(d):
86 return "\n".join(out) 115 return "\n".join(out)
87 116
88 def frame_plans(d): 117 def frame_plans(d):
118+ """un plan plein cadre par niveau, puis le rez-de-chaussée annoté et sa table d'objets"""
89 short = short_name(d["project"]); out = [] 119 short = short_name(d["project"]); out = []
90 for x in d["pages"]: 120 for x in d["pages"]:
91− lvl = x["level"] or x["label"]; rooms = x["rooms"] 121+ lvl = x["level"] or x["label"]
122+ ext = [w for w in x["walls"] if w["exterior"]]; ints = [w for w in x["walls"] if not w["exterior"]]
92 out.append(f"\\begin{{frame}}{{{tex(short)} --- plan : {tex(lvl)}}}") 123 out.append(f"\\begin{{frame}}{{{tex(short)} --- plan : {tex(lvl)}}}")
93− out.append("\\begin{columns}[T]\\begin{column}{0.6\\textwidth}\\begin{center}") 124+ out.append(steps([1]))
94− out.append(f"\\includegraphics[height=0.68\\textheight,width=\\textwidth,keepaspectratio]{{{d['dir']}/{x['png']}}}") 125+ out.append(f"\\begin{{center}}\\includegraphics[height=0.74\\textheight,width=0.96\\textwidth,keepaspectratio]{{{d['dir']}/{x['png']}}}\\end{{center}}")
95− out.append("\\end{center}\\end{column}\\begin{column}{0.38\\textwidth}\\footnotesize\\uqotitle{Lecture du plan}\\begin{itemize}\\setlength{\\itemsep}{1pt}") 126+ out.append(f"\\vspace{{-1mm}}{{\\scriptsize\\textcolor{{uqoGris}}{{Échelle {x['pxPerMeter']}~px/m, calibration exacte $\\cdot$ {len(x['rooms'])} pièce(s), {x['windows']} fenêtre(s), {x['doors']} porte(s) $\\cdot$ murs extérieurs {num(sum(w['lengthM'] for w in ext),1)}~m, cloisons {num(sum(w['lengthM'] for w in ints),1)}~m $\\cdot$ aire des pièces {num(x['totals']['floorAreaM2'])}~m\\textsuperscript{{2}}" + (f" $\\cdot$ empreinte {num(x['footprintM2'])}~m\\textsuperscript{{2}}" if x.get('footprintM2') else "") + "}}\\end{frame}\n")
96− out.append(f" \\item {x['pxPerMeter']}~px/m, {x['widthPx']}$\\times${x['heightPx']}~px ; incertitude de calibration : 0") 127+ g = d["ground"]
97− out.append(f" \\item {len(rooms)} pièce(s), {x['windows']} fenêtre(s), {x['doors']} porte(s)") 128+ # plan annoté : six épingles → ce que chaque objet devient
98− if rooms: 129+ ext = [w for w in g["walls"] if w["exterior"]]; ints = [w for w in g["walls"] if not w["exterior"]]
99− out.append(" \\item " + cut("; ".join(tex(r["name"]) for r in rooms), 110)) 130+ legend = {"ext": f"\\textbf{{Murs extérieurs}} : {num(sum(w['lengthM'] for w in ext),1)}~m, brut {num(sum(w['grossAreaM2'] for w in ext))}~m\\textsuperscript{{2}}, net {num(sum(w['netAreaM2'] for w in ext))}~m\\textsuperscript{{2}} $\\rightarrow$ ossature, isolation, revêtements",
100− out.append(" \\item Murs ext. 0,30~m, cloisons 0,12~m, ouvertures : objets mesurables (longueur, aires brute et nette, comptage)") 131+ "int": f"\\textbf{{Cloisons}} : {num(sum(w['lengthM'] for w in ints),1)}~m $\\rightarrow$ ossature 2$\\times$4, gypse deux faces",
101− out.append("\\end{itemize}\\end{column}\\end{columns}\\end{frame}\n") 132+ "win": f"\\textbf{{Fenêtres}} : {g['windows']} comptées $\\rightarrow$ unités, déduites des murs nets",
133+ "door": f"\\textbf{{Portes}} : {g['doors']} (ext., int., patio, garage) $\\rightarrow$ unités",
134+ "room": f"\\textbf{{Pièces}} : {len(g['rooms'])}, aire {num(g['totals']['floorAreaM2'])}~m\\textsuperscript{{2}} $\\rightarrow$ planchers par usage, plafonds, plinthes",
135+ "fp": f"\\textbf{{Empreinte}} {num(g['footprintM2'] or d['footprint'])}~m\\textsuperscript{{2}}, périmètre {num(d['perimeter'],1)}~m $\\rightarrow$ excavation, semelles, fondation, dalle, toiture"}
136+ out.append(f"\\begin{{frame}}{{{tex(short)} --- lire le plan : ce que chaque objet devient}}")
137+ out.append(steps([1, 3]))
138+ out.append("\\begin{columns}[T]\\begin{column}{0.5\\textwidth}\\begin{center}\\begin{tikzpicture}")
139+ out.append(f"\\node[anchor=south west, inner sep=0pt] (img) at (0,0) {{\\includegraphics[width=\\textwidth,height=0.62\\textheight,keepaspectratio]{{{d['dir']}/{g['png']}}}}};")
140+ order = ["ext", "int", "win", "door", "room", "fp"]; pins = {pn["key"]: pn for pn in g["pins"]}
141+ k = 0
142+ for key in order:
143+ if key in pins and key in legend: k += 1; out.append(f"\\qspin{{{pins[key]['at']['x']}}}{{{pins[key]['at']['y']}}}{{{k}}}")
144+ out.append("\\end{tikzpicture}\\end{center}\\end{column}\\begin{column}{0.48\\textwidth}\\scriptsize\\begin{enumerate}\\setlength{\\itemsep}{1pt}")
145+ for key in order:
146+ if key in pins and key in legend: out.append(f" \\item {legend[key]}")
147+ out.append("\\end{enumerate}\\end{column}\\end{columns}\\end{frame}\n")
148+ # table des objets du rez-de-chaussée
149+ out.append(f"\\begin{{frame}}{{{tex(short)} --- les objets mesurés du plan ({tex(g['level'] or g['label'])})}}")
150+ out.append(steps([1, 3]))
151+ wrows = [[cut(tex(w["name"]), 19), "ext." if w["exterior"] else "cloison", num(w["lengthM"], 1), num(w["grossAreaM2"], 1), num(w["openingsAreaM2"], 1), num(w["netAreaM2"], 1)] for w in sorted(g["walls"], key=lambda w: -w["lengthM"])[:9]]
152+ rrows = [[cut(tex(r["name"]), 18), num(r["areaM2"], 1), num(r["perimeterM"], 1)] for r in sorted(g["rooms"], key=lambda r: -r["areaM2"])[:9]]
153+ out.append("\\begin{columns}[T]\\begin{column}{0.55\\textwidth}")
154+ out.append(table(wrows, ["Mur (h " + num(g["walls"][0]["heightM"], 2) + "~m)", "Type", "L (m)", "Brut", "Ouv.", "Net"], "l l r r r r", "\\scriptsize", "0.92"))
155+ out.append("\\end{column}\\begin{column}{0.43\\textwidth}")
156+ out.append(table(rrows, ["Pièce (usage sur le plan)", "Aire m\\textsuperscript{2}", "Périm. m"], "l r r", "\\scriptsize", "0.92"))
157+ out.append("\\end{column}\\end{columns}")
158+ opn = {}
159+ for o in g["openings"]: key = ("fenêtre" if o["kind"] == "window" else "porte ext." if o["exterior"] and o["kind"] == "door" else "porte-patio" if o["kind"] == "patio" else "porte garage" if o["kind"] == "garage" else "porte int."); opn[key] = opn.get(key, 0) + 1
160+ out.append("{\\scriptsize\\textcolor{uqoGris}{Ouvertures de ce niveau : " + ", ".join(f"{v} {tex(k)}" for k, v in opn.items()) + f" ; aire des ouvertures déduite une seule fois des murs (net = brut -- ouvertures). {len(g['walls'])} murs, {len(g['rooms'])} pièces au total" + (" (9 plus grands affichés)" if len(g['walls']) > 9 or len(g['rooms']) > 9 else "") + ".}}\\end{frame}\n")
161+ return "\n".join(out)
162+
163+def frame_demarche_a(d):
164+ """du plan aux mesures de base : les grandeurs d'entrée des formules"""
165+ short = short_name(d["project"]); g = d["ground"]; s = d["project"]["spec"]
166+ ext = [w for w in g["walls"] if w["exterior"]]
167+ rows = [["Empreinte $F$", f"{num(d['footprint'])}~m\\textsuperscript{{2}}", "polygone « empreinte » du rez-de-chaussée (ou boucle des murs extérieurs)"],
168+ ["Périmètre $P$", f"{num(d['perimeter'],1)}~m", "longueur de la boucle des murs extérieurs du rez-de-chaussée"],
169+ ["Hauteur d'étage $h$", f"{num(s.get('ceilingHeightM', 2.44),2)}~m", "fiche technique (hauteur de plafond)"],
170+ ["Hauteur du mur de fondation", f"{num(s.get('foundationWallHeightM'),2)}~m", "fiche technique"],
171+ ["Murs extérieurs bruts (tous niveaux)", f"{num(d['extGross'])}~m\\textsuperscript{{2}}", "$\\Sigma$ longueur $\\times$ hauteur, + pignons"],
172+ ["Murs extérieurs nets", f"{num(d['extNet'])}~m\\textsuperscript{{2}}", "brut -- aire des ouvertures (déduite une seule fois)"],
173+ ["Cloisons (tous niveaux)", f"{num(d['intGross'])}~m\\textsuperscript{{2}}", "$\\Sigma$ longueur $\\times$ hauteur"],
174+ ["Aire des pièces (hors sol)", f"{num(d['roomsArea'])}~m\\textsuperscript{{2}}", "$\\Sigma$ polygones des pièces, par usage"],
175+ ["Fenêtres / portes", f"{d['windowsAll']} / {d['doorsAll']}", "comptées sur tous les niveaux, avec leur mur"],
176+ ["Facteur de pente du toit", f"{num(d['slope'],3)}", f"$\\sqrt{{1 + ({s.get('roofPitch')}/12)^2}}$ (fiche : pente {s.get('roofPitch')}/12)"]]
177+ out = [f"\\begin{{frame}}{{{tex(short)} --- démarche A : du plan aux grandeurs de base}}", steps([1, 2, 3])]
178+ out.append(table(rows, ["Grandeur", "Valeur", "D'où elle vient"], "l r l", "\\scriptsize", "0.95"))
179+ out.append("{\\tiny\\textcolor{uqoGris}{Ces dix grandeurs alimentent presque toutes les formules du relevé ; elles sont recalculées à chaque modification du plan ou de la fiche.}}\\end{frame}\n")
180+ return "\n".join(out)
181+
182+def frames_demarche_b(d):
183+ """des grandeurs aux quantités : formule, entrées, résultat (données du registre)"""
184+ short = short_name(d["project"]); out = []
185+ sel1 = [m for m in d["qs"] if m["wbs"] in ("31", "03", "05", "06") and m["inputs"]][:8]
186+ sel2 = [m for m in d["qs"] if m["wbs"] in ("07", "08", "09", "22", "23", "26") and m["inputs"]][:8]
187+ for title, sel in (("site, fondations, structure", sel1), ("enveloppe, finitions, mécanique", sel2)):
188+ if not sel: continue
189+ out.append(f"\\begin{{frame}}{{{tex(short)} --- démarche B : des grandeurs aux quantités ({tex(title)})}}")
190+ out.append(steps([3]))
191+ rows = [[cut(tex(m["name"]), 26), cut(tex(m["formula"].replace("Σ ", "somme des ")), 80), cut(kv_fr(m["inputs"]), 80), f"\\textbf{{{num(m['value'], 2 if m['value'] < 100 else 0)}}} {unit(m['unit'])}"] for m in sel[:7]]
192+ out.append(table(rows, ["Famille", "Formule", "Entrées (du plan ou de la fiche)", "Résultat"], "p{2.7cm} p{4.5cm} p{4.5cm} r", "\\scriptsize", "0.92"))
193+ out.append("{\\tiny\\textcolor{uqoGris}{Formule, entrées et résultat sont ceux du registre de mesures d'UQO Éval ; une mesure modifiée à la main rend la ligne « périmée » jusqu'au recalcul.}}\\end{frame}\n")
194+ return "\n".join(out)
195+
196+def frame_demarche_c(d):
197+ """de la quantité au coût : quatre lignes travaillées"""
198+ short = short_name(d["project"])
199+ pick = []
200+ for divs in (("03",), ("06", "05"), ("07",), ("08",), ("09",), ("22", "23", "26")):
201+ c = [l for l in d["lines"] if l["basis"] == "rsmeans" and l["wbs"] in divs and l.get("takeoffQuantity")]
202+ if c: pick.append(max(c, key=lambda l: l["located"]))
203+ pick = sorted(pick, key=lambda l: -l["located"])[:5]
204+ out = [f"\\begin{{frame}}{{{tex(short)} --- démarche C : de la quantité au coût (cinq lignes travaillées)}}", steps([3, 4])]
205+ rows = []
206+ for l in pick:
207+ m = re.match(r"^(.*?) — (.*?) — RSMeans (\d{12})$", l["description"]); fam, lab, ln = (m.group(1), m.group(2), m.group(3)) if m else (l["description"], "", "")
208+ conv = l["quantity"] / l["takeoffQuantity"] if l["takeoffQuantity"] else 1
209+ tq = next((mm for mm in d["qs"] if mm["name"] == fam), None); tu = unit(tq["unit"]) if tq else ""
210+ q_txt = f"{num(l['takeoffQuantity'], 2 if l['takeoffQuantity'] < 100 else 0)} {tu}" + (f" $\\times$ {num(conv, 3)} = {num(l['quantity'], 1 if l['quantity'] < 100 else 0)} {unit(l['unit'])}" if abs(conv - 1) > 1e-6 else "")
211+ price = f"{money(l['unitMaterial'],2)} + {money(l['unitLabour'],2)}" + (f" + {money(l['unitEquipment'],2)}" if l["unitEquipment"] else "") + f" = {money(l['unitDirect'],2)}"
212+ rows.append([cut(tex(fam), 26), f"\\texttt{{{ln}}} {cut(tex(lab), 44)}", q_txt, price, f"\\textbf{{{money(l['located'])}}}"])
213+ out.append(table(rows, ["Famille", "Ligne RSMeans", "Quantité (relevé $\\rightarrow$ RSMeans)", "Bare : mat. + MO (+ éq.) / unité", "Montant"], "p{2.2cm} p{3.6cm} p{3.2cm} p{3.0cm} r", "\\scriptsize", "0.92"))
214+ loc = d["version"]["result"]["lines"][0]["provenance"]["source"]
215+ out.append(f"{{\\tiny\\textcolor{{uqoGris}}{{Montant = quantité convertie $\\times$ coût unitaire bare ({tex(loc)}). Les conversions (m\\textsuperscript{{2}} $\\rightarrow$ pi\\textsuperscript{{2}} $\\times$ 10,764 ; m\\textsuperscript{{3}} $\\rightarrow$ vg\\textsuperscript{{3}} $\\times$ 1,308 ; m $\\rightarrow$ pi $\\times$ 3,281) et les facteurs de quantité documentés (ex. m\\textsuperscript{{2}} de mur $\\rightarrow$ m d'ossature $\\div$ 2,44) sont faits par le moteur.}}}}\\end{{frame}}\n")
102 return "\n".join(out) 216 return "\n".join(out)
103 217
104 def frames_releve(d): 218 def frames_releve(d):
@@ -110,7 +224,8 @@ def frames_releve(d):
110 nch = -(-len(rows) // 11); size = -(-len(rows) // nch); chunks = [rows[i:i + size] for i in range(0, len(rows), size)] 224 nch = -(-len(rows) // 11); size = -(-len(rows) // nch); chunks = [rows[i:i + size] for i in range(0, len(rows), size)]
111 for ci, ch in enumerate(chunks): 225 for ci, ch in enumerate(chunks):
112 suffix = f" ({ci+1}/{len(chunks)})" if len(chunks) > 1 else "" 226 suffix = f" ({ci+1}/{len(chunks)})" if len(chunks) > 1 else ""
113− out.append(f"\\begin{{frame}}{{{tex(short)} --- relevé : {tex(title)}{suffix}}}") 227+ out.append(f"\\begin{{frame}}{{{tex(short)} --- relevé complet : {tex(title)}{suffix}}}")
228+ out.append(steps([3]))
114 trows = [[m["wbs"], cut(tex(m["name"]), 46), num(m["value"], 2 if m["value"] < 100 else 0), unit(m["unit"]), cut(tex(m["formula"].replace("Σ ", "somme des ")), 58)] for m in ch] 229 trows = [[m["wbs"], cut(tex(m["name"]), 46), num(m["value"], 2 if m["value"] < 100 else 0), unit(m["unit"]), cut(tex(m["formula"].replace("Σ ", "somme des ")), 58)] for m in ch]
115 out.append(table(trows, ["Div.", "Mesure du registre (QS)", "Quantité", "Unité", "Formule (plan ou fiche)"], "l l r l l", "\\scriptsize", "0.95")) 230 out.append(table(trows, ["Div.", "Mesure du registre (QS)", "Quantité", "Unité", "Formule (plan ou fiche)"], "l l r l l", "\\scriptsize", "0.95"))
116 if ci == len(chunks) - 1: 231 if ci == len(chunks) - 1:
@@ -126,7 +241,7 @@ def frame_prix(d):
126 m = re.match(r"^(.*?) — (.*?) — RSMeans (\d{12})$", l["description"]) 241 m = re.match(r"^(.*?) — (.*?) — RSMeans (\d{12})$", l["description"])
127 fam, ln = (m.group(1), m.group(3)) if m else (l["description"], "") 242 fam, ln = (m.group(1), m.group(3)) if m else (l["description"], "")
128 rows.append([cut(tex(fam), 28), f"\\texttt{{{ln}}}", num(l["quantity"], 1 if l["quantity"] < 100 else 0), unit(l["unit"]), money(l["unitMaterial"], 2), money(l["unitLabour"], 2), money(l["unitEquipment"], 2) if l["unitEquipment"] else "---", money(l["located"])]) 243 rows.append([cut(tex(fam), 28), f"\\texttt{{{ln}}}", num(l["quantity"], 1 if l["quantity"] < 100 else 0), unit(l["unit"]), money(l["unitMaterial"], 2), money(l["unitLabour"], 2), money(l["unitEquipment"], 2) if l["unitEquipment"] else "---", money(l["located"])])
129− out = [f"\\begin{{frame}}{{{tex(short)} --- prix unitaires RSMeans (11 lignes les plus lourdes)}}"] 244+ out = [f"\\begin{{frame}}{{{tex(short)} --- prix unitaires RSMeans (11 lignes les plus lourdes)}}", steps([4])]
130 out.append(table(rows, ["Famille", "Ligne RSMeans", "Qté", "Unité", "Matériau", "M.-d'\\oe uvre", "Équip.", "Montant"], "l l r l r r r r", "\\scriptsize", "0.95")) 245 out.append(table(rows, ["Famille", "Ligne RSMeans", "Qté", "Unité", "Matériau", "M.-d'\\oe uvre", "Équip.", "Montant"], "l l r l r r r r", "\\scriptsize", "0.95"))
131 loc = d["version"]["result"]["lines"][0]["provenance"]["source"] 246 loc = d["version"]["result"]["lines"][0]["provenance"]["source"]
132 out.append(f"{{\\tiny\\textcolor{{uqoGris}}{{Coûts unitaires bare (matériau + MO + équipement, sans O\\&P), {tex(loc)} ; quantités converties par le moteur (m\\textsuperscript{{2}} $\\rightarrow$ pi\\textsuperscript{{2}}, m\\textsuperscript{{3}} $\\rightarrow$ vg\\textsuperscript{{3}}).}}}}\\end{{frame}}\n") 247 out.append(f"{{\\tiny\\textcolor{{uqoGris}}{{Coûts unitaires bare (matériau + MO + équipement, sans O\\&P), {tex(loc)} ; quantités converties par le moteur (m\\textsuperscript{{2}} $\\rightarrow$ pi\\textsuperscript{{2}}, m\\textsuperscript{{3}} $\\rightarrow$ vg\\textsuperscript{{3}}).}}}}\\end{{frame}}\n")
@@ -139,7 +254,7 @@ def frame_divisions(d):
139 rows.append(["\\textbf{Total direct}", f"\\textbf{{{money(r['totals']['located'])}}}", "\\textbf{100\\,\\%}"]) 254 rows.append(["\\textbf{Total direct}", f"\\textbf{{{money(r['totals']['located'])}}}", "\\textbf{100\\,\\%}"])
140 top = sorted(by, key=lambda w: -w["located"])[:3] 255 top = sorted(by, key=lambda w: -w["located"])[:3]
141 mat, lab, eq = r["totals"]["material"], r["totals"]["labour"], r["totals"]["equipment"]; tot = mat + lab + eq 256 mat, lab, eq = r["totals"]["material"], r["totals"]["labour"], r["totals"]["equipment"]; tot = mat + lab + eq
142− out = [f"\\begin{{frame}}{{{tex(short)} --- coûts directs par division}}", "\\begin{columns}[T]\\begin{column}{0.55\\textwidth}"] 257+ out = [f"\\begin{{frame}}{{{tex(short)} --- coûts directs par division}}", steps([4]), "\\begin{columns}[T]\\begin{column}{0.55\\textwidth}"]
143 out.append(table(rows, ["Division MasterFormat", "Direct", "Part"], "l r r", "\\scriptsize", "0.9")) 258 out.append(table(rows, ["Division MasterFormat", "Direct", "Part"], "l r r", "\\scriptsize", "0.9"))
144 out.append("\\end{column}\\begin{column}{0.43\\textwidth}\\footnotesize") 259 out.append("\\end{column}\\begin{column}{0.43\\textwidth}\\footnotesize")
145 out.append("\\begin{notebox}[Les trois divisions lourdes]" + " ; ".join(f"\\textbf{{{w['wbs']}}} {DIV.get(w['wbs'],'')} ({num(w['sharePct'],1)}\\,\\%)" for w in top) + ".\\end{notebox}") 260 out.append("\\begin{notebox}[Les trois divisions lourdes]" + " ; ".join(f"\\textbf{{{w['wbs']}}} {DIV.get(w['wbs'],'')} ({num(w['sharePct'],1)}\\,\\%)" for w in top) + ".\\end{notebox}")
@@ -151,12 +266,12 @@ def frame_total(d):
151 short = short_name(d["project"]); r = d["version"]["result"]; t = r["totals"]; pa = r["params"] 266 short = short_name(d["project"]); r = d["version"]["result"]; t = r["totals"]; pa = r["params"]
152 rows = [["Direct (quantités $\\times$ coûts unitaires bare)", money(t["direct"])], ["Ajustement régional du module (RSMeans déjà localisé)", money(t["locationAdjustment"])], ["= Direct localisé", f"\\textbf{{{money(t['located'])}}}"], [f"Conditions générales {pa['generalConditionsPct']}\\,\\% du direct", money(t["generalConditions"])], [f"Frais généraux {pa['overheadPct']}\\,\\% du cumul", money(t["overhead"])], [f"Profit {pa['profitPct']}\\,\\% du cumul", money(t["profit"])], [f"Contingence {pa['contingencyPct']}\\,\\% du direct", money(t["contingency"])], ["\\textbf{Total hors taxes (coût à neuf 2026 T4)}", f"\\textbf{{{money(t['total'])}}}"]] 267 rows = [["Direct (quantités $\\times$ coûts unitaires bare)", money(t["direct"])], ["Ajustement régional du module (RSMeans déjà localisé)", money(t["locationAdjustment"])], ["= Direct localisé", f"\\textbf{{{money(t['located'])}}}"], [f"Conditions générales {pa['generalConditionsPct']}\\,\\% du direct", money(t["generalConditions"])], [f"Frais généraux {pa['overheadPct']}\\,\\% du cumul", money(t["overhead"])], [f"Profit {pa['profitPct']}\\,\\% du cumul", money(t["profit"])], [f"Contingence {pa['contingencyPct']}\\,\\% du direct", money(t["contingency"])], ["\\textbf{Total hors taxes (coût à neuf 2026 T4)}", f"\\textbf{{{money(t['total'])}}}"]]
153 heated = d["heated"] or 1 268 heated = d["heated"] or 1
154− out = [f"\\begin{{frame}}{{{tex(short)} --- du coût direct au coût à neuf}}", "\\begin{columns}[T]\\begin{column}{0.58\\textwidth}"] 269+ out = [f"\\begin{{frame}}{{{tex(short)} --- étape 5 : du coût direct au coût à neuf}}", steps([5, 6]), "\\begin{columns}[T]\\begin{column}{0.58\\textwidth}"]
155 out.append(table(rows, ["Étape (ordre d'application)", "Montant"], "l r", "\\footnotesize", "1.0")) 270 out.append(table(rows, ["Étape (ordre d'application)", "Montant"], "l r", "\\footnotesize", "1.0"))
156 out.append("\\end{column}\\begin{column}{0.4\\textwidth}\\footnotesize\\begin{center}") 271 out.append("\\end{column}\\begin{column}{0.4\\textwidth}\\footnotesize\\begin{center}")
157 out.append(kpi("uqoBleu", money(t["total"] / heated), "par m\\textsuperscript{2} chauffé") + kpi("uqoTeal", money(t["total"] / heated / 10.7639), "par pi\\textsuperscript{2} chauffé")) 272 out.append(kpi("uqoBleu", money(t["total"] / heated), "par m\\textsuperscript{2} chauffé") + kpi("uqoTeal", money(t["total"] / heated / 10.7639), "par pi\\textsuperscript{2} chauffé"))
158 out.append("\\end{center}") 273 out.append("\\end{center}")
159− out.append(f"\\begin{{importbox}}[Multiplicateur]Direct $\\rightarrow$ total : $\\times$~{num(t['total']/t['direct'],3)}. Le Total O\\&P de RSMeans n'est pas additionné (il contient déjà l'O\\&P de l'installateur).\\end{{importbox}}") 274+ out.append(f"\\begin{{importbox}}[Multiplicateur]Direct $\\rightarrow$ total : $\\times$~{num(t['total']/t['direct'],3)}. Le Total O\\&P de RSMeans n'est pas additionné (il contient déjà l'O\\&P de l'installateur). Révision figée : {tex(d['version']['label'])}, empreinte SHA-256 {tex(d['version']['contentHash'][:12])}….\\end{{importbox}}")
160 out.append("\\end{column}\\end{columns}\\end{frame}\n") 275 out.append("\\end{column}\\end{columns}\\end{frame}\n")
161 return "\n".join(out) 276 return "\n".join(out)
162 277
@@ -170,7 +285,7 @@ LECTURE = {
170 285
171 def frame_lecture(d): 286 def frame_lecture(d):
172 short = short_name(d["project"]); title, pts, q = LECTURE[d["n"]] 287 short = short_name(d["project"]); title, pts, q = LECTURE[d["n"]]
173− out = [f"\\begin{{frame}}{{{tex(short)} --- lecture de l'évaluateur}}", f"\\uqotitle{{{title}}}", "\\begin{itemize}"] + [f" \\item {x}" for x in pts] 288+ out = [f"\\begin{{frame}}{{{tex(short)} --- lecture de l'évaluateur}}", steps([6]), f"\\uqotitle{{{title}}}", "\\begin{itemize}"] + [f" \\item {x}" for x in pts]
174 out.append(f"\\end{{itemize}}\\vspace{{1mm}}\\begin{{quizbox}}[Question à la classe]{q}\\end{{quizbox}}\\end{{frame}}\n") 289 out.append(f"\\end{{itemize}}\\vspace{{1mm}}\\begin{{quizbox}}[Question à la classe]{q}\\end{{quizbox}}\\end{{frame}}\n")
175 return "\n".join(out) 290 return "\n".join(out)
176 291
@@ -207,6 +322,26 @@ def intro(loc):
207 \\end{tikzpicture} 322 \\end{tikzpicture}
208 \\end{center} 323 \\end{center}
209 \\end{frame} 324 \\end{frame}
325+""")
326+ out.append("""\\begin{frame}{Le fil conducteur de chaque cas}
327+\\begin{columns}[T]\\begin{column}{0.56\\textwidth}\\footnotesize
328+Chaque cas suit le même chemin, repéré par l'indicateur en haut à droite des diapositives :
329+\\begin{enumerate}\\setlength{\\itemsep}{1pt}
330+ \\item \\textbf{Fiche du cas} --- ce que le plan donne, ce que la fiche fixe
331+ \\item \\textbf{Plans} plein cadre par niveau, puis plan annoté (six objets) et table des objets mesurés
332+ \\item \\textbf{Démarche A} --- du plan aux dix grandeurs de base ($F$, $P$, $h$, murs, pièces, ouvertures, pente)
333+ \\item \\textbf{Démarche B} --- des grandeurs aux quantités : formule, entrées, résultat
334+ \\item \\textbf{Relevé complet} --- toutes les mesures du registre, par division
335+ \\item \\textbf{Démarche C} --- de la quantité au coût : conversion, coût unitaire bare, montant
336+ \\item \\textbf{Prix unitaires}, \\textbf{divisions}, \\textbf{majorations} $\\rightarrow$ coût à neuf
337+ \\item \\textbf{Lecture de l'évaluateur} et question à la classe
338+\\end{enumerate}
339+\\end{column}\\begin{column}{0.42\\textwidth}\\footnotesize
340+\\begin{center}{\\tiny\\qsstep{1}{1}{Plan}\\qsstep{1}{2}{Fiche}\\qsstep{0}{3}{Relevé}\\qsstep{0}{4}{Prix}\\qsstep{0}{5}{Majorations}\\qsstep{0}{6}{Révision}}\\end{center}
341+\\begin{notebox}[Lire l'indicateur]Les étapes en bleu sont celles que la diapositive travaille ; les six étapes sont celles de la méthode.\\end{notebox}
342+\\begin{exbox}[Pourquoi tant de détail]Au TP2 et à l'examen final, on vous demande exactement cette traçabilité : quantité $\\leftarrow$ formule $\\leftarrow$ plan, prix $\\leftarrow$ source datée, total $\\leftarrow$ majorations ordonnées.\\end{exbox}
343+\\end{column}\\end{columns}
344+\\end{frame}
210 """) 345 """)
211 out.append("""\\begin{frame}{Étape 1 --- lire le plan : ce qui devient une quantité} 346 out.append("""\\begin{frame}{Étape 1 --- lire le plan : ce qui devient une quantité}
212 \\begin{columns}[T]\\begin{column}{0.46\\textwidth} 347 \\begin{columns}[T]\\begin{column}{0.46\\textwidth}
@@ -273,9 +408,9 @@ def intro(loc):
273 rows = [] 408 rows = []
274 for c in loc["cmp"]: 409 for c in loc["cmp"]:
275 pr = {x["loc"]: x["p"] for x in c["prices"]} 410 pr = {x["loc"]: x["p"] for x in c["prices"]}
276− rows.append([cut(tex(c["desc"]), 42), tex(c["unit"])] + [money(pr[k]["total"], 2) if pr.get(k) and pr[k]["total"] is not None else "---" for k in keep]) 411+ rows.append([cut(tex(c["desc"]), 36) + f" ({tex(c['unit'])})"] + [money(pr[k]["total"], 2) if pr.get(k) and pr[k]["total"] is not None else "---" for k in keep])
277 out.append("\\begin{frame}{Localisation --- la même ligne RSMeans dans sept villes (coût bare, MO syndiquée)}") 412 out.append("\\begin{frame}{Localisation --- la même ligne RSMeans dans sept villes (coût bare, MO syndiquée)}")
278− out.append(table(rows, ["Ligne", "Unité"] + [names[k] for k in keep], "l l r r r r r r r", "\\scriptsize", "0.95")) 413+ out.append(table(rows, ["Ligne (unité RSMeans)"] + [names[k] for k in keep], "l r r r r r r r", "\\scriptsize", "0.95"))
279 out.append("\\begin{notebox}[Ce qu'on observe]\\footnotesize Les matériaux varient peu (fenêtre, toilette) ; la \\textbf{main-d'\\oe uvre} fait la différence (ossature, gypse). RSMeans localise par \\textbf{section MasterFormat} : les facteurs de section reproduisent les prix extraits à l'arrondi près (p90 $<$ 0,1\\,\\%) ; un facteur par division se trompe de 20\\,\\% une fois sur dix.\\end{notebox}\n\\end{frame}\n") 414 out.append("\\begin{notebox}[Ce qu'on observe]\\footnotesize Les matériaux varient peu (fenêtre, toilette) ; la \\textbf{main-d'\\oe uvre} fait la différence (ossature, gypse). RSMeans localise par \\textbf{section MasterFormat} : les facteurs de section reproduisent les prix extraits à l'arrondi près (p90 $<$ 0,1\\,\\%) ; un facteur par division se trompe de 20\\,\\% une fois sur dix.\\end{notebox}\n\\end{frame}\n")
280 out.append("""\\begin{frame}{Étape 5 --- les majorations, dans l'ordre} 415 out.append("""\\begin{frame}{Étape 5 --- les majorations, dans l'ordre}
281 \\begin{columns}[T]\\begin{column}{0.52\\textwidth}\\footnotesize 416 \\begin{columns}[T]\\begin{column}{0.52\\textwidth}\\footnotesize
@@ -360,12 +495,14 @@ def main():
360 all_ds = [load(n) for n in ALL]; ds = {d["n"]: d for d in all_ds} 495 all_ds = [load(n) for n in ALL]; ds = {d["n"]: d for d in all_ds}
361 parts = ["% Généré par gen_qs_cas.py — ne pas éditer à la main (données : images/qs-cas/*/data.json, révisions figées UQO Éval / RSMeans 2026 T4)", 496 parts = ["% Généré par gen_qs_cas.py — ne pas éditer à la main (données : images/qs-cas/*/data.json, révisions figées UQO Éval / RSMeans 2026 T4)",
362 "\\providecommand{\\qskpi}[3][uqoBleu]{\\begin{tikzpicture}[baseline=(b.base)]\\node[fill=#1!8, draw=#1!40, rounded corners=2pt, inner xsep=4pt, inner ysep=2.5pt, align=center, text width=26mm] (b) {{\\textcolor{#1}{\\normalsize\\textbf{#2}}}\\\\[-1pt]{\\tiny\\textcolor{uqoGris}{#3}}};\\end{tikzpicture}}", 497 "\\providecommand{\\qskpi}[3][uqoBleu]{\\begin{tikzpicture}[baseline=(b.base)]\\node[fill=#1!8, draw=#1!40, rounded corners=2pt, inner xsep=4pt, inner ysep=2.5pt, align=center, text width=26mm] (b) {{\\textcolor{#1}{\\normalsize\\textbf{#2}}}\\\\[-1pt]{\\tiny\\textcolor{uqoGris}{#3}}};\\end{tikzpicture}}",
498+ "\\providecommand{\\qsstep}[3]{\\ifnum#1=1\\colorlet{qsfill}{uqoBleu}\\colorlet{qstext}{uqoBlanc}\\else\\colorlet{qsfill}{uqoGrisClair}\\colorlet{qstext}{uqoGris}\\fi\\tikz[baseline=-0.5ex]{\\node[rounded corners=1pt, inner xsep=3pt, inner ysep=1.5pt, fill=qsfill, text=qstext, font=\\tiny\\bfseries] {#2 #3};}\\hspace{1pt}}",
499+ "\\providecommand{\\qspin}[3]{\\path ($(img.south west)!#1!(img.south east)$) coordinate (qx); \\path ($(img.south west)!#2!(img.north west)$) coordinate (qy); \\node[circle, fill=uqoOr, text=uqoNavy, font=\\fontsize{6.5}{7}\\selectfont\\bfseries, inner sep=0.8pt, minimum size=3.4mm, draw=uqoNavy, line width=0.4pt] at (qx |- qy) {#3};}",
363 "\\section{Atelier --- Quantity survey : cinq cas complets (plans, quantités, coûts)}", intro(loc)] 500 "\\section{Atelier --- Quantity survey : cinq cas complets (plans, quantités, coûts)}", intro(loc)]
364 for n in CASES: 501 for n in CASES:
365 d = ds[n]; short = short_name(d["project"]) 502 d = ds[n]; short = short_name(d["project"])
366 parts.append(f"% ---------------- {short}") 503 parts.append(f"% ---------------- {short}")
367 parts.append(f"\\begin{{frame}}[plain]\\begin{{center}}\\vspace{{1.2cm}}{{\\Huge\\textcolor{{uqoBleu}}{{\\textbf{{{tex(short)}}}}}}}\\\\[4mm]{{\\large\\textcolor{{uqoGris}}{{{tex(d['project']['municipality'])} $\\cdot$ RSMeans 2026 T4 $\\cdot$ {len(d['qs'])} mesures $\\cdot$ {len(d['lines'])} lignes chiffrées}}}}\\end{{center}}\\end{{frame}}\n") 504 parts.append(f"\\begin{{frame}}[plain]\\begin{{center}}\\vspace{{1.2cm}}{{\\Huge\\textcolor{{uqoBleu}}{{\\textbf{{{tex(short)}}}}}}}\\\\[4mm]{{\\large\\textcolor{{uqoGris}}{{{tex(d['project']['municipality'])} $\\cdot$ RSMeans 2026 T4 $\\cdot$ {len(d['qs'])} mesures $\\cdot$ {len(d['lines'])} lignes chiffrées}}}}\\end{{center}}\\end{{frame}}\n")
368− parts += [frame_fiche(d), frame_plans(d), frames_releve(d), frame_prix(d), frame_divisions(d), frame_total(d), frame_lecture(d)] 505+ parts += [frame_fiche(d), frame_plans(d), frame_demarche_a(d), frames_demarche_b(d), frames_releve(d), frame_demarche_c(d), frame_prix(d), frame_divisions(d), frame_total(d), frame_lecture(d)]
369 parts.append(synthese(all_ds)) 506 parts.append(synthese(all_ds))
370 os.makedirs(os.path.dirname(OUT), exist_ok=True) 507 os.makedirs(os.path.dirname(OUT), exist_ok=True)
371 txt = "\n".join(parts); open(OUT, "w").write(txt) 508 txt = "\n".join(parts); open(OUT, "w").write(txt)
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas1/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas1/Sous_sol.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas1/data.json +373 −9
@@ -60,17 +60,131 @@
60 "widthPx": 860, 60 "widthPx": 860,
61 "heightPx": 705, 61 "heightPx": 705,
62 "png": "Sous_sol.png", 62 "png": "Sous_sol.png",
63+ "crop": {
64+ "x0": 41.5,
65+ "y0": 41.5,
66+ "x1": 818.5,
67+ "y1": 663.5
68+ },
63 "objects": 9, 69 "objects": 9,
70+ "pins": [
71+ {
72+ "key": "ext",
73+ "label": "Murs extérieurs",
74+ "at": {
75+ "x": 0.5,
76+ "y": 0.866
77+ }
78+ },
79+ {
80+ "key": "int",
81+ "label": "Cloisons",
82+ "at": {
83+ "x": 0.301,
84+ "y": 0.745
85+ }
86+ },
87+ {
88+ "key": "win",
89+ "label": "Fenêtres",
90+ "at": {
91+ "x": 0.343,
92+ "y": 0.134
93+ }
94+ },
95+ {
96+ "key": "room",
97+ "label": "Pièces (aire, périmètre)",
98+ "at": {
99+ "x": 0.5,
100+ "y": 0.5
101+ }
102+ },
103+ {
104+ "key": "fp",
105+ "label": "Empreinte et périmètre",
106+ "at": {
107+ "x": 0.108,
108+ "y": 0.865
109+ }
110+ }
111+ ],
112+ "walls": [
113+ {
114+ "name": "Murs extérieurs",
115+ "exterior": true,
116+ "lengthM": 42.6,
117+ "heightM": 2.44,
118+ "thicknessM": 0.3,
119+ "grossAreaM2": 103.944,
120+ "openingsAreaM2": 1.2,
121+ "netAreaM2": 102.744
122+ },
123+ {
124+ "name": "Cloison salle mécanique",
125+ "exterior": false,
126+ "lengthM": 6,
127+ "heightM": 2.3,
128+ "thicknessM": 0.12,
129+ "grossAreaM2": 13.8,
130+ "openingsAreaM2": 0,
131+ "netAreaM2": 13.8
132+ }
133+ ],
64 "rooms": [ 134 "rooms": [
65 { 135 {
66 "name": "Sous-sol", 136 "name": "Sous-sol",
67− "usage": "sous-sol" 137+ "usage": "sous-sol",
138+ "areaM2": 106.8,
139+ "perimeterM": 41.8,
140+ "heightM": 2.3
68 }, 141 },
69 { 142 {
70 "name": "Salle mécanique", 143 "name": "Salle mécanique",
71− "usage": "salle mécanique" 144+ "usage": "salle mécanique",
145+ "areaM2": 7.84,
146+ "perimeterM": 11.2,
147+ "heightM": 2.3
72 } 148 }
73 ], 149 ],
150+ "openings": [
151+ {
152+ "kind": "window",
153+ "name": "Fenêtre de sous-sol",
154+ "widthM": 0.8,
155+ "heightM": 0.5,
156+ "areaM2": 0.4,
157+ "wall": "Murs extérieurs",
158+ "exterior": true
159+ },
160+ {
161+ "kind": "window",
162+ "name": "Fenêtre de sous-sol",
163+ "widthM": 0.8,
164+ "heightM": 0.5,
165+ "areaM2": 0.4,
166+ "wall": "Murs extérieurs",
167+ "exterior": true
168+ },
169+ {
170+ "kind": "window",
171+ "name": "Fenêtre de sous-sol",
172+ "widthM": 0.8,
173+ "heightM": 0.5,
174+ "areaM2": 0.4,
175+ "wall": "Murs extérieurs",
176+ "exterior": true
177+ }
178+ ],
179+ "footprintM2": 117.5,
180+ "totals": {
181+ "wallLengthM": 48.6,
182+ "wallNetAreaM2": 116.544,
183+ "extWallNetAreaM2": 102.744,
184+ "floorAreaM2": 114.64,
185+ "doors": 0,
186+ "windows": 3
187+ },
74 "windows": 3, 188 "windows": 3,
75 "doors": 0 189 "doors": 0
76 }, 190 },
@@ -82,37 +196,287 @@
82 "widthPx": 860, 196 "widthPx": 860,
83 "heightPx": 705, 197 "heightPx": 705,
84 "png": "Rez_de_chausse_e.png", 198 "png": "Rez_de_chausse_e.png",
199+ "crop": {
200+ "x0": 41.5,
201+ "y0": 41.5,
202+ "x1": 818.5,
203+ "y1": 663.5
204+ },
85 "objects": 26, 205 "objects": 26,
206+ "pins": [
207+ {
208+ "key": "ext",
209+ "label": "Murs extérieurs",
210+ "at": {
211+ "x": 0.5,
212+ "y": 0.866
213+ }
214+ },
215+ {
216+ "key": "int",
217+ "label": "Cloisons",
218+ "at": {
219+ "x": 0.5,
220+ "y": 0.5
221+ }
222+ },
223+ {
224+ "key": "win",
225+ "label": "Fenêtres",
226+ "at": {
227+ "x": 0.284,
228+ "y": 0.866
229+ }
230+ },
231+ {
232+ "key": "door",
233+ "label": "Portes",
234+ "at": {
235+ "x": 0.202,
236+ "y": 0.866
237+ }
238+ },
239+ {
240+ "key": "room",
241+ "label": "Pièces (aire, périmètre)",
242+ "at": {
243+ "x": 0.284,
244+ "y": 0.683
245+ }
246+ },
247+ {
248+ "key": "fp",
249+ "label": "Empreinte et périmètre",
250+ "at": {
251+ "x": 0.108,
252+ "y": 0.865
253+ }
254+ }
255+ ],
256+ "walls": [
257+ {
258+ "name": "Murs extérieurs",
259+ "exterior": true,
260+ "lengthM": 42.6,
261+ "heightM": 2.44,
262+ "thicknessM": 0.3,
263+ "grossAreaM2": 103.944,
264+ "openingsAreaM2": 18.96,
265+ "netAreaM2": 84.984
266+ },
267+ {
268+ "name": "Cloison centrale",
269+ "exterior": false,
270+ "lengthM": 12.2,
271+ "heightM": 2.44,
272+ "thicknessM": 0.12,
273+ "grossAreaM2": 29.768,
274+ "openingsAreaM2": 0,
275+ "netAreaM2": 29.768
276+ },
277+ {
278+ "name": "Cloison Séjour",
279+ "exterior": false,
280+ "lengthM": 4.55,
281+ "heightM": 2.44,
282+ "thicknessM": 0.12,
283+ "grossAreaM2": 11.102,
284+ "openingsAreaM2": 0,
285+ "netAreaM2": 11.102
286+ },
287+ {
288+ "name": "Cloison Cuisine / salle à manger",
289+ "exterior": false,
290+ "lengthM": 4.55,
291+ "heightM": 2.44,
292+ "thicknessM": 0.12,
293+ "grossAreaM2": 11.102,
294+ "openingsAreaM2": 0,
295+ "netAreaM2": 11.102
296+ },
297+ {
298+ "name": "Cloison Chambre principale",
299+ "exterior": false,
300+ "lengthM": 4.55,
301+ "heightM": 2.44,
302+ "thicknessM": 0.12,
303+ "grossAreaM2": 11.102,
304+ "openingsAreaM2": 0,
305+ "netAreaM2": 11.102
306+ },
307+ {
308+ "name": "Cloison Chambre 2",
309+ "exterior": false,
310+ "lengthM": 4.55,
311+ "heightM": 2.44,
312+ "thicknessM": 0.12,
313+ "grossAreaM2": 11.102,
314+ "openingsAreaM2": 0,
315+ "netAreaM2": 11.102
316+ },
317+ {
318+ "name": "Cloison Chambre 3",
319+ "exterior": false,
320+ "lengthM": 4.55,
321+ "heightM": 2.44,
322+ "thicknessM": 0.12,
323+ "grossAreaM2": 11.102,
324+ "openingsAreaM2": 0,
325+ "netAreaM2": 11.102
326+ }
327+ ],
86 "rooms": [ 328 "rooms": [
87 { 329 {
88 "name": "Séjour", 330 "name": "Séjour",
89− "usage": "séjour" 331+ "usage": "séjour",
332+ "areaM2": 23.399,
333+ "perimeterM": 19.44,
334+ "heightM": 2.44
90 }, 335 },
91 { 336 {
92 "name": "Cuisine / salle à manger", 337 "name": "Cuisine / salle à manger",
93− "usage": "cuisine" 338+ "usage": "cuisine",
339+ "areaM2": 20.721,
340+ "perimeterM": 18.22,
341+ "heightM": 2.44
94 }, 342 },
95 { 343 {
96 "name": "Hall / escalier", 344 "name": "Hall / escalier",
97− "usage": "hall" 345+ "usage": "hall",
346+ "areaM2": 7.331,
347+ "perimeterM": 12.12,
348+ "heightM": 2.44
98 }, 349 },
99 { 350 {
100 "name": "Chambre principale", 351 "name": "Chambre principale",
101− "usage": "chambre" 352+ "usage": "chambre",
353+ "areaM2": 17.507,
354+ "perimeterM": 16.756,
355+ "heightM": 2.44
102 }, 356 },
103 { 357 {
104 "name": "Chambre 2", 358 "name": "Chambre 2",
105− "usage": "chambre" 359+ "usage": "chambre",
360+ "areaM2": 12.687,
361+ "perimeterM": 14.56,
362+ "heightM": 2.44
106 }, 363 },
107 { 364 {
108 "name": "Chambre 3", 365 "name": "Chambre 3",
109− "usage": "chambre" 366+ "usage": "chambre",
367+ "areaM2": 11.616,
368+ "perimeterM": 14.072,
369+ "heightM": 2.44
110 }, 370 },
111 { 371 {
112 "name": "Salle de bain", 372 "name": "Salle de bain",
113− "usage": "salle de bain" 373+ "usage": "salle de bain",
374+ "areaM2": 8.938,
375+ "perimeterM": 12.852,
376+ "heightM": 2.44
114 } 377 }
115 ], 378 ],
379+ "openings": [
380+ {
381+ "kind": "window",
382+ "name": "Fenêtre Séjour",
383+ "widthM": 1.8,
384+ "heightM": 1.3,
385+ "areaM2": 2.34,
386+ "wall": "Murs extérieurs",
387+ "exterior": true
388+ },
389+ {
390+ "kind": "window",
391+ "name": "Fenêtre Cuisine / salle à manger",
392+ "widthM": 1.8,
393+ "heightM": 1.3,
394+ "areaM2": 2.34,
395+ "wall": "Murs extérieurs",
396+ "exterior": true
397+ },
398+ {
399+ "kind": "window",
400+ "name": "Fenêtre Chambre principale",
401+ "widthM": 1.2,
402+ "heightM": 1.3,
403+ "areaM2": 1.56,
404+ "wall": "Murs extérieurs",
405+ "exterior": true
406+ },
407+ {
408+ "kind": "window",
409+ "name": "Fenêtre Chambre 2",
410+ "widthM": 1.2,
411+ "heightM": 1.3,
412+ "areaM2": 1.56,
413+ "wall": "Murs extérieurs",
414+ "exterior": true
415+ },
416+ {
417+ "kind": "window",
418+ "name": "Fenêtre Chambre 3",
419+ "widthM": 1.2,
420+ "heightM": 1.3,
421+ "areaM2": 1.56,
422+ "wall": "Murs extérieurs",
423+ "exterior": true
424+ },
425+ {
426+ "kind": "window",
427+ "name": "Fenêtre Salle de bain",
428+ "widthM": 0.9,
429+ "heightM": 0.9,
430+ "areaM2": 0.81,
431+ "wall": "Murs extérieurs",
432+ "exterior": true
433+ },
434+ {
435+ "kind": "door",
436+ "name": "Porte d'entrée",
437+ "widthM": 0.9,
438+ "heightM": 2.1,
439+ "areaM2": 1.89,
440+ "wall": "Murs extérieurs",
441+ "exterior": true
442+ },
443+ {
444+ "kind": "door",
445+ "name": "Porte-patio",
446+ "widthM": 1.8,
447+ "heightM": 2.1,
448+ "areaM2": 3.78,
449+ "wall": "Murs extérieurs",
450+ "exterior": true
451+ },
452+ {
453+ "kind": "window",
454+ "name": "Fenêtre latérale",
455+ "widthM": 1.2,
456+ "heightM": 1.3,
457+ "areaM2": 1.56,
458+ "wall": "Murs extérieurs",
459+ "exterior": true
460+ },
461+ {
462+ "kind": "window",
463+ "name": "Fenêtre latérale",
464+ "widthM": 1.2,
465+ "heightM": 1.3,
466+ "areaM2": 1.56,
467+ "wall": "Murs extérieurs",
468+ "exterior": true
469+ }
470+ ],
471+ "footprintM2": 117.5,
472+ "totals": {
473+ "wallLengthM": 77.55,
474+ "wallNetAreaM2": 170.262,
475+ "extWallNetAreaM2": 84.984,
476+ "floorAreaM2": 102.199,
477+ "doors": 2,
478+ "windows": 8
479+ },
116 "windows": 8, 480 "windows": 8,
117 "doors": 2 481 "doors": 2
118 } 482 }
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas2/E_tage.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas2/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas2/Sous_sol.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas2/data.json +607 −15
@@ -60,17 +60,131 @@
60 "widthPx": 830, 60 "widthPx": 830,
61 "heightPx": 705, 61 "heightPx": 705,
62 "png": "Sous_sol.png", 62 "png": "Sous_sol.png",
63+ "crop": {
64+ "x0": 41.5,
65+ "y0": 41.5,
66+ "x1": 788.5,
67+ "y1": 663.5
68+ },
63 "objects": 9, 69 "objects": 9,
70+ "pins": [
71+ {
72+ "key": "ext",
73+ "label": "Murs extérieurs",
74+ "at": {
75+ "x": 0.5,
76+ "y": 0.866
77+ }
78+ },
79+ {
80+ "key": "int",
81+ "label": "Cloisons",
82+ "at": {
83+ "x": 0.313,
84+ "y": 0.745
85+ }
86+ },
87+ {
88+ "key": "win",
89+ "label": "Fenêtres",
90+ "at": {
91+ "x": 0.345,
92+ "y": 0.134
93+ }
94+ },
95+ {
96+ "key": "room",
97+ "label": "Pièces (aire, périmètre)",
98+ "at": {
99+ "x": 0.5,
100+ "y": 0.5
101+ }
102+ },
103+ {
104+ "key": "fp",
105+ "label": "Empreinte et périmètre",
106+ "at": {
107+ "x": 0.112,
108+ "y": 0.865
109+ }
110+ }
111+ ],
112+ "walls": [
113+ {
114+ "name": "Murs extérieurs",
115+ "exterior": true,
116+ "lengthM": 41.4,
117+ "heightM": 2.44,
118+ "thicknessM": 0.3,
119+ "grossAreaM2": 101.016,
120+ "openingsAreaM2": 1.2,
121+ "netAreaM2": 99.816
122+ },
123+ {
124+ "name": "Cloison salle mécanique",
125+ "exterior": false,
126+ "lengthM": 6,
127+ "heightM": 2.3,
128+ "thicknessM": 0.12,
129+ "grossAreaM2": 13.8,
130+ "openingsAreaM2": 0,
131+ "netAreaM2": 13.8
132+ }
133+ ],
64 "rooms": [ 134 "rooms": [
65 { 135 {
66 "name": "Sous-sol", 136 "name": "Sous-sol",
67− "usage": "sous-sol" 137+ "usage": "sous-sol",
138+ "areaM2": 101.46,
139+ "perimeterM": 40.6,
140+ "heightM": 2.3
68 }, 141 },
69 { 142 {
70 "name": "Salle mécanique", 143 "name": "Salle mécanique",
71− "usage": "salle mécanique" 144+ "usage": "salle mécanique",
145+ "areaM2": 7.84,
146+ "perimeterM": 11.2,
147+ "heightM": 2.3
148+ }
149+ ],
150+ "openings": [
151+ {
152+ "kind": "window",
153+ "name": "Fenêtre de sous-sol",
154+ "widthM": 0.8,
155+ "heightM": 0.5,
156+ "areaM2": 0.4,
157+ "wall": "Murs extérieurs",
158+ "exterior": true
159+ },
160+ {
161+ "kind": "window",
162+ "name": "Fenêtre de sous-sol",
163+ "widthM": 0.8,
164+ "heightM": 0.5,
165+ "areaM2": 0.4,
166+ "wall": "Murs extérieurs",
167+ "exterior": true
168+ },
169+ {
170+ "kind": "window",
171+ "name": "Fenêtre de sous-sol",
172+ "widthM": 0.8,
173+ "heightM": 0.5,
174+ "areaM2": 0.4,
175+ "wall": "Murs extérieurs",
176+ "exterior": true
72 } 177 }
73 ], 178 ],
179+ "footprintM2": 111.86,
180+ "totals": {
181+ "wallLengthM": 47.4,
182+ "wallNetAreaM2": 113.616,
183+ "extWallNetAreaM2": 99.816,
184+ "floorAreaM2": 109.3,
185+ "doors": 0,
186+ "windows": 3
187+ },
74 "windows": 3, 188 "windows": 3,
75 "doors": 0 189 "doors": 0
76 }, 190 },
@@ -82,37 +196,287 @@
82 "widthPx": 1045, 196 "widthPx": 1045,
83 "heightPx": 705, 197 "heightPx": 705,
84 "png": "Rez_de_chausse_e.png", 198 "png": "Rez_de_chausse_e.png",
199+ "crop": {
200+ "x0": 41.5,
201+ "y0": 41.5,
202+ "x1": 1003.5,
203+ "y1": 663.5
204+ },
85 "objects": 27, 205 "objects": 27,
206+ "pins": [
207+ {
208+ "key": "ext",
209+ "label": "Murs extérieurs",
210+ "at": {
211+ "x": 0.388,
212+ "y": 0.866
213+ }
214+ },
215+ {
216+ "key": "int",
217+ "label": "Cloisons",
218+ "at": {
219+ "x": 0.388,
220+ "y": 0.5
221+ }
222+ },
223+ {
224+ "key": "win",
225+ "label": "Fenêtres",
226+ "at": {
227+ "x": 0.238,
228+ "y": 0.866
229+ }
230+ },
231+ {
232+ "key": "door",
233+ "label": "Portes",
234+ "at": {
235+ "x": 0.159,
236+ "y": 0.866
237+ }
238+ },
239+ {
240+ "key": "room",
241+ "label": "Pièces (aire, périmètre)",
242+ "at": {
243+ "x": 0.801,
244+ "y": 0.404
245+ }
246+ },
247+ {
248+ "key": "fp",
249+ "label": "Empreinte et périmètre",
250+ "at": {
251+ "x": 0.087,
252+ "y": 0.865
253+ }
254+ }
255+ ],
256+ "walls": [
257+ {
258+ "name": "Murs extérieurs",
259+ "exterior": true,
260+ "lengthM": 41.4,
261+ "heightM": 2.44,
262+ "thicknessM": 0.3,
263+ "grossAreaM2": 101.016,
264+ "openingsAreaM2": 16.59,
265+ "netAreaM2": 84.426
266+ },
267+ {
268+ "name": "Cloison centrale",
269+ "exterior": false,
270+ "lengthM": 11.6,
271+ "heightM": 2.44,
272+ "thicknessM": 0.12,
273+ "grossAreaM2": 28.304,
274+ "openingsAreaM2": 0,
275+ "netAreaM2": 28.304
276+ },
277+ {
278+ "name": "Cloison Salon",
279+ "exterior": false,
280+ "lengthM": 4.55,
281+ "heightM": 2.44,
282+ "thicknessM": 0.12,
283+ "grossAreaM2": 11.102,
284+ "openingsAreaM2": 0,
285+ "netAreaM2": 11.102
286+ },
287+ {
288+ "name": "Cloison Salle à manger",
289+ "exterior": false,
290+ "lengthM": 4.55,
291+ "heightM": 2.44,
292+ "thicknessM": 0.12,
293+ "grossAreaM2": 11.102,
294+ "openingsAreaM2": 0,
295+ "netAreaM2": 11.102
296+ },
297+ {
298+ "name": "Cloison Cuisine",
299+ "exterior": false,
300+ "lengthM": 4.55,
301+ "heightM": 2.44,
302+ "thicknessM": 0.12,
303+ "grossAreaM2": 11.102,
304+ "openingsAreaM2": 0,
305+ "netAreaM2": 11.102
306+ },
307+ {
308+ "name": "Cloison Bureau / salle familiale",
309+ "exterior": false,
310+ "lengthM": 4.55,
311+ "heightM": 2.44,
312+ "thicknessM": 0.12,
313+ "grossAreaM2": 11.102,
314+ "openingsAreaM2": 0,
315+ "netAreaM2": 11.102
316+ },
317+ {
318+ "name": "Murs du garage",
319+ "exterior": true,
320+ "lengthM": 15.3,
321+ "heightM": 3,
322+ "thicknessM": 0.3,
323+ "grossAreaM2": 45.9,
324+ "openingsAreaM2": 6.39,
325+ "netAreaM2": 39.51
326+ }
327+ ],
86 "rooms": [ 328 "rooms": [
87 { 329 {
88 "name": "Salon", 330 "name": "Salon",
89− "usage": "séjour" 331+ "usage": "séjour",
332+ "areaM2": 24.76,
333+ "perimeterM": 20.06,
334+ "heightM": 2.44
90 }, 335 },
91 { 336 {
92 "name": "Salle à manger", 337 "name": "Salle à manger",
93− "usage": "salle à manger" 338+ "usage": "salle à manger",
339+ "areaM2": 14.575,
340+ "perimeterM": 15.42,
341+ "heightM": 2.44
94 }, 342 },
95 { 343 {
96 "name": "Hall / escalier", 344 "name": "Hall / escalier",
97− "usage": "hall" 345+ "usage": "hall",
346+ "areaM2": 9.482,
347+ "perimeterM": 13.1,
348+ "heightM": 2.44
98 }, 349 },
99 { 350 {
100 "name": "Cuisine", 351 "name": "Cuisine",
101− "usage": "cuisine" 352+ "usage": "cuisine",
353+ "areaM2": 22.213,
354+ "perimeterM": 18.9,
355+ "heightM": 2.44
102 }, 356 },
103 { 357 {
104 "name": "Bureau / salle familiale", 358 "name": "Bureau / salle familiale",
105− "usage": "bureau" 359+ "usage": "bureau",
360+ "areaM2": 17.121,
361+ "perimeterM": 16.58,
362+ "heightM": 2.44
106 }, 363 },
107 { 364 {
108 "name": "Salle d'eau", 365 "name": "Salle d'eau",
109− "usage": "salle d'eau" 366+ "usage": "salle d'eau",
367+ "areaM2": 9.482,
368+ "perimeterM": 13.1,
369+ "heightM": 2.44
110 }, 370 },
111 { 371 {
112 "name": "Garage", 372 "name": "Garage",
113− "usage": "garage" 373+ "usage": "garage",
374+ "areaM2": 26.65,
375+ "perimeterM": 21.2,
376+ "heightM": 3
377+ }
378+ ],
379+ "openings": [
380+ {
381+ "kind": "window",
382+ "name": "Fenêtre Salon",
383+ "widthM": 1.8,
384+ "heightM": 1.3,
385+ "areaM2": 2.34,
386+ "wall": "Murs extérieurs",
387+ "exterior": true
388+ },
389+ {
390+ "kind": "window",
391+ "name": "Fenêtre Salle à manger",
392+ "widthM": 1.2,
393+ "heightM": 1.3,
394+ "areaM2": 1.56,
395+ "wall": "Murs extérieurs",
396+ "exterior": true
397+ },
398+ {
399+ "kind": "window",
400+ "name": "Fenêtre Cuisine",
401+ "widthM": 1.8,
402+ "heightM": 1.3,
403+ "areaM2": 2.34,
404+ "wall": "Murs extérieurs",
405+ "exterior": true
406+ },
407+ {
408+ "kind": "window",
409+ "name": "Fenêtre Bureau / salle familiale",
410+ "widthM": 1.2,
411+ "heightM": 1.3,
412+ "areaM2": 1.56,
413+ "wall": "Murs extérieurs",
414+ "exterior": true
415+ },
416+ {
417+ "kind": "door",
418+ "name": "Porte d'entrée",
419+ "widthM": 0.9,
420+ "heightM": 2.1,
421+ "areaM2": 1.89,
422+ "wall": "Murs extérieurs",
423+ "exterior": true
424+ },
425+ {
426+ "kind": "door",
427+ "name": "Porte-patio",
428+ "widthM": 1.8,
429+ "heightM": 2.1,
430+ "areaM2": 3.78,
431+ "wall": "Murs extérieurs",
432+ "exterior": true
433+ },
434+ {
435+ "kind": "window",
436+ "name": "Fenêtre latérale",
437+ "widthM": 1.2,
438+ "heightM": 1.3,
439+ "areaM2": 1.56,
440+ "wall": "Murs extérieurs",
441+ "exterior": true
442+ },
443+ {
444+ "kind": "window",
445+ "name": "Fenêtre latérale",
446+ "widthM": 1.2,
447+ "heightM": 1.3,
448+ "areaM2": 1.56,
449+ "wall": "Murs extérieurs",
450+ "exterior": true
451+ },
452+ {
453+ "kind": "door",
454+ "name": "Porte de garage",
455+ "widthM": 2.7,
456+ "heightM": 2.1,
457+ "areaM2": 5.67,
458+ "wall": "Murs du garage",
459+ "exterior": true
460+ },
461+ {
462+ "kind": "window",
463+ "name": "Fenêtre garage",
464+ "widthM": 0.9,
465+ "heightM": 0.8,
466+ "areaM2": 0.72,
467+ "wall": "Murs du garage",
468+ "exterior": true
114 } 469 }
115 ], 470 ],
471+ "footprintM2": 111.86,
472+ "totals": {
473+ "wallLengthM": 86.5,
474+ "wallNetAreaM2": 196.648,
475+ "extWallNetAreaM2": 123.936,
476+ "floorAreaM2": 124.283,
477+ "doors": 3,
478+ "windows": 7
479+ },
116 "windows": 7, 480 "windows": 7,
117 "doors": 3 481 "doors": 3
118 }, 482 },
@@ -124,33 +488,261 @@
124 "widthPx": 830, 488 "widthPx": 830,
125 "heightPx": 705, 489 "heightPx": 705,
126 "png": "E_tage.png", 490 "png": "E_tage.png",
491+ "crop": {
492+ "x0": 41.5,
493+ "y0": 41.5,
494+ "x1": 788.5,
495+ "y1": 663.5
496+ },
127 "objects": 23, 497 "objects": 23,
498+ "pins": [
499+ {
500+ "key": "ext",
501+ "label": "Murs extérieurs",
502+ "at": {
503+ "x": 0.5,
504+ "y": 0.866
505+ }
506+ },
507+ {
508+ "key": "int",
509+ "label": "Cloisons",
510+ "at": {
511+ "x": 0.5,
512+ "y": 0.5
513+ }
514+ },
515+ {
516+ "key": "win",
517+ "label": "Fenêtres",
518+ "at": {
519+ "x": 0.286,
520+ "y": 0.866
521+ }
522+ },
523+ {
524+ "key": "door",
525+ "label": "Portes",
526+ "at": {
527+ "x": 0.205,
528+ "y": 0.866
529+ }
530+ },
531+ {
532+ "key": "room",
533+ "label": "Pièces (aire, périmètre)",
534+ "at": {
535+ "x": 0.286,
536+ "y": 0.683
537+ }
538+ },
539+ {
540+ "key": "fp",
541+ "label": "Empreinte et périmètre",
542+ "at": {
543+ "x": 0.112,
544+ "y": 0.865
545+ }
546+ }
547+ ],
548+ "walls": [
549+ {
550+ "name": "Murs extérieurs",
551+ "exterior": true,
552+ "lengthM": 41.4,
553+ "heightM": 2.44,
554+ "thicknessM": 0.3,
555+ "grossAreaM2": 101.016,
556+ "openingsAreaM2": 15.84,
557+ "netAreaM2": 85.176
558+ },
559+ {
560+ "name": "Cloison centrale",
561+ "exterior": false,
562+ "lengthM": 11.6,
563+ "heightM": 2.44,
564+ "thicknessM": 0.12,
565+ "grossAreaM2": 28.304,
566+ "openingsAreaM2": 0,
567+ "netAreaM2": 28.304
568+ },
569+ {
570+ "name": "Cloison Chambre principale",
571+ "exterior": false,
572+ "lengthM": 4.55,
573+ "heightM": 2.44,
574+ "thicknessM": 0.12,
575+ "grossAreaM2": 11.102,
576+ "openingsAreaM2": 0,
577+ "netAreaM2": 11.102
578+ },
579+ {
580+ "name": "Cloison Salle de bain",
581+ "exterior": false,
582+ "lengthM": 4.55,
583+ "heightM": 2.44,
584+ "thicknessM": 0.12,
585+ "grossAreaM2": 11.102,
586+ "openingsAreaM2": 0,
587+ "netAreaM2": 11.102
588+ },
589+ {
590+ "name": "Cloison Chambre 2",
591+ "exterior": false,
592+ "lengthM": 4.55,
593+ "heightM": 2.44,
594+ "thicknessM": 0.12,
595+ "grossAreaM2": 11.102,
596+ "openingsAreaM2": 0,
597+ "netAreaM2": 11.102
598+ },
599+ {
600+ "name": "Cloison Chambre 3",
601+ "exterior": false,
602+ "lengthM": 4.55,
603+ "heightM": 2.44,
604+ "thicknessM": 0.12,
605+ "grossAreaM2": 11.102,
606+ "openingsAreaM2": 0,
607+ "netAreaM2": 11.102
608+ }
609+ ],
128 "rooms": [ 610 "rooms": [
129 { 611 {
130 "name": "Chambre principale", 612 "name": "Chambre principale",
131− "usage": "chambre" 613+ "usage": "chambre",
614+ "areaM2": 22.213,
615+ "perimeterM": 18.9,
616+ "heightM": 2.44
132 }, 617 },
133 { 618 {
134 "name": "Salle de bain", 619 "name": "Salle de bain",
135− "usage": "salle de bain" 620+ "usage": "salle de bain",
621+ "areaM2": 12.029,
622+ "perimeterM": 14.26,
623+ "heightM": 2.44
136 }, 624 },
137 { 625 {
138 "name": "Hall / escalier", 626 "name": "Hall / escalier",
139− "usage": "hall" 627+ "usage": "hall",
628+ "areaM2": 14.575,
629+ "perimeterM": 15.42,
630+ "heightM": 2.44
140 }, 631 },
141 { 632 {
142 "name": "Chambre 2", 633 "name": "Chambre 2",
143− "usage": "chambre" 634+ "usage": "chambre",
635+ "areaM2": 18.139,
636+ "perimeterM": 17.044,
637+ "heightM": 2.44
144 }, 638 },
145 { 639 {
146 "name": "Chambre 3", 640 "name": "Chambre 3",
147− "usage": "chambre" 641+ "usage": "chambre",
642+ "areaM2": 16.103,
643+ "perimeterM": 16.116,
644+ "heightM": 2.44
148 }, 645 },
149 { 646 {
150 "name": "Chambre 4", 647 "name": "Chambre 4",
151− "usage": "chambre" 648+ "usage": "chambre",
649+ "areaM2": 14.575,
650+ "perimeterM": 15.42,
651+ "heightM": 2.44
152 } 652 }
153 ], 653 ],
654+ "openings": [
655+ {
656+ "kind": "window",
657+ "name": "Fenêtre Chambre principale",
658+ "widthM": 1.2,
659+ "heightM": 1.3,
660+ "areaM2": 1.56,
661+ "wall": "Murs extérieurs",
662+ "exterior": true
663+ },
664+ {
665+ "kind": "window",
666+ "name": "Fenêtre Salle de bain",
667+ "widthM": 0.9,
668+ "heightM": 0.9,
669+ "areaM2": 0.81,
670+ "wall": "Murs extérieurs",
671+ "exterior": true
672+ },
673+ {
674+ "kind": "window",
675+ "name": "Fenêtre Chambre 2",
676+ "widthM": 1.2,
677+ "heightM": 1.3,
678+ "areaM2": 1.56,
679+ "wall": "Murs extérieurs",
680+ "exterior": true
681+ },
682+ {
683+ "kind": "window",
684+ "name": "Fenêtre Chambre 3",
685+ "widthM": 1.2,
686+ "heightM": 1.3,
687+ "areaM2": 1.56,
688+ "wall": "Murs extérieurs",
689+ "exterior": true
690+ },
691+ {
692+ "kind": "window",
693+ "name": "Fenêtre Chambre 4",
694+ "widthM": 1.2,
695+ "heightM": 1.3,
696+ "areaM2": 1.56,
697+ "wall": "Murs extérieurs",
698+ "exterior": true
699+ },
700+ {
701+ "kind": "door",
702+ "name": "Porte d'entrée",
703+ "widthM": 0.9,
704+ "heightM": 2.1,
705+ "areaM2": 1.89,
706+ "wall": "Murs extérieurs",
707+ "exterior": true
708+ },
709+ {
710+ "kind": "door",
711+ "name": "Porte-patio",
712+ "widthM": 1.8,
713+ "heightM": 2.1,
714+ "areaM2": 3.78,
715+ "wall": "Murs extérieurs",
716+ "exterior": true
717+ },
718+ {
719+ "kind": "window",
720+ "name": "Fenêtre latérale",
721+ "widthM": 1.2,
722+ "heightM": 1.3,
723+ "areaM2": 1.56,
724+ "wall": "Murs extérieurs",
725+ "exterior": true
726+ },
727+ {
728+ "kind": "window",
729+ "name": "Fenêtre latérale",
730+ "widthM": 1.2,
731+ "heightM": 1.3,
732+ "areaM2": 1.56,
733+ "wall": "Murs extérieurs",
734+ "exterior": true
735+ }
736+ ],
737+ "footprintM2": 111.86,
738+ "totals": {
739+ "wallLengthM": 71.2,
740+ "wallNetAreaM2": 157.888,
741+ "extWallNetAreaM2": 85.176,
742+ "floorAreaM2": 97.634,
743+ "doors": 2,
744+ "windows": 7
745+ },
154 "windows": 7, 746 "windows": 7,
155 "doors": 2 747 "doors": 2
156 } 748 }
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas3/2e_e_tage.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas3/E_tage.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas3/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas3/Sous_sol.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas3/data.json +776 −17
@@ -60,17 +60,131 @@
60 "widthPx": 830, 60 "widthPx": 830,
61 "heightPx": 770, 61 "heightPx": 770,
62 "png": "Sous_sol.png", 62 "png": "Sous_sol.png",
63+ "crop": {
64+ "x0": 41.5,
65+ "y0": 41.5,
66+ "x1": 788.5,
67+ "y1": 728.5
68+ },
63 "objects": 9, 69 "objects": 9,
70+ "pins": [
71+ {
72+ "key": "ext",
73+ "label": "Murs extérieurs",
74+ "at": {
75+ "x": 0.5,
76+ "y": 0.878
77+ }
78+ },
79+ {
80+ "key": "int",
81+ "label": "Cloisons",
82+ "at": {
83+ "x": 0.313,
84+ "y": 0.769
85+ }
86+ },
87+ {
88+ "key": "win",
89+ "label": "Fenêtres",
90+ "at": {
91+ "x": 0.345,
92+ "y": 0.122
93+ }
94+ },
95+ {
96+ "key": "room",
97+ "label": "Pièces (aire, périmètre)",
98+ "at": {
99+ "x": 0.5,
100+ "y": 0.5
101+ }
102+ },
103+ {
104+ "key": "fp",
105+ "label": "Empreinte et périmètre",
106+ "at": {
107+ "x": 0.112,
108+ "y": 0.878
109+ }
110+ }
111+ ],
112+ "walls": [
113+ {
114+ "name": "Murs extérieurs",
115+ "exterior": true,
116+ "lengthM": 44,
117+ "heightM": 2.44,
118+ "thicknessM": 0.3,
119+ "grossAreaM2": 107.36,
120+ "openingsAreaM2": 1.2,
121+ "netAreaM2": 106.16
122+ },
123+ {
124+ "name": "Cloison salle mécanique",
125+ "exterior": false,
126+ "lengthM": 6,
127+ "heightM": 2.3,
128+ "thicknessM": 0.12,
129+ "grossAreaM2": 13.8,
130+ "openingsAreaM2": 0,
131+ "netAreaM2": 13.8
132+ }
133+ ],
64 "rooms": [ 134 "rooms": [
65 { 135 {
66 "name": "Sous-sol", 136 "name": "Sous-sol",
67− "usage": "sous-sol" 137+ "usage": "sous-sol",
138+ "areaM2": 116.28,
139+ "perimeterM": 43.2,
140+ "heightM": 2.3
68 }, 141 },
69 { 142 {
70 "name": "Salle mécanique", 143 "name": "Salle mécanique",
71− "usage": "salle mécanique" 144+ "usage": "salle mécanique",
145+ "areaM2": 7.84,
146+ "perimeterM": 11.2,
147+ "heightM": 2.3
72 } 148 }
73 ], 149 ],
150+ "openings": [
151+ {
152+ "kind": "window",
153+ "name": "Fenêtre de sous-sol",
154+ "widthM": 0.8,
155+ "heightM": 0.5,
156+ "areaM2": 0.4,
157+ "wall": "Murs extérieurs",
158+ "exterior": true
159+ },
160+ {
161+ "kind": "window",
162+ "name": "Fenêtre de sous-sol",
163+ "widthM": 0.8,
164+ "heightM": 0.5,
165+ "areaM2": 0.4,
166+ "wall": "Murs extérieurs",
167+ "exterior": true
168+ },
169+ {
170+ "kind": "window",
171+ "name": "Fenêtre de sous-sol",
172+ "widthM": 0.8,
173+ "heightM": 0.5,
174+ "areaM2": 0.4,
175+ "wall": "Murs extérieurs",
176+ "exterior": true
177+ }
178+ ],
179+ "footprintM2": 127.33,
180+ "totals": {
181+ "wallLengthM": 50,
182+ "wallNetAreaM2": 119.96,
183+ "extWallNetAreaM2": 106.16,
184+ "floorAreaM2": 124.12,
185+ "doors": 0,
186+ "windows": 3
187+ },
74 "windows": 3, 188 "windows": 3,
75 "doors": 0 189 "doors": 0
76 }, 190 },
@@ -82,29 +196,244 @@
82 "widthPx": 830, 196 "widthPx": 830,
83 "heightPx": 770, 197 "heightPx": 770,
84 "png": "Rez_de_chausse_e.png", 198 "png": "Rez_de_chausse_e.png",
199+ "crop": {
200+ "x0": 41.5,
201+ "y0": 41.5,
202+ "x1": 788.5,
203+ "y1": 728.5
204+ },
85 "objects": 20, 205 "objects": 20,
206+ "pins": [
207+ {
208+ "key": "ext",
209+ "label": "Murs extérieurs",
210+ "at": {
211+ "x": 0.5,
212+ "y": 0.878
213+ }
214+ },
215+ {
216+ "key": "int",
217+ "label": "Cloisons",
218+ "at": {
219+ "x": 0.5,
220+ "y": 0.5
221+ }
222+ },
223+ {
224+ "key": "win",
225+ "label": "Fenêtres",
226+ "at": {
227+ "x": 0.306,
228+ "y": 0.878
229+ }
230+ },
231+ {
232+ "key": "door",
233+ "label": "Portes",
234+ "at": {
235+ "x": 0.205,
236+ "y": 0.878
237+ }
238+ },
239+ {
240+ "key": "room",
241+ "label": "Pièces (aire, périmètre)",
242+ "at": {
243+ "x": 0.306,
244+ "y": 0.689
245+ }
246+ },
247+ {
248+ "key": "fp",
249+ "label": "Empreinte et périmètre",
250+ "at": {
251+ "x": 0.112,
252+ "y": 0.878
253+ }
254+ }
255+ ],
256+ "walls": [
257+ {
258+ "name": "Murs extérieurs",
259+ "exterior": true,
260+ "lengthM": 44,
261+ "heightM": 2.44,
262+ "thicknessM": 0.3,
263+ "grossAreaM2": 107.36,
264+ "openingsAreaM2": 17.4,
265+ "netAreaM2": 89.96
266+ },
267+ {
268+ "name": "Logement 1 — Cloison centrale",
269+ "exterior": false,
270+ "lengthM": 11.6,
271+ "heightM": 2.44,
272+ "thicknessM": 0.12,
273+ "grossAreaM2": 28.304,
274+ "openingsAreaM2": 0,
275+ "netAreaM2": 28.304
276+ },
277+ {
278+ "name": "Logement 1 — Cloison Séjour",
279+ "exterior": false,
280+ "lengthM": 5.2,
281+ "heightM": 2.44,
282+ "thicknessM": 0.12,
283+ "grossAreaM2": 12.688,
284+ "openingsAreaM2": 0,
285+ "netAreaM2": 12.688
286+ },
287+ {
288+ "name": "Logement 1 — Cloison Chambre 1",
289+ "exterior": false,
290+ "lengthM": 5.2,
291+ "heightM": 2.44,
292+ "thicknessM": 0.12,
293+ "grossAreaM2": 12.688,
294+ "openingsAreaM2": 0,
295+ "netAreaM2": 12.688
296+ },
297+ {
298+ "name": "Logement 1 — Cloison Chambre 2",
299+ "exterior": false,
300+ "lengthM": 5.2,
301+ "heightM": 2.44,
302+ "thicknessM": 0.12,
303+ "grossAreaM2": 12.688,
304+ "openingsAreaM2": 0,
305+ "netAreaM2": 12.688
306+ }
307+ ],
86 "rooms": [ 308 "rooms": [
87 { 309 {
88 "name": "Logement 1 — Séjour", 310 "name": "Logement 1 — Séjour",
89− "usage": "séjour" 311+ "usage": "séjour",
312+ "areaM2": 28.426,
313+ "perimeterM": 21.36,
314+ "heightM": 2.44
90 }, 315 },
91 { 316 {
92 "name": "Logement 1 — Cuisine / salle à manger", 317 "name": "Logement 1 — Cuisine / salle à manger",
93− "usage": "cuisine" 318+ "usage": "cuisine",
319+ "areaM2": 28.426,
320+ "perimeterM": 21.36,
321+ "heightM": 2.44
94 }, 322 },
95 { 323 {
96 "name": "Logement 1 — Chambre 1", 324 "name": "Logement 1 — Chambre 1",
97− "usage": "chambre" 325+ "usage": "chambre",
326+ "areaM2": 22.579,
327+ "perimeterM": 19.04,
328+ "heightM": 2.44
98 }, 329 },
99 { 330 {
100 "name": "Logement 1 — Chambre 2", 331 "name": "Logement 1 — Chambre 2",
101− "usage": "chambre" 332+ "usage": "chambre",
333+ "areaM2": 19.656,
334+ "perimeterM": 17.88,
335+ "heightM": 2.44
102 }, 336 },
103 { 337 {
104 "name": "Logement 1 — Salle de bain", 338 "name": "Logement 1 — Salle de bain",
105− "usage": "salle de bain" 339+ "usage": "salle de bain",
340+ "areaM2": 13.81,
341+ "perimeterM": 15.56,
342+ "heightM": 2.44
106 } 343 }
107 ], 344 ],
345+ "openings": [
346+ {
347+ "kind": "window",
348+ "name": "Fenêtre Séjour",
349+ "widthM": 1.8,
350+ "heightM": 1.3,
351+ "areaM2": 2.34,
352+ "wall": "Murs extérieurs",
353+ "exterior": true
354+ },
355+ {
356+ "kind": "window",
357+ "name": "Fenêtre Cuisine / salle à manger",
358+ "widthM": 1.8,
359+ "heightM": 1.3,
360+ "areaM2": 2.34,
361+ "wall": "Murs extérieurs",
362+ "exterior": true
363+ },
364+ {
365+ "kind": "window",
366+ "name": "Fenêtre Chambre 1",
367+ "widthM": 1.2,
368+ "heightM": 1.3,
369+ "areaM2": 1.56,
370+ "wall": "Murs extérieurs",
371+ "exterior": true
372+ },
373+ {
374+ "kind": "window",
375+ "name": "Fenêtre Chambre 2",
376+ "widthM": 1.2,
377+ "heightM": 1.3,
378+ "areaM2": 1.56,
379+ "wall": "Murs extérieurs",
380+ "exterior": true
381+ },
382+ {
383+ "kind": "window",
384+ "name": "Fenêtre Salle de bain",
385+ "widthM": 0.9,
386+ "heightM": 0.9,
387+ "areaM2": 0.81,
388+ "wall": "Murs extérieurs",
389+ "exterior": true
390+ },
391+ {
392+ "kind": "door",
393+ "name": "Logement 1 — Porte d'entrée",
394+ "widthM": 0.9,
395+ "heightM": 2.1,
396+ "areaM2": 1.89,
397+ "wall": "Murs extérieurs",
398+ "exterior": true
399+ },
400+ {
401+ "kind": "door",
402+ "name": "Logement 1 — Porte-patio",
403+ "widthM": 1.8,
404+ "heightM": 2.1,
405+ "areaM2": 3.78,
406+ "wall": "Murs extérieurs",
407+ "exterior": true
408+ },
409+ {
410+ "kind": "window",
411+ "name": "Fenêtre latérale",
412+ "widthM": 1.2,
413+ "heightM": 1.3,
414+ "areaM2": 1.56,
415+ "wall": "Murs extérieurs",
416+ "exterior": true
417+ },
418+ {
419+ "kind": "window",
420+ "name": "Fenêtre latérale",
421+ "widthM": 1.2,
422+ "heightM": 1.3,
423+ "areaM2": 1.56,
424+ "wall": "Murs extérieurs",
425+ "exterior": true
426+ }
427+ ],
428+ "footprintM2": 127.33,
429+ "totals": {
430+ "wallLengthM": 71.2,
431+ "wallNetAreaM2": 156.328,
432+ "extWallNetAreaM2": 89.96,
433+ "floorAreaM2": 112.897,
434+ "doors": 2,
435+ "windows": 7
436+ },
108 "windows": 7, 437 "windows": 7,
109 "doors": 2 438 "doors": 2
110 }, 439 },
@@ -116,29 +445,244 @@
116 "widthPx": 830, 445 "widthPx": 830,
117 "heightPx": 770, 446 "heightPx": 770,
118 "png": "E_tage.png", 447 "png": "E_tage.png",
448+ "crop": {
449+ "x0": 41.5,
450+ "y0": 41.5,
451+ "x1": 788.5,
452+ "y1": 728.5
453+ },
119 "objects": 20, 454 "objects": 20,
455+ "pins": [
456+ {
457+ "key": "ext",
458+ "label": "Murs extérieurs",
459+ "at": {
460+ "x": 0.5,
461+ "y": 0.878
462+ }
463+ },
464+ {
465+ "key": "int",
466+ "label": "Cloisons",
467+ "at": {
468+ "x": 0.5,
469+ "y": 0.5
470+ }
471+ },
472+ {
473+ "key": "win",
474+ "label": "Fenêtres",
475+ "at": {
476+ "x": 0.306,
477+ "y": 0.878
478+ }
479+ },
480+ {
481+ "key": "door",
482+ "label": "Portes",
483+ "at": {
484+ "x": 0.205,
485+ "y": 0.878
486+ }
487+ },
488+ {
489+ "key": "room",
490+ "label": "Pièces (aire, périmètre)",
491+ "at": {
492+ "x": 0.306,
493+ "y": 0.689
494+ }
495+ },
496+ {
497+ "key": "fp",
498+ "label": "Empreinte et périmètre",
499+ "at": {
500+ "x": 0.112,
501+ "y": 0.878
502+ }
503+ }
504+ ],
505+ "walls": [
506+ {
507+ "name": "Murs extérieurs",
508+ "exterior": true,
509+ "lengthM": 44,
510+ "heightM": 2.44,
511+ "thicknessM": 0.3,
512+ "grossAreaM2": 107.36,
513+ "openingsAreaM2": 17.4,
514+ "netAreaM2": 89.96
515+ },
516+ {
517+ "name": "Logement 2 — Cloison centrale",
518+ "exterior": false,
519+ "lengthM": 11.6,
520+ "heightM": 2.44,
521+ "thicknessM": 0.12,
522+ "grossAreaM2": 28.304,
523+ "openingsAreaM2": 0,
524+ "netAreaM2": 28.304
525+ },
526+ {
527+ "name": "Logement 2 — Cloison Séjour",
528+ "exterior": false,
529+ "lengthM": 5.2,
530+ "heightM": 2.44,
531+ "thicknessM": 0.12,
532+ "grossAreaM2": 12.688,
533+ "openingsAreaM2": 0,
534+ "netAreaM2": 12.688
535+ },
536+ {
537+ "name": "Logement 2 — Cloison Chambre 1",
538+ "exterior": false,
539+ "lengthM": 5.2,
540+ "heightM": 2.44,
541+ "thicknessM": 0.12,
542+ "grossAreaM2": 12.688,
543+ "openingsAreaM2": 0,
544+ "netAreaM2": 12.688
545+ },
546+ {
547+ "name": "Logement 2 — Cloison Chambre 2",
548+ "exterior": false,
549+ "lengthM": 5.2,
550+ "heightM": 2.44,
551+ "thicknessM": 0.12,
552+ "grossAreaM2": 12.688,
553+ "openingsAreaM2": 0,
554+ "netAreaM2": 12.688
555+ }
556+ ],
120 "rooms": [ 557 "rooms": [
121 { 558 {
122 "name": "Logement 2 — Séjour", 559 "name": "Logement 2 — Séjour",
123− "usage": "séjour" 560+ "usage": "séjour",
561+ "areaM2": 28.426,
562+ "perimeterM": 21.36,
563+ "heightM": 2.44
124 }, 564 },
125 { 565 {
126 "name": "Logement 2 — Cuisine / salle à manger", 566 "name": "Logement 2 — Cuisine / salle à manger",
127− "usage": "cuisine" 567+ "usage": "cuisine",
568+ "areaM2": 28.426,
569+ "perimeterM": 21.36,
570+ "heightM": 2.44
128 }, 571 },
129 { 572 {
130 "name": "Logement 2 — Chambre 1", 573 "name": "Logement 2 — Chambre 1",
131− "usage": "chambre" 574+ "usage": "chambre",
575+ "areaM2": 22.579,
576+ "perimeterM": 19.04,
577+ "heightM": 2.44
132 }, 578 },
133 { 579 {
134 "name": "Logement 2 — Chambre 2", 580 "name": "Logement 2 — Chambre 2",
135− "usage": "chambre" 581+ "usage": "chambre",
582+ "areaM2": 19.656,
583+ "perimeterM": 17.88,
584+ "heightM": 2.44
136 }, 585 },
137 { 586 {
138 "name": "Logement 2 — Salle de bain", 587 "name": "Logement 2 — Salle de bain",
139− "usage": "salle de bain" 588+ "usage": "salle de bain",
589+ "areaM2": 13.81,
590+ "perimeterM": 15.56,
591+ "heightM": 2.44
140 } 592 }
141 ], 593 ],
594+ "openings": [
595+ {
596+ "kind": "window",
597+ "name": "Fenêtre Séjour",
598+ "widthM": 1.8,
599+ "heightM": 1.3,
600+ "areaM2": 2.34,
601+ "wall": "Murs extérieurs",
602+ "exterior": true
603+ },
604+ {
605+ "kind": "window",
606+ "name": "Fenêtre Cuisine / salle à manger",
607+ "widthM": 1.8,
608+ "heightM": 1.3,
609+ "areaM2": 2.34,
610+ "wall": "Murs extérieurs",
611+ "exterior": true
612+ },
613+ {
614+ "kind": "window",
615+ "name": "Fenêtre Chambre 1",
616+ "widthM": 1.2,
617+ "heightM": 1.3,
618+ "areaM2": 1.56,
619+ "wall": "Murs extérieurs",
620+ "exterior": true
621+ },
622+ {
623+ "kind": "window",
624+ "name": "Fenêtre Chambre 2",
625+ "widthM": 1.2,
626+ "heightM": 1.3,
627+ "areaM2": 1.56,
628+ "wall": "Murs extérieurs",
629+ "exterior": true
630+ },
631+ {
632+ "kind": "window",
633+ "name": "Fenêtre Salle de bain",
634+ "widthM": 0.9,
635+ "heightM": 0.9,
636+ "areaM2": 0.81,
637+ "wall": "Murs extérieurs",
638+ "exterior": true
639+ },
640+ {
641+ "kind": "door",
642+ "name": "Logement 2 — Porte d'entrée",
643+ "widthM": 0.9,
644+ "heightM": 2.1,
645+ "areaM2": 1.89,
646+ "wall": "Murs extérieurs",
647+ "exterior": true
648+ },
649+ {
650+ "kind": "door",
651+ "name": "Logement 2 — Porte-patio",
652+ "widthM": 1.8,
653+ "heightM": 2.1,
654+ "areaM2": 3.78,
655+ "wall": "Murs extérieurs",
656+ "exterior": true
657+ },
658+ {
659+ "kind": "window",
660+ "name": "Fenêtre latérale",
661+ "widthM": 1.2,
662+ "heightM": 1.3,
663+ "areaM2": 1.56,
664+ "wall": "Murs extérieurs",
665+ "exterior": true
666+ },
667+ {
668+ "kind": "window",
669+ "name": "Fenêtre latérale",
670+ "widthM": 1.2,
671+ "heightM": 1.3,
672+ "areaM2": 1.56,
673+ "wall": "Murs extérieurs",
674+ "exterior": true
675+ }
676+ ],
677+ "footprintM2": 127.33,
678+ "totals": {
679+ "wallLengthM": 71.2,
680+ "wallNetAreaM2": 156.328,
681+ "extWallNetAreaM2": 89.96,
682+ "floorAreaM2": 112.897,
683+ "doors": 2,
684+ "windows": 7
685+ },
142 "windows": 7, 686 "windows": 7,
143 "doors": 2 687 "doors": 2
144 }, 688 },
@@ -150,29 +694,244 @@
150 "widthPx": 830, 694 "widthPx": 830,
151 "heightPx": 770, 695 "heightPx": 770,
152 "png": "2e_e_tage.png", 696 "png": "2e_e_tage.png",
697+ "crop": {
698+ "x0": 41.5,
699+ "y0": 41.5,
700+ "x1": 788.5,
701+ "y1": 728.5
702+ },
153 "objects": 20, 703 "objects": 20,
704+ "pins": [
705+ {
706+ "key": "ext",
707+ "label": "Murs extérieurs",
708+ "at": {
709+ "x": 0.5,
710+ "y": 0.878
711+ }
712+ },
713+ {
714+ "key": "int",
715+ "label": "Cloisons",
716+ "at": {
717+ "x": 0.5,
718+ "y": 0.5
719+ }
720+ },
721+ {
722+ "key": "win",
723+ "label": "Fenêtres",
724+ "at": {
725+ "x": 0.306,
726+ "y": 0.878
727+ }
728+ },
729+ {
730+ "key": "door",
731+ "label": "Portes",
732+ "at": {
733+ "x": 0.205,
734+ "y": 0.878
735+ }
736+ },
737+ {
738+ "key": "room",
739+ "label": "Pièces (aire, périmètre)",
740+ "at": {
741+ "x": 0.306,
742+ "y": 0.689
743+ }
744+ },
745+ {
746+ "key": "fp",
747+ "label": "Empreinte et périmètre",
748+ "at": {
749+ "x": 0.112,
750+ "y": 0.878
751+ }
752+ }
753+ ],
754+ "walls": [
755+ {
756+ "name": "Murs extérieurs",
757+ "exterior": true,
758+ "lengthM": 44,
759+ "heightM": 2.44,
760+ "thicknessM": 0.3,
761+ "grossAreaM2": 107.36,
762+ "openingsAreaM2": 17.4,
763+ "netAreaM2": 89.96
764+ },
765+ {
766+ "name": "Logement 3 — Cloison centrale",
767+ "exterior": false,
768+ "lengthM": 11.6,
769+ "heightM": 2.44,
770+ "thicknessM": 0.12,
771+ "grossAreaM2": 28.304,
772+ "openingsAreaM2": 0,
773+ "netAreaM2": 28.304
774+ },
775+ {
776+ "name": "Logement 3 — Cloison Séjour",
777+ "exterior": false,
778+ "lengthM": 5.2,
779+ "heightM": 2.44,
780+ "thicknessM": 0.12,
781+ "grossAreaM2": 12.688,
782+ "openingsAreaM2": 0,
783+ "netAreaM2": 12.688
784+ },
785+ {
786+ "name": "Logement 3 — Cloison Chambre 1",
787+ "exterior": false,
788+ "lengthM": 5.2,
789+ "heightM": 2.44,
790+ "thicknessM": 0.12,
791+ "grossAreaM2": 12.688,
792+ "openingsAreaM2": 0,
793+ "netAreaM2": 12.688
794+ },
795+ {
796+ "name": "Logement 3 — Cloison Chambre 2",
797+ "exterior": false,
798+ "lengthM": 5.2,
799+ "heightM": 2.44,
800+ "thicknessM": 0.12,
801+ "grossAreaM2": 12.688,
802+ "openingsAreaM2": 0,
803+ "netAreaM2": 12.688
804+ }
805+ ],
154 "rooms": [ 806 "rooms": [
155 { 807 {
156 "name": "Logement 3 — Séjour", 808 "name": "Logement 3 — Séjour",
157− "usage": "séjour" 809+ "usage": "séjour",
810+ "areaM2": 28.426,
811+ "perimeterM": 21.36,
812+ "heightM": 2.44
158 }, 813 },
159 { 814 {
160 "name": "Logement 3 — Cuisine / salle à manger", 815 "name": "Logement 3 — Cuisine / salle à manger",
161− "usage": "cuisine" 816+ "usage": "cuisine",
817+ "areaM2": 28.426,
818+ "perimeterM": 21.36,
819+ "heightM": 2.44
162 }, 820 },
163 { 821 {
164 "name": "Logement 3 — Chambre 1", 822 "name": "Logement 3 — Chambre 1",
165− "usage": "chambre" 823+ "usage": "chambre",
824+ "areaM2": 22.579,
825+ "perimeterM": 19.04,
826+ "heightM": 2.44
166 }, 827 },
167 { 828 {
168 "name": "Logement 3 — Chambre 2", 829 "name": "Logement 3 — Chambre 2",
169− "usage": "chambre" 830+ "usage": "chambre",
831+ "areaM2": 19.656,
832+ "perimeterM": 17.88,
833+ "heightM": 2.44
170 }, 834 },
171 { 835 {
172 "name": "Logement 3 — Salle de bain", 836 "name": "Logement 3 — Salle de bain",
173− "usage": "salle de bain" 837+ "usage": "salle de bain",
838+ "areaM2": 13.81,
839+ "perimeterM": 15.56,
840+ "heightM": 2.44
174 } 841 }
175 ], 842 ],
843+ "openings": [
844+ {
845+ "kind": "window",
846+ "name": "Fenêtre Séjour",
847+ "widthM": 1.8,
848+ "heightM": 1.3,
849+ "areaM2": 2.34,
850+ "wall": "Murs extérieurs",
851+ "exterior": true
852+ },
853+ {
854+ "kind": "window",
855+ "name": "Fenêtre Cuisine / salle à manger",
856+ "widthM": 1.8,
857+ "heightM": 1.3,
858+ "areaM2": 2.34,
859+ "wall": "Murs extérieurs",
860+ "exterior": true
861+ },
862+ {
863+ "kind": "window",
864+ "name": "Fenêtre Chambre 1",
865+ "widthM": 1.2,
866+ "heightM": 1.3,
867+ "areaM2": 1.56,
868+ "wall": "Murs extérieurs",
869+ "exterior": true
870+ },
871+ {
872+ "kind": "window",
873+ "name": "Fenêtre Chambre 2",
874+ "widthM": 1.2,
875+ "heightM": 1.3,
876+ "areaM2": 1.56,
877+ "wall": "Murs extérieurs",
878+ "exterior": true
879+ },
880+ {
881+ "kind": "window",
882+ "name": "Fenêtre Salle de bain",
883+ "widthM": 0.9,
884+ "heightM": 0.9,
885+ "areaM2": 0.81,
886+ "wall": "Murs extérieurs",
887+ "exterior": true
888+ },
889+ {
890+ "kind": "door",
891+ "name": "Logement 3 — Porte d'entrée",
892+ "widthM": 0.9,
893+ "heightM": 2.1,
894+ "areaM2": 1.89,
895+ "wall": "Murs extérieurs",
896+ "exterior": true
897+ },
898+ {
899+ "kind": "door",
900+ "name": "Logement 3 — Porte-patio",
901+ "widthM": 1.8,
902+ "heightM": 2.1,
903+ "areaM2": 3.78,
904+ "wall": "Murs extérieurs",
905+ "exterior": true
906+ },
907+ {
908+ "kind": "window",
909+ "name": "Fenêtre latérale",
910+ "widthM": 1.2,
911+ "heightM": 1.3,
912+ "areaM2": 1.56,
913+ "wall": "Murs extérieurs",
914+ "exterior": true
915+ },
916+ {
917+ "kind": "window",
918+ "name": "Fenêtre latérale",
919+ "widthM": 1.2,
920+ "heightM": 1.3,
921+ "areaM2": 1.56,
922+ "wall": "Murs extérieurs",
923+ "exterior": true
924+ }
925+ ],
926+ "footprintM2": 127.33,
927+ "totals": {
928+ "wallLengthM": 71.2,
929+ "wallNetAreaM2": 156.328,
930+ "extWallNetAreaM2": 89.96,
931+ "floorAreaM2": 112.897,
932+ "doors": 2,
933+ "windows": 7
934+ },
176 "windows": 7, 935 "windows": 7,
177 "doors": 2 936 "doors": 2
178 } 937 }
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas4/E_tage.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas4/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas4/Sous_sol.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas4/data.json +556 −12
Large diff (631 lines) is not loaded by default to keep the page fast.Load diff
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas5/2e_e_tage.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas5/E_tage.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas5/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas5/Sous_sol.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas5/data.json +1175 −32
Large diff (1,339 lines) is not loaded by default to keep the page fast.Load diff
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas6/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas6/data.json +197 −4
Large diff (222 lines) is not loaded by default to keep the page fast.Load diff
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas7/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas7/data.json +102 −1
Large diff (115 lines) is not loaded by default to keep the page fast.Load diff
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas8/Rez_de_chausse_e.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas8/Sous_sol.png +0 −0

Binary file not shown.

modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/cas8/data.json +373 −9
Large diff (427 lines) is not loaded by default to keep the page fast.Load diff
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/images/qs-cas/localisation.json +0 −6002
Large diff (6,008 lines) is not loaded by default to keep the page fast.Load diff
modified IMM1033-20_Methodes_du_cout/02_Slides/sources/parties/seance07_qs_cas.tex +805 −181
Large diff (1,388 lines) is not loaded by default to keep the page fast.Load diff
Menu

Theme