Javascript 如何在SVG坐标系中从3个x/y点查找旋转度

Javascript 如何在SVG坐标系中从3个x/y点查找旋转度,javascript,math,svg,2d,coordinates,Javascript,Math,Svg,2d,Coordinates,很抱歉,我应该知道这一点。我在SVG二维坐标系上有2个点。我需要得到度(0-360),现在我能返回的就是0-180回到0,0-180上没有正负号。。。我可以找到相近的问题,但没有一个会导致0-360 以下是javascript中的代码: // center point, say 200,200 var rx = that.get("rotateOriginX"); // ember code but substitute 200,200 if you want var ry = th

很抱歉,我应该知道这一点。我在SVG二维坐标系上有2个点。我需要得到度(0-360),现在我能返回的就是0-180回到0,0-180上没有正负号。。。我可以找到相近的问题,但没有一个会导致0-360

以下是javascript中的代码:

// center point, say 200,200
var rx = that.get("rotateOriginX");     // ember code but substitute 200,200 if you want  
var ry = that.get("rotateOriginY");

// I create third point (directly up on coordinate system)
// 200, 190 - line straight up and down to angle vertex above
var p1x = rx;        
var p1y = ry - 10;   // this is negative 10 to go up because svg y axis starts in upper left

// mouse position variable, this can be 360 degrees around vertex
var p2x = d3.mouse(this.parentNode.parentNode)[0];   
var p2y = d3.mouse(this.parentNode.parentNode)[1];

// I have three points now
var p0c = Math.sqrt(Math.pow(rx-p1x, 2) + Math.pow(ry-p1y, 2));
var p1c = Math.sqrt(Math.pow(rx-p2x, 2) + Math.pow(ry-p2y, 2));
var p0p1 = Math.sqrt(Math.pow(p2x-p1x, 2) + Math.pow(p2y-p1y, 2));

// this always returns 0-180-0 but is not signed (+/-) 
// ALL I WANT IS 0-360 so I can rotate a shape to user's preference as determined by mouse
var degrees = (180 * (Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c))) / Math.PI);

解决办法是这样的,虽然任何一个“数学人”或女孩都可能会简化一些,但我觉得我把它复杂化了,但我得到了我需要的东西。如果你简化它,请提供一些解释

Math.acos返回一个从-180到180的浮点值,零面向右/东(如果视为指南针),0到-180覆盖圆周长的上半部分。0到+180从右向左延伸,覆盖圆的下半部圆周(180为360的一半)。这对于偶尔做一次数学的人来说可能很正常(0向右,逆时针增加数字)。因为我从2个x/y点开始,我知道我希望0面朝上/向北,所以我可以在函数中自动创建第三个点,只需要2个点作为参数

因此,有3个点,一个始终朝上/朝北,在2d平面上,我从Math.acos获得弧度,如上所述。然后我得到Math.atan2的结果,它给了我看起来像弧度的东西(0-180和0--180),但是它不是面向东/右,而是面向上/北,因此通过这个附加信息(以及它被符号[+-]),我可以推导出原始数字所在的象限(无符号的0-180)然后,如果点在左上方象限或左下方象限,我只需通过从360中减去来修正度变量

复杂,是的,功能是的,优雅,不。标记为回答不占用他人资源,但欢迎更合理的解释

findBearingOfTwoPoints: function(p1, p2, forceInt){
    var degrees = 0;
    try{
        var a1 = Math.sqrt(Math.pow(p1.x - p1.x, 2) + Math.pow(p1.y - (p1.y - 10), 2));
        var a2 = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
        var a3 = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - (p1.y - 10), 2));

        // this is probably better to be called radians
        degrees = (180 * (Math.acos((a2 * a2 + a1 * a1 - a3 * a3)/(2 * a2 * a1))) / Math.PI);

        var angle  = 0;
        var deltaY = p2.y - p1.y;
        var deltaX = p2.x - p1.x;
        angle  = (Math.atan2(deltaY, deltaX) * (180 / Math.PI));

        if(angle < -90 || angle > 90){
            degrees = 360 - degrees;
        }

        if(forceInt===true){
            degrees = parseInt(degrees);
        }
    }
    catch(e){
        //
    }
    return degrees;
},
findbearingoftwoints:函数(p1、p2、forceInt){
变量度=0;
试一试{
var a1=Math.sqrt(Math.pow(p1.x-p1.x,2)+Math.pow(p1.y-(p1.y-10),2));
vara2=Math.sqrt(Math.pow(p1.x-p2.x,2)+Math.pow(p1.y-p2.y,2));
var a3=Math.sqrt(Math.pow(p2.x-p1.x,2)+Math.pow(p2.y-(p1.y-10),2));
//这可能更适合称为弧度
度=(180*(数学acos((a2*a2+a1*a1-a3*a3)/(2*a2*a1))/Math.PI);
var角=0;
var deltaY=p2.y-p1.y;
增值税=p2.x-p1.x;
角度=(数学atan2(deltaY,deltaX)*(180/数学PI));
如果(角度<-90 | |角度>90){
度=360度;
}
如果(forceInt==真){
度=parseInt(度);
}
}
捕获(e){
//
}
返回度;
},
  • acos,asin

    • 是四象限的
    • 但在整个范围内并不精确
    • 还有一些其他的问题,比如需要夹紧
  • atan(dy/dx)

    • 只有2象限
    • 这是因为
      atan(dy/dx)
      松开了原始
      dx,dy的符号
  • 四象限
    atan(dy/dx)
    =
    atan2(dy,dx)
    atanxy(dx,dy)

    • 它只是
      atan
      ,带有一些dx,dy符号的决策表来处理所有象限
    • 这是我的C++