, если это значение maxJsonLength является int, то насколько велико его int 32bit / 64bit / 16bit .... Я просто хочу быть уверенным, какое максимальное значение я могу установить как my maxJsonLength
<scripting>
<webServices>
<jsonSerialization maxJsonLength="2147483647">
</jsonSerialization>
</webServices>
</scripting>
Я думаю, что вы ищете внутреннее произведение (вы также можете просмотреть запись скалярное произведение ) двух углов. В вашем случае это дает:
float dx21 = x2-x1;
float dx31 = x3-x1;
float dy21 = y2-y1;
float dy31 = y3-y1;
float m12 = sqrt( dx21*dx21 + dy21*dy21 );
float m13 = sqrt( dx31*dx31 + dy31*dy31 );
float theta = acos( (dx21*dx31 + dy21*dy31) / (m12 * m13) );
Ответ в радианах.
РЕДАКТИРОВАТЬ: Вот полная реализация. Замените проблемные значения в p1, p2 и p3 и дайте мне знать, что вы получите. Точка p1 - это вершина, в которой две прямые пересекаются, в соответствии с вашим определением двух прямых.
#include <math.h>
#include <iostream>
template <typename T> class Vector2D
{
private:
T x;
T y;
public:
explicit Vector2D(const T& x=0, const T& y=0) : x(x), y(y) {}
Vector2D(const Vector2D<T>& src) : x(src.x), y(src.y) {}
virtual ~Vector2D() {}
// Accessors
inline T X() const { return x; }
inline T Y() const { return y; }
inline T X(const T& x) { this->x = x; }
inline T Y(const T& y) { this->y = y; }
// Vector arithmetic
inline Vector2D<T> operator-() const
{ return Vector2D<T>(-x, -y); }
inline Vector2D<T> operator+() const
{ return Vector2D<T>(+x, +y); }
inline Vector2D<T> operator+(const Vector2D<T>& v) const
{ return Vector2D<T>(x+v.x, y+v.y); }
inline Vector2D<T> operator-(const Vector2D<T>& v) const
{ return Vector2D<T>(x-v.x, y-v.y); }
inline Vector2D<T> operator*(const T& s) const
{ return Vector2D<T>(x*s, y*s); }
// Dot product
inline T operator*(const Vector2D<T>& v) const
{ return x*v.x + y*v.y; }
// l-2 norm
inline T norm() const { return sqrt(x*x + y*y); }
// inner angle (radians)
static T angle(const Vector2D<T>& v1, const Vector2D<T>& v2)
{
return acos( (v1 * v2) / (v1.norm() * v2.norm()) );
}
};
int main()
{
Vector2D<double> p1(215, 294);
Vector2D<double> p2(174, 228);
Vector2D<double> p3(303, 294);
double rad = Vector2D<double>::angle(p2-p1, p3-p1);
double deg = rad * 180.0 / M_PI;
std::cout << "rad = " << rad << "\tdeg = " << deg << std::endl;
p1 = Vector2D<double>(153, 457);
p2 = Vector2D<double>(19, 457);
p3 = Vector2D<double>(15, 470);
rad = Vector2D<double>::angle(p2-p1, p3-p1);
deg = rad * 180.0 / M_PI;
std::cout << "rad = " << rad << "\tdeg = " << deg << std::endl;
return 0;
}
Приведенный выше код дает:
rad = 2.12667 deg = 121.849
rad = 0.0939257 deg = 5.38155
Получение внешнего угла по сравнению с внутренним полностью определяется порядком вычитания (подумайте об этом). Вам нужно вычесть меньшую тэту из большей, чтобы всегда надежно получить внутренний угол. Вы также, вероятно, захотите использовать функцию atan2
из-за ожидаемого типа данных.
if (result > 180)
{
result = 360 - result;
}
Таким образом, это всегда будет внутренний угол. Просто добавьте его после получения результата.
Надеюсь, я правильно понял ваш вопрос, поскольку мне нужен острый угол, а не тупой угол пересечения двух линий. Я прав?
Острый и тупой углы пересечения дополняют друг друга на 180 градусов.то есть
acute + obtuse = PI.
http://www.mathworks.com/access/helpdesk/help/techdoc/ref/atan.html показывает, что атан асимптотичен при +/- pi / 2.
Следовательно, максимальная разница между двумя результатами атана равна пи или 180 градусов, независимо от того, используете ли вы нотацию +/-
или положительную нотацию от 0 до пи
градиента.
Рассмотрим следующий псевдокод:
acuteAngle(m1, m2){
a = atan(m1) - atan(m2);
// if obtuse get the complementary acute angle:
if (a>PI/2)
a = PI - a;
return a;
}
Функция sharpAngle
математически иллюстрирует, что вам нужно сделать.
Однако его нельзя использовать для значений углов в окрестности PI / 2, потому что двоичное сравнение углов с результатами в этой окрестности вызывает сомнения, представлен ли тупой или острый угол.
Следовательно, мы должны сравнить координаты точек двух прямых.
Мы выясняем, является ли 3-я линия, образованная из [(x2, y2) (x3, y3)]
, короче, равна или длиннее гипотетической гипотенузы.
В силу теоремы Пифагора Гипотенуза образуется, если угол составляет точно PI / 2 или 90 градусов. Назовем его гипотетическую линию гипотенузы L3Hypo.
Путем геометрической визуализации в уме,
Следовательно,
L1.lengthSquared = sq(x2-x1) + sq(y2-y1)
L2.lengthSquared = sq(x3-x1) + sq(y3-y1)
L3Hypo.lengthSquared = L1.lengthSquared + L2.lengthSquared
L3.lengthSquared = sq(x3-x2) + sq(y3-y2)
Следовательно, следующий псевдокод,
struct Point{
double x, y;
}
// no need to struct, for clarity only
struct Line{
double lengthSquared;
}
#define sq(n) (n*n)
int isObtuse(Point P1, P2, P3){
Line L1, L2, L3, L3Hypo;
L1.lengthSquared = sq(P2.x-P1.x) + sq(P2.y-P1.y);
L2.lengthSquared = sq(P3.x-P1.x) + sq(P3.y-P1.y);
L3Hypo.lengthSquared = L1.lengthSquared + L2.lengthSquared;
L3.lengthSquared = sq(P3.x-P2.x) + sq(P3.y-P2.y);
if (L3>L3Hypo) return 1; //obtuse
else if (L3<L3Hypo) return -1; //acute
else return 0;
}
Предполагая, что у вас уже есть функция getGradient (Point P, Q):
double m1m2 = getGradient(P1,P2);
double m1m3 = getGradient(P1,P3);
double a = Abs(atan(m1m2) - atan(m1m3));
if (isObtuse(P1, P2, P3)>0)
a = PI - a;
Возможно, я допустил несколько опечаток в псевдокоде (надеюсь, нет), но я продемонстрировал суть концепции. Если так, кто-нибудь может быть так любезен, чтобы отредактировать опечатки.
Далее Однако, поразмыслив над этим, я обнаружил, что борьба за точность сводится к ее самому слабому звену из-за директивы
#define PI 3.14159blah..blah..blah.
Итак, мы могли бы также избавить от всех проблем и просто сделать следующее:
double m1m2 = getGradient(P1,P2);
double m1m3 = getGradient(P1,P3);
double a = Abs(atan(m1m2) - atan(m1m3));
double b = PI - a;
return min(a, b);//the smaller of the two is the acute
Внутренний угол между двумя векторами (v1, v2) = arc cos ( внутреннее произведение(v1,v2) / (модуль(v1) * модуль(v2)) ).
Где внутреннее произведение(v1,v2) = xv1*xv2 + yv1*yv2
модуль(v) = sqrt(pow(xv,2) + pow(yv,2))
Итак, ответ на ваш вопрос реализован на следующем примере:
#define PI 3.14159258
int main()
{
double x1,y1,x2,y2,y3;
double m1, m2;
double mod1, mod2, innerp, angle;
cout << "x1 :";
cin >> x1;
cout << "y1 :";
cin >> y1;
cout << "x2 :";
cin >> x2;
cout << "y2 :";
cin >> y2;
cout << "y3 :";
cin >> y3;
m1 = atan((y2-y1)/(x2-x1)) * 180 / PI;
m2 = atan((y3-y1)/(x2-x1)) * 180 / PI;
mod1 = sqrt(pow(y2-y1,2)+pow(x2-x1,2));
mod2 = sqrt(pow(y3-y1,2)+pow(x2-x1,2));
innerp = (x2-x1)*(x2-x1) + (y2-y1)*(y3-y1);
angle = acos(innerp / (mod1 * mod2)) * 180 / PI;
cout << "m1 : " << m1 << endl;
cout << "m2 : " << m2 << endl;
cout << "angle : " << angle << endl;
}
Вся суть гораздо проще, чем приведенные ответы:
При использовании atan(slope) вы теряете (буквально) один бит информации, то есть существует ровно два угла (theta) и (theta+PI) в диапазоне (0..2*PI), которые дают одинаковое значение для функции tan().
Просто используйте atan2(deltax, deltay), и вы получите прямой угол. Например
atan2(1,1) == PI/4
atan2(-1,-1) == 5*PI/4
Затем вычтите, возьмите абсолютное значение, и если больше PI, вычтите из 2*PI.