001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.math.geometry.point; 031 032import java.io.DataInput; 033import java.io.DataOutput; 034import java.io.IOException; 035import java.io.PrintWriter; 036import java.util.Random; 037import java.util.Scanner; 038 039import Jama.Matrix; 040 041/** 042 * Simple concrete implementation of a two dimensional point. 043 * 044 * @author Jonathon Hare 045 */ 046public class Point2dImpl implements Point2d, Cloneable { 047 /** 048 * The x-coordinate 049 */ 050 public float x; 051 052 /** 053 * The y-coordinate 054 */ 055 public float y; 056 057 /** 058 * Construct a Point2dImpl with the given (x, y) coordinates 059 * 060 * @param x 061 * x-coordinate 062 * @param y 063 * y-coordinate 064 */ 065 public Point2dImpl(float x, float y) 066 { 067 this.x = x; 068 this.y = y; 069 } 070 071 /** 072 * Construct a Point2dImpl with the (x,y) coordinates given via another 073 * point. 074 * 075 * @param p 076 * The point to copy from. 077 */ 078 public Point2dImpl(Point2d p) 079 { 080 this.copyFrom(p); 081 } 082 083 /** 084 * Construct a Point2dImpl at the origin. 085 */ 086 public Point2dImpl() 087 { 088 // do nothing 089 } 090 091 /** 092 * Construct a {@link Point2dImpl} using the first two ordinates of a 093 * {@link Coordinate}. 094 * 095 * @param coord 096 * the {@link Coordinate} 097 */ 098 public Point2dImpl(Coordinate coord) { 099 x = coord.getOrdinate(0).floatValue(); 100 y = coord.getOrdinate(1).floatValue(); 101 } 102 103 /** 104 * Construct a Point2dImpl with the given (x, y) coordinates. The values 105 * will be cast to single precision. 106 * 107 * @param x 108 * x-coordinate 109 * @param y 110 * y-coordinate 111 */ 112 public Point2dImpl(double x, double y) 113 { 114 this.x = (float) x; 115 this.y = (float) y; 116 } 117 118 @Override 119 public float getX() { 120 return x; 121 } 122 123 @Override 124 public void setX(float x) { 125 this.x = x; 126 } 127 128 @Override 129 public float getY() { 130 return y; 131 } 132 133 @Override 134 public void setY(float y) { 135 this.y = y; 136 } 137 138 @Override 139 public void copyFrom(Point2d p) 140 { 141 this.x = p.getX(); 142 this.y = p.getY(); 143 } 144 145 @Override 146 public String toString() { 147 return "(" + x + "," + y + ")"; 148 } 149 150 @Override 151 public Point2dImpl clone() { 152 Point2dImpl clone; 153 try { 154 clone = (Point2dImpl) super.clone(); 155 } catch (final CloneNotSupportedException e) { 156 return null; 157 } 158 return clone; 159 } 160 161 @Override 162 public Float getOrdinate(int dimension) { 163 if (dimension == 0) 164 return x; 165 return y; 166 } 167 168 @Override 169 public int getDimensions() { 170 return 2; 171 } 172 173 @Override 174 public void translate(float x, float y) { 175 this.x += x; 176 this.y += y; 177 } 178 179 @Override 180 public void translate(Point2d v) { 181 this.x += v.getX(); 182 this.y += v.getY(); 183 } 184 185 @Override 186 public Point2dImpl transform(Matrix transform) { 187 if (transform.getRowDimension() == 3) { 188 float xt = (float) transform.get(0, 0) * getX() + (float) transform.get(0, 1) * getY() 189 + (float) transform.get(0, 2); 190 float yt = (float) transform.get(1, 0) * getX() + (float) transform.get(1, 1) * getY() 191 + (float) transform.get(1, 2); 192 final float zt = (float) transform.get(2, 0) * getX() + (float) transform.get(2, 1) * getY() 193 + (float) transform.get(2, 2); 194 195 xt /= zt; 196 yt /= zt; 197 198 return new Point2dImpl(xt, yt); 199 } else if (transform.getRowDimension() == 2 && transform.getColumnDimension() == 2) { 200 final float xt = (float) transform.get(0, 0) * getX() + (float) transform.get(0, 1) * getY(); 201 final float yt = (float) transform.get(1, 0) * getX() + (float) transform.get(1, 1) * getY(); 202 203 return new Point2dImpl(xt, yt); 204 } else if (transform.getRowDimension() == 2 && transform.getColumnDimension() == 3) { 205 final float xt = (float) transform.get(0, 0) * getX() + (float) transform.get(0, 1) * getY() 206 + (float) transform.get(0, 2); 207 final float yt = (float) transform.get(1, 0) * getX() + (float) transform.get(1, 1) * getY() 208 + (float) transform.get(1, 2); 209 210 return new Point2dImpl(xt, yt); 211 } 212 throw new IllegalArgumentException("Transform matrix has unexpected size"); 213 } 214 215 @Override 216 public boolean equals(Object o) { 217 if (!(o instanceof Point2d)) 218 return false; 219 final Point2d p = (Point2d) o; 220 return p.getX() == this.x && p.getY() == this.y; 221 } 222 223 @Override 224 public int hashCode() 225 { 226 return toString().hashCode(); 227 } 228 229 @Override 230 public Point2d minus(Point2d a) { 231 return new Point2dImpl(this.x - a.getX(), this.y - a.getY()); 232 } 233 234 @Override 235 public void readASCII(Scanner in) throws IOException { 236 x = in.nextFloat(); 237 y = in.nextFloat(); 238 } 239 240 @Override 241 public String asciiHeader() { 242 return "Point2d"; 243 } 244 245 @Override 246 public void readBinary(DataInput in) throws IOException { 247 x = in.readFloat(); 248 y = in.readFloat(); 249 } 250 251 @Override 252 public byte[] binaryHeader() { 253 return "PT2D".getBytes(); 254 } 255 256 @Override 257 public void writeASCII(PrintWriter out) throws IOException { 258 out.format("%f %f", x, y); 259 } 260 261 @Override 262 public void writeBinary(DataOutput out) throws IOException { 263 out.writeFloat(x); 264 out.writeFloat(y); 265 } 266 267 @Override 268 public Point2dImpl copy() { 269 return clone(); 270 } 271 272 /** 273 * Create a random point in ([0..1], [0..1]). 274 * 275 * @return random point. 276 */ 277 public static Point2d createRandomPoint() { 278 return new Point2dImpl((float) Math.random(), (float) Math.random()); 279 } 280 281 /** 282 * Create a random point in ([0..1], [0..1]) with the given random number 283 * generator. 284 * 285 * @param rng 286 * the random number generator 287 * @return random point. 288 */ 289 public static Point2d createRandomPoint(Random rng) { 290 return new Point2dImpl(rng.nextFloat(), rng.nextFloat()); 291 } 292 293 /** 294 * @param calculateCentroid 295 * @return a point from a double array 296 */ 297 public static Point2d fromDoubleArray(double[] calculateCentroid) { 298 return new Point2dImpl((float) calculateCentroid[0], (float) calculateCentroid[1]); 299 } 300 301 @Override 302 public void setOrdinate(int dimension, Number value) { 303 if (dimension == 0) 304 x = value.floatValue(); 305 if (dimension == 1) 306 y = value.floatValue(); 307 } 308}