限制分段角度

发布于 2024-09-07 07:18:13 字数 849 浏览 5 评论 0原文

我需要限制角度,使其适合一段。我绘制并链接到下面的图表,以更好地描述我所追求的内容。

我正在尝试为计算机程序计算此值,其中我有一个角度(斜率)和一个点(鼠标指针)。距离对我来说并不重要,重要的是角度。如果该点位于b1(绿色区域)内,那就没问题。但如果该点位于 b2b3(红色或橙色)区域内,则角度应快速恢复到绿色区域的限制(沿着线 s)。

图表我的问题
(来源:adamharte.com

主要问题我我在弄清楚这一点时,正在将角度捕捉到正确的一侧,例如,如果该点位于红色区域,则该角度应捕捉到红色一侧的角度 s ,反之亦然。

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

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

的值

,否则当角度在 0 到 2Pi 之间时我会收到错误。

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

感谢您阅读我的提问。

I need to limit an angle so it fits into a segment. I have drawn and links to a diagram below to better describe what I am after.

I am trying to calculate this for a computer program, where I have an angle (slope), and a point (the mouse pointer). The distance does not matter to me, just the angles. If the point is within b1 (green area) then that's fine. But if the point is within b2 or b3 (red or orange) areas, then the angle should snap back to the limit of the green area (along the line s).

Diagram of my problem
(source: adamharte.com)

The main problem I am having in figuring this out, is snapping the angle to the correct side e.g. If the point is in the red area, then the angle should snap to the angle s on the red side and vice versa.

I am also having trouble because s could be any angle, so I am being tripped up because I can't just do something like this:

if a(radians) is greater than
s(radians) then set a to the value of s

or I will get errors when the angle goes between zero and 2Pi.

So How would I work this out? Do I have to rotate everything back to a zero point or something then put it back when I have made my calculations?

Thanks for reading my questing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柒夜笙歌凉 2024-09-14 07:18:13

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

尝试一下。

First code in an ATAN2() function, to calculate the absolute angle for the point relative to horizontal plane. Then subtract the angle of the slope. if the result is <0 then snap to 0 and if the result is >180 snap to 180. The add the angle of the slope back to get your final angle

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

try it.

日记撕了你也走了 2024-09-14 07:18:13

我必须做出一些假设,因为您没有指定如何定义斜率。不管怎样,你应该能够从方程中得到 θ。

这是一个满足您要求的示例。让它发挥作用是一个有趣的挑战,它应该可以帮助您入门。注意:对我有帮助的一件事是总是保持 -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);
    }
}

}

I'd have to make some assumptions since you don't specify how you define slope. Either way you should be able to get a theta from the equation.

Here is an example that does what you require. It was a fun challenge to get it to work and it should get you started. Note: one thing that helped me was always keeping angles between -pi and pi. I also use vector projection to get the line that is drawn to look like it correctly lies on the slope.

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文