Math 基于半径计算从正方形中心到边的矢量

Math 基于半径计算从正方形中心到边的矢量,math,vector,2d,Math,Vector,2d,给定一个正方形(由x,y,宽度,高度描述)和一个角度(以弧度为单位),我需要计算一个向量,该向量从正方形中心开始,终止于与正方形边缘以给定角度碰撞的点 我真的最感兴趣的是它的碰撞点,所以如果这能使计算更有效,请告诉我 这可以推广到矩形吗?一般来说,多边形如何?一般化为矩形,如果a=向量与水平递增计数器cloclkwise的角度,则可以通过以下公式计算点坐标: let dx = distance from center horizontally, and dy = distance fo

给定一个正方形(由x,y,宽度,高度描述)和一个角度(以弧度为单位),我需要计算一个向量,该向量从正方形中心开始,终止于与正方形边缘以给定角度碰撞的点

我真的最感兴趣的是它的碰撞点,所以如果这能使计算更有效,请告诉我


这可以推广到矩形吗?一般来说,多边形如何?

一般化为矩形,如果a=向量与水平递增计数器cloclkwise的角度,则可以通过以下公式计算点坐标:

let dx = distance from center horizontally, and 
    dy = distance form the center vertically, then 

 dx =  if (tan(a) == 0, then width/2, else Min( height / (2 * tan(a)), width/2)
 dy =  if ABS(a) == Pi/2 then height/2 else  Min( (width/2) * tan(a)),  height/2)
那么点的坐标是:

   px = (x+width/2) + dx for right quadrants (Pi/2 >= a >= - Pi/2);
      = (x+width/2) - dx for left quadrants  (Pi/2 <= a <= 3Pi/2)
   py = (y+height/2) + dy for lower quadrants (Pi <= a <= 2Pi);
      = (y+height/2) - dy for upper quadrants (0 <= a <= Pi);
右象限的px=(x+width/2)+dx(Pi/2>=a>=-Pi/2);
=(x+width/2)-dx表示左象限(Pi/2给定正方形的宽度和高度,然后可以确定正方形的中心(x+.5w,y+.5h)

从这里,您可以使用一些三角学来确定矢量线的长度:

tan(角度)=0.5x/a

式中,a=正方形中心与正方形边缘之间的距离。点为x=a,y=(高度)


请温柔一点,因为我已经用了一段时间了!:-)

编辑:矩形的正确解。如果宽度或高度为零,它甚至不会崩溃! 语言:C++ .< /P> tan(89.99999)感谢James Fassett测试我的代码

#include <cstdio>                  
#include <math.h>                  

// declare nonstandard signum function
double sign(double x);                

//define pi because I forgot where it's declared
double const pi = 3.14159;                      

//declare non-standard contangent function      
double cot(double x);                           

int main()                                      
{                                               
    for (double angle = 0.0 ; angle<2*pi; angle += 0.1){
            //angle should be within [0, 2*pi) range    
            //x and y point to the _middle_ of the rectangle
            double x = 0; double y = 0 ;                    
            double width = 1, height = 4;                   
            double base_angle = atan(height/width);         
              // the angle between rectangle diagonal and Ox axis
            double px,py;                                        
            // Which side we're on?                              
            bool left = (fabs(angle - pi) < base_angle);         
            bool right = (angle> 2*pi-base_angle || angle < base_angle);
            bool top = (fabs(angle - pi/2) <= fabs(pi/2 - base_angle)); 
            bool bottom = (fabs(angle - 3*pi/2) <= fabs(pi/2 - base_angle));
            // The helper values used to adjust sides                       
            int lr = (left?-1:0) + (right?1:0);                             
            int tb = (bottom?-1:0) + (top?1:0);                             
            if (lr) {                                                       
                            // we're on vertical edge of rectangle          
                            px = x+width/2*lr;                              
                            py = y+width/2*tan(angle)*lr;
            } else {
                            // we're on the horizontal edge or in the corner
                            px = x+height/2*cot(angle)*tb;
                            py = y+height/2*tb;
            }
            printf("  a = %d deg: x = %lf; y = %lf\n",(int)(angle/pi*180),px,py);
    }

    return 0;
}

// define nonstandard signum function
double sign(double x)
{
    if (x<0) return -1;
    if (x>0) return 1;
    return 0;
}

//define non-standard contangent function
double cot(double x)
{
    return tan(pi/2 - x);
}
#包括
#包括
//声明非标准符号函数
双符号(双x);
//定义pi,因为我忘了它在哪里声明
双常数pi=3.14159;
//声明非标准连续函数
双胶辊(双x);
int main()
{                                               

对于(双角度=0.0;角度向量将是
center+(cos(角度),sin(角度))*magnity
。如果要将其与正方形相交,则需要确定大小。可以使用以下正方形获得:

float abs_cos_angle= fabs(cos(angle));
float abs_sin_angle= fabs(sin(angle));
if (width/2/abs_cos_angle <= height/2/abs_sin_angle)
{
    magnitude= fabs(width/2/abs_cos_angle);
}
else
{
    magnitude= height/2/abs_sin_angle;
}
float abs_cos_angle=fabs(cos(angle));
浮动绝对值sin角度=fabs(sin(角度));

如果(width/2/abs\u cos\u angle编辑:Pavel现在有另一个工作实现(他很好地致力于调试他的解决方案),但我将把它作为另一个仅适用于正方形的替代方案(Pavel的矩形工作)

专用函数CalculateInTransquare(宽度:数字,角度:数字):点
{
//单角缠绕
角度=(数学PI*2+角度)%(数学PI*2);
//从中心计算归一化向量
//将一个正方形的边缘考虑在内
//八个可能的象限
var-myX:数字;
var-myY:数字;
如果(角度<数学PI/4)
{
myX=1;
myY=数学tan(角度);
}
否则如果(角度<数学PI/2)
{
myX=Math.tan(Math.PI/2-角度);
myY=1;
}
否则如果(角度<3*数学PI/4)
{
myX=-Math.tan(angle-Math.PI/2);
myY=1;
}
else if(角度<数学PI)
{
myX=-1;
myY=Math.tan(Math.PI-角度);
}
否则如果(角度<5*数学PI/4)
{
myX=-1;
myY=-Math.tan(angle-Math.PI);
}
否则如果(角度<3*数学PI/2)
{
myX=-Math.tan((3*Math.PI/2)-角度);
myY=-1;
}
否则如果(角度<7*数学PI/4)
{
myX=Math.tan(角度-(3*Math.PI/2));
myY=-1;
}
其他的
{
myX=1;
myY=-Math.tan(Math.PI*2-角度);
}
//缩放并平移向量
返回新点(
(myX*宽度/2)+宽度/2,
(myY*宽度/2)+宽度/2);
}

在大多数语言中,如果角度为+/-pi/2弧度,则无论是否在Min()范围内,tan(角度)都会放大所有值。这并不适用于[0,2*pi]范围内的所有值。例如,当a=6.201503898186251时,则dx=-305.38621689379323,这显然是不正确的。将dx的计算更改为包含Max(-width/2)正确限定值,但在许多范围内(包括[0,pi/2]内)答案仍然不正确你的问题不够精确,无法确定答案是什么。从一个矩形的中心开始,对于足够大的角度值,我可以从中心画8条线,与该角度的矩形边相交-导致8个向量。你想要哪一个?一般来说,关于plygons,你应该首先定义你的概念多边形的中心。@Vinay:角度在0-2*pi范围内@Pavel:别介意多边形-我想的是正多边形,但除了理论上的Corry Pavel,我对它没有什么兴趣,但“符号”是不是意味着“正弦”?cot是余弦还是余切?当我做出这些假设时,并非所有计算点都位于矩形的周长上。哦,符号表示“符号”,或“符号”。+1表示正数,-1表示负数,0表示零。cot表示余切。查看维基百科,了解这些函数在英语中的表示方式。[[主题外]顺便说一句,重新检查一下学校所有的数学题:例如“直角三角形”对我来说是个惊喜。]我已经测试过了,虽然对某些角度范围正确,但对大多数人来说都是错误的。看我的答案,它更详细,但更正确。我修正了我的帖子。它包含了几个拼写错误(宽度没有乘以2,我忘记了矩形的左侧),但数学上没有错误!请用绿色标记我的解决方案,并免费使用代码:)最难的一点是确定a——从中心到矩形边缘的距离。如果我能做到这一点,那么sohcahtoa就是我所需要的。上面的方程在求解时提供了这一点。你有角度(因此有切线),你有x。你所需要的就是解a,
float abs_cos_angle= fabs(cos(angle));
float abs_sin_angle= fabs(sin(angle));
if (width/2*abs_sin_angle <= height/2*abs_cos_angle)
{
    magnitude= width/2/abs_cos_angle;
}
else
{
    magnitude= height/2/abs_sin_angle;
}
    double magnitude;
    double abs_cos_angle= fabs(cos(angle));
    double abs_sin_angle= fabs(sin(angle));
    if (width/2*abs_sin_angle <= height/2*abs_cos_angle)
    {
        magnitude= width/2/abs_cos_angle;
    }
    else
    {
        magnitude= height/2/abs_sin_angle;
    }

    double check_x= x + cos(angle)*magnitude;
    double check_y= y + sin(angle)*magnitude;

    printf("  a = %d deg: x = %lf; y = %lf\n",(int)(angle/pi*180),check_x,check_y);
private function calculatePointOnSquare(width:Number, angle:Number):Point
{
    // simple angle wrapping             
    angle = (Math.PI*2 + angle) % (Math.PI*2);

    // calculate a normalized vector from the centre
    // of a square to the edge taking into account
    // the eight possible quadrants
    var myX:Number;
    var myY:Number;
    if(angle < Math.PI/4)
    {
        myX = 1;
        myY = Math.tan(angle);
    }
    else if(angle < Math.PI/2)
    {
        myX = Math.tan(Math.PI/2 - angle);
        myY = 1;
    }
    else if(angle < 3*Math.PI/4)
    {
        myX = -Math.tan(angle - Math.PI/2);
        myY = 1;
    }
    else if(angle < Math.PI)
    {
        myX = -1;
        myY = Math.tan(Math.PI - angle);
    }
    else if(angle < 5*Math.PI/4)
    {
        myX = -1;
        myY = -Math.tan(angle - Math.PI);
    }
    else if(angle < 3*Math.PI/2)
    {
        myX = -Math.tan((3*Math.PI/2) - angle);
        myY = -1;
    }
    else if(angle < 7*Math.PI/4)
    {
        myX = Math.tan(angle - (3*Math.PI/2));
        myY = -1;
    }
    else
    {
        myX = 1;
        myY = -Math.tan(Math.PI*2 - angle);
    }

    // scale and translate the vector
    return new Point(
        (myX * width/2) + width/2, 
        (myY * width/2) + width/2);
}