2016-03-31 3 views

ответ

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)); 
} 

Вы можете сделать это намного быстрее, но если вы хотите ускорить, то, вероятно, использовать библиотеку.

+0

танка я попытаюсь что :) – Bobby

0

Использование продукта вектор точка:

а. б = | || Ь | соз $ \ 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)

и

| б | = SQRT (v2.x * v2.x + v2.y * v2.y + v2.z * v2.z)

Разделить Лучший результат на двух нижних результатов, а затем принять его ARccOS, угол запоминания будет в радианах.

+0

Да, это основная математика участвует, но есть несколько шагов, отсутствует при использовании процессора для выполнения вычислений: вы должны проверить, чтобы вектор3 не был вектором 0, иначе у вас будет деление на 0, а когда вы вычисляете угол cos, вам все равно нужно сдерживать значения, вызванные ошибки округления. Помимо этого вы находитесь на месте! –

0

Основная математическая формула для вычисления угла между двумя векторами как таковой:

Рассмотрим & б быть векторами.

точка Ь = абс (а) * абс (б) * COS (угол)

-> COS-1 ((точка б)/(абс (а) * абс (б))

Даже если вы работаете в 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++ классов, которые находятся в пределах одного моей математики библиотеки. Это используется как демонстрация того, как можно вычислить угол между двумя векторами.

3

Использование acos(a.b/(|a||b|) нестабильно, когда угол небольшой (или около 180 градусов). В двухмерном или трехмерном случае вместо этого следует использовать 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); 
Смежные вопросы