Самый элегантный способ обрезать линию? - PullRequest
3 голосов
/ 09 марта 2009

У меня есть Rectangle2D и Line2D. Я хочу «обрезать» линию так, чтобы осталась только та часть линии, которая находится внутри прямоугольника. Если ни одна из линий не находится внутри прямоугольника, я хочу, чтобы линия была установлена ​​на (0,0,0,0). В основном что-то вроде

Rectangle2D.intersect(Line2D src, Line2D dest)

или что-то подобное.

Есть ли способ сделать это с помощью API java.awt.geom? Или элегантный способ кодировать его «от руки»?

Ответы [ 4 ]

3 голосов
/ 09 марта 2009

Исходный код для Rectangle2D.intersectLine() может быть полезным:

public boolean intersectsLine(double x1, double y1, double x2, double y2) {
    int out1, out2;
    if ((out2 = outcode(x2, y2)) == 0) {
        return true;
    }
    while ((out1 = outcode(x1, y1)) != 0) {
        if ((out1 & out2) != 0) {
            return false;
        }
        if ((out1 & (OUT_LEFT | OUT_RIGHT)) != 0) {
            double x = getX();
            if ((out1 & OUT_RIGHT) != 0) {
                x += getWidth();
            }
            y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
            x1 = x;
        } else {
            double y = getY();
            if ((out1 & OUT_BOTTOM) != 0) {
                y += getHeight();
            }
            x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
            y1 = y;
        }
    }
    return true;
}

, где outcode() определяется как:

public int outcode(double x, double y) {
    int out = 0;
    if (this.width <= 0) {
        out |= OUT_LEFT | OUT_RIGHT;
    } else if (x < this.x) {
        out |= OUT_LEFT;
    } else if (x > this.x + this.width) {
        out |= OUT_RIGHT;
    }
    if (this.height <= 0) {
        out |= OUT_TOP | OUT_BOTTOM;
    } else if (y < this.y) {
        out |= OUT_TOP;
    } else if (y > this.y + this.height) {
        out |= OUT_BOTTOM;
    }
    return out;
}

(из OpenJDK )

Не должно быть очень сложно изменить это на клип вместо того, чтобы возвращать true или false.

1 голос
/ 09 марта 2009

Нет хорошего способа сделать это с AWT. Ваша лучшая ставка - что-то вроде алгоритма Коэна-Сазерленда . Вот ссылка с примером кода Java (lern2indent, amirite?), Чтобы показать вам, как это делается.

0 голосов
/ 11 марта 2009

Ну, я все сделал сам.

Для тех, кто интересуется, я решил решить эту проблему, превратив линию в прямоугольник (с getBounds), затем используя Rectangle.intersect(clipRect,lineRect,intersectLineRect), чтобы создать пересечение, затем превратив пересечение в линию.

0 голосов
/ 09 марта 2009

Обычно нужно ограничить область отсечения в графическом контексте Graphics2D.clip. Возможно, вы захотите вызвать Graphics.create, чтобы не мешать исходному контексту.

Graphics2D g = (Graphics2D)gOrig.create();
try {
    g.clip(clip);
    ...
} finally {
    g.dispose();
}
...