Предельный угол на сегмент - PullRequest
1 голос
/ 25 июня 2010

Мне нужно ограничить угол, чтобы он вписался в сегмент. Я нарисовал и привел ссылки на диаграмму ниже, чтобы лучше описать, что я хочу.

Я пытаюсь рассчитать это для компьютерной программы, где у меня есть угол ( наклон ) и точка (указатель мыши). Расстояние не имеет значения для меня, только углы. Если точка находится в пределах b1 (зеленая зона), то это нормально. Но если точка находится в пределах b2 или b3 (красных или оранжевых) областей, то угол должен вернуться к границе зеленой области (вдоль линии s *). 1012 *).

Диаграмма моей проблемы http://sandbox.adamharte.com/dump/trigdiagram.jpg

Основная проблема, с которой я сталкиваюсь при выяснении этого, - это привязка угла к правильной стороне, например. Если точка находится в красной области, то угол должен привязываться к углу s на красной стороне и наоборот.

У меня тоже проблемы, потому что s может быть под любым углом, поэтому меня сбивают с толку, потому что я не могу просто сделать что-то вроде этого:

если a (радианы) больше чем с (радианы), затем установите a на значение с

или я получу ошибки, когда угол будет между нулем и 2Pi.

Так, как бы я решил это? Должен ли я повернуть все обратно к нулевой точке или что-то еще, а затем положить его обратно, когда я сделаю свои вычисления?

Спасибо за чтение моего квеста.

Ответы [ 2 ]

1 голос
/ 21 июля 2010

Первый код в функции ATAN2 (), чтобы вычислить абсолютный угол для точки относительно горизонтальной плоскости.Затем вычтите угол наклона.если результат <0, то привязка к 0, а если результат> 180, привязка к 180. Добавьте угол наклона назад, чтобы получить окончательный угол

psi = (angle of slope)
a = atan2(x,y)
th = a-psi
if( th<0 ) { th=0; }
if( th>pi ) { th=pi; }
a = th+psi

, попробуйте.

0 голосов
/ 26 июня 2010

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

Вот пример, который делает то, что вам нужно. Это было забавное испытание, чтобы заставить его работать, и это должно помочь вам начать. Примечание: одна вещь, которая мне помогла, это всегда , сохраняющая углы между -pi и pi. Я также использую векторную проекцию , чтобы нарисованная линия выглядела так, как будто она правильно лежит на склоне.

package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;

public class CircleSnap extends Sprite
{
    private static const DEG_TO_RAD:Number = (Math.PI / 180);
    private static const RAD_TO_DEG:Number = (180 / Math.PI);

    private static const centerPoint:Point = new Point(200, 200);
    private static const RADIUS:int = 100;

    private var slope:Number;

    private var circle:Sprite;
    private var line:Sprite;

    public function CircleSnap()
    {
        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
    }

    private function addedToStage(event:Event):void
    {
        // choose a random slope (between -Math.PI to Math.PI)
        slope = (Math.random()*Math.PI*2) - Math.PI;

        // draw the circle
        circle = makeColoredCircle();
        addChild(circle);

        circle.x = centerPoint.x;
        circle.y = centerPoint.y;
        circle.rotation = slope * RAD_TO_DEG;

        line = new Sprite();
        addChild(line);

        stage.addEventListener(MouseEvent.MOUSE_MOVE, drawLine);
    }

    private function drawLine(event:MouseEvent):void
    {
        line.graphics.clear();

        // calculate the angle of the line
        var lineAngle:Number = Math.atan2(
            stage.mouseY - centerPoint.y,
            stage.mouseX - centerPoint.x);

        var angleDiff:Number = (lineAngle - slope);
        if(Math.abs(angleDiff) > Math.PI)
        {
            // wrap the angle between -pi and pi
            var angleDir:int = angleDiff > 0 ? -1 : 1;
            angleDiff = (Math.PI*2 - Math.abs(angleDiff)) * angleDir;
        }

        // assume we just draw to the mouse position
        var destX:Number = stage.mouseX;
        var destY:Number = stage.mouseY;
        // if we are in the top area of the circle
        if(angleDiff < 0)
        {
            // calculate the length
            var xDiff:Number = stage.mouseX - centerPoint.x;
            var yDiff:Number = stage.mouseY - centerPoint.y;
            // we use Math.cos here to project the new line onto the slope
            var len:Number = Math.cos(angleDiff) * Math.sqrt(xDiff*xDiff+yDiff*yDiff);
            destX = Math.cos(slope) * len + centerPoint.x;
            destY = Math.sin(slope) * len + centerPoint.y;
        }

        // draw the line
        line.graphics.lineStyle(3, 0x00FFFF);
        line.graphics.moveTo(centerPoint.x, centerPoint.y);
        line.graphics.lineTo(destX, destY);
    }

    private function makeColoredCircle():Sprite
    {
        var circle:Sprite = new Sprite();
        var bottomHalf:Sprite = new Sprite();
        circle.addChild(bottomHalf);
        bottomHalf.graphics.beginFill(0xFF0000);
        halfCircle(bottomHalf.graphics, 0, 0, RADIUS);
        var topLeftQuarter:Sprite = new Sprite();
        circle.addChild(topLeftQuarter);
        topLeftQuarter.graphics.beginFill(0x00FF00);
        quarterCircle(topLeftQuarter.graphics, 0, 0, RADIUS);
        topLeftQuarter.rotation = 180
        var topRightQuarter:Sprite = new Sprite();
        circle.addChild(topRightQuarter);
        topRightQuarter.graphics.beginFill(0x0000FF);
        quarterCircle(topRightQuarter.graphics, 0, 0, RADIUS);
        topRightQuarter.rotation = -90;
        return circle;
    }

    // found this here: http://actionsnippet.com/?p=1515
    private function halfCircle(g:Graphics, x:Number,y:Number,r:Number):void
    {
        var c1:Number=r * (Math.SQRT2 - 1);
        var c2:Number=r * Math.SQRT2 / 2;
        g.moveTo(x+r,y);
        g.curveTo(x+r,y+c1,x+c2,y+c2);
        g.curveTo(x+c1,y+r,x,y+r);
        g.curveTo(x-c1,y+r,x-c2,y+c2);
        g.curveTo(x-r,y+c1,x-r,y);
    }

    // modified from halfCircle found here: http://actionsnippet.com/?p=1515
    private function quarterCircle(g:Graphics, x:Number,y:Number,r:Number):void
    {
        var c1:Number=r * (Math.SQRT2 - 1);
        var c2:Number=r * Math.SQRT2 / 2;
        g.moveTo(x+r,y);
        g.curveTo(x+r,y+c1,x+c2,y+c2);
        g.curveTo(x+c1,y+r,x,y+r);
        g.lineTo(x, y);
    }
}

}
...