Android/Java, как проверить, пересекаются ли прямоугольник и отрезок линии без line2d

в моей игре для Android мне нужно проверить пересечение прямоугольника и отрезка. Я не могу использовать line2d как android не поддерживает это. Я просмотрел похожие вопросы, касающиеся строк, и попытался изменить их, но потерпел неудачу. Я также понимаю это Q/A что в основном то, что я хочу, однако я потерпел неудачу. Например, вот мой код для класса Line, который включает мою попытку пересечения. В результате некоторые непересечения возвращали true, а некоторые пересечения возвращали false. РЕДАКТИРОВАТЬ: Оли Чарльзворт помог мне, и вот рабочий код для любых гуглов.

   package com.example.HelloAndroid;

import android.graphics.Rect;

public class Segment {
    int x1;
    int y1;
    int x2;
    int y2;
    double m;
    double b;
    boolean ishoriz;
    boolean isvert;

    public Segment(int x1s, int y1s, int x2s, int y2s) {
        if (x1s > x2s) {
            this.x1 = x2s;
            this.x2 = x1s;
        } else {
            this.x1 = x1s;
            this.x2 = x2s;
        }
        if (y1s > y2s) {
            this.y1 = y2s;
            this.y2 = y1s;
        } else {
            this.y1 = y1s;
            this.y2 = y2s;
        }
        int ydif = y2s - y1s;
        int xdif = x2s - x1s;
        if (ydif == 0) {
            this.ishoriz = true;
            this.m = 0;
            this.b = x1s;
        } else if (xdif == 0) {
            this.isvert = true;
        } else {
            this.m = (double) ydif / xdif;
            double r = (double) ydif / xdif;
            this.b = y1s - (r * x1s);
            this.isvert = false;
            this.ishoriz = false;
        }
    }

    public final boolean intersected(Segment s, Segment s2) {
        if (s.ishoriz && s2.ishoriz) {
            //parallel
            return false;
        }

        if (s.isvert && s2.isvert) {
            //parallel

            return false;
        }

        if (s.isvert) {
            //x is constant see if the x is on the other line
            int x = s.x1;
            //add 2 for round-off error
            if (s2.x1 <= x + 2 && s2.x2 + 2 >= x) {
                //solve and check if y is on both segments
                int y = (int) ((s.m * x) + s.b);
                if(s.y1<=y+2&&s.y2+2>=y)
                {
                    if(s2.y1<=y+2&&s2.y2+2>=y)
                    {
                return true;}
            }
            }
            return false;
        }

        if (s2.isvert) {
            //x is constant see if the x is on the other line
            int x = s2.x1;
            //add 2 for round-off error
            if (s.x1 <= x + 2 && s.x2 + 2 >= x) {
                //solve and check if y is on both segments
                int y = (int) ((s.m * x) + s.b);
                if(s.y1<=y+2&&s.y2+2>=y)
                {
                    if(s2.y1<=y+2&&s2.y2+2>=y)
                    {
                return true;}
            }
            }
            return false;
        }

        if (s.ishoriz) {
            //y is constant see if the y is on the other line
            int y = s.y1;
            //add 2 for round-off error
            if (s2.y1 <= y + 2 && s2.y2 + 2 >= y) {
                //solve and check if x is on both segments
                int x=(int) ((y-s.b)/s.m);
                if(s.x1<=x+2&&s.x2+2>=x)
                {
                    if(s2.x1<=x+2&&s2.x2+2>=x)
                return true;}
            return false;
        }}

        if (s2.ishoriz) {
            //y is constant see if the y is on the other line
            int y = s2.y1;
            //add 2 for round-off error
            if (s.y1 <= y + 2 && s.y2 + 2 >= y) {
                //solve and check if x is on both segments
                int x=(int) ((y-s.b)/s.m);
                if(s.x1<=x+2&&s.x2+2>=x)
                {
                    if(s2.x1<=x+2&&s2.x2+2>=x)
                return true;}
            }
            return false;
        }

        if (s.m == s2.m) {
            //parallel
            return false;
        }

        // use substitution
        // (s.m-s2.m)x=s2.b-s.b
        int x = (int) (s.m - s2.m);
        x = (int) ((s2.b - s.b) / x);
        // find y
        int y = (int) ((x * s.m) + s.b);
        //check if the values are in between for both lines
        //add 2 for round-off error
        if (s.y1 <= y + 2) {
            if (s.y2 + 2 >= y) {
                if (s2.y1 <= y + 2) {
                    if (s2.y2 + 2 >= y) {
                        if (s.x1 <= x + 2) {
                            if (s.x2 + 2 >= x) {
                                if (s2.x1 <= x + 2) {
                                    if (s2.x2 + 2 >= x) {
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    public final boolean intersects2(Segment s, Rect r) {
        //created lines of the rect
        Segment top = new Segment(r.left, r.top, r.right, r.top);
        Segment left = new Segment(r.left, r.top, r.left, r.bottom);
        Segment bottom = new Segment(r.left, r.bottom, r.right, r.bottom);
        Segment right = new Segment(r.right, r.top, r.right, r.bottom);
        boolean topp = s.intersected(s, top);
        if (topp) {
            return true;
        }
        boolean leftp = s.intersected(s, left);
        if (leftp) {
            return true;
        }
        boolean bottomp = s.intersected(s, bottom);
        if (bottomp) {
            return true;
        }
        boolean rightp = s.intersected(s, right);
        if (rightp) {
            return true;
        } else {
            return false;
        }
    }

}


person jersam515    schedule 30.03.2012    source источник
comment
Итак, каков результат? Чему вы научились, когда пытались это отладить?   -  person Oliver Charlesworth    schedule 30.03.2012
comment
@Oli Charlesworth Результаты добавлены. Если я могу спросить, что в моем вопросе неясно, поэтому я могу это исправить?   -  person jersam515    schedule 30.03.2012
comment
Как правило, если какой-то код не работает, первое, что нужно сделать, это отладить проблему, либо запустив ее в отладчике, либо добавив операторы печати для наблюдения за значениями промежуточных переменных. Вы делали что-то из этого?   -  person Oliver Charlesworth    schedule 30.03.2012
comment
Так что же произошло, когда вы отладили логику пересечения?   -  person Oliver Charlesworth    schedule 30.03.2012
comment
Хотя в моих тестовых строках мой m инициализируется m, а в моем реальном приложении - нет, например, когда разница x равна -370, а разница y равна 223, я получаю наклон или m 0   -  person jersam515    schedule 30.03.2012
comment
Попробуйте объявить все ваши переменные-члены как final.   -  person Oliver Charlesworth    schedule 30.03.2012
comment
@Oli Charlesworth: Когда я объявляю переменные-члены как окончательные, я получаю сообщение об ошибке, что они не могут быть назначены, если я назначаю их во время инициализации, или ошибку о том, что переменная, возможно, не была инициализирована.   -  person jersam515    schedule 30.03.2012
comment
В яблочко. Это почти наверняка проблемы, которые вы должны решить.   -  person Oliver Charlesworth    schedule 30.03.2012
comment
@Oli Charlesworth: Это не имеет смысла, вы хотите, чтобы я объявил его окончательным и при этом имел возможность повторно инициализировать эти переменные? Если только я не упустил что-то невозможное.   -  person jersam515    schedule 30.03.2012
comment
Но зачем вам переназначать переменные-члены? Такой метод, как intersects, не должен изменять состояние объекта. (Кстати, ваш фрагмент кода почти невозможно прочитать, потому что в нем нет отступов. Так что, возможно, я что-то упустил...)   -  person Oliver Charlesworth    schedule 30.03.2012
comment
@Oli Charlsworth: Когда я очистил свой код, я заметил свою ошибку. Я не могу отблагодарить вас, не могли бы вы поместить свой последний комментарий в качестве ответа, чтобы я мог принять его и проголосовать за него? Для всех, кто ищет метод, я добавил фиксированный код в OP с некоторыми комментариями.   -  person jersam515    schedule 30.03.2012
comment
Не беспокойтесь, я рад, что смог помочь. Я поместил свои комментарии в форму ответа ниже.   -  person Oliver Charlesworth    schedule 30.03.2012


Ответы (1)


Возможно, вы неправильно инициализируете все свои переменные-члены. В общем, вы должны стремиться сделать как можно больше переменных-членов final по (по крайней мере) двум причинам:

  • компилятор будет обеспечивать их инициализацию в конструкторе.
  • компилятор не позволит вам случайно перезаписать их в обычной функции-члене.

Другими словами, вы всегда должны стремиться к тому, чтобы компилятор обнаруживал ваши ошибки за вас!

person Oliver Charlesworth    schedule 30.03.2012