我需要限制一个角度,以便它适合一个片段。我已经绘制并链接到下面的图表,以更好地描述我的目标。
我正在尝试为计算机程序计算这个,我有一个角度(斜率)和一个点(鼠标指针)。距离对我来说无关紧要,只是角度。如果该点在 b1 (绿色区域)内,那就没问题。但如果该点位于 b2 或 b3 (红色或橙色)区域内,则角度应该回弹到绿色区域的极限(沿着行)小号)。
Diagram of my problem http://sandbox.adamharte.com/dump/trigdiagram.jpg
我在解决这个问题时遇到的主要问题是将角度捕捉到正确的一侧,例如如果该点位于红色区域,则角度应与红色侧的角度s对齐,反之亦然。
我也遇到了麻烦,因为 s 可能是任何角度,所以我被绊倒因为我不能做这样的事情:
如果 a (弧度)大于 s (弧度)然后将 a 设置为 s的值
或者当角度介于0和2Pi之间时我会收到错误。
那我该如何解决这个问题呢?我是否必须将所有内容旋转回零点或其他内容,然后在进行计算时将其放回原位?
感谢您阅读我的任务。
答案 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);
}
}
}