Повернуть Линию/Отрезок в 2D пространстве

Пишу свой редактор геометрический фигур на C# Windows Forms.

Есть задача: повернуть Отрезок по оси Y за одну из её концов (т.е. во время поворота одна точка Отрезка статична, другая может поворачиваться). Нужно, чтобы по нажатию кнопки мыши по рабочей области, один из концов Линии (пусть будет конец отрезка) поворачивался на нужный угол, и за основу расчетов брал позицию курсора мыши при клике.

Поворот Отрезка строится на основе матрицы поворота.

Так как я не силен в геометрии, попросил дорогого товарища ДЖПТ решить эту задачку, но он как-то тухло справился, выдав некорректный код (ниже), который практически рандомно вращает Отрезок, причем еще удлиняя/сокращая его, чего вообще не должно быть..

ПОМОГИТЕ ПЛИЗ!

Методы в backend формочки

private void LineRotate(Point cursorLocation)
{
    var selectedLines = _selectionService.GetSelectedShapesOfType<Line>();
    if (selectedLines == null || !selectedLines.Any())
    {
        ssInfo.Text = "Нет выделенных линий для поворота";
        return;
    }

    ShapeFactory.Shapes.OfType<Line>()
        .Where(line => selectedLines.Contains(line))
        .ToList()
        .ForEach(line => line.Rotate(GetAngleBetweenCursorAndLine(cursorLocation, line)));
}
private static double GetAngleBetweenCursorAndLine(Point cursorLocation, Line line)
{
    var lineVector = new Vertex(line.End.X - line.Start.X, line.End.Y - line.Start.Y);
    var cursorVector = new Vertex(cursorLocation.X - line.Start.X, cursorLocation.Y - line.Start.Y);

    return Math.Atan2(cursorVector.Y, cursorVector.X) - Math.Atan2(lineVector.Y, lineVector.X);
}

Метод класса Line

public void Rotate(double angle)
{
    var rotationMatrix = Matrix.CreateRotationMatrix(angle);
    End = rotationMatrix.Apply(End);
}

Матрица поворота (класс Matrix)

public static Matrix CreateRotationMatrix(double angle)
{
    double cos = Math.Cos(angle);
    double sin = Math.Sin(angle);

    double[,] rotationMatrix = new double[,]
    {
        { cos, -sin, 0 },
        { sin, cos, 0 },
        { 0, 0, 1 }
    };
    return new Matrix(rotationMatrix);
}

public Vertex Apply(Vertex point)
{
    double[] pointArray = { point.X, point.Y, 1 };
    double[] result = new double[3];

    for (int i = 0; i < 3; i++)
        result[i] = _matrix[i, 0] * pointArray[0] + _matrix[i, 1] * pointArray[1] + _matrix[i, 2] * pointArray[2];

    return new Vertex((int)result[0], (int)result[1]);
}

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

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

Вот вся нужная математика:

//компоненты текущего вектора и нового направления 
curr_dx = endx - startx
curr_dy = endy - starty
dx = mousex - startx
dy = mousey - starty

//угол, чтобы довернуть первый вектор до второго
rotangle = atan2(dx*curr_dy-dy*curr_dx, dx*curr_dx+dy*curr_dy)

//координаты конца отрезка после поворота относительно начала
new_x = startx + curr_dx*cos(rotangle)-curr_dy*sin(rotangle)
new_y = starty + curr_dx*sin(rotangle)+curr_dy*cos(rotangle)
→ Ссылка