diff --git a/frontend/textbooks/geometry_10_r4.html b/frontend/textbooks/geometry_10_r4.html index 22a2d49..59359c8 100644 --- a/frontend/textbooks/geometry_10_r4.html +++ b/frontend/textbooks/geometry_10_r4.html @@ -916,88 +916,199 @@ function runQuizInput(id, items, xpReward){ } /* ===== Stereo3D vizes ===== */ +/* === §11: ПДСК с тикaми и точкой M(2;1;3) === */ function buildCoordSystem(){ const S = window.STEREO3D; if(!S) return; - const sc = new S.Scene(400,300,{view:'CABINET',scale:50}); - sc.addArrow([0,0,0],[2.8,0,0],{color:'#dc2626',width:2.2,label:'x'}); - sc.addArrow([0,0,0],[0,2.8,0],{color:'#16a34a',width:2.2,label:'y'}); - sc.addArrow([0,0,0],[0,0,2.6],{color:'#1e3a8a',width:2.2,label:'z'}); - sc.addVertex([0,0,0],'O',{dx:-18,dy:16,color:'#0b1d33'}); - const M = [1.4,1.8,2.0]; - sc.addVertex(M,'M(2;3;4)',{dx:10,dy:-8,color:'#7c3aed',fontSize:13}); - sc.addEdge(M,[M[0],M[1],0],{stroke:'#94a3b8',width:1,dash:'3 3'}); - sc.addEdge([M[0],M[1],0],[M[0],0,0],{stroke:'#94a3b8',width:1,dash:'3 3'}); - sc.addEdge([M[0],M[1],0],[0,M[1],0],{stroke:'#94a3b8',width:1,dash:'3 3'}); + const sc = new S.Scene(460,340,{view:'CABINET',scale:48}); + /* Оси с длинными стрелками */ + sc.addArrow([0,0,0],[3.4,0,0],{color:'#dc2626',width:2.6}); + sc.addArrow([0,0,0],[0,3.4,0],{color:'#16a34a',width:2.6}); + sc.addArrow([0,0,0],[0,0,3.4],{color:'#1e3a8a',width:2.6}); + sc.addLabel('x',[3.4,0,0],{dx:14,dy:8,color:'#dc2626',fontSize:16,anchor:'start'}); + sc.addLabel('y',[0,3.4,0],{dx:14,dy:8,color:'#16a34a',fontSize:16,anchor:'start'}); + sc.addLabel('z',[0,0,3.4],{dx:-10,dy:-4,color:'#1e3a8a',fontSize:16,anchor:'end'}); + /* Тики 1, 2, 3 на каждой оси (короткие штрихи + цифры) */ + for(let i = 1; i <= 3; i++){ + sc.addEdge([i,-0.08,0],[i,0.08,0],{stroke:'#dc2626',width:1.6}); + sc.addLabel(String(i),[i,0,0],{dx:-3,dy:18,color:'#dc2626',fontSize:11,anchor:'middle'}); + sc.addEdge([-0.08,i,0],[0.08,i,0],{stroke:'#16a34a',width:1.6}); + sc.addLabel(String(i),[0,i,0],{dx:8,dy:16,color:'#16a34a',fontSize:11,anchor:'start'}); + sc.addEdge([-0.1,0,i],[0.1,0,i],{stroke:'#1e3a8a',width:1.6}); + sc.addLabel(String(i),[0,0,i],{dx:-12,dy:4,color:'#1e3a8a',fontSize:11,anchor:'end'}); + } + sc.addVertex([0,0,0],'O',{dx:-20,dy:18,color:'#0b1d33',fontSize:14}); + /* Точка M(2;1;3) — числа совпадают с реальными координатами */ + const M = [2,1,3]; + /* Пунктиры из M к плоскости Oxy (вертикально вниз), затем к осям */ + sc.addEdge(M,[2,1,0],{stroke:'#a78bfa',width:1.4,dash:'4 3'}); + sc.addEdge([2,1,0],[2,0,0],{stroke:'#a78bfa',width:1.4,dash:'4 3'}); + sc.addEdge([2,1,0],[0,1,0],{stroke:'#a78bfa',width:1.4,dash:'4 3'}); + sc.addEdge(M,[0,0,3],{stroke:'#a78bfa',width:1.4,dash:'4 3'}); + /* Маленькие маркеры на проекциях */ + sc.addVertex([2,1,0],'',{r:2.5,fill:'#a78bfa'}); + /* Точка M жирная */ + sc.addVertex(M,'M (2; 1; 3)',{dx:12,dy:-8,color:'#7c3aed',fontSize:15,r:5,fill:'#7c3aed'}); const el = document.getElementById('viz11-coords'); if(el) el.innerHTML = sc.render(); } +/* === §11: Расстояние между точками (3D-Пифагор) === */ function buildDistanceFormula(){ const S = window.STEREO3D; if(!S) return; - const sc = new S.Scene(400,280,{view:'CABINET',scale:50}); - sc.addArrow([0,0,0],[2.4,0,0],{color:'#94a3b8',width:1.4}); - sc.addArrow([0,0,0],[0,2.0,0],{color:'#94a3b8',width:1.4}); - sc.addArrow([0,0,0],[0,0,1.6],{color:'#94a3b8',width:1.4}); - const B = [1.8,1.4,1.2]; - sc.addEdge([0,0,0],[1.8,0,0],{stroke:'#dc2626',width:2}); - sc.addEdge([1.8,0,0],[1.8,1.4,0],{stroke:'#16a34a',width:2}); - sc.addEdge([1.8,1.4,0],B,{stroke:'#1e3a8a',width:2}); - sc.addEdge([0,0,0],B,{stroke:'#7c3aed',width:3}); - sc.addVertex([0,0,0],'A',{dx:-14,dy:14,color:'#0b1d33'}); - sc.addVertex(B,'B',{dx:10,dy:-4,color:'#7c3aed'}); + const sc = new S.Scene(460,320,{view:'CABINET',scale:50}); + /* Серые оси для контекста */ + sc.addArrow([0,0,0],[3.0,0,0],{color:'#cbd5e1',width:1.4}); + sc.addArrow([0,0,0],[0,3.0,0],{color:'#cbd5e1',width:1.4}); + sc.addArrow([0,0,0],[0,0,2.6],{color:'#cbd5e1',width:1.4}); + sc.addLabel('x',[3.0,0,0],{dx:10,dy:8,color:'#94a3b8',fontSize:12,anchor:'start'}); + sc.addLabel('y',[0,3.0,0],{dx:10,dy:8,color:'#94a3b8',fontSize:12,anchor:'start'}); + sc.addLabel('z',[0,0,2.6],{dx:-8,dy:-2,color:'#94a3b8',fontSize:12,anchor:'end'}); + /* A(0;0;0), B(2;2;2) */ + const A = [0,0,0]; + const B = [2,2,2]; + /* Параллелепипед-подсказка: рёбра вдоль осей с цветовой кодировкой */ + sc.addEdge(A,[2,0,0],{stroke:'#dc2626',width:2.8}); + sc.addEdge([2,0,0],[2,2,0],{stroke:'#16a34a',width:2.8}); + sc.addEdge([2,2,0],B,{stroke:'#1e3a8a',width:2.8}); + /* Бледные грани куба-подсказки */ + sc.addEdge(A,[0,2,0],{stroke:'#94a3b8',width:1,dash:'3 3'}); + sc.addEdge([0,2,0],[2,2,0],{stroke:'#94a3b8',width:1,dash:'3 3'}); + sc.addEdge(A,[0,0,2],{stroke:'#94a3b8',width:1,dash:'3 3'}); + sc.addEdge([0,0,2],B,{stroke:'#94a3b8',width:1,dash:'3 3'}); + sc.addEdge([2,0,0],[2,0,2],{stroke:'#94a3b8',width:1,dash:'3 3'}); + sc.addEdge([2,0,2],B,{stroke:'#94a3b8',width:1,dash:'3 3'}); + /* Главная диагональ */ + sc.addEdge(A,B,{stroke:'#7c3aed',width:4}); + /* Вершины */ + sc.addVertex(A,'A',{dx:-18,dy:16,color:'#0b1d33',fontSize:15,r:5,fill:'#0b1d33'}); + sc.addVertex(B,'B',{dx:12,dy:-4,color:'#7c3aed',fontSize:15,r:5,fill:'#7c3aed'}); + /* Подписи Δx, Δy, Δz на цветных рёбрах */ + sc.addLabel('Δx=2',[1,0,0],{dx:0,dy:18,color:'#dc2626',fontSize:13,anchor:'middle'}); + sc.addLabel('Δy=2',[2,1,0],{dx:14,dy:6,color:'#16a34a',fontSize:13,anchor:'start'}); + sc.addLabel('Δz=2',[2,2,1],{dx:14,dy:0,color:'#1e3a8a',fontSize:13,anchor:'start'}); + /* Маркер прямого угла в B (показывая 3D-Пифагор) */ + sc.addRightAngleMark([2,2,0],[1.6,2,0],[2,2,0.4],{color:'#d97706',width:1.6,size:0.20}); const el = document.getElementById('viz11-dist'); if(el) el.innerHTML = sc.render(); } +/* === §12: Сложение векторов — параллелограмм + треугольник === */ function buildVectorAdd(){ const S = window.STEREO3D; if(!S) return; - const sc = new S.Scene(400,240,{view:'CABINET',scale:50}); - const O = [0,0,0]; const A = [1.8,0.3,0]; const B = [0.6,1.4,0]; const C = [A[0]+B[0],A[1]+B[1],A[2]+B[2]]; - sc.addEdge(O,A,{stroke:'#1e3a8a',width:1.2,dash:'4 3'}); - sc.addEdge(O,B,{stroke:'#94a3b8',width:1.2,dash:'4 3'}); - sc.addEdge(A,C,{stroke:'#94a3b8',width:1.2,dash:'4 3'}); - sc.addEdge(B,C,{stroke:'#1e3a8a',width:1.2,dash:'4 3'}); - sc.addArrow(O,A,{color:'#dc2626',width:2.6,label:'a',lx:0,ly:18}); - sc.addArrow(A,C,{color:'#16a34a',width:2.6,label:'b',lx:14,ly:-4}); - sc.addArrow(O,C,{color:'#7c3aed',width:2.8,label:'a+b',lx:-30,ly:0}); - sc.addVertex(O,'O',{dx:-14,dy:14,color:'#0b1d33'}); + const sc = new S.Scene(460,260,{view:'CABINET',scale:60}); + const O = [0,0,0]; + const A = [1.8,0.2,0]; /* конец a */ + const B = [0.5,1.5,0]; /* конец b (из O) */ + const C = [A[0]+B[0],A[1]+B[1],A[2]+B[2]]; /* конец a+b */ + /* Параллелограмм-подсказка: вторая копия b из O и a' из B */ + sc.addArrow(O,B,{color:'#16a34a',width:2,label:'',lx:0,ly:0}); + sc.addEdge(B,C,{stroke:'#94a3b8',width:1.4,dash:'4 3'}); + /* Треугольник: a из O, b' из конца a */ + sc.addArrow(O,A,{color:'#dc2626',width:3.2,label:'a',lx:-4,ly:20}); + sc.addArrow(A,C,{color:'#16a34a',width:3.2,label:'b',lx:14,ly:0}); + /* Сумма a+b — фиолетовая, толстая, диагональ */ + sc.addArrow(O,C,{color:'#7c3aed',width:4,label:'a + b',lx:-44,ly:8}); + sc.addVertex(O,'O',{dx:-18,dy:18,color:'#0b1d33',fontSize:14,r:4,fill:'#0b1d33'}); + /* Подпись правила */ + sc.addLabel('правило треугольника',[1.5,0.85,0],{dx:0,dy:30,color:'#475569',fontSize:11,anchor:'middle'}); const el = document.getElementById('viz12-add'); if(el) el.innerHTML = sc.render(); } +/* === §12: Базис i,j,k и разложение вектора === */ function buildVectorBasis(){ const S = window.STEREO3D; if(!S) return; - const sc = new S.Scene(400,280,{view:'CABINET',scale:55}); - sc.addArrow([0,0,0],[2.4,0,0],{color:'#94a3b8',width:1.2}); - sc.addArrow([0,0,0],[0,2.4,0],{color:'#94a3b8',width:1.2}); - sc.addArrow([0,0,0],[0,0,2.2],{color:'#94a3b8',width:1.2}); - sc.addArrow([0,0,0],[1,0,0],{color:'#dc2626',width:2.8,label:'i',lx:-2,ly:18}); - sc.addArrow([0,0,0],[0,1,0],{color:'#16a34a',width:2.8,label:'j',lx:14,ly:8}); - sc.addArrow([0,0,0],[0,0,1],{color:'#1e3a8a',width:2.8,label:'k',lx:-14,ly:-2}); - const a = [1.8,1.2,1.4]; - sc.addArrow([0,0,0],a,{color:'#7c3aed',width:3,label:'a',lx:8,ly:-4}); - sc.addEdge(a,[a[0],a[1],0],{stroke:'#94a3b8',width:1,dash:'3 3'}); + const sc = new S.Scene(460,320,{view:'CABINET',scale:60}); + /* Бледные оси */ + sc.addArrow([0,0,0],[2.8,0,0],{color:'#cbd5e1',width:1.2}); + sc.addArrow([0,0,0],[0,2.8,0],{color:'#cbd5e1',width:1.2}); + sc.addArrow([0,0,0],[0,0,2.8],{color:'#cbd5e1',width:1.2}); + sc.addLabel('x',[2.8,0,0],{dx:10,dy:8,color:'#94a3b8',fontSize:12,anchor:'start'}); + sc.addLabel('y',[0,2.8,0],{dx:10,dy:8,color:'#94a3b8',fontSize:12,anchor:'start'}); + sc.addLabel('z',[0,0,2.8],{dx:-8,dy:-2,color:'#94a3b8',fontSize:12,anchor:'end'}); + /* Базисные единичные векторы — яркие */ + sc.addArrow([0,0,0],[1,0,0],{color:'#dc2626',width:3.4,label:'i',lx:-4,ly:22}); + sc.addArrow([0,0,0],[0,1,0],{color:'#16a34a',width:3.4,label:'j',lx:18,ly:10}); + sc.addArrow([0,0,0],[0,0,1],{color:'#1e3a8a',width:3.4,label:'k',lx:-14,ly:-2}); + /* Произвольный вектор a = 2i + 1.5j + 1.5k */ + const a = [2,1.5,1.5]; + /* Покажем разложение через ступенчатую ломаную (2i, потом 1.5j, потом 1.5k) */ + sc.addArrow([0,0,0],[2,0,0],{color:'#fda4af',width:2.2,dash:'5 3'}); /* 2i */ + sc.addArrow([2,0,0],[2,1.5,0],{color:'#86efac',width:2.2,dash:'5 3'}); /* +1.5j */ + sc.addArrow([2,1.5,0],a,{color:'#bfdbfe',width:2.2,dash:'5 3'}); /* +1.5k */ + /* Итоговый вектор a — толстый фиолетовый */ + sc.addArrow([0,0,0],a,{color:'#7c3aed',width:3.6,label:'a = 2i + 1.5j + 1.5k',lx:14,ly:-8}); + /* Метки координат */ + sc.addLabel('2',[1,0,0],{dx:0,dy:18,color:'#dc2626',fontSize:11,anchor:'middle'}); + sc.addLabel('1.5',[2,0.75,0],{dx:14,dy:8,color:'#16a34a',fontSize:11,anchor:'start'}); + sc.addLabel('1.5',[2,1.5,0.75],{dx:14,dy:0,color:'#1e3a8a',fontSize:11,anchor:'start'}); const el = document.getElementById('viz12-basis'); if(el) el.innerHTML = sc.render(); } +/* === §13: Скалярное произведение + проекция b на a === */ function buildDotProduct(){ const S = window.STEREO3D; if(!S) return; - const sc = new S.Scene(400,240,{view:'CABINET',scale:55}); - const O = [0,0,0]; const a = [1.8,0.5,0]; const b = [1.2,1.5,0.4]; - sc.addArrow(O,a,{color:'#dc2626',width:3,label:'a',lx:4,ly:18}); - sc.addArrow(O,b,{color:'#1e3a8a',width:3,label:'b',lx:-22,ly:-2}); - sc.addAngleMark(O,a,b,{r:0.5,color:'#d97706',width:1.8,label:'φ'}); - sc.addVertex(O,'O',{dx:-14,dy:14,color:'#0b1d33'}); + const sc = new S.Scene(460,280,{view:'CABINET',scale:65}); + const O = [0,0,0]; + /* В плоскости z=0 для наглядности */ + const a = [2.4,0.3,0]; + const b = [1.3,1.7,0]; + /* Векторы */ + sc.addArrow(O,a,{color:'#dc2626',width:3.4,label:'a',lx:-4,ly:22}); + sc.addArrow(O,b,{color:'#1e3a8a',width:3.4,label:'b',lx:-22,ly:-2}); + /* Проекция b на a: проекция конца b на прямую a */ + const aLen2 = a[0]*a[0]+a[1]*a[1]+a[2]*a[2]; + const dot = a[0]*b[0]+a[1]*b[1]+a[2]*b[2]; + const t = dot/aLen2; + const proj = [a[0]*t,a[1]*t,a[2]*t]; + /* Линия проекции (b -> proj) */ + sc.addEdge(b,proj,{stroke:'#94a3b8',width:1.4,dash:'3 3'}); + /* Жирный отрезок |b|cos φ вдоль a */ + sc.addEdge(O,proj,{stroke:'#d97706',width:4}); + /* Маркер прямого угла на проекции (между линией проекции и направлением a) */ + const aDir = [a[0]-proj[0]||-a[0], a[1]-proj[1]||-a[1], 0]; + const perpDir = [b[0]-proj[0], b[1]-proj[1], 0]; + sc.addRightAngleMark(proj,[proj[0]-0.18,proj[1]+0,0],[proj[0]+perpDir[0]*0.12,proj[1]+perpDir[1]*0.12,0],{color:'#7c3aed',width:1.4,size:0.16}); + /* Метка проекции */ + sc.addLabel('|b|·cos φ',[proj[0]/2,proj[1]/2,0],{dx:0,dy:22,color:'#d97706',fontSize:12,anchor:'middle'}); + /* Угол φ */ + sc.addAngleMark(O,a,b,{r:0.5,color:'#f59e0b',width:1.8,label:'φ'}); + sc.addVertex(O,'O',{dx:-16,dy:18,color:'#0b1d33',fontSize:13,r:4,fill:'#0b1d33'}); const el = document.getElementById('viz13-dot'); if(el) el.innerHTML = sc.render(); } +/* === §14: Куб ABCDA1B1C1D1 в ПДСК с координатами всех 8 вершин + диагональ === */ function buildCubeInCoords(){ const S = window.STEREO3D; if(!S) return; - const sc = new S.Scene(420,320,{view:'CABINET',scale:70,center:[100,220]}); - sc.addArrow([0,0,0],[1.6,0,0],{color:'#94a3b8',width:1.3}); - sc.addArrow([0,0,0],[0,1.6,0],{color:'#94a3b8',width:1.3}); - sc.addArrow([0,0,0],[0,0,1.6],{color:'#94a3b8',width:1.3}); - sc.addLabel('x',[1.6,0,0],{dx:8,dy:8,color:'#475569',fontSize:12,anchor:'start'}); - sc.addLabel('y',[0,1.6,0],{dx:10,dy:8,color:'#475569',fontSize:12,anchor:'start'}); - sc.addLabel('z',[0,0,1.6],{dx:-6,dy:-2,color:'#475569',fontSize:12,anchor:'end'}); - sc.addBox({center:[0.5,0.5,0.5],size:[1,1,1],labels:true,color:'#fef3c7',opacity:0.25}); + const sc = new S.Scene(500,360,{view:'CABINET',scale:75,center:[120,250]}); + /* Оси с подписями */ + sc.addArrow([0,0,0],[1.7,0,0],{color:'#dc2626',width:1.8}); + sc.addArrow([0,0,0],[0,1.7,0],{color:'#16a34a',width:1.8}); + sc.addArrow([0,0,0],[0,0,1.7],{color:'#1e3a8a',width:1.8}); + sc.addLabel('x',[1.7,0,0],{dx:10,dy:10,color:'#dc2626',fontSize:13,anchor:'start'}); + sc.addLabel('y',[0,1.7,0],{dx:12,dy:8,color:'#16a34a',fontSize:13,anchor:'start'}); + sc.addLabel('z',[0,0,1.7],{dx:-8,dy:-2,color:'#1e3a8a',fontSize:13,anchor:'end'}); + /* Тик "1" на каждой оси */ + sc.addEdge([1,-0.06,0],[1,0.06,0],{stroke:'#dc2626',width:1.4}); + sc.addLabel('1',[1,0,0],{dx:-3,dy:18,color:'#dc2626',fontSize:11,anchor:'middle'}); + sc.addEdge([-0.06,1,0],[0.06,1,0],{stroke:'#16a34a',width:1.4}); + sc.addLabel('1',[0,1,0],{dx:8,dy:14,color:'#16a34a',fontSize:11,anchor:'start'}); + sc.addEdge([-0.08,0,1],[0.08,0,1],{stroke:'#1e3a8a',width:1.4}); + sc.addLabel('1',[0,0,1],{dx:-10,dy:4,color:'#1e3a8a',fontSize:11,anchor:'end'}); + /* Куб с ребром 1 */ + sc.addBox({center:[0.5,0.5,0.5],size:[1,1,1],labels:true,color:'#fef3c7',opacity:0.30}); + /* Главная диагональ AC1 — выделить */ + sc.addEdge([0,0,0],[1,1,1],{stroke:'#7c3aed',width:3.4,dash:'6 3'}); + sc.addLabel('|AC₁| = √3',[0.5,0.5,0.5],{dx:18,dy:-2,color:'#7c3aed',fontSize:13,anchor:'start'}); + /* Координаты всех 8 вершин рядом с буквами */ + const vc = [ + [[0,0,0],'(0;0;0)',-30,28], + [[1,0,0],'(1;0;0)',-2,28], + [[1,1,0],'(1;1;0)',12,18], + [[0,1,0],'(0;1;0)',-32,18], + [[0,0,1],'(0;0;1)',-44,2], + [[1,0,1],'(1;0;1)',-2,-2], + [[1,1,1],'(1;1;1)',14,-12], + [[0,1,1],'(0;1;1)',-44,-12] + ]; + vc.forEach(v=>{ sc.addLabel(v[1],v[0],{dx:v[2],dy:v[3],color:'#78350f',fontSize:9,anchor:'start'}); }); const el = document.getElementById('viz14-cube'); if(el) el.innerHTML = sc.render(); }