feat(geom11 ch3 wave1): §5 «Сфера» + 3D + уравнение + сечения
This commit is contained in:
@@ -396,7 +396,7 @@ function buildParaSelector(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
const BUILT=new Set();
|
const BUILT=new Set();
|
||||||
const BUILDERS = { p5:()=>buildStub('p5'), p6:()=>buildStub('p6'), p7:()=>buildStub('p7'), final3:()=>buildStub('final3') };
|
const BUILDERS = { p5:buildP5, p6:()=>buildStub('p6'), p7:()=>buildStub('p7'), final3:()=>buildStub('final3') };
|
||||||
function ensureBuilt(id){ if(BUILT.has(id)) return; const fn=BUILDERS[id]; if(fn){ fn(); BUILT.add(id); } }
|
function ensureBuilt(id){ if(BUILT.has(id)) return; const fn=BUILDERS[id]; if(fn){ fn(); BUILT.add(id); } }
|
||||||
function goTo(id){
|
function goTo(id){
|
||||||
STATE.current=id; ensureBuilt(id);
|
STATE.current=id; ensureBuilt(id);
|
||||||
@@ -411,14 +411,24 @@ function goTo(id){
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SIDEBARS = {
|
const SIDEBARS = {
|
||||||
p5:{title:"Шпаргалка § 5", rows:[["Тема", "Сфера"],["Формула","$(x-a)^2+(y-b)^2+(z-c)^2=R^2$"]]},
|
p5:{title:"Шпаргалка § 5", rows:[
|
||||||
|
["Тема", "Сфера"],
|
||||||
|
["Сфера", "множество точек, $|OM|=R$"],
|
||||||
|
["Шар", "множество точек, $|OM|\\\\le R$"],
|
||||||
|
["Уравнение", "$(x-a)^2+(y-b)^2+(z-c)^2=R^2$"],
|
||||||
|
["Касательная", "плоскость $\\\\perp$ радиусу $OM$"],
|
||||||
|
["Сечение", "окружность $r=\\\\sqrt{R^2-d^2}$"],
|
||||||
|
["Большой круг", "$d=0$, $r=R$"],
|
||||||
|
["Площадь", "$S=4\\\\pi R^2$"],
|
||||||
|
["Объём шара", "$V=\\\\tfrac{4}{3}\\\\pi R^3$"]
|
||||||
|
]},
|
||||||
p6:{title:"Шпаргалка § 6", rows:[["Тема", "Шар"],["Формула","$S=4\\\\pi R^2$, $V=\\\\frac{4}{3}\\\\pi R^3$"]]},
|
p6:{title:"Шпаргалка § 6", rows:[["Тема", "Шар"],["Формула","$S=4\\\\pi R^2$, $V=\\\\frac{4}{3}\\\\pi R^3$"]]},
|
||||||
p7:{title:"Шпаргалка § 7", rows:[["Тема", "Правильные многогранники"],["Формула","5 платоновых тел"]]},
|
p7:{title:"Шпаргалка § 7", rows:[["Тема", "Правильные многогранники"],["Формула","5 платоновых тел"]]},
|
||||||
final3:{title:"Финал раздела 3", rows:[["§ 5–§ 7","теория раздела 3"],["Награда","+50 XP"]]}
|
final3:{title:"Финал раздела 3", rows:[["§ 5–§ 7","теория раздела 3"],["Награда","+50 XP"]]}
|
||||||
};
|
};
|
||||||
|
|
||||||
const TIPS=[
|
const TIPS=[
|
||||||
{sec:'p5',html:"§ 5 «Сфера» — содержание в разработке. $(x-a)^2+(y-b)^2+(z-c)^2=R^2$"},
|
{sec:'p5',html:"Сфера: $|OM|=R$. Уравнение $(x-a)^2+(y-b)^2+(z-c)^2=R^2$. Сечение плоскостью — окружность $r=\\\\sqrt{R^2-d^2}$."},
|
||||||
{sec:'p6',html:"§ 6 «Шар» — содержание в разработке. $S=4\\\\\\\\pi R^2$, $V=\\\\\\\\frac{4}{3}\\\\\\\\pi R^3$"},
|
{sec:'p6',html:"§ 6 «Шар» — содержание в разработке. $S=4\\\\\\\\pi R^2$, $V=\\\\\\\\frac{4}{3}\\\\\\\\pi R^3$"},
|
||||||
{sec:'p7',html:"§ 7 «Правильные многогранники» — содержание в разработке. 5 платоновых тел"},
|
{sec:'p7',html:"§ 7 «Правильные многогранники» — содержание в разработке. 5 платоновых тел"},
|
||||||
{sec:'final3',html:"Финал раздела 3 — интегрированные задачи по разделу."}
|
{sec:'final3',html:"Финал раздела 3 — интегрированные задачи по разделу."}
|
||||||
@@ -625,6 +635,357 @@ function wireReadBtn(paraId){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===== § 5 «Сфера» — Wave 1 ===== */
|
||||||
|
|
||||||
|
function buildP5(){
|
||||||
|
const box = document.getElementById('p5-body');
|
||||||
|
if(!box) return;
|
||||||
|
let html = '';
|
||||||
|
|
||||||
|
/* === ТЕОРИЯ === */
|
||||||
|
|
||||||
|
html += makeCard('theory', 'Определение и элементы', '§ 5.1',
|
||||||
|
'<p><b>Сфера</b> — множество всех точек пространства, равноудалённых от заданной точки $O$ (<b>центра</b>).</p>'
|
||||||
|
+ '<p><b>Шар</b> — множество точек, для которых $|OM|\\le R$, где $O$ — центр, $R$ — радиус. Шар ограничен сферой; сфера — поверхность шара.</p>'
|
||||||
|
+ '<p><b>Элементы:</b></p>'
|
||||||
|
+ '<ul style="margin:6px 0 10px 22px;line-height:1.7">'
|
||||||
|
+ '<li><b>Центр</b> $O$ — точка, от которой все точки сферы равноудалены.</li>'
|
||||||
|
+ '<li><b>Радиус</b> $R=|OM|$ для любой точки $M$ сферы.</li>'
|
||||||
|
+ '<li><b>Диаметр</b> — отрезок через центр между двумя точками сферы. Длина $d=2R$.</li>'
|
||||||
|
+ '<li><b>Хорда</b> — отрезок между двумя точками сферы (не обязательно через центр).</li>'
|
||||||
|
+ '</ul>'
|
||||||
|
+ '<p><b>Уравнение сферы</b> в декартовой системе координат. Для центра $C(a,b,c)$ и радиуса $R$:</p>'
|
||||||
|
+ '<p style="text-align:center;margin:8px 0">$$(x-a)^2+(y-b)^2+(z-c)^2=R^2$$</p>'
|
||||||
|
+ '<p>Если центр в начале координат:</p>'
|
||||||
|
+ '<p style="text-align:center;margin:8px 0">$$x^2+y^2+z^2=R^2$$</p>'
|
||||||
|
+ '<p>Уравнение выражает то, что квадрат расстояния от точки $(x,y,z)$ до центра $C$ равен $R^2$.</p>');
|
||||||
|
|
||||||
|
html += makeCard('rule', 'Касательная плоскость', '§ 5.2',
|
||||||
|
'<p><b>Касательная плоскость к сфере</b> — плоскость, имеющая со сферой <b>ровно одну</b> общую точку. Эту точку называют <b>точкой касания</b>.</p>'
|
||||||
|
+ '<p><b>Признак касания</b> (необходимый и достаточный):</p>'
|
||||||
|
+ '<p style="background:var(--sec-acc-soft,var(--pri-soft));border-left:4px solid var(--sec-acc,var(--pri));padding:8px 12px;border-radius:6px;margin:8px 0">Плоскость касается сферы в точке $M$ тогда и только тогда, когда она <b>перпендикулярна радиусу $OM$</b>, проведённому в точку касания.</p>'
|
||||||
|
+ '<p>Через каждую точку сферы можно провести <b>единственную</b> касательную плоскость.</p>'
|
||||||
|
+ '<p>Расстояние от центра сферы до касательной плоскости равно радиусу $R$.</p>'
|
||||||
|
+ '<details class="spoiler"><summary>Пример: касательная к сфере $x^2+y^2+z^2=25$ в точке $M(3;4;0)$</summary><div class="spoiler-body">'
|
||||||
|
+ '<p>Центр $O(0;0;0)$, радиус-вектор $\\overrightarrow{OM}=(3;4;0)$ направлен из центра в точку касания.</p>'
|
||||||
|
+ '<p>Значит нормаль касательной плоскости $\\vec{n}=(3;4;0)$. Уравнение плоскости в точке $M$:</p>'
|
||||||
|
+ '<p>$3(x-3)+4(y-4)+0\\cdot(z-0)=0$, то есть $3x+4y=25$.</p>'
|
||||||
|
+ '</div></details>');
|
||||||
|
|
||||||
|
html += makeCard('example', 'Сечения сферы и большой круг', '§ 5.3',
|
||||||
|
'<p><b>Сечение сферы плоскостью</b>, пересекающей её — всегда <b>окружность</b>. Это следует из того, что точки сечения равноудалены от проекции центра сферы на эту плоскость.</p>'
|
||||||
|
+ '<p>Связь радиуса сечения $r$, радиуса сферы $R$ и расстояния $d$ от центра сферы до секущей плоскости:</p>'
|
||||||
|
+ '<p style="text-align:center;margin:8px 0">$$r=\\sqrt{R^2-d^2}$$</p>'
|
||||||
|
+ '<p><b>Три случая:</b></p>'
|
||||||
|
+ '<ul style="margin:6px 0 10px 22px;line-height:1.7">'
|
||||||
|
+ '<li>$d<R$ — пересечение есть, сечение — окружность радиуса $r$.</li>'
|
||||||
|
+ '<li>$d=R$ — плоскость касается сферы; «сечение» вырождается в точку.</li>'
|
||||||
|
+ '<li>$d>R$ — общих точек нет.</li>'
|
||||||
|
+ '</ul>'
|
||||||
|
+ '<p><b>Большой круг</b> — сечение, проходящее через центр сферы ($d=0$). Радиус большого круга максимален и равен $R$.</p>'
|
||||||
|
+ '<p>Любые два больших круга пересекаются по диаметру сферы.</p>'
|
||||||
|
+ '<details class="spoiler"><summary>Пример: $R=5$, $d=3$</summary><div class="spoiler-body">'
|
||||||
|
+ '<p>$r=\\sqrt{R^2-d^2}=\\sqrt{25-9}=\\sqrt{16}=4$.</p>'
|
||||||
|
+ '<p>Сечение — окружность радиуса $4$ в секущей плоскости.</p>'
|
||||||
|
+ '</div></details>');
|
||||||
|
|
||||||
|
/* === ИНТЕРАКТИВ 1 — 3D-визуализатор сферы === */
|
||||||
|
html += '<div class="wg" id="p5-iv1">'
|
||||||
|
+ '<div class="wg-header"><span class="wg-badge">3D · сфера</span><div class="wg-title">Визуализатор сферы (каркас)</div></div>'
|
||||||
|
+ '<div class="wg-help">Меняй радиус $R$ ползунком, вращай мышью или выбирай вид. После <b>4 разных значений $R$</b> — +10 XP.</div>'
|
||||||
|
+ '<div class="sliders">'
|
||||||
|
+ '<label>$R$ (радиус):<b id="p5-iv1-R-v">2.0</b><input type="range" id="p5-iv1-R" min="1" max="4" step="0.1" value="2"></label>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div class="g3d-tools">'
|
||||||
|
+ '<button class="btn" data-view="iso">Изо</button>'
|
||||||
|
+ '<button class="btn" data-view="front">Спереди</button>'
|
||||||
|
+ '<button class="btn" data-view="top">Сверху</button>'
|
||||||
|
+ '<button class="btn" data-view="side">Сбоку</button>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px;text-align:center"><svg id="p5-iv1-svg" viewBox="0 0 480 400" width="100%" style="max-width:480px;height:auto"></svg></div>'
|
||||||
|
+ '<div class="score-display" style="margin-top:10px;flex-wrap:wrap">'
|
||||||
|
+ '<span>$R=$<b id="p5-iv1-R-o">—</b></span>'
|
||||||
|
+ '<span>$d=2R=$<b id="p5-iv1-d-o">—</b></span>'
|
||||||
|
+ '<span>$S=4\\pi R^2\\approx$<b id="p5-iv1-S-o">—</b></span>'
|
||||||
|
+ '<span>$V=\\tfrac{4}{3}\\pi R^3\\approx$<b id="p5-iv1-V-o">—</b></span>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div style="font-size:.78rem;color:var(--muted);margin-top:6px">Разных $R$ изучено: <b id="p5-iv1-cnt">0</b> / 4</div>'
|
||||||
|
+ '</div>';
|
||||||
|
|
||||||
|
/* === ИНТЕРАКТИВ 2 — Уравнение сферы и проверка точки === */
|
||||||
|
html += '<div class="wg" id="p5-iv2">'
|
||||||
|
+ '<div class="wg-header"><span class="wg-badge">уравнение</span><div class="wg-title">Уравнение сферы и проверка точки</div></div>'
|
||||||
|
+ '<div class="wg-help">Введи центр $C(a;b;c)$ и радиус $R$ — получи уравнение. Затем введи точку $M(x_0;y_0;z_0)$ — узнай, лежит ли она на сфере, внутри шара или вне.</div>'
|
||||||
|
+ '<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:10px 12px;margin-bottom:10px">'
|
||||||
|
+ '<p style="font-weight:700;margin-bottom:6px">Параметры сферы</p>'
|
||||||
|
+ '<div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-bottom:8px">'
|
||||||
|
+ '<span>$a=$</span><input type="text" class="tinp" id="p5-iv2-a" value="0" style="width:60px">'
|
||||||
|
+ '<span>$b=$</span><input type="text" class="tinp" id="p5-iv2-b" value="0" style="width:60px">'
|
||||||
|
+ '<span>$c=$</span><input type="text" class="tinp" id="p5-iv2-c" value="0" style="width:60px">'
|
||||||
|
+ '<span>$R=$</span><input type="text" class="tinp" id="p5-iv2-R" value="5" style="width:60px">'
|
||||||
|
+ '<button class="btn primary" id="p5-iv2-show">Показать уравнение</button>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div id="p5-iv2-eq" style="font-size:1rem;line-height:1.7;margin-top:6px"></div>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:10px 12px">'
|
||||||
|
+ '<p style="font-weight:700;margin-bottom:6px">Проверка точки $M(x_0;y_0;z_0)$</p>'
|
||||||
|
+ '<div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-bottom:8px">'
|
||||||
|
+ '<span>$x_0=$</span><input type="text" class="tinp" id="p5-iv2-x0" value="3" style="width:60px">'
|
||||||
|
+ '<span>$y_0=$</span><input type="text" class="tinp" id="p5-iv2-y0" value="4" style="width:60px">'
|
||||||
|
+ '<span>$z_0=$</span><input type="text" class="tinp" id="p5-iv2-z0" value="0" style="width:60px">'
|
||||||
|
+ '<button class="btn primary" id="p5-iv2-check">Проверить точку</button>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div id="p5-iv2-pt" style="font-size:.94rem;line-height:1.65;margin-top:6px"></div>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '</div>';
|
||||||
|
|
||||||
|
/* === ИНТЕРАКТИВ 3 — Сечение сферы (квикфайр 6) === */
|
||||||
|
html += '<div class="wg" id="p5-iv3">'
|
||||||
|
+ '<div class="wg-header"><span class="wg-badge">квикфайр · 6 заданий</span><div class="wg-title">Сечение сферы плоскостью</div></div>'
|
||||||
|
+ '<div class="wg-help">Сравни $d$ и $R$. Выбери, что получится при пересечении: окружность, точка (касание) или ничего.</div>'
|
||||||
|
+ '<div id="p5-iv3-list"></div>'
|
||||||
|
+ '<div class="score-display" style="margin-top:10px">Верно: <b id="p5-iv3-score">0</b> / 6</div>'
|
||||||
|
+ '</div>';
|
||||||
|
|
||||||
|
/* === ИНТЕРАКТИВ 4 — Тренажёр === */
|
||||||
|
html += '<div class="wg" id="p5-iv4">'
|
||||||
|
+ '<div class="wg-header"><span class="wg-badge">тренажёр · 6 задач</span><div class="wg-title">Сечения, расстояния и уравнения</div></div>'
|
||||||
|
+ '<div class="wg-help">Введи числовой ответ. Допуск $\\pm 0{,}05$ для дробных значений.</div>'
|
||||||
|
+ '<div id="p5-iv4-list"></div>'
|
||||||
|
+ '<div class="score-display" style="margin-top:10px">Решено: <b id="p5-iv4-score">0</b> / 6</div>'
|
||||||
|
+ '</div>';
|
||||||
|
|
||||||
|
html += secNav(null, 'p6');
|
||||||
|
html += readButton('p5');
|
||||||
|
|
||||||
|
box.innerHTML = html;
|
||||||
|
renderMath(box);
|
||||||
|
|
||||||
|
/* ====== JS-логика интерактивов ====== */
|
||||||
|
|
||||||
|
/* IV1 — 3D-визуализатор */
|
||||||
|
(function(){
|
||||||
|
if(!window.G3D) return;
|
||||||
|
const svg = document.getElementById('p5-iv1-svg');
|
||||||
|
const elR = document.getElementById('p5-iv1-R');
|
||||||
|
const vR = document.getElementById('p5-iv1-R-v');
|
||||||
|
const oR = document.getElementById('p5-iv1-R-o');
|
||||||
|
const oD = document.getElementById('p5-iv1-d-o');
|
||||||
|
const oS = document.getElementById('p5-iv1-S-o');
|
||||||
|
const oV = document.getElementById('p5-iv1-V-o');
|
||||||
|
const oCnt = document.getElementById('p5-iv1-cnt');
|
||||||
|
if(!svg) return;
|
||||||
|
const scene = G3D.createScene({W:480, H:400, scale:60, camDist:8, rotX:-0.35, rotY:0.7});
|
||||||
|
const seen = new Set();
|
||||||
|
let xpGiven = false;
|
||||||
|
const PI = 3.14;
|
||||||
|
|
||||||
|
function draw(){
|
||||||
|
const R = +elR.value;
|
||||||
|
vR.textContent = R.toFixed(1);
|
||||||
|
const sph = G3D.sphereWireframe(R, 6, 12);
|
||||||
|
const M = G3D.buildRotMatrix(scene);
|
||||||
|
svg.innerHTML = G3D.renderSphereWireframe(sph, M, scene);
|
||||||
|
oR.textContent = R.toFixed(1);
|
||||||
|
oD.textContent = (2*R).toFixed(1);
|
||||||
|
oS.textContent = (4*PI*R*R).toFixed(2);
|
||||||
|
oV.textContent = ((4/3)*PI*R*R*R).toFixed(2);
|
||||||
|
const key = R.toFixed(1);
|
||||||
|
seen.add(key);
|
||||||
|
oCnt.textContent = Math.min(seen.size, 4);
|
||||||
|
if(seen.size >= 4 && !xpGiven){
|
||||||
|
xpGiven = true;
|
||||||
|
addXp(10, 'p5-iv1');
|
||||||
|
bumpProgress('p5', 15);
|
||||||
|
const note = document.createElement('div');
|
||||||
|
note.className = 'feedback ok';
|
||||||
|
note.innerHTML = '✓ +10 XP за изучение 4 разных радиусов!';
|
||||||
|
note.style.cssText = 'display:block;margin-top:8px';
|
||||||
|
const host = document.getElementById('p5-iv1');
|
||||||
|
if(host) host.appendChild(note);
|
||||||
|
setTimeout(function(){ try{ note.remove(); }catch(e){} }, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw();
|
||||||
|
G3D.attachOrbit(svg, scene, draw);
|
||||||
|
elR.addEventListener('input', draw);
|
||||||
|
document.querySelectorAll('#p5-iv1 .g3d-tools .btn').forEach(function(b){
|
||||||
|
b.addEventListener('click', function(){ G3D.presetView(scene, b.dataset.view, draw); });
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* IV2 — Уравнение сферы + проверка точки */
|
||||||
|
(function(){
|
||||||
|
let xpGiven = false, eqShown = false, ptChecked = false;
|
||||||
|
function parseNum(id){ const v = (document.getElementById(id).value||'').replace(',', '.').trim(); const x = parseFloat(v); return isFinite(x) ? x : NaN; }
|
||||||
|
function fmtSign(v, useVar){
|
||||||
|
// возвращает строку для "(x - a)" с учётом знака
|
||||||
|
if(v === 0) return useVar;
|
||||||
|
if(v > 0) return '('+useVar+' - '+fmt(v)+')';
|
||||||
|
return '('+useVar+' + '+fmt(-v)+')';
|
||||||
|
}
|
||||||
|
function maybeXp(){
|
||||||
|
if(eqShown && ptChecked && !xpGiven){
|
||||||
|
xpGiven = true;
|
||||||
|
addXp(10, 'p5-iv2');
|
||||||
|
bumpProgress('p5', 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById('p5-iv2-show').addEventListener('click', function(){
|
||||||
|
const a = parseNum('p5-iv2-a'), b = parseNum('p5-iv2-b'), c = parseNum('p5-iv2-c'), R = parseNum('p5-iv2-R');
|
||||||
|
const out = document.getElementById('p5-iv2-eq');
|
||||||
|
if(!isFinite(a)||!isFinite(b)||!isFinite(c)||!isFinite(R)||R<=0){
|
||||||
|
out.innerHTML = '<span style="color:var(--bad)">✗ Введи корректные числа ($R>0$).</span>';
|
||||||
|
renderMath(out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fx = fmtSign(a, 'x');
|
||||||
|
const fy = fmtSign(b, 'y');
|
||||||
|
const fz = fmtSign(c, 'z');
|
||||||
|
const R2 = R*R;
|
||||||
|
const eq = '$$' + fx + '^2 + ' + fy + '^2 + ' + fz + '^2 = ' + fmt(R2) + '$$';
|
||||||
|
out.innerHTML = '<p>Центр $C('+fmt(a)+';'+fmt(b)+';'+fmt(c)+')$, радиус $R='+fmt(R)+'$.</p>'
|
||||||
|
+ '<p>Уравнение сферы:</p>' + eq;
|
||||||
|
renderMath(out);
|
||||||
|
eqShown = true;
|
||||||
|
maybeXp();
|
||||||
|
});
|
||||||
|
document.getElementById('p5-iv2-check').addEventListener('click', function(){
|
||||||
|
const a = parseNum('p5-iv2-a'), b = parseNum('p5-iv2-b'), c = parseNum('p5-iv2-c'), R = parseNum('p5-iv2-R');
|
||||||
|
const x0 = parseNum('p5-iv2-x0'), y0 = parseNum('p5-iv2-y0'), z0 = parseNum('p5-iv2-z0');
|
||||||
|
const out = document.getElementById('p5-iv2-pt');
|
||||||
|
if(!isFinite(a)||!isFinite(b)||!isFinite(c)||!isFinite(R)||R<=0||!isFinite(x0)||!isFinite(y0)||!isFinite(z0)){
|
||||||
|
out.innerHTML = '<span style="color:var(--bad)">✗ Введи корректные числа.</span>';
|
||||||
|
renderMath(out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dx = x0 - a, dy = y0 - b, dz = z0 - c;
|
||||||
|
const lhs = dx*dx + dy*dy + dz*dz;
|
||||||
|
const R2 = R*R;
|
||||||
|
const dist = Math.sqrt(lhs);
|
||||||
|
let verdict = '', color = '';
|
||||||
|
if(Math.abs(lhs - R2) < 1e-6){ verdict = 'лежит <b>на сфере</b>'; color = 'var(--ok)'; }
|
||||||
|
else if(lhs < R2){ verdict = 'лежит <b>внутри шара</b>'; color = '#2563eb'; }
|
||||||
|
else { verdict = 'лежит <b>вне шара</b>'; color = 'var(--warn)'; }
|
||||||
|
out.innerHTML = '<p>Подставляем $M('+fmt(x0)+';'+fmt(y0)+';'+fmt(z0)+')$:</p>'
|
||||||
|
+ '<p>$('+fmt(x0)+'-'+fmt(a)+')^2+('+fmt(y0)+'-'+fmt(b)+')^2+('+fmt(z0)+'-'+fmt(c)+')^2 = '
|
||||||
|
+ fmt(dx*dx)+'+'+fmt(dy*dy)+'+'+fmt(dz*dz)+' = '+fmt(lhs)+'$</p>'
|
||||||
|
+ '<p>Сравниваем с $R^2='+fmt(R2)+'$. Расстояние $|CM|='+fmt(+dist.toFixed(4))+'$.</p>'
|
||||||
|
+ '<p style="color:'+color+';font-weight:700">✓ Точка $M$ '+verdict+'.</p>';
|
||||||
|
renderMath(out);
|
||||||
|
ptChecked = true;
|
||||||
|
maybeXp();
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* IV3 — Сечение сферы (квикфайр) */
|
||||||
|
(function(){
|
||||||
|
const tasks = [
|
||||||
|
{ R:5, d:3, a:'circle' },
|
||||||
|
{ R:5, d:5, a:'point' },
|
||||||
|
{ R:5, d:6, a:'none' },
|
||||||
|
{ R:10, d:0, a:'circle' },
|
||||||
|
{ R:3, d:3.5, a:'none' },
|
||||||
|
{ R:7, d:7, a:'point' }
|
||||||
|
];
|
||||||
|
const NAMES = {circle:'Окружность', point:'Точка', none:'Нет общих точек'};
|
||||||
|
const HINTS = {
|
||||||
|
circle: function(t){ const r = Math.sqrt(t.R*t.R - t.d*t.d); return '$d<R$, сечение — окружность радиуса $r=\\sqrt{'+t.R+'^2-'+t.d+'^2}='+fmt(+r.toFixed(4))+'$'+(t.d===0?' (большой круг)':'')+'.'; },
|
||||||
|
point: function(t){ return '$d=R='+t.R+'$, плоскость касается сферы — общая точка одна.'; },
|
||||||
|
none: function(t){ return '$d='+t.d+'>R='+t.R+'$, плоскость не пересекает сферу.'; }
|
||||||
|
};
|
||||||
|
const list = document.getElementById('p5-iv3-list');
|
||||||
|
const scoreEl = document.getElementById('p5-iv3-score');
|
||||||
|
const solved = new Set();
|
||||||
|
let xpGiven = false;
|
||||||
|
list.innerHTML = tasks.map(function(t, i){
|
||||||
|
return '<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:10px 12px;margin-bottom:8px">'
|
||||||
|
+ '<div style="margin-bottom:8px"><b>Задание '+(i+1)+'.</b> Сфера $R='+t.R+'$, расстояние от центра до плоскости $d='+t.d+'$. Что получится?</div>'
|
||||||
|
+ '<div style="display:flex;gap:6px;flex-wrap:wrap">'
|
||||||
|
+ '<button class="btn" data-i="'+i+'" data-v="circle">Окружность</button>'
|
||||||
|
+ '<button class="btn" data-i="'+i+'" data-v="point">Точка</button>'
|
||||||
|
+ '<button class="btn" data-i="'+i+'" data-v="none">Нет общих точек</button>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div class="feedback" id="p5-iv3-fb-'+i+'"></div>'
|
||||||
|
+ '</div>';
|
||||||
|
}).join('');
|
||||||
|
renderMath(list);
|
||||||
|
list.querySelectorAll('button[data-i]').forEach(function(b){
|
||||||
|
b.addEventListener('click', function(){
|
||||||
|
const i = +b.dataset.i, v = b.dataset.v, t = tasks[i];
|
||||||
|
const fb = document.getElementById('p5-iv3-fb-'+i);
|
||||||
|
if(solved.has(i)) return;
|
||||||
|
if(v === t.a){
|
||||||
|
feedback(fb, true, '✓ Верно — '+NAMES[t.a]+'. '+HINTS[t.a](t));
|
||||||
|
solved.add(i);
|
||||||
|
scoreEl.textContent = solved.size;
|
||||||
|
if(solved.size === tasks.length && !xpGiven){
|
||||||
|
xpGiven = true;
|
||||||
|
addXp(15, 'p5-iv3');
|
||||||
|
bumpProgress('p5', 25);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
feedback(fb, false, '✗ Не то. Сравни $d$ и $R$ внимательнее.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* IV4 — Тренажёр */
|
||||||
|
(function(){
|
||||||
|
const tasks = [
|
||||||
|
{ q:'Сфера $R=5$. Радиус сечения плоскостью на расстоянии $d=3$ от центра: $r=\\,?$', a:4, tol:0.05 },
|
||||||
|
{ q:'Сфера с центром $C(2;3;-1)$, точка $M(5;7;3)$. Расстояние $|CM|=\\,?$ (точность 0,01)', a:6.40, tol:0.05 },
|
||||||
|
{ q:'Сфера $R=13$. Сечение — окружность радиуса $12$. Найти $d$ (расстояние от центра до плоскости).', a:5, tol:0.05 },
|
||||||
|
{ q:'К сфере $R=5$ построена касательная плоскость. Расстояние от центра до плоскости: $d=\\,?$', a:5, tol:0.05 },
|
||||||
|
{ q:'Точка $A(3;4;0)$ принадлежит сфере с центром в начале координат. Найти $R$.', a:5, tol:0.05 },
|
||||||
|
{ q:'Сфера $x^2+y^2+z^2=100$. Радиус большого круга: $R=\\,?$', a:10, tol:0.05 }
|
||||||
|
];
|
||||||
|
const list = document.getElementById('p5-iv4-list');
|
||||||
|
const scoreEl = document.getElementById('p5-iv4-score');
|
||||||
|
const solved = new Set();
|
||||||
|
let xpGiven = false;
|
||||||
|
list.innerHTML = tasks.map(function(t, i){
|
||||||
|
return '<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:10px 12px;margin-bottom:8px">'
|
||||||
|
+ '<div style="margin-bottom:6px"><b>Задача '+(i+1)+'.</b> '+t.q+'</div>'
|
||||||
|
+ '<div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center">'
|
||||||
|
+ '<input type="text" class="tinp" id="p5-iv4-inp-'+i+'" placeholder="число" style="width:140px">'
|
||||||
|
+ '<button class="btn primary" data-i="'+i+'">Проверить</button>'
|
||||||
|
+ '</div>'
|
||||||
|
+ '<div class="feedback" id="p5-iv4-fb-'+i+'"></div>'
|
||||||
|
+ '</div>';
|
||||||
|
}).join('');
|
||||||
|
renderMath(list);
|
||||||
|
list.querySelectorAll('button[data-i]').forEach(function(b){
|
||||||
|
b.addEventListener('click', function(){
|
||||||
|
const i = +b.dataset.i, t = tasks[i];
|
||||||
|
const inp = document.getElementById('p5-iv4-inp-'+i);
|
||||||
|
const fb = document.getElementById('p5-iv4-fb-'+i);
|
||||||
|
const raw = (inp.value || '').replace(',', '.').trim();
|
||||||
|
const val = parseFloat(raw);
|
||||||
|
if(!isFinite(val)){ feedback(fb, false, '✗ Введи число'); return; }
|
||||||
|
if(Math.abs(val - t.a) <= t.tol){
|
||||||
|
feedback(fb, true, '✓ Верно!');
|
||||||
|
if(!solved.has(i)){
|
||||||
|
solved.add(i);
|
||||||
|
scoreEl.textContent = solved.size;
|
||||||
|
if(solved.size === tasks.length && !xpGiven){
|
||||||
|
xpGiven = true;
|
||||||
|
addXp(15, 'p5-iv4');
|
||||||
|
bumpProgress('p5', 25);
|
||||||
|
setTimeout(function(){ achievement('p5_done'); }, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
feedback(fb, false, '✗ Не точно. Пересчитай аккуратно.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
wireReadBtn('p5');
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== STUB BUILDER — единый для всех параграфов раздела (Phase 0) ===== */
|
/* ===== STUB BUILDER — единый для всех параграфов раздела (Phase 0) ===== */
|
||||||
|
|
||||||
function buildStub(id){
|
function buildStub(id){
|
||||||
@@ -706,6 +1067,10 @@ function buildStub(id){
|
|||||||
const SEARCH_INDEX = (function(){
|
const SEARCH_INDEX = (function(){
|
||||||
const arr=[];
|
const arr=[];
|
||||||
PARAS.forEach(p=>arr.push({kind:'Параграф',title:p.num+' '+p.name,desc:p.sub||'',sec:p.id}));
|
PARAS.forEach(p=>arr.push({kind:'Параграф',title:p.num+' '+p.name,desc:p.sub||'',sec:p.id}));
|
||||||
|
arr.push({kind:'Теория',title:'Сфера и шар: определение',desc:'центр, радиус, диаметр, хорда',sec:'p5'});
|
||||||
|
arr.push({kind:'Теория',title:'Уравнение сферы',desc:'(x-a)^2+(y-b)^2+(z-c)^2=R^2',sec:'p5'});
|
||||||
|
arr.push({kind:'Теория',title:'Касательная плоскость к сфере',desc:'перпендикулярна радиусу в точке касания',sec:'p5'});
|
||||||
|
arr.push({kind:'Теория',title:'Сечение сферы плоскостью',desc:'r = sqrt(R^2 - d^2), большой круг',sec:'p5'});
|
||||||
return arr;
|
return arr;
|
||||||
})();
|
})();
|
||||||
function initSearch(){
|
function initSearch(){
|
||||||
|
|||||||
Reference in New Issue
Block a user