我试图在点的角度之间做一些比较,但很快我遇到了一些奇怪的结果。
在这个例子中,我尝试旋转线条使它们指向中心,但线条看起来比它们应该很快的角度。然后,在中心的正上方和下方,线条开始指向各种方向(These values are beyond the mathematical range of atan(x))。
如何从Math.atan()获得准确的结果?有没有其他方法可以进行此计算?
我上传了一个'工作'这个小提琴的版本: https://jsfiddle.net/0y2p6p3n/。我在Chrome工作。
HTML:
<div id="content">
</div>
的javascript:
let points = [];
let amount = 1000;
let width = 300;
let height = 300;
for (let i = 0; i<amount;i++) {
let x = Math.random();
let y = Math.random();
let point = {x, y};
points.push(point);
points[i].tan = Math.atan(0.5 - points[i].y)/(0.5 - points[i].x);
points[i].error = Math.abs(points[i].tan) > 3.14/2 ? true : false;
}
for (let point of points) {
let line = document.createElement("div");
line.classList.add("line");
line.style.marginTop = point.y*height + "px";
line.style.marginLeft = point.x*width + "px";
line.style.transform = "rotateZ(" + ((point.tan*(180/Math.PI))) + "deg)";
point.error == true && line.classList.add("error");
document.getElementById("content").appendChild(line);
}
的CSS:
#content {
position: relative;
}
.line {
position: absolute;
height: 1px;
width: 10px;
background-color: black;
}
.error {
background-color: red;
}
答案 0 :(得分:4)
您正在使用
points[i].tan = Math.atan(0.5 - points[i].y)/(0.5 - points[i].x);
应该是
points[i].tan = Math.atan( (0.5 - points[i].y)/(0.5 - points[i].x) );
let points = [];
let amount = 1000;
let width = 300;
let height = 300;
for (let i = 0; i<amount;i++) {
let x = Math.random();
let y = Math.random();
let point = {x, y};
points.push(point);
points[i].tan = Math.atan( (0.5 - points[i].y)/(0.5 - points[i].x) );
points[i].error = Math.abs(points[i].tan) > 3.14/2 ? true : false;
}
for (let point of points) {
let line = document.createElement("div");
line.classList.add("line");
line.style.marginTop = point.y*height + "px";
line.style.marginLeft = point.x*width + "px";
line.style.transform = "rotateZ(" + ((point.tan*(180/Math.PI))) + "deg)";
point.error == true && line.classList.add("error");
document.getElementById("content").appendChild(line);
}
#content {
position: relative;
}
.line {
position: absolute;
height: 1px;
width: 10px;
background-color: black;
}
.error {
background-color: red;
}
<div id="content"></div>
答案 1 :(得分:3)
正如您所提到的,确切的渐近线(即pi / 2和-pi / 2)不在atan
的有效域之内,这使得这些值的atan
成为不可能。您还可能需要处理这样一个事实:atan始终返回一个参考角度,这可能不是您希望答案所在的象限。这些都是众所周知的问题,大多数语言都有一个简单的治疗方法,称为atan2。如果是javascript,请参阅the MDN reference for atan2。
对代码的更改很简单;只需更改
points[i].tan = Math.atan(0.5 - points[i].y)/(0.5 - points[i].x);
到
points[i].tan = Math.atan2(0.5 - points[i].y, 0.5 - points[i].x);
如果您查看updated fiddle,您可能会发现其行为有了很大改善。
atan2没有给你更高的精度,但它确实给你超过[0..2pi]的整个范围的值,而你不必做任何额外的工作来弄清楚答案应该在哪个象限,以及在其范围内支持pi / 2和-pi / 2。通过了解x或y(或两者)是否为负值来帮助这样做,如果你自己进行除法,这个事实会被隐藏。
应该注意的是,我对您的代码所做的最重大的更改不是atan2,但是,它正在改变您对括号的使用。虽然我通常使用atan时主动使用atan2,但你的实际问题是误用括号,使得Oriol的回答是正确的。