限制段的角度

时间:2010-06-24 20:36:26

标签: actionscript-3 math trigonometry

我需要限制一个角度,以便它适合一个片段。我已经绘制并链接到下面的图表,以更好地描述我的目标。

我正在尝试为计算机程序计算这个,我有一个角度(斜率)和一个点(鼠标指针)。距离对我来说无关紧要,只是角度。如果该点在 b1 (绿色区域)内,那就没问题。但如果该点位于 b2 b3 (红色或橙色)区域内,则角度应该回弹到绿色区域的极限(沿着行)小号)。

Diagram of my problem http://sandbox.adamharte.com/dump/trigdiagram.jpg

我在解决这个问题时遇到的主要问题是将角度捕捉到正确的一侧,例如如果该点位于红色区域,则角度应与红色侧的角度s对齐,反之亦然。

我也遇到了麻烦,因为 s 可能是任何角度,所以我被绊倒因为我不能做这样的事情:

  

如果 a (弧度)大于    s (弧度)然后将 a 设置为 s的值

或者当角度介于0和2Pi之间时我会收到错误。

那我该如何解决这个问题呢?我是否必须将所有内容旋转回零点或其他内容,然后在进行计算时将其放回原位?

感谢您阅读我的任务。

2 个答案:

答案 0 :(得分:1)

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

试一试。

答案 1 :(得分:0)

我必须做一些假设,因为你没有指定如何定义斜率。无论哪种方式,你都应该从等式中得到θ。

这是一个满足您需求的示例。让它开始工作是一个有趣的挑战,它应该让你开始。注意:有一件事帮助了我总是保持-pi和pi之间的角度。我还使用vector projection来绘制的线条看起来正好位于斜坡上。

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);
    }
}

}