Мне нужен мой код, чтобы найти 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
Порядок ввода каждой вершины не указан.
Если у вас есть три вершины, то у вас есть половина прямоугольника: прямоугольный треугольник. Сначала нужно определить, какая точка находится под прямым углом. Вы можете сделать это по-разному. Один из способов — применить теорему Пифагора: найти две самые дальние вершины. Оставшаяся вершина находится под прямым углом (другим способом может быть вычисление скалярного произведения между каждой парой ребер, а та, которая ближе всего к нулю, образует прямой угол).
Давайте назовем вершину под прямым углом A
и два других B
а также C
, Теперь векторы двух более коротких ребер прямоугольного треугольника B-A
а также C-A
, Если вы добавите эти края в A
вы получите 4-ю вершину:
D=A+(B-A)-(C-A)=B+C-A
Работа с векторами — очень интересная тема. Вот несколько хороших объяснений о вектор
Чтобы ответить на ваш вопрос:
Из трех заданных вершин 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. Если длина между двумя точками меньше этого значения, эти две точки можно рассматривать как уникальную точку — они остаются в одной и той же позиции).