Нахождение 4-й вершины прямоугольника

Мне нужен мой код, чтобы найти 4-ую вершину прямоугольника. Пытался что-то сделать но как всегда не получилось. Это работает в некоторых случаях, бот не каждый раз. Может ли кто-нибудь помочь мне с этим?
Кроме того, это должно быть сделано с 2 классами, один для вершин и другой для целого прямоугольника.
Проблема в том, что мой код работает для определенной настройки вершины. Я много чего пробовал, но все равно не получилось.

Вот код:

#include <iostream>
#include <cmath>
using namespace std;

class vertex{
public:
double x;
double y;
void insert(){
cin>>x;
cin>>y;
}
};

class rect{
private:
double ax, ay, bx, by, cx, cy, dx, dy;
public:
void insert_data(vertex A, vertex B, vertex C){         //inserting rectangle data
ax=A.x;
ay=A.y;
bx=B.x;
by=B.y;
cx=C.x;
cy=C.y;
}
void calculate(){           //finding 4h vertex coordinates
dx=cx+(abs(ax-bx));
dy=cy+(abs(ay+by));
}
void out(){                 //output
cout<<dx<<" "<<dy;
}

};
using namespace std;

int main() {
vertex A, B, C;
A.insert();
B.insert();
C.insert();
rect X;
X.insert_data(A, B, C);
X.calculate();
X.out();return 0;
}

Поскольку я думаю об этом сейчас, он может иметь какое-то отношение к вставке координат в правильные переменные, но не может придумать решение, чтобы это исправить.

Например:
Входные данные:
1 1
0 3
3 2
Выход:
2 4

Порядок ввода каждой вершины не указан.

3

Решение

Если у вас есть три вершины, то у вас есть половина прямоугольника: прямоугольный треугольник. Сначала нужно определить, какая точка находится под прямым углом. Вы можете сделать это по-разному. Один из способов — применить теорему Пифагора: найти две самые дальние вершины. Оставшаяся вершина находится под прямым углом (другим способом может быть вычисление скалярного произведения между каждой парой ребер, а та, которая ближе всего к нулю, образует прямой угол).

Давайте назовем вершину под прямым углом Aи два других B а также C, Теперь векторы двух более коротких ребер прямоугольного треугольника B-A а также C-A, Если вы добавите эти края в Aвы получите 4-ю вершину:

D=A+(B-A)-(C-A)=B+C-A

2

Другие решения

Работа с векторами — очень интересная тема. Вот несколько хороших объяснений о вектор

Чтобы ответить на ваш вопрос:

Из трех заданных вершин A, B и C у вас есть только три случая прямого угла: в A, в B или в C. Если вы нашли правильный угол, например, в B (независимо от порядка A и C) , у вас есть координата D, рассчитанная по формуле: D = A + C — B.

Чтобы определить, что прямой угол равен B: произведение точек двух векторов BA и BC равно 0, независимо от порядка A и C.

В C ++ (не C) вы должны добавить операторы для управления векторами в вашем классе вершин, вот пример:

#define MY_EPSILON 10E-6

class vertex {
public:
double X, Y;
vertex(double x_, double y_ ) :X(x_), Y( y_){}
vertex():X(0), Y(0){}

vertex operator +( vertex v ){ return vertex( X + v.X, Y + v.Y ); }
vertex operator -( vertex v ){ return vertex( X - v.X, Y - v.Y ); }
double dot( vertex v ){ return X * v.X + Y * v.Y; }
double length() { return sqrt(X * X + Y * Y ); }
vertex normalize( bool &bOk ){
double len = length(); bOk = false;
if( len > MY_EPSILON ){  bOk = true; return vertex( X/len, Y/len ); }
return *this;
}
};

std::ostream & operator << ( std::ostream & s, vertex v ){
s << std::setprecision(6) << "(" << v.X << "," << v.Y << ") ";
return s;
}

Точечное произведение двух векторов:

Чтобы проверить, находится ли прямой угол в точке B, мы можем использовать следующую функцию, она вычислит произведение точек двух нормализованных векторов AB и BC:

bool isRighAngle( vertex a, vertex b, vertex c){
bool bOkAB, bOkBC;
vertex uAB = ( b - a ).normalize( bOkAB ), uBC = ( c - b ).normalize( bOkBC );
return bOkAB && bOkBC && fabs(uAB.dot( uBC )) < MY_EPSILON;
}

Обратите внимание, что когда мы сравниваем двойное значение с нулем, всегда используем эпсилон, для двойного нет абсолютного нуля. Эта функция также возвращает false, если один из нормализованных векторов не может быть вычислен (две точки расположены слишком близко друг к другу).

Вычислить последнюю координату под прямым углом:

Эта следующая функция возвращает true, если последний кординат D рассчитывается по прямому углу B:

    bool getLastCoordinateIfRightAngle( vertex a, vertex b, vertex c, vertex & d ){
if( isRighAngle( a, b, c ) ){
d = (a + c) - b;
return true;
}
return false;
}

Ищите правильный угол:

Таким образом, чтобы найти последнюю координату D из 3 вершин A, B и C, вы должны выполнить тест для трех случаев прямого угла, тест останавливается, когда решение найдено:

    bool getLastCoordinate( vertex a, vertex b, vertex c, vertex &d ){

if( getLastCoordinateIfRightAngle( a, b, c, d )   //if B is at the right angle
|| getLastCoordinateIfRightAngle( a, c, b, d ) //if C is at the right angle
|| getLastCoordinateIfRightAngle( b, a, c, d ) ) //if A is at the right angle
{
return true;
}

//No right angle found.
return false;
}

Быстрый тест :

Мы можем сделать быстрый тест, если он работает:

    int main(int argc, char *argv[])
{
vertex A(0.0, 0.0), B(1.0, 0.0), C(0.0, 1.0), D;

if( getLastCoordinate( A, B, C, D ) ){
std::cout << "D coordinate " << D << " found from inputs :  " << A << B << C << std::endl;
}else {
std::cout << "D coordinate not found for input:  " << A << B << C << std::endl;
}

return 0;
}

EPSILON CHOICE:

Это зависит от вашего домена: если вы работаете в очень маленьком объектном домене, который (X, Y) очень мал (например, близок к 10E-5), у вас будут некоторые трудности в вычислениях (плавающая точка в GPU очень ограничена в точность). Лучше преобразовать рабочий домен в нормальный диапазон.
В приведенном выше примере EPSILON установлен на 10E-6. Если длина между двумя точками меньше этого значения, эти две точки можно рассматривать как уникальную точку — они остаются в одной и той же позиции).

1

По вопросам рекламы [email protected]