/* * ome.util.math.geom2D.Segment * * Copyright 2006 University of Dundee. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.util.math.geom2D; /** * A segment 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: * 2005/06/09 15:01:32 $) </small> * @since OME2.2 */ public class Segment { /** The origin of the segment's first element. */ public final double originX1; /** The origin of the segment's first element. */ public final double originX2; /** The end point of the segment's first element. */ public final double directionX1; /** The end point of the segment's second element. */ public final double directionX2; /** * Creates a new instance. * * @param originX1 The origin of the segment's first element. * @param originX2 The origin of the segment's second element. * @param endX1 The end point's first element. * @param endX2 The end point's second element. */ public Segment(double originX1, double originX2, double endX1, double endX2) { if (originX1 == endX1 && originX2 == endX2) { throw new IllegalArgumentException("Need two different points."); } this.originX1 = originX1; this.originX2 = originX2; /* * Calculate the vector associated to the origin and the destination end * point of this segment. This is the map that makes the set * A = <b>R</b><sup>2</sup> an affine space over the vector space * V = <b>R</b><sup>2</sup> and is defined by: * <p> * <nobr><i> f: AxA ---> V <br> * f(a, b) = b - a = (b<sub>1</sub> - a<sub>1</sub>, b<sub>2</sub> - a<sub>2</sub>) * </i></nobr> * </p> */ directionX1 = endX1 - originX1; directionX2 = endX2 - originX2; } /** * Returns the point of this line defined by <code>k</code>. More * precisely, this method returns the * <code>{@code origin}+k{@code direction}</code> point. * * @param k * The coefficient to select the point. Must be in the range * <code>[0, 1]</code>. * @return See above. */ public PlanePoint getPoint(double k) { if (k < 0 || k > 1) { throw new IllegalArgumentException("Coefficient must be in the " + "range [0, 1]."); } return new PlanePoint(originX1 + k * directionX1, originX2 + k * directionX2); } /** * Tells whether a specified point lies on this line. * * @param x1 The first element of the point to test * @param x2 The second element of the point to test * @return <code>true</code> if <code>p</code> lies on this line, * <code>false</code> otherwise. */ public boolean lies(double x1, double x2) { boolean result = false; double k1, k2; if (directionX1 == 0 && directionX2 != 0) { k2 = (x2 - originX2) / directionX2; if (k2 < 0 || k2 > 1) { result = false; } else { result = x1 == originX1; } } else if (directionX1 != 0 && directionX2 == 0) { k1 = (x1 - originX1) / directionX1; if (k1 < 0 || k1 > 1) { result = false; } else { result = x2 == originX2; } } else if (directionX1 != 0 && directionX2 != 0) { k1 = (x1 - originX1) / directionX1; k2 = (x2 - originX2) / directionX2; if (k1 == k2) { if (k1 < 0 || k1 > 1) { result = false; } else { result = true; } } } return result; } /** * Performs an equality test based on a point on this line defined * by <code>k</code> as in {@link #getPoint(double)} and another given * point. * @param k The coefficient to select the point. Must be in the range * <code>[0, 1]</code>. * @param x1 The point to test's first element. * @param x2 The point to test's second element. * @return <code>true</code> if the points are geometrically equal, * <code>false</code> otherwise. */ public boolean equals(double k, double x1, double x2) { if (k < 0 || k > 1) { throw new IllegalArgumentException("Coefficient must be in the " + "range [0, 1]."); } double kPointX1 = originX1 + k * directionX1; double kPointX2 = originX2 + k * directionX2; return kPointX1 == x1 && kPointX2 == x2; } /** * Overridden to reflect equality of abstract values (data object) as * opposite to object identity. * * @see Object#equals(Object) */ @Override public boolean equals(Object o) { boolean isEqual = false; if (o != null && o instanceof Line) { Line other = (Line) o; isEqual = other.origin.x1 == originX1 && other.origin.x2 == originX2 && other.direction.x1 == directionX1 && other.direction.x2 == directionX2; } return isEqual; } /** * Overridden to reflect equality of abstract values (data object) as * opposite to object identity. * * @see Object#hashCode() */ @Override public int hashCode() { long bits = Double.doubleToLongBits(originX1); bits ^= Double.doubleToLongBits(originX2) * 31; return (int) bits ^ (int) (bits >> 32); } }