Java examples for 2D Graphics:Rectangle
Clip the specified line to the given rectangle
/*/*from ww w . jav a 2 s.c o m*/ * A Collection of Miscellaneous Utilities * * Copyright 2010 * The President and Fellows of Harvard College. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ //package com.java2s; import java.awt.geom.*; public class Main { /** * Clip the specified line to the given rectangle * * @param line the line (<code>null</code> not permitted). * @param rect the clipping rectangle (<code>null</code> not permitted). * * @return <code>true</code> if the clipped line is visible, and * <code>false</code> otherwise. */ public static boolean clipLine(Line2D line, Rectangle2D rect) { // From: JFreeChart, (C) Copyright 2000-2008, by Object Refinery Limited and Contributors // Distributed under the GNU Lesser General Public License // http://www.java2s.com/Code/Java/2D-Graphics-GUI/Clipsthespecifiedlinetothegivenrectangle.htm double x1 = line.getX1(); double y1 = line.getY1(); double x2 = line.getX2(); double y2 = line.getY2(); double minX = rect.getMinX(); double maxX = rect.getMaxX(); double minY = rect.getMinY(); double maxY = rect.getMaxY(); int f1 = rect.outcode(x1, y1); int f2 = rect.outcode(x2, y2); while ((f1 | f2) != 0) { if ((f1 & f2) != 0) { return false; } double dx = (x2 - x1); double dy = (y2 - y1); // update (x1, y1), (x2, y2) and f1 and f2 using intersections // then recheck if (f1 != 0) { // first point is outside, so we update it against one of the // four sides then continue if ((f1 & Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT && dx != 0.0) { y1 = y1 + (minX - x1) * dy / dx; x1 = minX; } else if ((f1 & Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT && dx != 0.0) { y1 = y1 + (maxX - x1) * dy / dx; x1 = maxX; } else if ((f1 & Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM && dy != 0.0) { x1 = x1 + (maxY - y1) * dx / dy; y1 = maxY; } else if ((f1 & Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP && dy != 0.0) { x1 = x1 + (minY - y1) * dx / dy; y1 = minY; } f1 = rect.outcode(x1, y1); } else if (f2 != 0) { // second point is outside, so we update it against one of the // four sides then continue if ((f2 & Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT && dx != 0.0) { y2 = y2 + (minX - x2) * dy / dx; x2 = minX; } else if ((f2 & Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT && dx != 0.0) { y2 = y2 + (maxX - x2) * dy / dx; x2 = maxX; } else if ((f2 & Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM && dy != 0.0) { x2 = x2 + (maxY - y2) * dx / dy; y2 = maxY; } else if ((f2 & Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP && dy != 0.0) { x2 = x2 + (minY - y2) * dx / dy; y2 = minY; } f2 = rect.outcode(x2, y2); } } line.setLine(x1, y1, x2, y2); return true; // the line is visible - if it wasn't, we'd have // returned false from within the while loop above } /** * Clip the specified line to the given ellipse * * @param line the line (<code>null</code> not permitted). * @param ellipse the ellipse (<code>null</code> not permitted). * * @return <code>true</code> if the clipped line is visible, and * <code>false</code> otherwise. */ public static boolean clipLine(Line2D line, Ellipse2D ellipse) { // Parts of the code come from: // Original author: Sean James McKenzie // http://www.baconandgames.com/2010/02/22/intersection-of-an-ellipse-and-a-line-in-as3/ boolean in1 = ellipse.contains(line.getP1()); boolean in2 = ellipse.contains(line.getP2()); if (in1 && in2) return true; // Normalize the points relative to the center of the ellipse double x1 = line.getX1() - ellipse.getCenterX(); double y1 = -line.getY1() + ellipse.getCenterY(); double x2 = line.getX2() - ellipse.getCenterX(); double y2 = -line.getY2() + ellipse.getCenterY(); // Check if we need to flip the coordinate system boolean flip = false; double a = ellipse.getWidth() / 2; double b = ellipse.getHeight() / 2; double dx = x2 - x1; double dy = y2 - y1; if (dx == 0 && dy == 0) return false; if (dx == 0) { double t; t = x1; x1 = y1; y1 = t; t = x2; x2 = y2; y2 = t; t = dx; dx = dy; dy = t; t = a; a = b; b = t; flip = true; } // Get the slope of the line and the slope intercept double m = dy / dx; double si = y2 - m * x2; // Get the coefficients double A = b * b + a * a * m * m; double B = 2 * a * a * si * m; double C = a * a * si * si - a * a * b * b; // Variables for the intercepts double x3, y3, x4, y4; // Use the quadratic equation to find x double radicand = B * B - 4 * A * C; if (radicand >= 0) { // We have two intercepts // Solve for x values using the quadratic equation x3 = (-B - Math.sqrt(radicand)) / (2 * A); x4 = (-B + Math.sqrt(radicand)) / (2 * A); // Calculate y y3 = m * x3 + si; y4 = m * x4 + si; // Revert to the original coordinate system if (flip) { double t; t = x3; x3 = y3; y3 = t; t = x4; x4 = y4; y4 = t; } x1 = line.getX1(); y1 = line.getY1(); x2 = line.getX2(); y2 = line.getY2(); x3 += ellipse.getCenterX(); y3 = ellipse.getCenterY() - y3; x4 += ellipse.getCenterX(); y4 = ellipse.getCenterY() - y4; // Set the line - only point 2 is in the ellipse if (!in1 && in2) { // Make sure point 1 is closer to point 3 double d13 = (x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3); double d14 = (x1 - x4) * (x1 - x4) + (y1 - y4) * (y1 - y4); if (d13 > d14) { double t; t = x3; x3 = x4; x4 = t; t = y3; y3 = y4; y4 = t; } line.setLine(x3, y3, x2, y2); return true; } // Set the line - only point 1 is in the ellipse if (in1 && !in2) { // Make sure point 2 is closer to point 4 double d23 = (x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3); double d24 = (x2 - x4) * (x2 - x4) + (y2 - y4) * (y2 - y4); if (d23 < d24) { double t; t = x3; x3 = x4; x4 = t; t = y3; y3 = y4; y4 = t; } line.setLine(x1, y1, x4, y4); return true; } // Both points are outside of the ellipse; // check that the points are on the line boolean bx = (x1 >= x3 && x3 <= x2) || (x2 >= x3 && x3 <= x1); boolean by = (y1 >= y3 && y3 <= y2) || (y2 >= y3 && y3 <= y1); if (!(bx && by)) return false; // Make sure point 1 is closer to point 3 double d13 = (x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3); double d14 = (x1 - x4) * (x1 - x4) + (y1 - y4) * (y1 - y4); if (d13 > d14) { double t; t = x3; x3 = x4; x4 = t; t = y3; y3 = y4; y4 = t; } // Set the line line.setLine(x3, y3, x4, y4); return true; } else if (radicand == 0) { // We have only one intercept x3 = -B / (2 * A); y3 = m * x3 + si; // Revert to the original coordinate system if (flip) { double t; t = x3; x3 = y3; y3 = t; } x3 += ellipse.getCenterX(); y3 = ellipse.getCenterY() - y3; // Check whether point 3 lies on the line boolean bx = (x1 >= x3 && x3 <= x2) || (x2 >= x3 && x3 <= x1); boolean by = (y1 >= y3 && y3 <= y2) || (y2 >= y3 && y3 <= y1); if (!(bx && by)) return false; // Set the line line.setLine(x3, y3, x3, y3); return true; } else { // No intercept return false; } } }