/* * org.openmicroscopy.shoola.util.math.geom2D.Line * *------------------------------------------------------------------------------ * Copyright (C) 2006 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.util.math.geom2D; //Java imports //Third-party libraries //Application-internal dependencies import org.openmicroscopy.shoola.util.ui.UIUtilities; /** * An oriented line in the Euclidean space <b>R</b><sup>2</sup>. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author <br>Andrea Falconi      * <a href="mailto:a.falconi@dundee.ac.uk"> * a.falconi@dundee.ac.uk</a> * @version 2.2 * <small> * (<b>Internal version:</b> $Revision$ $Date$) * </small> * @since OME2.2 */ public class Line { /** * The origin point of the line. * Any point (within the line) that falls on the half line that has the * same orientation as the {@link #direction} unit vector is said to have * positive orientation — this also includes the {@link #origin} point. * All other points of the line are said to have (strictly) negative * orientation. */ public final PlanePoint origin; /** * The unit vector that, given the {@link #origin} point, identifies this * line. */ public final PlanePoint direction; /** * Creates a new object to represent the line passing through the * <code>o</code> and <code>p</code> points. * The <code>o</code> point is taken to define the origin of the line * and the direction is defined by the <i>op</i> vector. * * @param o The origin of the line. Mustn't be <code>null</code>. * @param p A point of the line. Mustn't be <code>null</code> nor the same * as <code>o</code>. */ public Line(PlanePoint o, PlanePoint p) { if (o == null) throw new NullPointerException("No origin."); if (p == null) throw new NullPointerException("No point p."); if (o.equals(p)) throw new IllegalArgumentException("Need two different points."); origin = o; direction = origin.vec(p).normalize(); } /** * Creates a new object to represent the line passing through * <code>o</code> and having direction <i>pq</i>. * The <code>p</code> and <code>q</code> points are, respectively, the tail * and head of the vector <i>pq</i> that is taken to define the direction * of the line. * * @param p Tail of a vector. Mustn't be <code>null</code>. * @param q Head of a vector. Mustn't be <code>null</code> nor the same * as <code>q</code>. * @param o The origin of the line. Mustn't be <code>null</code>. */ public Line(PlanePoint p, PlanePoint q, PlanePoint o) { if (p == null) throw new NullPointerException("No point p."); if (q == null) throw new NullPointerException("No point q."); if (o == null) throw new NullPointerException("No origin."); if (p.equals(q)) throw new IllegalArgumentException("Need two different points."); origin = o; direction = p.vec(q).normalize(); } /** * Returns the point of this line defined by <code>k</code>. * More precisely, this method returns the * <code>{@link #origin}+k{@link #direction}</code> point. * * @param k The coefficient to select the point. * @return See above. */ public PlanePoint getPoint(double k) { return new PlanePoint(origin.x1 + k*direction.x1, origin.x2 + k*direction.x2); } /** * Tells whether the specified point lies on this line. * * @param p The point to test. Mustn't be <code>null</code>. * @return <code>true</code> if <code>p</code> lies on this line, * <code>false</code> otherwise. */ public boolean lies(PlanePoint p) { if (p == null) throw new NullPointerException("No point."); if (direction.x1 == 0) return (p.x1 == origin.x1); if (direction.x2 == 0) return (p.x2 == origin.x2); double k1 = (p.x1-origin.x1)/direction.x1, k2 = (p.x2-origin.x2)/direction.x2; return Math.abs(k1-k2) < UIUtilities.EPSILON; } /** * Tells whether the specified point lies on this line and within the * specified orientation. * The <code>positiveOrientation</code> parameter is used to specify which * side (with respect to the {@link #origin}) of the line to check. If * <code>true</code>, then we check to see whether <code>p</code> falls on * the half line that has the same orientation as the {@link #direction} * unit vector — this also includes the {@link #origin}. * If <code>false</code>, we check to see whether <code>p</code> falls on * the opposite half line. * * @param p The point to test. Mustn't be <code>null</code>. * @param positiveOrientation <code>true</code> for the positive * orientation, <code>false</code> for the * strictly negative orientation. * @return <code>true</code> if <code>p</code> lies on this line, * <code>false</code> otherwise. */ public boolean lies(PlanePoint p, boolean positiveOrientation) { if (!lies(p)) return false; double k; if (direction.x1 != 0) k = (p.x1-origin.x1)/direction.x1; else k = (p.x2-origin.x2)/direction.x2; //direction.x2 can't be 0 too. if (positiveOrientation) return (0 <= k); return (k < 0); } /** * Overridden to reflect equality of abstract values (data object) as * opposite to object identity. * @see Object#equals(Object) */ public boolean equals(Object o) { boolean isEqual = false; if (o != null && o instanceof Line) { Line other = (Line) o; isEqual = (origin == other.origin && direction == other.direction); } return isEqual; } /** * Overridden to reflect equality of abstract values (data object) as * opposite to object identity. * @see Object#hashCode() */ public int hashCode() { return origin.hashCode(); } }