найдите, формируют ли 4 точки на плоскости прямоугольник?

Кто-то может показать мне в псевдокоде C-стиля, как записать, функция (представьте точки однако, Вам нравится), который возвращает true, если 4 точки (args к функции) формируют прямоугольник и ложь иначе?

Я предложил решение, которое сначала пытается найти 2 отличных пар точек с равным x-значением, затем делает это для оси y. Но код довольно длинен. Просто любопытный видеть то, что придумывают другие.

51
задан Josh Lee 22 February 2010 в 04:29
поделиться

7 ответов

Не уверен, что это устранит вашу проблему, но в JavaScript значение null не совпадает с значением undefined. Написанный код подходит для тестирования, если переменная не определена. IE:

<script>
window.onload = function()
{
     alert(typeof(abcd) == "undefined"); //true
     abcd = null;
     alert(typeof(abcd) == "undefined"); //false
};
</script>

Кстати, тип null - "object".

-121--4378563-

Вы можете считать HEAD "текущей ветвью". При переключении ветвей с помощью git checkout редакция HEAD изменяется, указывая на кончик новой ветви.

Вы можете увидеть, на что указывает HEAD:

cat .git/HEAD

В моем случае результат:

$ cat .git/HEAD
ref: refs/heads/master

HEAD может ссылаться на конкретную редакцию, которая не связана с именем ветви. Эта ситуация называется отсоединенный HEAD .

-121--1762196-

Если точки A, B, C & D, и вы знаете порядок, то вы рассчитываете векторы:

x = B-A, y = C-B, z = D-C и w = A-D

Тогда возьмите точечные произведения (x точка y), (y точка Если все они равны нулю, то у вас есть прямоугольник.

3
ответ дан 7 November 2019 в 09:58
поделиться

Расстояние от одной точки до трех других должно образовывать правильный треугольник:

|   /      /|
|  /      / |
| /      /  |
|/___   /___|
d1 = sqrt( (x2-x1)^2 + (y2-y1)^2 ) 
d2 = sqrt( (x3-x1)^2 + (y3-y1)^2 ) 
d3 = sqrt( (x4-x1)^2 + (y4-y1)^2 ) 
if d1^2 == d2^2 + d3^2 then it's a rectangle

Упрощая:

d1 = (x2-x1)^2 + (y2-y1)^2
d2 = (x3-x1)^2 + (y3-y1)^2
d3 = (x4-x1)^2 + (y4-y1)^2
if d1 == d2+d3 or d2 == d1+d3 or d3 == d1+d2 then return true
4
ответ дан 7 November 2019 в 09:58
поделиться
  • найти центр масс угловых точек: cx = (x1 + x2 + x3 + x4) / 4, cy = (y1 + y2 + y3 + y4) / 4
  • проверить, является ли квадрат расстояний от центра масса для всех 4 углов равна
 bool isRectangle (double x1, double y1, 
double x2, double y2, 
double x3, double y3, 
double x4, double y4) 
 {
double cx, cy; 
double dd1, dd2, dd3, dd4; 
 
cx = (x1 + x2 + x3 + x4) / 4; 
cy = (y1 + y2 + y3 + y4) / 4; 
 
dd1 = sqr (cx-x1) + sqr (cy-y1) ; 
dd2 = sqr (cx-x2) + sqr (cy-y2); 
dd3 = sqr (cx-x3) + sqr (cy-y3); 
dd4 = sqr (cx-x4) + sqr (cy-y4); 
return dd1 == dd2 && dd1 == dd3 && dd1 == dd4; 
} 
 

( Конечно, на практике проверка равенства двух чисел с плавающей запятой a и b должна выполняться с конечной точностью: например, abs (ab) <1E-6)

61
ответ дан 7 November 2019 в 09:58
поделиться
struct point
{
    int x, y;
}

// tests if angle abc is a right angle
int IsOrthogonal(point a, point b, point c)
{
    return (b.x - a.x) * (b.x - c.x) + (b.y - a.y) * (b.y - c.y) == 0;
}

int IsRectangle(point a, point b, point c, point d)
{
    return
        IsOrthogonal(a, b, c) &&
        IsOrthogonal(b, c, d) &&
        IsOrthogonal(c, d, a);
}

Если порядок неизвестен заранее, нам потребуется более сложная проверка:

int IsRectangleAnyOrder(point a, point b, point c, point d)
{
    return IsRectangle(a, b, c, d) ||
           IsRectangle(b, c, a, d) ||
           IsRectangle(c, a, b, d);
}
40
ответ дан 7 November 2019 в 09:58
поделиться

Делая еще один шаг вперед в предложении точечного произведения, проверьте, перпендикулярны ли два вектора, образованные любыми 3 точками, а затем посмотрите, совпадают ли x и y с четвертой точкой.

Если есть точки [Ax,Ay] [Bx,By] [Cx,Cy] [Dx,Dy]

вектор v = B-A вектор u = C-A

v(dot)u/|v|||u| == cos(theta)

поэтому если (v.u == 0), то прямо здесь есть пара перпендикулярных линий.

Вообще-то я не знаю программирования на C, но вот вам немного "мета" программирования :P

if (v==[0,0] || u==[0,0] || u==v || D==A) {not a rectangle, not even a quadrilateral}

var dot = (v1*u1 + v2*u2); //computes the "top half" of (v.u/|v||u|)
if (dot == 0) { //potentially a rectangle if true

    if (Dy==By && Dx==Cx){
     is a rectangle
    }

    else if (Dx==Bx && Dy==Cy){
     is a rectangle
    }
}
else {not a rectangle}

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

Итак, с вычислительной точки зрения, чтобы получить v и u, нужно выполнить четыре вычитания, два умножения, одно сложение и проверить где-то от 1 до 7 равенств.

Может быть, я выдумываю, но я смутно помню, что где-то читал, что вычитание и умножение - это "более быстрые" вычисления. Я предполагаю, что объявление переменных/массивов и установка их значений также достаточно быстры?

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

Edit: попробуйте это, основываясь на моем комментарии ниже:

A = [a1,a2];
B = [b1,b2];
C = [c1,c2];
D = [d1,d2];

u = (b1-a1,b2-a2);
v = (c1-a1,c2-a2);

if ( u==0 || v==0 || A==D || u==v)
    {!rectangle} // get the obvious out of the way

var dot = u1*v1 + u2*v2;
var pgram = [a1+u1+v1,a2+u2+v2]
if (dot == 0 && pgram == D) {rectangle} // will be true 50% of the time if rectangle
else if (pgram == D) {
    w = [d1-a1,d2-a2];

    if (w1*u1 + w2*u2 == 0) {rectangle} //25% chance
    else if (w1*v1 + w2*v2 == 0) {rectangle} //25% chance

    else {!rectangle}
}
else {!rectangle}
1
ответ дан 7 November 2019 в 09:58
поделиться

Мы знаем, что две прямые прямые линии перпендикулярны, если произведение их наклонов равно -1, поскольку учитывая, что мы можем найти наклон трех последовательных линий, а затем умножить их, чтобы проверить, действительно ли они перпендикулярны или нет. Предположим, у нас есть прямые L1, L2, L3. Теперь, если L1 перпендикулярно L2, а L2 перпендикулярно L3, то это прямоугольник и наклон m (L1) * m (L2) = - 1 и m (L2) * m (L3) = - 1, то он подразумевает, что это прямоугольник. Код выглядит следующим образом

bool isRectangle(double x1,double y1,
        double x2,double y2,
        double x3,double y3,
        double x4,double y4){
    double m1,m2,m3;
    m1 = (y2-y1)/(x2-x1);
    m2 = (y2-y3)/(x2-x3);
    m3 = (y4-y3)/(x4-x3);

    if((m1*m2)==-1 && (m2*m3)==-1)
        return true;
    else
        return false;
}
1
ответ дан 7 November 2019 в 09:58
поделиться
  • переместите четырехугольник так, чтобы одна из его вершин теперь лежала в начале координат
  • , три оставшиеся точки образуют три вектора из начала
  • , одну из они должны представлять диагональ
  • , две другие должны представлять стороны
  • по правилу параллелограмма , если стороны образуют диагональ, у нас есть параллелограмм
  • , если стороны образуют прямой угол, это параллелограмм с прямым углом
  • противоположные углы параллелограмма равны
  • последовательные углы параллелограмма являются дополнительными
  • поэтому все углы прямые
  • это прямоугольник
  • много однако более сжатый код: -)

     static bool IsRectangle (
    int x1, int y1, int x2, int y2, 
    int x3, int y3, int x4, int y4) 
     {
    x2 - = x1; х3 - = х1; х4 - = х1; y2 - = y1; y3 - = y1; y4 - = y1; 
    return 
     (x2 + x3 == x4 && y2 + y3 == y4 && x2 * x3 == -y2 * y3) || 
     (x2 + x4 == x3 && y2 + y4 == y3 && x2 * x4 == -y2 * y4) || 
     (x3 + x4 == x2 && y3 + y4 == y2 && x3 * x4 == -y3 * y4); 
    } 
     
  • (Если вы хотите заставить его работать со значениями с плавающей запятой, пожалуйста, не просто слепо заменяйте объявления int в заголовки. Это плохая практика. Они существуют по какой-то причине. При сравнении результатов с плавающей запятой всегда следует работать с некоторой верхней границей ошибки.)

5
ответ дан 7 November 2019 в 09:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: