Покраска с помощью соседних вершин
Описание
Для начала я вам покажу эту картинку:
И так...
У меня есть основная (черная) вершина, нулевой (черный) угол и другие вершины связанные с ним.
У главной вершины есть свойство palette: Map<number, Color>
который из себя представляет список связанных с ним вершин по типу [Угол вершины считая с основной линии, цвет вершины]
, как показано на картинке.
Мне нужно покрасить основную вершину с помощью соседних вершин вот так:
Серые линии биссектрисы. Все углы в диапазоне [0, 2π)
Так же
Для своего же удобства я создал функцию который красит по заданным углам:
function fillSector(beginAngle: number, endAngle: number, color: Color): void;
Проблема
Я уже 3 часа не могу правильно рассчитать откуда у меня должна начаться покраска и до куда для определенного цвета, в основном из-за разреза в части с черной линией. Чуть выше этой линии у меня углы ближе к 0, а чуть ниже 2π.
Вопрос
Мне нужно узнать правильный подход к алгоритму, который будет считать сектор покраски.
Пример
Результат для примера сверху должно быть что-то вроде такого:
function aWonderfulFunction(palette: Map<number, Color>): Map<number, Color>;
const palette = new Map([
[1 / 4 * PI, Color.RED], // От угла 1/4π приходит красный цвет
[5 / 6 * PI, Color.GREEN], // От угла 5/6π приходит зеленый цвет
[3 / 2 * PI, Color.BLUE], // От угла 3/2π приходит синий цвет
]);
const result = aWonderfulFunction(palette);
console.log(result);
// new Map([
// [13 / 24 * PI, Color.RED], // От начала (0π) до биссектрисы красно-зеленого (которая под углом 13/24π) красим красным цветом
// [14 / 12 * PI, Color.GREEN], // От биссектрисы красно-зеленого (13/24π) до биссектрисы зелено-синего (которая под углом 14/12π) красим зеленым цветом
// [15 / 8 * PI, Color.BLUE], // От биссектрисы зелено-синего (14/12π) до биссектрисы сине-красного (которая под углом 15/8π) красим синим цветом
// [2 * PI, Color.RED], // От биссектрисы сине-красного (14/12π) до конца (2π) красим красным цветом
// ]);
Ответы (2 шт):
Есть ещё такой способ, который не боится переходов через 0
(не подходит напрямую, если разность углов >=Pi):
csum = cos(a)+cos(b)
ssum = sin(a)+sin(b)
middle = atan2(ssum, csum)
По сути - складываются единичные направляющие вектора углов, определяется направление суммарного вектора.
Для поиска биссектрисы нужно найти на сколько один угол отличается от второго и разделить пополам и прибавить к первому.
Для углов, между которым нет перехода через угол 2π
формула будет простой
(a + b) / 2
в противном случае нужна корректировка, например, добавить второму углу 2π - это позволит найти верную разницу между углами
(a + (b+2π))/2
Теперь уже результат может быть больше 2π - и этот случай так же можно скорректировать либо вычитанием 2π в случае необходимости, либо взятием остатка от деления
В js формулу можно обобщить до следующей:
var angle = ((firtsAngle + secondAngle + (firtsAngle > secondAngle)*2*Math.PI)/2) % (2*Math.PI)