При постройке нормали с углом больше 90 градусов нормаль строится в противоположную сторону

Дано отрезок (или сегмент Полилинии) в 3D пространстве. Требутеся построить нормаль к выбранному отрезку с определенным углом наклона, заданным пользователем в градусах.

Если угол наклона указано от 0 до 90 включительно, то угол поворота корректен, НО, если угол указан больше 90, то тогда угол поворота идет в обратную сторону. Например, если ввести значение 100 градусов, то угол наклона станет 80 градусов; если указать 120 градусов, то тогда 60 градусов.

Также, нормаль с любым углом должна строиться по часовой стрелке.

Буду очень признателен, если Вы мне объясните мат. часть в этой проблеме..

P.S. Глобальная переменная Angle уже переведена в радианы.

if (Angle != 0)
{
    Double cos = Math.Cos(Angle);
    Double sin = Math.Sin(Angle);
    Double tan = Math.Tan(Angle);

    Vertex VA = new Vertex(0, 0, 1);
    Vertex axisN = GetULikeMatrix().TransformNormal(VA).Normalize();

    Vertex initialPoint = MV.Inverse().Transform(Point1);
    Vertex targetPoint = MV.Inverse().Transform(V);

    Double edgeLength = new Edge(initialPoint, targetPoint).Length();
    Double height = edgeLength * Math.Abs(tan);

    // Задается угол поворота с помощью тангенса.
    V = targetPoint + axisN * height;

    if (Math.Round(cos, 3) == 0)
    {
        if (sin > 0) V = initialPoint + axisN * edgeLength;
        if (sin < 0) V = initialPoint - axisN * edgeLength;
    }

    // Задается необходимая длина.
    V = initialPoint + (V - initialPoint).Normalize() * edgeLength;
    V = MV.Transform(V);
}

Ответы (1 шт):

Автор решения: maestro

Не могу понять, что вокруг чего вы крутите, в коде куча необъявленных идентификаторов. Я недавно решал кое-что подобное, здесь функция на Python, которая находит вектор, перпендикулярный вектору a, повёрнутый на угол alpha в радианах. Если вектор a не совпадает с вектором z, то за начало отсчёта (нулевой угол) берётся направление "вверх". В остальных случаях берётся какая-то из других координатных осей.

def _calc_view_up(x_a, y_a, z_a, alpha=0):
    """
    Функция рассчитывает вектор c, перпендикулярный вектору a, такой, что
    его проекция на положительное направление оси Z максимально,
    то есть это вектор, направленный "вверх". 
    Если вектор a совпадает с осью Z, то значение вектора c 
    принимается равным [1, 0, 0] (ось X). 
    Затем рассчитывает вектор b, который получается поворотом вектора c 
    вокруг вектора a. Возвращает вектор b.
    
    PAREMETERS
    ----------
    x_a, y_a, z_a: float
        Вектор a, вокруг которого нужно выполнить поворот
    alpha: float
        Угол поворота в радианах
    """
    a = np.array([x_a, y_a, z_a])
    if x_a==y_a==z_a==0:
        return np.array([0, 0, 1])
    elif z_a == 0:
        c = np.array([0, 0, 1])
    elif x_a==0 and y_a == 0:
        c = np.array([1, 0, 0])
    else:
        mag = np.sqrt(np.sum(a**2))
        x_c1 = ((x_a*z_a)/(math.sqrt(y_a**2+x_a**2)*mag))
        x_c2 = -x_c1
        y_c1 = ((y_a*z_a)/(math.sqrt(y_a**2+x_a**2)*mag))
        y_c2 = -y_c1
        z_c1 = -(y_a*y_c1+x_a*x_c1)/z_a
        z_c2 = -z_c1
        if z_c1 > 0:
            c = np.array([x_c1, y_c1, z_c1])
        else:
            c = np.array([x_c2, y_c2, z_c2])
    a = a / np.sqrt(np.sum(a**2))
    b = c * np.cos(alpha) + np.cross(a, c) * np.sin(alpha)
    return b

Объяснение

→ Ссылка