/* * Copyright 2006, United States Government as represented by the Administrator * for the National Aeronautics and Space Administration. No copyright is * claimed in the United States under Title 17, U.S. Code. All Other Rights * Reserved. */ package gov.nasa.ial.mde.math; import gov.nasa.ial.mde.solver.MdeFeatureNode; import gov.nasa.ial.mde.util.MathUtil; /** * This class represents a point with <code>double</code> <code>x</code> * and <code>y</code> values. * * @author Dr. Robert Shelton * @version 1.0 * @since 1.0 */ public class PointXY { /** The x value of the point. */ public double x; /** The y value of the point. */ public double y; // digits to display and left/right delimiters for ordered pair notation private int numDigits = 3; private MdeNumberFormat mnf = null; private String leftDelim = "("; private String rightDelim = ")"; /** Default constructor not allowed. */ @SuppressWarnings("unused") private PointXY() { throw new RuntimeException("Default constructor not allowed."); } /** * Creates an instance of <code>PointXY</code> with the <code>x</code> * and <code>y</code> point values specified by the <code>xy</code> array. * <p> * The <code>x</code> value is specified at array index 0. * <p> * The <code>y</code> value is specified at array index 1. * * @param xy the x and y point values specified in an array. * @exception IllegalArgumentException is thrown if the <code>xy</code> array * length is not excatly 2. */ public PointXY(double[] xy) { this(xy[0],xy[1]); if (xy.length != 2) { throw new IllegalArgumentException("The xy array length must be exactly 2."); } } // end PointXY /** * Creates an instance of <code>PointXY</code> with the <code>x</code> * and <code>y</code> point values specified. * * @param x the x value of the point. * @param y the y value of the point. */ public PointXY(double x, double y) { this.x = x; this.y = y; setDisplayDigits(); } /** * Translates this point by the specified delta's in x and y. * * @param deltax the value to add to this points x value. * @param deltay the value to add to this points y value. */ public void translate(double deltax, double deltay) { x += deltax; y += deltay; } /** * Returns a new <code>PointXY</code> instance representing the * translation of this point by the specified delta's in x and y. * * @param deltax the value to add to this points x value. * @param deltay the value to add to this points y value. * @return a new point representing the translation of this point * by the specified delta's in x and y. */ public PointXY newTranslatedPoint(double deltax, double deltay) { return new PointXY(x + deltax, y + deltay); } /** * Returns a new <code>PointXY</code> instance representing the sum * of this point and the specified point. * * @param p the point to add to the values of this point. * @return a new <code>PointXY</code> instance representing the sum * of this point and the specified point. */ public PointXY sum(PointXY p) { return newTranslatedPoint(p.x, p.y); } // end sum /** * Returns a new <code>PointXY</code> instance representing the difference * between this point and the specified point. * * @param p the point to subtract the values from this point. * @return a new <code>PointXY</code> instance representing the difference * between this point and the specified point. */ public PointXY difference(PointXY p) { return newTranslatedPoint(-p.x, -p.y); } // end difference /** * Returns a new <code>PointRT</code> instance representing this <code>PointXY</code> * in Polar coordinates. * * @return a new <code>PointRT</code> instance of this point in Polar coordinates. */ public PointRT toPolar() { double r = Math.sqrt(x * x + y * y); // double theta = Math.atan(y/x); // use four-quadrant atan function to handle angles in 2nd and 4th // quads double theta = Math.atan2(y, x); return new PointRT(r, theta); } // end toPolar // various pretty print methods // e.g., that print values with specified number of digits, // printing with (,{,[,),},}, whatever // How about one really good one? /** * Returns a string representation of this <code>PointXY</code> object using * the <code>[</code> character as the left delimiter and the <code>]</code> * character as the right delimiter. * * @return a string representation of this <code>PointXY</code> object. * @see java.lang.Object#toString() */ public String toString() { StringBuffer strBuff = new StringBuffer(20); strBuff.append(leftDelim).append(MathUtil.trimDouble(x, numDigits)) .append(", ").append(MathUtil.trimDouble(y, numDigits)) .append(rightDelim); return strBuff.toString(); } // end toString /** * Returns the formatted string representation of the <code>x</code> * value of this point. * * @return the formatted string representation of the <code>x</code> * value of this point. */ public String getXString() { return getNumberFormat().format(x); } // end getXString /** * Returns the formatted string representation of the <code>y</code> * value of this point. * * @return the formatted string representation of the <code>y</code> * value of this point. */ public String getYString() { return getNumberFormat().format(y); } // end getYString /** * Set the number of digits to display for the formatted <code>x</code> * and <code>y</code> point values. * * @param numDigits the number of digits to format the <code>x</code> * and <code>y</code> point values for display. */ public void setDisplayDigits(int numDigits) { this.numDigits = numDigits; setDisplayDigits(); } // end setDisplayDigits private void setDisplayDigits() { getNumberFormat().setMinimumFractionDigits(0); getNumberFormat().setMaximumFractionDigits(numDigits); } // end setDisplayDigits /** * Sets the left and right delimiters used for the string representation * of this string returned by the <code>toString()</code> method. * * @param ld the left delimiter * @param rd the right delimiter * @see #toString() */ public void setDelimiters(String ld, String rd) { this.leftDelim = ld; this.rightDelim = rd; } // end setDelimiters /** * Returns the MDE Feature Node for this point. * * @return the MDE Feature Node for this point. */ public MdeFeatureNode getMFN() { MdeFeatureNode t = new MdeFeatureNode(); t.addKey("X"); t.addValue("X", getXString()); t.addKey("Y"); t.addValue("Y", getYString()); return t; } // end getMFN /** * This method is called to dispose of resources used by this. * <code>PointXY</code>. The <code>PointXY</code> will be * invalid and must not be used once this method has been called. */ public void dispose() { mnf = null; } private MdeNumberFormat getNumberFormat() { // We use delayed instantiation. if (mnf == null) { mnf = MdeNumberFormat.getInstance(); } return mnf; } } // end class PointXY