我有2分:
v1 = {x:1,y:0,z:0}
v2 = {x:0,y:2,z:0}
我想计算这两点的角度。 我知道如何在2D中制作它,但不是在3D中,我有点迷失^^
基本上像在Unity中一样:
http://docs.unity3d.com/ScriptReference/Vector3.Angle.html
感谢您提示:3
答案 0 :(得分:3)
当角度很小(或接近180度)时,使用acos(a.b/(|a||b|)
是不稳定的。在2D或3D情况下,解决方案是使用atan2(,)
代替。
对于3D,计算点积和交叉产品的长度:
let dot = v1.x * v2.x + v1.y * v2.y + v3.z * v3.z;
let crossX = v1.y * v2.z - v1.z * v2.y;
let crossY = v1.z * v2.x - v1.x * v2.z;
let crossZ = v1.x * v2.y - v1.y * v2.x;
let crosslen = sqrt(crossX*crossX + crossY*crossY + crossZ*crossZ);
return atan2(dot, crosslen);
答案 1 :(得分:2)
听起来对于这个项目你想要找到一个你可以阅读而不会发疯的矢量数学参考。
For this case,点积v1.v2 = x1*x2 + y1*y2 + z1*z2 = |v1| * |v2| * cos theta
,表示您的角度为
function angle(v1, v2) {
return Math.acos(dotProduct(v1, v2) / (length(v1) * length(v2)));
}
function dotProduct(v1, v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
function length(v) {
return Math.sqrt(dotProduct(v, v));
}
你可以加快速度,但如果你想要速度,那么可能会使用一个库。
答案 2 :(得分:0)
使用矢量点积:
a。 b = | a || b | cos $ \ theta $
用你的记谱法:
v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
虽然
| A | = sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z)
和
| B | = sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z)
将最高结果除以底部两个结果,然后取其 arccos ,记住角度将以弧度为单位。
答案 3 :(得分:0)
计算两个向量之间角度的基本数学公式如下:
考虑一个& b是矢量。
点b = abs(a)* abs(b)* cos(角度)
- > cos-1((a点b)/(abs(a)* abs(b))
即使你在javascript中工作,计算的概念也是一样的:我能为你做的是向我展示我用Vector3类编写的用c ++编写的函数
// -----------------------------------------------------------------------
// GetCosAngle()
// Returns The cos(Angle) Value Between This Vector And Vector V. This
// Is Less Expensive Than Using GetAngle
inline float Vector3::GetCosAngle( const Vector3 &v3, const bool bNormalized ) {
// a . b = |a||b|cos(angle)
// -> cos-1((a.b)/(|a||b|))
// Make Sure We Do Not Divide By Zero
float fMagA = Length();
if ( fMagA <= Math::ZERO ) {
// This (A) Is An Invalid Vector
return 0;
}
float fValue = 0;
if ( bNormalized ) {
// v3 Is Already Normalized
fValue = Dot(v3)/fMagA;
}
else {
float fMagB = v3.Length();
if ( fMagB <= Math::ZERO) {
// B Is An Invalid Vector
return 0;
}
fValue = Dot(v3)/(fMagA*fMagB);
}
// Correct Value Due To Rounding Problem
Math::Constrain( -1.0f, 1.0f, fValue );
return fValue;
} // GetCosAngle
// -----------------------------------------------------------------------
// GetAngle()
// Returns The Angle Between This Vector And Vector V in Radians.
// This Is More Expensive Than Using GetCosAngle
inline float Vector3::GetAngle( const Vector3 &v3, const bool bNormalized, bool bRadians ) {
// a . b = |a||b|cos(angle)
// -> cos-1((a.b)/(|a||b|))
if ( bRadians ) {
return acos( this->GetCosAngle( v3 ) );
}
else {
// Convert To Degrees
return Math::Radian2Degree( acos( GetCosAngle( v3, bNormalized ) ) );
}
} // GetAngle
以下是Vector3类中用于执行这些计算的附加函数:
// -----------------------------------------------------------------------
// Length()
// Return The Length Of This Vector
inline float Vector3::Length() const {
return sqrtf( _fX * _fX +
_fY * _fY +
_fZ * _fZ );
} // Length
// -----------------------------------------------------------------------
// Dot()
// Return The Dot Product Between This Vector And Another One
inline float Vector3::Dot( const Vector3 v3 ) const {
return ( _fX * v3._fX +
_fY * v3._fY +
_fZ * v3._fZ );
} // Dot
以下是我在这些计算中使用的数学函数和值:
const float Math::PI = 4.0f * atan(1.0f); // tan(pi/4) = 1
const float Math::PI_INVx180 = 180.0f / Math::PI;
const float Math::ZERO = (float)1e-7;
// -----------------------------------------------------------------------
// Constrain()
// Prevent Value From Going Outside The Min, Max Range.
template<class T>
inline void Math::Constrain( T min, T max, T &value ) {
if ( value < min ) {
value = min;
return;
}
if ( value > max ) {
value = max;
}
} // Constrain
/ -----------------------------------------------------------------------
// Radian2Degree()
// Convert Angle In Radians To Degrees
inline float Math::Radian2Degree( float fRadians ) {
return fRadians * PI_INVx180;
} // Radian2Degree
现在正如我所说,这些属于我的一个数学库中的几个c ++类。这用于演示如何计算两个向量之间的角度。