772 lines
24 KiB
Typst
772 lines
24 KiB
Typst
#import "@preview/polylux:0.4.0": *
|
|
#import "@preview/cetz:0.5.0"
|
|
#import "@preview/cetz-plot:0.1.3": plot
|
|
|
|
#set math.mat(delim: "[")
|
|
|
|
// Infos
|
|
#let auteur = "Anthony PERRONI"
|
|
#let numero = "49871"
|
|
#let titre = "Codes LDPC"
|
|
#let annee = "2025 - 2026"
|
|
|
|
// Template
|
|
#let myslide(partie, contenu) = slide[
|
|
// Header
|
|
#block(width: 100%, fill: black, inset: (top: 0.6cm, bottom: 0.6cm, left: 1.5cm, right: 1.5cm))[
|
|
#set text(fill: white, size: 28pt, weight: "bold")
|
|
#partie
|
|
]
|
|
// Contenu
|
|
#pad(x: 1.5cm, top: 0.2cm)[
|
|
#set text(size: 20pt)
|
|
#contenu
|
|
]
|
|
|
|
// Footer
|
|
#v(1fr)
|
|
#context {
|
|
// let cur = counter(page).get().first()
|
|
// let tot = counter(page).final().first()
|
|
let cur = counter("logical-slide").get().first()
|
|
let tot = counter("logical-slide").final().first()
|
|
|
|
if cur > 1 {
|
|
block(width: 100%, fill: black, inset: (top: 0.2cm, bottom: 0.2cm, left: 1.5cm, right: 1.5cm))[
|
|
#set text(fill: white, size: 12pt, weight: "bold")
|
|
#grid(
|
|
columns: (1.5fr, 2fr, 1fr, auto),
|
|
align: (left, center, center, right),
|
|
[#auteur n°#numero], [#titre], [#annee], [#(cur - 1) / #(tot - 1)],
|
|
)
|
|
]
|
|
}
|
|
}
|
|
]
|
|
|
|
// Plan
|
|
#let design_plan(items) = {
|
|
let r = 6pt
|
|
let epaisseur = 2pt
|
|
let hauteur_ligne = 2.5em
|
|
let espace_vertical = 20pt
|
|
|
|
pad(left: 1cm, top: 1cm)[
|
|
#block[
|
|
#place(dx: r, dy: hauteur_ligne / 2)[
|
|
#line(
|
|
length: (items.len() - 1) * (hauteur_ligne + espace_vertical),
|
|
angle: 90deg,
|
|
stroke: epaisseur + black,
|
|
)
|
|
]
|
|
|
|
#grid(
|
|
columns: (2 * r, auto),
|
|
column-gutter: 20pt,
|
|
row-gutter: espace_vertical,
|
|
..items
|
|
.map(item => (
|
|
box(height: hauteur_ligne, align(center + horizon)[
|
|
#circle(radius: r, fill: white, stroke: epaisseur + black)
|
|
]),
|
|
box(height: hauteur_ligne, align(left + horizon)[
|
|
#text(weight: "bold", size: 1.1em)[#item]
|
|
]),
|
|
))
|
|
.flatten()
|
|
)
|
|
]
|
|
]
|
|
}
|
|
|
|
// Graphe de Tanner en filigrane
|
|
#let graphe_tanner_fond(taille, spread) = {
|
|
cetz.canvas(length: taille, {
|
|
import cetz.draw: *
|
|
|
|
let n_var = 18
|
|
let n_chk = 9
|
|
let var_y = 11
|
|
let chk_y = -8
|
|
|
|
// Calcul automatique pour que le graphe soit centré sur X=0
|
|
let dist_v = (n_var - 1) * spread
|
|
let v_start = -dist_v / 2
|
|
let vpos = range(n_var).map(i => (v_start + i * spread, var_y))
|
|
|
|
let spread_c = dist_v / (n_chk - 1)
|
|
let c_start = -dist_v / 2
|
|
let cpos = range(n_chk).map(i => (c_start + i * spread_c, chk_y))
|
|
|
|
let edges = (
|
|
(0, 0),
|
|
(0, 4),
|
|
(0, 8),
|
|
(1, 1),
|
|
(1, 5),
|
|
(1, 0),
|
|
(2, 2),
|
|
(2, 6),
|
|
(2, 1),
|
|
(3, 3),
|
|
(3, 7),
|
|
(3, 2),
|
|
(4, 4),
|
|
(4, 8),
|
|
(4, 3),
|
|
(5, 5),
|
|
(5, 0),
|
|
(5, 4),
|
|
(6, 6),
|
|
(6, 1),
|
|
(6, 5),
|
|
(7, 7),
|
|
(7, 2),
|
|
(7, 6),
|
|
(8, 8),
|
|
(8, 3),
|
|
(8, 7),
|
|
(9, 0),
|
|
(9, 3),
|
|
(9, 6),
|
|
(10, 1),
|
|
(10, 4),
|
|
(10, 7),
|
|
(11, 2),
|
|
(11, 5),
|
|
(11, 8),
|
|
(12, 0),
|
|
(12, 5),
|
|
(12, 7),
|
|
(13, 1),
|
|
(13, 3),
|
|
(13, 8),
|
|
(14, 2),
|
|
(14, 4),
|
|
(14, 6),
|
|
(15, 0),
|
|
(15, 4),
|
|
(15, 7),
|
|
(16, 1),
|
|
(16, 5),
|
|
(16, 8),
|
|
(17, 2),
|
|
(17, 3),
|
|
(17, 6),
|
|
)
|
|
|
|
for e in edges {
|
|
let vp = vpos.at(e.at(0))
|
|
let cp = cpos.at(e.at(1))
|
|
line((vp.at(0), vp.at(1)), (cp.at(0), cp.at(1)), stroke: 0.45pt + rgb("#e0e0e0"))
|
|
}
|
|
|
|
for p in vpos {
|
|
circle((p.at(0), p.at(1)), radius: 0.25, fill: white, stroke: 0.8pt + rgb("#cccccc"))
|
|
}
|
|
|
|
for p in cpos {
|
|
let (x, y) = p
|
|
rect((x - 0.25, y - 0.25), (x + 0.25, y + 0.25), fill: white, stroke: 0.8pt + rgb("#cccccc"))
|
|
}
|
|
})
|
|
}
|
|
|
|
// Schema Shannon
|
|
// #let canal_shannon_intro() = {
|
|
// cetz.canvas({
|
|
// import cetz.draw: *
|
|
//
|
|
// // Styles
|
|
// let s = (stroke: 2pt + black)
|
|
// let s_fleche = (stroke: 2pt + black)
|
|
// let pointe_pleine = (end: "stealth", fill: black)
|
|
//
|
|
// let espacement = 5.5
|
|
//
|
|
// // Blocs
|
|
// content((0, 0), [Source], name: "src", frame: "rect", ..s, padding: .3)
|
|
// content((espacement, 0), [Emetteur], name: "em", frame: "rect", ..s, padding: .3)
|
|
// content((espacement * 2, 0), [Canal], name: "chan", frame: "rect", ..s, padding: .3)
|
|
// content((espacement * 3, 0), [Récepteur], name: "rec", frame: "rect", ..s, padding: .3)
|
|
// content((espacement * 4, 0), [Destinataire], name: "dest", frame: "rect", ..s, padding: .3)
|
|
//
|
|
// // Bruit
|
|
// content((rel: (0, 1.8), to: "chan"), [Bruit], name: "bruit", frame: "rect", ..s, padding: .3)
|
|
//
|
|
// // Codage / Décodage
|
|
// content((rel: (0, 1), to: "em"), [*Codage*])
|
|
// content((rel: (0, 1), to: "rec"), [*Décodage*])
|
|
//
|
|
// // Flèches (On utilise s_fleche et pointe_pleine)
|
|
// line("src.east", "em.west", mark: pointe_pleine, ..s_fleche)
|
|
// line("em.east", "chan.west", mark: pointe_pleine, ..s_fleche)
|
|
// line("chan.east", "rec.west", mark: pointe_pleine, ..s_fleche)
|
|
// line("rec.east", "dest.west", mark: pointe_pleine, ..s_fleche)
|
|
// line("bruit.south", "chan.north", mark: pointe_pleine, ..s_fleche)
|
|
//
|
|
// // Annotation
|
|
// let note-style = (size: 0.75em, style: "italic")
|
|
// content((espacement * 0.5, -0.5), text(..note-style)[Message])
|
|
// content((espacement * 1.5, -0.5), text(..note-style)[Signal])
|
|
// content((espacement * 2.5, -0.5), text(..note-style)[Signal])
|
|
// content((espacement * 3.5, -0.5), text(..note-style)[Message])
|
|
// })
|
|
// }
|
|
|
|
#let canal_shannon_intro() = {
|
|
// Couleurs
|
|
let col-u = blue // Signal propre
|
|
let col-p = orange // Signal bruité
|
|
let C_MAIN = black
|
|
let C_BG = rgb("#f8f9fa") // Le gris très clair demandé
|
|
let C_LABEL = black
|
|
|
|
cetz.canvas(length: 1cm, {
|
|
import cetz.draw: *
|
|
|
|
let x_left = 4.0 ; let x_right = 16.0 ; let x_noise = 22.5
|
|
let y_top = 14.5 ; let y_mid = 9.0 ; let y_bot = 3.5
|
|
|
|
// Style des lignes avec flèches
|
|
let s_ligne = (stroke: 1.5pt + C_MAIN, mark: (end: "stealth", fill: C_MAIN, size: 0.25))
|
|
let s_bruit_fleche = (stroke: (paint: black, thickness: 1.5pt, dash: "dashed"), mark: (end: "stealth", fill: black, size: 0.25))
|
|
|
|
// Fonction de bloc avec le nouveau fond
|
|
let bloc(pos, txt, stxt, n) = {
|
|
content(pos, [#set align(center); #text(C_MAIN, weight: "bold", size: 1.2em)[#txt] \ #text(C_MAIN, size: 0.85em, style: "italic")[#stxt]],
|
|
frame: "rect", fill: C_BG, stroke: C_MAIN + 1.5pt, padding: 0.7, radius: 0.3, name: n)
|
|
}
|
|
|
|
// --- ONDES (Bruit dosé : "tremblement" au lieu de "chaos") ---
|
|
let wave_vert(x, y_start, y_end, is_noisy) = {
|
|
let n_points = 200
|
|
let color = if is_noisy { col-p } else { col-u }
|
|
|
|
line(..range(n_points + 1).map(i => {
|
|
let t = i / n_points
|
|
let y = y_start + t * (y_end - y_start)
|
|
|
|
// Enveloppe pour raccord propre
|
|
let env = if t < 0.05 { t/0.05 } else if t > 0.95 { (1-t)/0.05 } else { 1.0 }
|
|
|
|
let signal = 0.35 * calc.sin(t * 6 * calc.pi)
|
|
|
|
// Bruit dosé : on a baissé les fréquences et l'amplitude
|
|
let bruit = if is_noisy {
|
|
(0.08 * calc.sin(t * 45 * calc.pi) + 0.05 * calc.cos(t * 97 * calc.pi))
|
|
} else { 0 }
|
|
|
|
(x + (signal + bruit) * env, y)
|
|
}), stroke: color + 1.6pt)
|
|
}
|
|
|
|
wave_vert(x_right, y_top - 1.5, y_mid + 1, false) // Bleu
|
|
wave_vert(x_right, y_mid - 1, y_bot + 1.5, true) // Orange
|
|
|
|
// --- BLOCS ---
|
|
bloc((x_left, y_top), "Source", "Information", "src")
|
|
bloc((x_right, y_top), "Émetteur", "Codage", "em")
|
|
bloc((x_right, y_mid), "Canal", "", "canal")
|
|
bloc((x_noise, y_mid), "Bruit", "", "bruit")
|
|
bloc((x_right, y_bot), "Récepteur", "Décodage", "rec")
|
|
bloc((x_left, y_bot), "Destinataire", "Information", "dest")
|
|
|
|
// --- CONNEXIONS ---
|
|
line("src.east", "em.west", ..s_ligne)
|
|
line("bruit.west", "canal.east", ..s_bruit_fleche)
|
|
line("rec.west", "dest.east", ..s_ligne)
|
|
|
|
// --- ANNOTATIONS ---
|
|
let lab(pos, body, color: C_LABEL, anchor: "center") = content(pos, text(size: 0.95em, fill: color, style: "italic", weight: "medium")[#body], anchor: anchor)
|
|
|
|
lab(((x_left + x_right)/2 - 0.3, y_top + 0.7), "Message")
|
|
lab((x_right + 1.2, (y_top + y_mid)/2), "Signal", color: col-u, anchor: "west")
|
|
lab((x_right + 1.2, (y_mid + y_bot)/2), "Signal + Bruit", color: col-p, anchor: "west")
|
|
lab(((x_left + x_right)/2 + 0.3, y_bot - 0.7), "Message reçu")
|
|
})
|
|
}
|
|
|
|
#let plongement_schema() = {
|
|
cetz.canvas(length: 1.5cm, {
|
|
import cetz.draw: *
|
|
|
|
// Styles
|
|
let style-pointille = (stroke: (paint: black, thickness: 1.2pt, dash: "dashed"))
|
|
let style-point = (fill: black, stroke: none)
|
|
let rayon-point = 0.08
|
|
let pointe-fleche = (end: "stealth", fill: black)
|
|
|
|
let m = (
|
|
p00: (-4, 0),
|
|
p01: (-2, 0),
|
|
p11: (-2, -2),
|
|
p10: (-4, -2),
|
|
)
|
|
|
|
// Arêtes pointillés
|
|
line(m.p00, m.p01, m.p11, m.p10, close: true, ..style-pointille)
|
|
|
|
// Points sur les sommets
|
|
circle(m.p00, radius: rayon-point, ..style-point)
|
|
circle(m.p01, radius: rayon-point, ..style-point)
|
|
circle(m.p11, radius: rayon-point, ..style-point)
|
|
circle(m.p10, radius: rayon-point, ..style-point)
|
|
|
|
// Étiquettes
|
|
content(m.p00, [00], anchor: "south-east", padding: .2)
|
|
content(m.p01, [01], anchor: "south-west", padding: .2)
|
|
content(m.p11, [11], anchor: "north-west", padding: .2)
|
|
content(m.p10, [10], anchor: "north-east", padding: .2)
|
|
|
|
content((-3, -2.6), [$FF_2^2$])
|
|
|
|
line((-1.2, -1), (1.2, -1), mark: pointe-fleche, stroke: 1.5pt + black)
|
|
content((0, -0.6), [*Plongement*])
|
|
|
|
// Sommets face arrière
|
|
let cb = (p000: (2.5, 0), p001: (4.5, 0), p011: (4.5, -2), p010: (2.5, -2))
|
|
// Sommets face avant (décalés)
|
|
let cf = (p100: (3.5, 1), p101: (5.5, 1), p111: (5.5, -1), p110: (3.5, -1))
|
|
|
|
// Arêtes pointillés du cube
|
|
line(cb.p000, cb.p001, cb.p011, cb.p010, close: true, ..style-pointille) // Face arrière
|
|
line(cf.p100, cf.p101, cf.p111, cf.p110, close: true, ..style-pointille) // Face avant
|
|
line(cb.p000, cf.p100, ..style-pointille) // Liaisons
|
|
line(cb.p001, cf.p101, ..style-pointille)
|
|
line(cb.p011, cf.p111, ..style-pointille)
|
|
line(cb.p010, cf.p110, ..style-pointille)
|
|
|
|
// Points sur les sommets du cube
|
|
circle(cb.p000, radius: rayon-point, ..style-point)
|
|
circle(cb.p001, radius: rayon-point, ..style-point)
|
|
circle(cb.p011, radius: rayon-point, ..style-point)
|
|
circle(cb.p010, radius: rayon-point, ..style-point)
|
|
circle(cf.p100, radius: rayon-point, ..style-point)
|
|
circle(cf.p101, radius: rayon-point, ..style-point)
|
|
circle(cf.p111, radius: rayon-point, ..style-point)
|
|
circle(cf.p110, radius: rayon-point, ..style-point)
|
|
|
|
// Étiquettes du cube
|
|
content(cb.p000, [000], anchor: "south-east", padding: .2)
|
|
// content(cb.p001, [001], anchor: "south-west", padding: .2)
|
|
content((rel: (-0.85, 0.1), to: cb.p001), [001], anchor: "south-west", padding: .2)
|
|
content(cb.p011, [011], anchor: "north-west", padding: .2)
|
|
content(cb.p010, [010], anchor: "north-east", padding: .2)
|
|
content(cf.p100, [100], anchor: "south-east", padding: .2)
|
|
content(cf.p101, [101], anchor: "south-west", padding: .2)
|
|
content(cf.p111, [111], anchor: "north-west", padding: .2)
|
|
// content(cf.p110, [110], anchor: "north-east", padding: .2)
|
|
content((rel: (0.85, -0.1), to: cf.p110), [110], anchor: "north-east", padding: .2)
|
|
|
|
content((4, -2.6), [$FF_2^3$])
|
|
})
|
|
}
|
|
|
|
#let definition(
|
|
titre: "Définition",
|
|
accent: black,
|
|
titre_taille: 1.13em,
|
|
corps_taille: 1.2em,
|
|
contenu,
|
|
) = {
|
|
block(
|
|
width: 100%,
|
|
fill: rgb("#f8f9fa"),
|
|
stroke: 0.5pt + gray.lighten(60%),
|
|
radius: 8pt,
|
|
clip: true,
|
|
|
|
grid(
|
|
columns: (5pt, 1fr),
|
|
rows: auto,
|
|
fill: (col, row) => if col == 0 { accent },
|
|
[],
|
|
block(
|
|
width: 100%,
|
|
inset: (x: 16pt, y: 15pt),
|
|
{
|
|
{
|
|
set text(fill: accent, weight: 800, size: titre_taille, tracking: 0.5pt)
|
|
show math.equation: set text(weight: 700, size: 1.05em)
|
|
titre
|
|
}
|
|
v(18pt, weak: true)
|
|
{
|
|
set text(size: corps_taille)
|
|
set par(leading: 0.7em, justify: false)
|
|
contenu
|
|
}
|
|
},
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
#let limite_shannon_graphique() = {
|
|
let col-shannon = red.darken(10%)
|
|
let col-code-long = blue.darken(20%)
|
|
let col-code-short = gray.lighten(10%)
|
|
set text(size: 11pt)
|
|
|
|
move(dx: -5pt, dy: 0pt)[
|
|
#cetz.canvas({
|
|
import cetz.draw: *
|
|
|
|
plot.plot(
|
|
size: (23, 15),
|
|
|
|
// 1. On grossit les labels d'axes (15pt)
|
|
x-label: pad(bottom: 30pt)[#move(dy: 80pt)[#text(size: 18pt)[$E_b/N_0$ (dB)]]],
|
|
y-label: move(dx: -20pt, dy: -10pt)[#text(size: 18pt)[Bit Error Rate (BER)]],
|
|
|
|
x-min: 0,
|
|
x-max: 10,
|
|
y-min: -8.5,
|
|
y-max: 0.2,
|
|
x-tick-step: 1,
|
|
y-tick-step: 2,
|
|
|
|
// Axis
|
|
x-format: x => move(dy: 14pt)[#text(size: 16pt)[#x]],
|
|
y-format: y => move(dx: -5pt)[#text(size: 16pt)[$10^(#y)$]],
|
|
|
|
x-grid: true,
|
|
y-grid: true,
|
|
|
|
// Légende positionnée en bas.
|
|
legend: "north-east",
|
|
legend-style: (
|
|
stroke: 0.5pt + gray,
|
|
fill: white,
|
|
padding: 0.2,
|
|
offset: (-161.4pt, -45.1pt),
|
|
),
|
|
{
|
|
// 1. Limite de Shannon (Asymptote)
|
|
plot.add(
|
|
((1.5, -8.5), (1.5, 0.2)),
|
|
style: (stroke: (paint: col-shannon, thickness: 2pt, dash: "dashed")),
|
|
label: [Limite de Shannon],
|
|
)
|
|
|
|
// 2. Petit bloc linéaire (n ≈ 100) - Ultra-densifié (smooth)
|
|
plot.add(
|
|
(
|
|
(0.0, 0.00),
|
|
(0.2, -0.01),
|
|
(0.4, -0.03),
|
|
(0.6, -0.05),
|
|
(0.8, -0.07),
|
|
(1.0, -0.10),
|
|
(1.2, -0.13),
|
|
(1.4, -0.17),
|
|
(1.6, -0.21),
|
|
(1.8, -0.25),
|
|
(2.0, -0.30),
|
|
(2.2, -0.36),
|
|
(2.4, -0.43),
|
|
(2.6, -0.51),
|
|
(2.8, -0.60),
|
|
(3.0, -0.70),
|
|
(3.2, -0.80),
|
|
(3.4, -0.91),
|
|
(3.6, -1.03),
|
|
(3.8, -1.16),
|
|
(4.0, -1.30),
|
|
(4.2, -1.44),
|
|
(4.4, -1.59),
|
|
(4.6, -1.75),
|
|
(4.8, -1.92),
|
|
(5.0, -2.10),
|
|
(5.2, -2.28),
|
|
(5.4, -2.47),
|
|
(5.6, -2.67),
|
|
(5.8, -2.88),
|
|
(6.0, -3.10),
|
|
(6.2, -3.32),
|
|
(6.4, -3.55),
|
|
(6.6, -3.79),
|
|
(6.8, -4.04),
|
|
(7.0, -4.30),
|
|
(7.2, -4.56),
|
|
(7.4, -4.83),
|
|
(7.6, -5.11),
|
|
(7.8, -5.40),
|
|
(8.0, -5.70),
|
|
(8.2, -6.00),
|
|
(8.4, -6.31),
|
|
(8.6, -6.63),
|
|
(8.8, -6.96),
|
|
(9.0, -7.30),
|
|
(9.2, -7.62),
|
|
(9.4, -7.95),
|
|
(9.6, -8.29),
|
|
(9.8, -8.64),
|
|
(10.0, -9.00),
|
|
),
|
|
style: (stroke: (paint: col-code-short, thickness: 1.5pt)),
|
|
label: [Code court ($n approx 100$)],
|
|
)
|
|
|
|
// 3. Grand bloc linéaire (n = 64 800) - Ultra-densifié (smooth & waterfall net)
|
|
plot.add(
|
|
(
|
|
(0.0, 0.0),
|
|
(0.2, -0.005),
|
|
(0.4, -0.01),
|
|
(0.6, -0.02),
|
|
(0.8, -0.035),
|
|
(1.0, -0.05),
|
|
(1.1, -0.07),
|
|
(1.2, -0.10),
|
|
(1.3, -0.14),
|
|
(1.4, -0.20),
|
|
(1.45, -0.28),
|
|
(1.50, -0.40),
|
|
(1.52, -0.45),
|
|
(1.54, -0.52),
|
|
(1.56, -0.60),
|
|
(1.58, -0.69),
|
|
(1.60, -0.80),
|
|
(1.62, -0.92),
|
|
(1.64, -1.05),
|
|
(1.66, -1.19),
|
|
(1.68, -1.34),
|
|
(1.70, -1.50),
|
|
(1.72, -1.69),
|
|
(1.74, -1.89),
|
|
(1.76, -2.11),
|
|
(1.78, -2.35),
|
|
(1.80, -2.60),
|
|
(1.82, -2.88),
|
|
(1.84, -3.18),
|
|
(1.86, -3.50),
|
|
(1.88, -3.84),
|
|
(1.90, -4.20),
|
|
(1.92, -4.52),
|
|
(1.94, -4.86),
|
|
(1.96, -5.22),
|
|
(1.98, -5.60),
|
|
(2.00, -6.00),
|
|
(2.02, -6.32),
|
|
(2.04, -6.64),
|
|
(2.06, -6.94),
|
|
(2.08, -7.23),
|
|
(2.10, -7.50),
|
|
(2.12, -7.66),
|
|
(2.14, -7.81),
|
|
(2.16, -7.95),
|
|
(2.18, -8.08),
|
|
(2.20, -8.20),
|
|
(2.22, -8.32),
|
|
(2.24, -8.44),
|
|
(2.25, -8.50),
|
|
),
|
|
style: (stroke: (paint: col-code-long, thickness: 3.5pt)),
|
|
label: [Code long ($n = 64\,800$)],
|
|
)
|
|
},
|
|
)
|
|
})
|
|
]
|
|
}
|
|
|
|
#let decor_matrice_etoilee() = {
|
|
// Ajuste length (ex: 0.6mm ou 0.7mm) selon ta diapo
|
|
cetz.canvas(length: 0.7mm, {
|
|
import cetz.draw: *
|
|
|
|
// --- 1. Paramètres de la Matrice ---
|
|
let nx = 430
|
|
let ny = 265
|
|
|
|
// --- 2. Paramètres de la Loupe ---
|
|
let loupe_x = nx * 0.70
|
|
let loupe_y = -ny / 2.0
|
|
let R = 50.0
|
|
let zoom = 3.0
|
|
|
|
// --- 3. Paramètre d'Estompage (Gauche uniquement) ---
|
|
let fade_left = 220.0
|
|
|
|
// Palette de couleurs
|
|
let col_focus = rgb("#0284c7")
|
|
let col_fade = rgb("#64748b")
|
|
let col_grid = rgb("#e2e8f0")
|
|
|
|
// --- Fonction pseudo-aléatoire ---
|
|
let pseudo_rand(x, y) = {
|
|
let v = x * 7919 + y * 104729 + (x * x) * 313 + (y * y) * 991 + (x * y) * 101
|
|
calc.rem(calc.abs(v), 100)
|
|
}
|
|
|
|
// --- ÉTAPE A : Dessin de la matrice (Fade à gauche uniquement) ---
|
|
for x in range(nx) {
|
|
for y in range(ny) {
|
|
let hash = pseudo_rand(x, y)
|
|
let is_active = hash < 12
|
|
|
|
if is_active {
|
|
// L'intensité ne dépend plus que de la position X
|
|
let intensity = calc.min(1.0, x / fade_left)
|
|
|
|
if intensity > 0.05 {
|
|
let radius = 0.20 + 0.15 * intensity
|
|
let c = col_fade.lighten((1.0 - intensity) * 80%)
|
|
circle((x, -y), radius: radius, fill: c, stroke: none)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- ÉTAPE B : Dessin de la Loupe ---
|
|
circle((loupe_x, loupe_y), radius: R, fill: white, stroke: none)
|
|
|
|
// Grille zoomée
|
|
let limit = 20
|
|
for k in range(-limit, limit + 1) {
|
|
let offset = k * zoom
|
|
if calc.abs(offset) < R {
|
|
let half_chord = calc.sqrt(R * R - offset * offset)
|
|
line((loupe_x + offset, loupe_y + half_chord), (loupe_x + offset, loupe_y - half_chord), stroke: 0.5pt + col_grid)
|
|
line((loupe_x - half_chord, loupe_y + offset), (loupe_x + half_chord, loupe_y + offset), stroke: 0.5pt + col_grid)
|
|
}
|
|
}
|
|
|
|
// Points zoomés
|
|
let search_r = int(R / zoom) + 2
|
|
let lx_int = int(loupe_x)
|
|
let ly_idx = int(-loupe_y)
|
|
|
|
for x in range(lx_int - search_r, lx_int + search_r + 1) {
|
|
for y in range(ly_idx - search_r, ly_idx + search_r + 1) {
|
|
let hash = pseudo_rand(x, y)
|
|
if hash < 12 {
|
|
let dx = x - loupe_x
|
|
let dy = -y - loupe_y
|
|
let d_orig = calc.sqrt(dx * dx + dy * dy)
|
|
let d_zoom = d_orig * zoom
|
|
|
|
if d_zoom <= R - 1.2 {
|
|
circle((loupe_x + dx * zoom, loupe_y + dy * zoom), radius: 1.1, fill: col_focus, stroke: none)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bordures de la Loupe
|
|
circle((loupe_x, loupe_y), radius: R, stroke: 1.8pt + col_focus.lighten(20%))
|
|
circle((loupe_x, loupe_y), radius: R + 1.5, stroke: 1.0pt + col_focus.lighten(50%))
|
|
circle((loupe_x, loupe_y), radius: R + 3.5, stroke: 0.5pt + col_focus.lighten(80%))
|
|
})
|
|
}
|
|
|
|
#let hldpc() = {
|
|
import cetz.draw: *
|
|
|
|
let points = (
|
|
(7,0), (10,0), (15,0), (22,0), (24,0), (29,0), (3,1), (6,1), (18,1), (19,1), (25,1), (27,1),
|
|
(5,2), (9,2), (13,2), (14,2), (17,2), (28,2), (0,3), (8,3), (11,3), (16,3), (20,3), (26,3),
|
|
(1,4), (2,4), (4,4), (12,4), (21,4), (23,4), (5,5), (6,5), (8,5), (10,5), (21,5), (29,5),
|
|
(14,6), (15,6), (16,6), (18,6), (22,6), (28,6), (0,7), (1,7), (4,7), (9,7), (20,7), (26,7),
|
|
(2,8), (3,8), (11,8), (12,8), (17,8), (19,8), (7,9), (13,9), (23,9), (24,9), (25,9), (27,9),
|
|
(0,10), (6,10), (15,10), (18,10), (21,10), (26,10), (2,11), (7,11), (10,11), (17,11), (22,11), (27,11),
|
|
(8,12), (11,12), (14,12), (20,12), (23,12), (29,12), (4,13), (5,13), (9,13), (13,13), (16,13), (19,13),
|
|
(1,14), (3,14), (12,14), (24,14), (25,14), (28,14)
|
|
)
|
|
|
|
cetz.canvas(length: 0.45cm, {
|
|
let nx = 30
|
|
let ny = 15
|
|
let cell_size = 1.0
|
|
let h_width = nx * cell_size
|
|
let h_height = ny * cell_size
|
|
|
|
// Palette unifiée
|
|
let color_blue = blue
|
|
let color_orange = orange
|
|
let col_dot_base = gray.darken(30%)
|
|
|
|
// Définition des couleurs de fond (lighten)
|
|
let col_row_bg = color_blue.lighten(90%)
|
|
let col_col_bg = color_orange.lighten(90%)
|
|
// Calcul du mélange pour l'intersection
|
|
let col_mix_bg = col_row_bg.mix(col_col_bg)
|
|
|
|
// Label "H ="
|
|
content((-3.4, -h_height / 2), text(size: 1.6em, weight: "bold")[$bold(H) = $])
|
|
|
|
// Sélection visuelle (Focus)
|
|
let sel_row = 7
|
|
let sel_col = 10
|
|
|
|
// Rectangles de fond
|
|
rect((0, -sel_row), (h_width, -sel_row - 1), fill: col_row_bg, stroke: none)
|
|
rect((sel_col, 0), (sel_col + 1, -h_height), fill: col_col_bg, stroke: none)
|
|
rect((sel_col, -sel_row), (sel_col + 1, -sel_row - 1), fill: col_mix_bg, stroke: none)
|
|
|
|
// Grands crochets matriciels
|
|
let b_w = 0.6
|
|
set-style(stroke: (thickness: 1.5pt, cap: "round"))
|
|
line((b_w, 0.3), (0, 0.3), (0, -h_height - 0.3), (b_w, -h_height - 0.3))
|
|
line((h_width - b_w, 0.3), (h_width, 0.3), (h_width, -h_height - 0.3), (h_width - b_w, -h_height - 0.3))
|
|
|
|
// Dessin des points
|
|
for (x, y) in points {
|
|
let px = x + 0.5
|
|
let py = -y - 0.5
|
|
|
|
let is_row = (y == sel_row)
|
|
let is_col = (x == sel_col)
|
|
|
|
let d_col = col_dot_base
|
|
let r = 0.16
|
|
|
|
if is_row {
|
|
d_col = color_blue
|
|
r = 0.24
|
|
} else if is_col {
|
|
d_col = color_orange
|
|
r = 0.24
|
|
}
|
|
|
|
circle((px, py), radius: r, fill: d_col, stroke: none)
|
|
}
|
|
|
|
// 5. Légendes w_r et w_c
|
|
content((h_width + 0.5, -sel_row - 0.5), anchor: "west", text(fill: color_blue, weight: "bold", size: 1.1em)[$w_r = 6$])
|
|
content((sel_col + 0.5, 0.8), anchor: "south", text(fill: color_orange, weight: "bold", size: 1.1em)[$w_c = 3$])
|
|
})
|
|
}
|
|
|
|
#let hldpc_dual(row1: 0, row2: 14) = {
|
|
import cetz.draw: *
|
|
let points = ((7,0), (10,0), (15,0), (22,0), (24,0), (29,0), (3,1), (6,1), (18,1), (19,1), (25,1), (27,1), (5,2), (9,2), (13,2), (14,2), (17,2), (28,2), (0,3), (8,3), (11,3), (16,3), (20,3), (26,3), (1,4), (2,4), (4,4), (12,4), (21,4), (23,4), (5,5), (6,5), (8,5), (10,5), (21,5), (29,5), (14,6), (15,6), (16,6), (18,6), (22,6), (28,6), (0,7), (1,7), (4,7), (9,7), (20,7), (26,7), (2,8), (3,8), (11,8), (12,8), (17,8), (19,8), (7,9), (13,9), (23,9), (24,9), (25,9), (27,9), (0,10), (6,10), (15,10), (18,10), (21,10), (26,10), (2,11), (7,11), (10,11), (17,11), (22,11), (27,11), (8,12), (11,12), (14,12), (20,12), (23,12), (29,12), (4,13), (5,13), (9,13), (13,13), (16,13), (19,13), (1,14), (3,14), (12,14), (24,14), (25,14), (28,14))
|
|
|
|
cetz.canvas(length: 0.35cm, {
|
|
let nx = 30; let ny = 15
|
|
let col_1 = orange; let col_2 = blue
|
|
|
|
content((-3.4, -7.5), text(size: 1.6em )[$H = $])
|
|
|
|
// Fonds de lignes
|
|
rect((0, -row1), (nx, -row1 - 1), fill: col_1.lighten(90%), stroke: none)
|
|
if row2 != none { rect((0, -row2), (nx, -row2 - 1), fill: col_2.lighten(90%), stroke: none) }
|
|
|
|
// Crochets
|
|
set-style(stroke: (thickness: 1.2pt))
|
|
line((0.5, 0.3), (0, 0.3), (0, -ny - 0.3), (0.5, -ny - 0.3))
|
|
line((nx - 0.5, 0.3), (nx, 0.3), (nx, -ny - 0.3), (nx - 0.5, -ny - 0.3))
|
|
|
|
for (x, y) in points {
|
|
let d_col = gray.darken(30%)
|
|
let r = 0.15
|
|
if y == row1 { d_col = col_1; r = 0.22 }
|
|
else if y == row2 { d_col = col_2; r = 0.22 }
|
|
circle((x + 0.5, -y - 0.5), radius: r, fill: d_col, stroke: none)
|
|
}
|
|
})
|
|
}
|