Это правильный способ проверить, являются ли две линии коллинеарными? - PullRequest
1 голос
/ 11 ноября 2011

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

bool line::isColinear(line)
{
     bool line2=false;
     line l1,l2;

     if (l1.slope()==l2.slope())
     {
         if (l1.y_int()==l2.y_int())
         {
             line2 =true;
             return line2;
         }
     }
     else
     { 
         line2 =false;
     }

}

// Вот копия моего класса линии

class line
{
    private:

    point p1,p2;

    public:

    bool isColinear(line);
    bool isParallel(line);
    point solve(line);
    double slope();
    double y_int();
    void  Display(ostream&);
};

Ответы [ 4 ]

2 голосов
/ 11 ноября 2011
  1. Вы сохраняете линию между двумя точками. Наклон линии обычно определяется как

    slope = (y2 - y1) / ( x2 - x1 )

если x1 равно x2 , вы можете иметь деление на ноль ошибок / исключений.

Другие вещи, о которых нужно быть осторожными

  1. Если вы сохраняете координаты точки в виде целых чисел, вы можете просто делить целочисленное деление, а не получить то, что ожидаете
  2. Если вы используете двойные значения повсюду, пожалуйста, используйте допуски при их сравнении
1 голос
/ 11 ноября 2011

Я предполагаю, что, поскольку l1 и l2 неинициализированы, их методы slope делят на ноль. Инициализируйте их правильно или переключитесь на правильные переменные, и вы исправите свое падение.

Даже если вы заработаете, тест, скорее всего, не пройдёт. Вы не можете сравнивать числа с плавающей запятой и ожидать, что они будут равны, даже если кажется, что они должны быть равны. Вам следует прочитать Что должен знать каждый ученый об арифметике с плавающей точкой .

1 голос
/ 11 ноября 2011

Здесь недостаточно, чтобы действительно судить о том, что идет не так, поэтому несколько общих черт:

  • Никогда не сравнивайте значения с плавающей точкой напрямую на равенство. Это не будет работать удивительное количество времени. Вместо этого сравните их разницу с такой малой суммой, что вы можете назвать это «нулем» (обычно мы называем это «эпсилон»):

    if (abs((num1 - num2)) < 0.001) {
        /* pretend they're equal */
    } else {
        /* not equal */
    }
    
  • line2 не требуется в этом примере. Вы также можете вернуть true или false непосредственно из заключений. Часто даже return true или return false излишне сбивают с толку. Предположим, что вы немного переписали этот метод для трех методов. (Что может или не может быть улучшением. Просто примите это на некоторое время.)

    bool line::compare_slope(line l2) {
        return fabs((l2.slope() - self.slope()) < 0.001; // don't hardcode this
    }
    
    bool line::compare_origin(line l2) {
        return fabs((l2.y_int() - self.y_int()) < 0.001; // nor this
    }
    
    bool line::is_colinear(line l2) {
        return compare_slope(l2) && compare_origin(l2);
    }
    

    Нет true или false, жестко запрограммированный в любом месте - вместо этого вы полагаетесь на значение условных выражений для вычисления true или false. (И, между прочим, повторение этих функций показывает, что функция floating_comparison(double f1, double f2, double epsilon) может значительно упростить модификацию эпсилона либо для всего проекта, либо для вычисления эпсилона на основе абсолютных значений рассматриваемых чисел с плавающей запятой.)

0 голосов
/ 11 ноября 2011

Простая формула для линии (в 2D) (полученная из здесь ):

P1 (x1, y1) и P2 (x2, y2) - это точки, определяющиеline.

(y-y1) (x2-x1) + (y1-y2) (x-x1) = 0 (давайте использовать f (x, y) = 0)

Чтобы проверить, совпадают ли две строки, представьте, что вторая строка определяется точками P3 (x3, y3), P4 (x4, y4).

Чтобы убедиться, что эти строки «вполне»то же самое вы должны проверить, находятся ли две точки (P3, P4), определяющие вторую линию, «достаточно» близко к предыдущей.

Это легко сделать, вычисляя f (x3, y3) и f (x4)., y4).Если эти значения близки к 0, то линии совпадают.

Pseudocode:
// I would chose tolerance around 1
if ( f(x3,y3) < tolerance && f(x4,y4) < tolerance )
{
    // line P1,P2 is the same as P3,P4
}
...