feat: Phase 5 планиметрии — касательные (tangent) + параллельный перенос (translate)
- gTangentPoints(O, P, r): касательные через полярно-полярную точку M=O+v*r²/d, h=r√(d²-r²)/d - tangent: 2 derived_line (which=0/1) из внешней точки к окружности; оба пересчитываются при движении точки или изменении радиуса/центра; _pendingCircRef хранит окружность-источник - translate: derived point P'=P+(B-A) по вектору AB; 3-фазный ввод с onHintChange(tool,2/3) - _hitTestCircle(): найти окружность под курсором (HIT=12px) - _drawLineRefHighlight(): расширен для circle (рисует дугу подсветки) - _pendingCircRef очищается в setTool() - lab.html: кнопки Симметрия/Перенос/Касательные, _GEO_PHASE_HINTS словарь, _geoShowHint(name, phase) принимает числовой phase вместо boolean Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+25
-14
@@ -3861,10 +3861,18 @@
|
||||
|
||||
<div class="gp-section-title" style="margin-top:4px">Преобразования</div>
|
||||
<div class="geo-tool-grid">
|
||||
<button id="geo-btn-reflect" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('reflect',this)" title="Симметрия точки относительно прямой — клик на ось, затем на точку">
|
||||
<button id="geo-btn-reflect" class="geo-tool-btn" onclick="geoSetTool('reflect',this)" title="Симметрия точки относительно прямой — клик на ось, затем на точку">
|
||||
<svg viewBox="0 0 24 24" fill="none"><line x1="12" y1="2" x2="12" y2="22" stroke-width="1.5" stroke-dasharray="3,2"/><circle cx="6" cy="12" r="3" stroke-width="1.5"/><circle cx="18" cy="12" r="2.5" stroke-width="1.5" opacity=".5"/><line x1="9" y1="12" x2="15" y2="12" stroke-width="1" opacity=".6"/></svg>
|
||||
Симметрия
|
||||
</button>
|
||||
<button id="geo-btn-translate" class="geo-tool-btn" onclick="geoSetTool('translate',this)" title="Параллельный перенос — вектор AB, затем точка P">
|
||||
<svg viewBox="0 0 24 24" fill="none"><circle cx="6" cy="18" r="2.5" stroke-width="1.5"/><circle cx="18" cy="6" r="2.5" stroke-width="1.5"/><line x1="6" y1="18" x2="18" y2="6" stroke-width="1.5" marker-end="url(#arrow)"/><circle cx="14" cy="18" r="2.5" stroke-width="1.5" opacity=".4"/><circle cx="21" cy="9" r="2" stroke-width="1.5" stroke-dasharray="3,2"/></svg>
|
||||
Перенос
|
||||
</button>
|
||||
<button id="geo-btn-tangent" class="geo-tool-btn geo-tool-wide" onclick="geoSetTool('tangent',this)" title="Касательные из точки к окружности — клик на окружность, затем на точку">
|
||||
<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="7" stroke-width="1.5"/><line x1="4" y1="4" x2="19" y2="12" stroke-width="1.5" stroke-dasharray="4,3"/><line x1="4" y1="20" x2="19" y2="12" stroke-width="1.5" stroke-dasharray="4,3"/><circle cx="4" cy="12" r="2.5" fill="currentColor"/></svg>
|
||||
Касательные
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="gp-section-title" style="margin-top:4px">Правильный многоугольник</div>
|
||||
@@ -5374,6 +5382,8 @@
|
||||
incircle: 'Кликни 3 точки треугольника — получи вписанную окружность',
|
||||
reflect: 'Сначала кликни на ось симметрии (прямую/отрезок)',
|
||||
ngon: 'Клик — центр правильного многоугольника; второй клик — вершина',
|
||||
tangent: 'Кликни на окружность — построим касательные',
|
||||
translate: 'Кликни начало вектора A',
|
||||
};
|
||||
|
||||
function geoSetTool(name, btnEl) {
|
||||
@@ -5384,24 +5394,25 @@
|
||||
_geoShowHint(name);
|
||||
}
|
||||
|
||||
function _geoShowHint(name, phase2) {
|
||||
const _GEO_PHASE_HINTS = {
|
||||
parallel_2: 'Теперь кликни на точку — через неё проведём прямую',
|
||||
perpendicular_2: 'Теперь кликни на точку — через неё проведём перпендикуляр',
|
||||
intersect_2: 'Теперь кликни на вторую прямую',
|
||||
foot_2: 'Теперь кликни на точку — найдём основание перпендикуляра',
|
||||
reflect_2: 'Теперь кликни на точку — получишь её симметричное отражение',
|
||||
tangent_2: 'Теперь кликни на внешнюю точку — получишь две касательные',
|
||||
translate_2: 'Теперь кликни конец вектора B',
|
||||
translate_3: 'Теперь кликни точку P — она будет перенесена',
|
||||
};
|
||||
|
||||
function _geoShowHint(name, phase) {
|
||||
const hint = document.getElementById('geo-hint');
|
||||
if (!hint) return;
|
||||
if (phase2) {
|
||||
const phase2hints = {
|
||||
parallel: 'Теперь кликни на точку — через неё проведём прямую',
|
||||
perpendicular: 'Теперь кликни на точку — через неё проведём перпендикуляр',
|
||||
intersect: 'Теперь кликни на вторую прямую',
|
||||
foot: 'Теперь кликни на точку — найдём основание перпендикуляра',
|
||||
reflect: 'Теперь кликни на точку — получишь её симметричное отражение',
|
||||
};
|
||||
hint.textContent = phase2hints[name] || _GEO_HINTS[name] || '';
|
||||
if (phase && phase > 1) {
|
||||
hint.textContent = _GEO_PHASE_HINTS[`${name}_${phase}`] || _GEO_HINTS[name] || '';
|
||||
} else {
|
||||
hint.textContent = _GEO_HINTS[name] || '';
|
||||
}
|
||||
// Показываем/скрываем n-selector только для ngon
|
||||
const ngonCtrl = document.getElementById('geo-ngon-ctrl');
|
||||
// ngon-ctrl всегда виден — расположен рядом с кнопкой в grid
|
||||
}
|
||||
|
||||
function geoNgonN(delta) {
|
||||
|
||||
Reference in New Issue
Block a user