fix(geom7 ch1): §6 — метки углов не накладываются на O; §5 — заливка секторов

§6 (вертикальные углы):
- SVG расширен 260×180 → 320×230
- Добавлены 4 полупрозрачных сектора как фон (красный для ∠1/∠2,
  оранжевый для ∠3/∠4) — сразу видно, какие углы вертикальны
- Метки ∠1, ∠2, ∠3, ∠4 теперь явные (со знаком "∠")
- Подпись O вынесена в (-26,-22) от вершины + пунктирная линия-указатель
  к самой точке — чтобы метка не перекрывала ∠1
- Чётко разнесены: ∠1, ∠2 (red, r=20) — на горизонтали;
  ∠3, ∠4 (orange, r=32) — на вертикали

§5 (виды углов):
- SVG расширен 140×120 → 180×150 (больше деталей)
- Каждый угол теперь имеет полупрозрачную заливку-сектор
  (цветом, соответствующим типу угла)
- Подпись типа угла увеличена до 12px, чётко читается
- Развёрнутый угол: полукруг закрашен, подпись 180° явная

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-29 08:11:01 +03:00
parent cccbb64159
commit 724c8a5817
+64 -20
View File
@@ -974,18 +974,39 @@ function buildP5(){
/* SVG: 4 угла — острый, прямой, тупой, развёрнутый */
function angleViz(deg, color, label){
if(!G) return '';
const b=G.svgBox(140,120,{id:'p5-a-'+deg,cell:20});
const V={x:30,y:90};
const A={x:120,y:90};
const b=G.svgBox(180,150,{id:'p5-a-'+deg,cell:20});
const V={x:40,y:115};
const A={x:160,y:115};
const rad=deg*Math.PI/180;
const B={x:V.x+85*Math.cos(-rad), y:V.y-85*Math.sin(rad)};
const Bd = 110;
const B={x:V.x+Bd*Math.cos(-rad), y:V.y-Bd*Math.sin(rad)};
let s=b.open;
s += G.segment(V,A,{color:'#0891b2',width:2});
s += G.segment(V,B,{color:'#0891b2',width:2});
if(deg===90) s += G.rightAngleMark(V,A,B,{color:'#dc2626',size:12});
else s += G.angle(V,A,B,{color:color,r:22,label:deg+'°',fontSize:11,labelOffset:14});
s += G.point(V.x,V.y,'',{r:3,color:'#0891b2'});
s += '<text x="70" y="115" text-anchor="middle" font-size="11" fill="#475569" font-weight="700" font-family="Unbounded">'+label+'</text>';
/* Заливка-сектор для наглядности */
if(deg < 180){
const wR = 36;
const a1 = 0;
const a2 = -rad;
let d=a2-a1; while(d>Math.PI) d-=2*Math.PI; while(d<-Math.PI) d+=2*Math.PI;
const sweep=d>0?1:0;
const large=Math.abs(d)>Math.PI?1:0;
const x1=V.x+wR*Math.cos(a1), y1=V.y+wR*Math.sin(a1);
const x2=V.x+wR*Math.cos(a2), y2=V.y+wR*Math.sin(a2);
s += '<path d="M '+V.x+' '+V.y+' L '+x1+' '+y1+' A '+wR+' '+wR+' 0 '+large+' '+sweep+' '+x2+' '+y2+' Z" fill="'+color+'" opacity="0.22"/>';
} else if(deg === 180){
/* Развёрнутый — закрашиваем полукруг */
s += '<path d="M '+(V.x-36)+' '+V.y+' A 36 36 0 0 1 '+(V.x+36)+' '+V.y+' Z" fill="'+color+'" opacity="0.18"/>';
}
/* Стороны угла */
s += G.segment(V,A,{color:'#0891b2',width:2.6});
s += G.segment(V,B,{color:'#0891b2',width:2.6});
/* Дуга/метка прямого угла */
if(deg===90) s += G.rightAngleMark(V,A,B,{color:'#dc2626',size:14});
else if(deg !== 180) s += G.angle(V,A,B,{color:color,r:26,width:2,label:deg+'°',fontSize:13,labelOffset:14});
else s += '<text x="'+(V.x+15)+'" y="'+(V.y-8)+'" font-size="13" fill="'+color+'" font-weight="800" font-family="Unbounded">180°</text>';
/* Вершина */
s += G.point(V.x,V.y,'',{r:4,color:'#0891b2'});
/* Подпись */
s += '<text x="90" y="140" text-anchor="middle" font-size="12" fill="#1e293b" font-weight="800" font-family="Unbounded">'+label+'</text>';
s += b.close;
return s;
}
@@ -1131,17 +1152,40 @@ function buildP6(){
+ G.point(V.x,V.y,'O',{color:'#475569',dx:-12,dy:18})
+ '<text x="130" y="20" text-anchor="middle" font-size="11" fill="#475569" font-weight="700" font-family="Unbounded">α + β = 180\xB0</text>'
+ b.close;
const b2=G.svgBox(260,180,{id:'p6-vert',cell:20});
const O={x:130,y:90};
const b2=G.svgBox(320,230,{id:'p6-vert',cell:20});
const O={x:160,y:115};
/* Полупрозрачные заливки секторов (для наглядности 4 углов) */
function wedge(V, p1, p2, r, fill){
const a1=Math.atan2(p1.y-V.y, p1.x-V.x);
const a2=Math.atan2(p2.y-V.y, p2.x-V.x);
let d=a2-a1; while(d>Math.PI) d-=2*Math.PI; while(d<-Math.PI) d+=2*Math.PI;
const sweep=d>0?1:0;
const large=Math.abs(d)>Math.PI?1:0;
const x1=V.x+r*Math.cos(a1), y1=V.y+r*Math.sin(a1);
const x2=V.x+r*Math.cos(a2), y2=V.y+r*Math.sin(a2);
return '<path d="M '+V.x+' '+V.y+' L '+x1+' '+y1+' A '+r+' '+r+' 0 '+large+' '+sweep+' '+x2+' '+y2+' Z" fill="'+fill+'"/>';
}
const P_R1={x:295,y:50}, P_R2={x:295,y:180}, P_L1={x:30,y:50}, P_L2={x:30,y:180};
svgVert = b2.open
+ G.line({x:30,y:30},{x:230,y:150},{color:'#0891b2',width:2})
+ G.line({x:30,y:150},{x:230,y:30},{color:'#7c3aed',width:2})
+ G.angle(O,{x:230,y:150},{x:230,y:30},{color:'#dc2626',r:24,label:'1',fontSize:12})
+ G.angle(O,{x:30,y:150},{x:30,y:30},{color:'#dc2626',r:24,label:'2',fontSize:12})
+ G.angle(O,{x:230,y:30},{x:30,y:30},{color:'#f59e0b',r:36,label:'3',fontSize:12})
+ G.angle(O,{x:230,y:150},{x:30,y:150},{color:'#f59e0b',r:36,label:'4',fontSize:12})
+ G.point(O.x,O.y,'O',{color:'#475569',dx:8,dy:-6})
+ '<text x="130" y="172" text-anchor="middle" font-size="11" fill="#475569" font-weight="700" font-family="Unbounded">∠1 = ∠2 (вертик.)</text>'
/* 4 цветных сектора как фон */
+ wedge(O, P_R2, P_R1, 28, 'rgba(220,38,38,.16)') /* ∠1 right */
+ wedge(O, P_L1, P_L2, 28, 'rgba(220,38,38,.16)') /* ∠2 left */
+ wedge(O, P_R1, P_L1, 28, 'rgba(234,88,12,.16)') /* ∠3 top */
+ wedge(O, P_L2, P_R2, 28, 'rgba(234,88,12,.16)') /* ∠4 bottom */
/* Прямые */
+ G.line({x:30,y:50},{x:295,y:180},{color:'#0891b2',width:2.5})
+ G.line({x:30,y:180},{x:295,y:50},{color:'#7c3aed',width:2.5})
/* Дуги углов */
+ G.angle(O,P_R2,P_R1,{color:'#dc2626',r:20,width:2.2,label:'∠1',fontSize:14,labelOffset:14})
+ G.angle(O,P_L1,P_L2,{color:'#dc2626',r:20,width:2.2,label:'∠2',fontSize:14,labelOffset:14})
+ G.angle(O,P_R1,P_L1,{color:'#ea580c',r:32,width:2.2,label:'∠3',fontSize:14,labelOffset:10})
+ G.angle(O,P_L2,P_R2,{color:'#ea580c',r:32,width:2.2,label:'∠4',fontSize:14,labelOffset:10})
/* Вершина O и подпись О (далеко от центра) */
+ G.point(O.x,O.y,'',{r:4,color:'#1e293b'})
+ '<text x="'+(O.x-26)+'" y="'+(O.y-22)+'" font-size="15" fill="#1e293b" font-weight="800" font-family="Unbounded">O</text>'
+ '<line x1="'+(O.x-18)+'" y1="'+(O.y-18)+'" x2="'+(O.x-3)+'" y2="'+(O.y-3)+'" stroke="#94a3b8" stroke-width="1" stroke-dasharray="2 2"/>'
/* Заголовок-легенда */
+ '<text x="160" y="220" text-anchor="middle" font-size="12" fill="#1e293b" font-weight="800" font-family="Unbounded">∠1=∠2, ∠3=∠4 — вертикальные</text>'
+ b2.close;
}