Question

I have a Rectangle2D and a Line2D. I want to "clip" the line so that only the part of the line which is within the rectangle remains. If none of the line is within the rectangle I want the line to be set to (0,0,0,0). Basically something along the lines of a

Rectangle2D.intersect(Line2D src, Line2D dest)

or something similar.

Is there a way to do this with the java.awt.geom API? Or an elegant way to code it "by hand"?

Was it helpful?

Solution 4

Well, I ended up doing it myself.

For those intereseted, I ended up solving it by turning the line into a rectangle (with getBounds), then using Rectangle.intersect(clipRect,lineRect,intersectLineRect) to create the intersection, then turning the intersection back into a line.

OTHER TIPS

The source code for Rectangle2D.intersectLine() might be helpful:

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;
}

where outcode() is defined as:

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;
}

(from OpenJDK)

It shouldn't be extremely difficult to change this to clip instead of returning true or false.

There's no pretty way to do it with AWT. Your best bet is something like the Cohen-Sutherland algorithm. Here's a link with example Java code (lern2indent, amirite?) to show you how it's done.

The usual thing to do is restrict the clipping region in the graphics context with Graphics2D.clip. You might want to call Graphics.create so that you do not interfere with the original context.

Graphics2D g = (Graphics2D)gOrig.create();
try {
    g.clip(clip);
    ...
} finally {
    g.dispose();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top