fix(geom7 ch5): переделаны рисунки §27 и §31 + KaTeX-ошибки
- KaTeX:
• PARAS p29/p30: убрана математика из psel-карточек
($M$ → M, $\perp$ → ⊥), т.к. psel не рендерил KaTeX.
• Boss "\§29-30" title: $\perp$ → ⊥ (boss-title не рендерился).
• Защитно добавлен renderMath(g) после buildParaSelector
и renderMath(cont) после вставки boss-карточек.
- §27 SVG: чистая 2-панельная схема с разделителем.
Слева: ЛИНЕЙКА (корпус с штрихами без цифр) → ↓ →
пример (точки A, B + прямая).
Справа: ЦИРКУЛЬ (шарнир + игла + грифель) → ↓ →
пример (окружность с центром O и радиусом r).
- §31 SVG: пересчитанные координаты, чёткие плашки-подписи
ГМТ 1 (биссектриса, красная) и ГМТ 2 (окружность, синяя).
Точки K₁, K₂ — крупные зелёные с белой обводкой.
Дуги показывают, что биссектриса делит угол ровно пополам.
This commit is contained in:
@@ -317,8 +317,8 @@ function achievement(id,text){
|
||||
const PARAS = [
|
||||
{ id:'p27', num:'§ 27', name:'Простейшие построения', sub:'циркуль + линейка' },
|
||||
{ id:'p28', num:'§ 28', name:'Треугольник по 3 сторонам', sub:'отрезок + 2 окружн.' },
|
||||
{ id:'p29', num:'§ 29', name:'Биссектриса угла', sub:'3 дуги + точка $M$' },
|
||||
{ id:'p30', num:'§ 30', name:'Середина и $\\perp$', sub:'2 окружн. → 2 точки' },
|
||||
{ id:'p29', num:'§ 29', name:'Биссектриса угла', sub:'3 дуги + точка M' },
|
||||
{ id:'p30', num:'§ 30', name:'Середина и ⊥', sub:'2 окружн. → 2 точки' },
|
||||
{ id:'p31', num:'§ 31', name:'Метод ГМТ', sub:'2 ГМТ → пересечение' },
|
||||
{ id:'final5', num:'★', name:'Финал главы', sub:'Итоги \xB7 5 боссов', final:true },
|
||||
];
|
||||
@@ -333,6 +333,7 @@ function buildParaSelector(){
|
||||
card.addEventListener('click', ()=>goTo(p.id));
|
||||
g.appendChild(card);
|
||||
});
|
||||
if(window.renderMathInElement) try{ renderMath(g); }catch(e){}
|
||||
}
|
||||
|
||||
const BUILT=new Set();
|
||||
@@ -540,23 +541,47 @@ function buildP27(){
|
||||
|
||||
let svgTools='';
|
||||
if(G){
|
||||
const b=G.svgBox(320,160,{id:'p27-tools',cell:20});
|
||||
svgTools = b.open
|
||||
/* Линейка слева */
|
||||
+ '<rect x="20" y="40" width="120" height="22" fill="#fbcfe8" stroke="#be185d" stroke-width="1.5" rx="3"/>'
|
||||
+ '<text x="80" y="56" text-anchor="middle" font-size="11" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#be185d">ЛИНЕЙКА</text>'
|
||||
+ '<text x="80" y="82" text-anchor="middle" font-size="9" fill="#7c2d52">↑ прямая через 2 точки</text>'
|
||||
+ G.point(30,120,'',{r:3,color:'#1e293b'})
|
||||
+ G.point(130,128,'',{r:3,color:'#1e293b'})
|
||||
+ G.segment({x:30,y:120},{x:130,y:128},{color:'#0891b2',width:2})
|
||||
/* Циркуль справа: схематично */
|
||||
+ '<line x1="220" y1="30" x2="250" y2="80" stroke="#be185d" stroke-width="2.5"/>'
|
||||
+ '<line x1="280" y1="30" x2="250" y2="80" stroke="#be185d" stroke-width="2.5"/>'
|
||||
+ '<circle cx="250" cy="80" r="3" fill="#be185d"/>'
|
||||
+ '<text x="250" y="22" text-anchor="middle" font-size="11" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#be185d">ЦИРКУЛЬ</text>'
|
||||
+ G.circle({x:250,y:108},32,{color:'#0891b2',width:1.5,dash:'3 2'})
|
||||
+ '<text x="250" y="155" text-anchor="middle" font-size="9" fill="#7c2d52">↑ окружность</text>'
|
||||
/* Две панели: ЛИНЕЙКА слева, ЦИРКУЛЬ справа.
|
||||
В каждой панели: инструмент сверху → стрелка ↓ → результат снизу. */
|
||||
const b=G.svgBox(340,210,{id:'p27-tools',cell:0,grid:false,bg:'#fff'});
|
||||
/* Вертикальный разделитель */
|
||||
let s=b.open
|
||||
+ '<line x1="170" y1="15" x2="170" y2="195" stroke="#e2e8f0" stroke-width="1" stroke-dasharray="3 4"/>'
|
||||
/* ===== ЛЕВАЯ ПАНЕЛЬ — ЛИНЕЙКА ===== */
|
||||
+ '<text x="85" y="25" text-anchor="middle" font-size="11" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#be185d">ЛИНЕЙКА</text>'
|
||||
/* Корпус линейки */
|
||||
+ '<rect x="22" y="33" width="126" height="20" fill="#fbcfe8" stroke="#be185d" stroke-width="1.8" rx="2"/>';
|
||||
/* Маленькие штрихи на верхнем крае линейки (без чисел) */
|
||||
for(let i=0;i<=9;i++){ const x=22+i*14; s+='<line x1="'+x+'" y1="33" x2="'+x+'" y2="'+(33+(i%2===0?7:4))+'" stroke="#be185d" stroke-width="1"/>'; }
|
||||
s += '<text x="85" y="70" text-anchor="middle" font-size="8" fill="#7c2d52">(без делений)</text>'
|
||||
/* Стрелка ↓ */
|
||||
+ '<path d="M 85 80 L 85 100 M 80 95 L 85 100 L 90 95" fill="none" stroke="#10b981" stroke-width="2.2" stroke-linecap="round"/>'
|
||||
/* Результат: 2 точки и прямая через них */
|
||||
+ '<line x1="30" y1="148" x2="140" y2="158" stroke="#0891b2" stroke-width="2.2" stroke-linecap="round"/>'
|
||||
+ G.point(30,148,'A',{color:'#1e293b',dx:-12,dy:-2,fontSize:11,r:3.5})
|
||||
+ G.point(140,158,'B',{color:'#1e293b',dx:6,dy:-2,fontSize:11,r:3.5})
|
||||
+ '<text x="85" y="188" text-anchor="middle" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#0891b2">прямая через 2 точки</text>'
|
||||
/* ===== ПРАВАЯ ПАНЕЛЬ — ЦИРКУЛЬ ===== */
|
||||
+ '<text x="255" y="25" text-anchor="middle" font-size="11" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#be185d">ЦИРКУЛЬ</text>'
|
||||
/* Две ноги от шарнира вниз */
|
||||
+ '<line x1="255" y1="33" x2="228" y2="78" stroke="#be185d" stroke-width="3" stroke-linecap="round"/>'
|
||||
+ '<line x1="255" y1="33" x2="282" y2="78" stroke="#be185d" stroke-width="3" stroke-linecap="round"/>'
|
||||
/* Шарнир */
|
||||
+ '<circle cx="255" cy="33" r="3.5" fill="#fbcfe8" stroke="#be185d" stroke-width="1.5"/>'
|
||||
/* Игла (треугольник) на левой ноге */
|
||||
+ '<polygon points="228,78 224,85 232,85" fill="#dc2626"/>'
|
||||
/* Грифель на правой ноге */
|
||||
+ '<polygon points="282,78 278,85 286,85" fill="#0f172a"/>'
|
||||
/* Стрелка ↓ */
|
||||
+ '<path d="M 255 92 L 255 110 M 250 105 L 255 110 L 260 105" fill="none" stroke="#10b981" stroke-width="2.2" stroke-linecap="round"/>'
|
||||
/* Результат: окружность с центром O и пунктирным радиусом */
|
||||
+ '<circle cx="255" cy="148" r="26" fill="none" stroke="#7c3aed" stroke-width="2"/>'
|
||||
+ '<line x1="255" y1="148" x2="273" y2="129" stroke="#7c3aed" stroke-width="1.3" stroke-dasharray="3 2"/>'
|
||||
+ '<text x="265" y="138" font-size="9" fill="#6d28d9" font-weight="700">r</text>'
|
||||
+ G.point(255,148,'O',{color:'#1e293b',dx:-10,dy:-2,fontSize:11,r:3})
|
||||
+ '<text x="255" y="188" text-anchor="middle" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#7c3aed">окружность (O, r)</text>'
|
||||
+ b.close;
|
||||
svgTools = s;
|
||||
}
|
||||
|
||||
html += makeCard('theory', 'Что такое задача на построение?', '27.1', `
|
||||
@@ -1044,34 +1069,51 @@ function buildP31(){
|
||||
|
||||
let svgGMT='';
|
||||
if(G){
|
||||
const b=G.svgBox(300,200,{id:'p31-gmt',cell:20});
|
||||
const O={x:50,y:120};
|
||||
const ang=25*Math.PI/180;
|
||||
const len=240;
|
||||
/* Чистый рисунок: угол ∠AOB слева, биссектриса (ГМТ 1, красная)
|
||||
и окружность (ГМТ 2, синяя) пересекаются в двух точках K₁, K₂. */
|
||||
const b=G.svgBox(320,230,{id:'p31-gmt',cell:20});
|
||||
const O={x:50,y:135};
|
||||
const ang=20*Math.PI/180; /* половина раствора угла */
|
||||
const len=220;
|
||||
const Aend={x:O.x+len*Math.cos(-ang), y:O.y+len*Math.sin(-ang)};
|
||||
const Bend={x:O.x+len*Math.cos(ang), y:O.y+len*Math.sin(ang)};
|
||||
/* Биссектриса — ось x от O */
|
||||
/* Окружность с центром (170,80) радиуса 50.
|
||||
Пересечение биссектрисы (y=120) с этой окружностью:
|
||||
(x-170)² + (120-80)² = 2500 → (x-170)² = 900 → x = 140 или 200 */
|
||||
const Cc={x:170,y:80}, R=50;
|
||||
const K1={x:140,y:120}, K2={x:200,y:120};
|
||||
/* Окружность (ГМТ 2): центр Cc, радиус R.
|
||||
Биссектриса — горизонталь y=O.y от O.
|
||||
Пересечение: (x-Cc.x)² + (O.y-Cc.y)² = R² → x = Cc.x ± √(R² - dy²) */
|
||||
const Cc={x:180,y:90}, R=55;
|
||||
const dy = O.y - Cc.y;
|
||||
const dx = Math.sqrt(R*R - dy*dy);
|
||||
const K1={x:Cc.x-dx, y:O.y}, K2={x:Cc.x+dx, y:O.y};
|
||||
/* Конец биссектрисы — заходит чуть за K2 */
|
||||
const Bs={x:O.x+len,y:O.y};
|
||||
svgGMT = b.open
|
||||
/* Стороны угла */
|
||||
+ G.segment(O,Aend,{color:'#7c3aed',width:2.5})
|
||||
+ G.segment(O,Bend,{color:'#7c3aed',width:2.5})
|
||||
/* ГМТ 1: биссектриса */
|
||||
+ G.segment(O,{x:O.x+len,y:O.y},{color:'#dc2626',width:2,dash:'6 3'})
|
||||
/* ГМТ 2: окружность */
|
||||
+ G.circle(Cc,R,{color:'#0891b2',width:1.8,dash:'4 3'})
|
||||
/* Точки пересечения */
|
||||
+ G.point(K1.x,K1.y,'K₁',{color:'#059669',dx:-14,dy:-8,fontSize:12,r:4})
|
||||
+ G.point(K2.x,K2.y,'K₂',{color:'#059669',dx:6,dy:-8,fontSize:12,r:4})
|
||||
+ G.point(O.x,O.y,'O',{color:'#1e293b',dx:-14,dy:5,fontSize:12})
|
||||
+ G.point(Cc.x,Cc.y,'C',{color:'#0891b2',dx:6,dy:-6,fontSize:12,r:3})
|
||||
+ '<text x="'+(O.x+90)+'" y="'+(O.y-6)+'" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#dc2626">ГМТ 1: бис.</text>'
|
||||
+ '<text x="'+(Cc.x-30)+'" y="'+(Cc.y-R-6)+'" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#0891b2">ГМТ 2: окружн.</text>'
|
||||
+ '<text x="170" y="190" text-anchor="middle" font-size="11" font-weight="700" fill="#059669">K₁, K₂ = ГМТ 1 ∩ ГМТ 2</text>'
|
||||
+ G.point(O.x,O.y,'O',{color:'#1e293b',dx:-14,dy:5,fontSize:13})
|
||||
+ '<text x="'+(Aend.x+3)+'" y="'+(Aend.y-1)+'" font-size="12" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#7c3aed">A</text>'
|
||||
+ '<text x="'+(Bend.x+3)+'" y="'+(Bend.y+12)+'" font-size="12" font-family="Unbounded,Inter,sans-serif" font-weight="700" fill="#7c3aed">B</text>'
|
||||
/* Маленькие дуги показывают, что биссектриса делит угол пополам */
|
||||
+ G.arc(O,18,-ang,0,{color:'#dc2626',width:1.4})
|
||||
+ G.arc(O,18,0,ang,{color:'#dc2626',width:1.4})
|
||||
/* ГМТ 1 — биссектриса (красная пунктирная) */
|
||||
+ G.segment(O,Bs,{color:'#dc2626',width:2.2,dash:'7 4'})
|
||||
/* ГМТ 2 — окружность (синяя пунктирная) */
|
||||
+ G.circle(Cc,R,{color:'#0891b2',width:2,dash:'5 3'})
|
||||
+ G.point(Cc.x,Cc.y,'C',{color:'#0891b2',dx:6,dy:-6,fontSize:11,r:3})
|
||||
/* Точки пересечения K₁, K₂ — крупные зелёные с обводкой */
|
||||
+ '<circle cx="'+K1.x+'" cy="'+K1.y+'" r="5.5" fill="#10b981" stroke="#fff" stroke-width="2"/>'
|
||||
+ '<circle cx="'+K2.x+'" cy="'+K2.y+'" r="5.5" fill="#10b981" stroke="#fff" stroke-width="2"/>'
|
||||
+ '<text x="'+(K1.x-5)+'" y="'+(K1.y+25)+'" text-anchor="middle" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#047857">K₁</text>'
|
||||
+ '<text x="'+(K2.x+5)+'" y="'+(K2.y+25)+'" text-anchor="middle" font-size="13" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#047857">K₂</text>'
|
||||
/* Подпись ГМТ 1 (плашка справа от биссектрисы, за K₂) */
|
||||
+ '<rect x="'+(Bs.x-65)+'" y="'+(Bs.y-11)+'" width="62" height="20" rx="4" fill="#fee2e2" stroke="#dc2626" stroke-width="1"/>'
|
||||
+ '<text x="'+(Bs.x-34)+'" y="'+(Bs.y+3)+'" text-anchor="middle" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#dc2626">ГМТ 1: бис.</text>'
|
||||
/* Подпись ГМТ 2 (плашка сверху над окружностью) */
|
||||
+ '<rect x="'+(Cc.x-45)+'" y="'+(Cc.y-R-22)+'" width="90" height="20" rx="4" fill="#cffafe" stroke="#0891b2" stroke-width="1"/>'
|
||||
+ '<text x="'+Cc.x+'" y="'+(Cc.y-R-8)+'" text-anchor="middle" font-size="10" font-family="Unbounded,Inter,sans-serif" font-weight="800" fill="#0891b2">ГМТ 2: окружн.</text>'
|
||||
/* Итог снизу */
|
||||
+ '<text x="160" y="218" text-anchor="middle" font-size="11" font-weight="800" fill="#047857">K₁, K₂ = ГМТ 1 ∩ ГМТ 2</text>'
|
||||
+ b.close;
|
||||
}
|
||||
|
||||
@@ -1203,7 +1245,7 @@ const BOSSES = [
|
||||
]
|
||||
},
|
||||
{
|
||||
n:3, title:'Босс \xA729-30 — Биссектриса, середина, $\\perp$', color:'#7c3aed',
|
||||
n:3, title:'Босс \xA729-30 — Биссектриса, середина, ⊥', color:'#7c3aed',
|
||||
steps:[
|
||||
{ q:'По какому признаку доказываем равенство $\\triangle OXM = \\triangle OYM$ в построении бис.? «ССС», «СУС», «УСУ»', verify:(v)=>String(v).trim().toUpperCase().startsWith('ССС'), hint:'ССС — три стороны.' },
|
||||
{ q:'Сколько окружностей в построении серединного $\\perp$?', verify:(v)=>+v===2, hint:'Из $A$ и $B$.' },
|
||||
@@ -1288,6 +1330,7 @@ function buildFinal5(){
|
||||
+'<div class="feedback" id="boss-'+idx+'-fb"></div>'
|
||||
+'</div>';
|
||||
}).join('');
|
||||
if(window.renderMathInElement) try{ renderMath(cont); }catch(e){}
|
||||
|
||||
BOSSES.forEach((b,idx)=>{
|
||||
function show(){
|
||||
|
||||
Reference in New Issue
Block a user