Вращение круга с помощью мыши с направлением

Я вращаю круг с помощью мыши, но я хочу, чтобы был предел того, насколько далеко можно вращать круг. (Допустим, 3 полных раза). Когда он достигает своего предела, его больше нельзя повернуть в том же направлении, но можно в противоположном направлении. Я остановил его после максимальных поворотов, но теперь я пытаюсь найти направление, и каждый раз, когда моя мышь проходит ось x круга, направление меняется, потому что atan2 дает мне угол относительно оси x. Таким образом, новая позиция мыши находится в одном квадранте, а последняя позиция — в другом квадранте, поэтому вычитание этих углов не дает мне того, что я хочу. Я хорошо это объяснил? Какие-либо предложения?

private void HelmPb_MouseMove(object sender, MouseEventArgs e)
    {
        if ((e.Button != MouseButtons.Left) || _dontTurn) return;
        double angle = OffsetAngle();
        Point temp = MousePosition;
        float degrees = Convert.ToSingle(angle - _offsetAngle);
        float diff = _lastHelmAngle - degrees;
        float absDiff = Math.Abs(diff) % 360;
        if (absDiff > 180) absDiff = 360 - absDiff;
        double angle1 = Math.Atan2(_lastHelmPoint.Y, _lastHelmPoint.X);
        if (angle1 < 0) angle1 += 2*Math.PI;
        double angle2 = Math.Atan2(temp.Y, temp.X);
        if (angle2 < 0) angle2 += 2*Math.PI;
        double direction = angle1 - angle2;
        direction = direction*(180/Math.PI);
        _deltaHelmTurn += Convert.ToSingle(absDiff);
        if (_deltaHelmTurn >= (_maxHelmTurn*360.0))
        {
            if (direction > 0 && _lastHelmDirection > 0)
            {
                _deltaHelmTurn = Convert.ToSingle(_maxHelmTurn*360.0);
                degrees = Convert.ToSingle(_maxHelmTurn*360.0)%360;
            }
        }
        _lastHelmDirection = direction;
        _lastHelmPoint = MousePosition;
        _lastHelmAngle = Convert.ToSingle(degrees);
        _sameHelmRotation = Convert.ToSingle(degrees);
        HelmPb.Image.Dispose();
        WaterDepthPlot.Update();
        HelmPb.Image = RotateImage(_originalHelmImage, -degrees);
        HelmPb.Update();
    }

private double OffsetAngle()
    {
        int helmXMid = HelmPb.PointToScreen(Point.Empty).X + (HelmPb.Width / 2);
        int helmYMid = HelmPb.PointToScreen(Point.Empty).Y + (HelmPb.Height / 2);
        double angle = AngleFromPoints(MousePosition, new Point(helmXMid, helmYMid));
        return angle;
    }

private double AngleFromPoints(Point pt1, Point pt2)
    {
        Point p = new Point(pt1.X - pt2.X, pt1.Y - pt2.Y);
        double alpha;
        if (p.Y == 0) alpha = p.X > 0 ? 0d : 180d;
        else
        {
            double f = 1d * p.X / (Math.Sqrt(p.X * p.X + p.Y * p.Y));
            alpha = Math.Acos(f) * 180d / Math.PI;
            if (p.Y > 0) alpha = 360d - alpha;
        }
        return alpha;
    }

person Nolemonpledge    schedule 04.06.2015    source источник


Ответы (1)


Направление вращения между двумя векторами эквивалентно знаку их перекрестного произведения.

//Returns 1 for CCW, -1 for CW, 0 for no change
private int Direction(Point from, Point to)
{
    double cross = (from.x * to.y) - (from.y * to.x);
    return Math.Sign(cross);
}
person Rubixus    schedule 04.06.2015
comment
Кажется, есть проблема. Например, если начальная точка была (129,17), а конечная точка была (136,19), это по часовой стрелке, крест = (129 * 19) - (17 * 136) = 139,0, что означает его против часовой стрелки. Я делаю что-то неправильно? - person Nolemonpledge; 04.06.2015
comment
@ user3529319 - Переход от (129,17) к (136,19) осуществляется против часовой стрелки. Просмотреть график - person Rubixus; 04.06.2015