001 package edu.nrao.sss.astronomy; 002 003 import java.util.Date; 004 005 import javax.xml.bind.annotation.XmlElement; 006 import javax.xml.bind.annotation.XmlRootElement; 007 008 import edu.nrao.sss.measure.Distance; 009 import edu.nrao.sss.measure.Latitude; 010 import edu.nrao.sss.measure.Longitude; 011 012 /** 013 * A very basic implementation of a {@link SkyPosition sky position}. 014 * <p> 015 * <b>Version Info:</b> 016 * <table style="margin-left:2em"> 017 * <tr><td>$Revision: 1156 $</td></tr> 018 * <tr><td>$Date: 2008-03-12 11:43:13 -0600 (Wed, 12 Mar 2008) $</td></tr> 019 * <tr><td>$Author: dharland $</td></tr> 020 * </table></p> 021 * 022 * @author David M. Harland 023 * @since 2007-04-17 024 */ 025 @XmlRootElement 026 public class SimpleSkyPosition 027 extends AbsSkyPos 028 { 029 private Longitude longitude; 030 private Latitude latitude; 031 private Distance distance; 032 033 private Longitude longitudeUncertainty; 034 private Latitude latitudeUncertainty; 035 private Distance distanceUncertainty; 036 037 /** Creates a new equatorial, J2000, position. */ 038 public SimpleSkyPosition() 039 { 040 this(CelestialCoordinateSystem.EQUATORIAL, Epoch.J2000); 041 } 042 043 /** Creates a new instance with the given properties. */ 044 public SimpleSkyPosition(CelestialCoordinateSystem system, Epoch epoch) 045 { 046 super(system, epoch); 047 048 longitude = new Longitude(); 049 latitude = new Latitude(); 050 distance = new Distance(); 051 052 longitudeUncertainty = new Longitude(); 053 latitudeUncertainty = new Latitude(); 054 distanceUncertainty = new Distance(); 055 } 056 057 @Override 058 public void reset() 059 { 060 super.reset(); 061 062 longitude.reset(); 063 latitude.reset(); 064 distance.reset(); 065 066 longitudeUncertainty.reset(); 067 latitudeUncertainty.reset(); 068 distanceUncertainty.reset(); 069 } 070 071 //============================================================================ 072 // 073 //============================================================================ 074 075 /* (non-Javadoc) 076 * @see SkyPosition#getType() 077 */ 078 public SkyPositionType getType() { return SkyPositionType.SIMPLE; } 079 080 /* (non-Javadoc) 081 * @see edu.nrao.sss.astronomy.SkyPosition#isMoving() 082 */ 083 public boolean isMoving() { return false; } 084 085 //============================================================================ 086 // 087 //============================================================================ 088 089 /** 090 * Sets the longitude of this position. 091 * <p> 092 * If {@code newLongitude} is <i>null</i>, this method creates, and saves a 093 * reference to, a new longitude object. Otherwise it saves a reference 094 * to {@code newLongitude}. This means that any changes made to 095 * (a non-null) {@code newLongitude} by clients after this call 096 * <i>will</i> be reflected in this position.</p> 097 * 098 * @param newLongitude a new longitude for this position. 099 */ 100 public void setLongitude(Longitude newLongitude) 101 { 102 longitude = (newLongitude == null) ? new Longitude() : newLongitude; 103 } 104 105 /** 106 * Returns the current longitude of this position. 107 * <p> 108 * The returned object is guaranteed to be non-null and is also a reference 109 * to the internal longitude held by this position. This means any changes 110 * made by clients to the returned object will be reflected in this 111 * position.</p> 112 * 113 * @return the current longitude of this position. 114 */ 115 @XmlElement 116 @Override 117 public Longitude getLongitude() 118 { 119 return longitude; 120 } 121 122 /** 123 * Sets the latitude of this position. 124 * <p> 125 * If {@code newLatitude} is <i>null</i>, this method creates, and saves a 126 * reference to, a new latitude object. Otherwise it saves a reference 127 * to {@code newLatitude}. This means that any changes made to 128 * (a non-null) {@code newLatitude} by clients after this call 129 * <i>will</i> be reflected in this position.</p> 130 * 131 * @param newLatitude a new latitude for this position. 132 */ 133 public void setLatitude(Latitude newLatitude) 134 { 135 latitude = (newLatitude == null) ? new Latitude() : newLatitude; 136 } 137 138 /** 139 * Returns the current latitude of this position. 140 * <p> 141 * The returned object is guaranteed to be non-null and is also a reference 142 * to the internal latitude held by this position. This means any changes 143 * made by clients to the returned object will be reflected in this 144 * position.</p> 145 * 146 * @return the current latitude of this position. 147 */ 148 @XmlElement 149 @Override 150 public Latitude getLatitude() 151 { 152 return latitude; 153 } 154 155 /** 156 * Sets the distance of this position. 157 * <p> 158 * If {@code newDistance} is <i>null</i>, this method creates, and saves a 159 * reference to, a new distance object. Otherwise it saves a reference 160 * to {@code newDistance}. This means that any changes made to 161 * (a non-null) {@code newDistance} by clients after this call 162 * <i>will</i> be reflected in this position.</p> 163 * 164 * @param newDistance a new distance for this position. 165 */ 166 public void setDistance(Distance newDistance) 167 { 168 distance = (newDistance == null) ? new Distance() : newDistance; 169 } 170 171 /** 172 * Returns the current distance of this position. 173 * <p> 174 * The returned object is guaranteed to be non-null and is also a reference 175 * to the internal distance held by this position. This means any changes 176 * made by clients to the returned object will be reflected in this 177 * position.</p> 178 * 179 * @return the current distance of this position. 180 */ 181 @XmlElement 182 @Override 183 public Distance getDistance() 184 { 185 return distance; 186 } 187 188 //---------------------------------------------------------------------------- 189 // Position at point in time 190 //---------------------------------------------------------------------------- 191 192 /** 193 * Returns the longitude of this position at the given point in time. 194 * <p> 195 * The returned object is guaranteed to be non-null and is also a reference 196 * to the internal longitude held by this position. This means any changes 197 * made by clients to the returned object will be reflected in this 198 * position.</p> 199 * <p> 200 * Since this class has no concept of time, the value returned here will 201 * be the same as that returned by the corresponding no-argument method.</p> 202 * 203 * @return the longitude of this position at the given point in time. 204 */ 205 public Longitude getLongitude(Date time) 206 { 207 return longitude; 208 } 209 210 /** 211 * Returns the latitude of this position at the given point in time. 212 * <p> 213 * The returned object is guaranteed to be non-null and is also a reference 214 * to the internal latitude held by this position. This means any changes 215 * made by clients to the returned object will be reflected in this 216 * position.</p> 217 * <p> 218 * Since this class has no concept of time, the value returned here will 219 * be the same as that returned by the corresponding no-argument method.</p> 220 * 221 * @return the latitude of this position at the given point in time. 222 */ 223 public Latitude getLatitude(Date time) 224 { 225 return latitude; 226 } 227 228 /** 229 * Returns the distance of this position at the given point in time. 230 * <p> 231 * The returned object is guaranteed to be non-null and is also a reference 232 * to the internal distance held by this position. This means any changes 233 * made by clients to the returned object will be reflected in this 234 * position.</p> 235 * <p> 236 * Since this class has no concept of time, the value returned here will 237 * be the same as that returned by the corresponding no-argument method.</p> 238 * 239 * @return the distance at the given point in time. 240 */ 241 public Distance getDistance(Date time) 242 { 243 return distance; 244 } 245 246 //---------------------------------------------------------------------------- 247 // Uncertainties 248 //---------------------------------------------------------------------------- 249 250 /** 251 * Sets the uncertainty in the longitude of this position. 252 * <p> 253 * If {@code newUncertainty} is <i>null</i>, this method creates, and saves a 254 * reference to, a new longitude object. Otherwise it saves a reference 255 * to {@code newUncertainty}. This means that any changes made to 256 * (a non-null) {@code newUncertainty} by clients after this call 257 * <i>will</i> be reflected in this position.</p> 258 * 259 * @param newUncertainty a new value for the uncertainty of the longitude of 260 * this position. 261 */ 262 public void setLongitudeUncertainty(Longitude newUncertainty) 263 { 264 longitudeUncertainty = 265 (newUncertainty == null) ? new Longitude() : newUncertainty; 266 } 267 268 /** 269 * Returns the uncertainty in the longitude of this position. 270 * <p> 271 * The returned object is guaranteed to be non-null and is also a reference 272 * to the internal uncertainty held by this position. This means any changes 273 * made by clients to the returned object will be reflected in this 274 * position.</p> 275 * 276 * @return the uncertainty in the longitude of this position. 277 */ 278 @XmlElement 279 @Override 280 public Longitude getLongitudeUncertainty() 281 { 282 return longitudeUncertainty; 283 } 284 285 /** 286 * Sets the uncertainty in the latitude of this position. 287 * <p> 288 * If {@code newUncertainty} is <i>null</i>, this method creates, and saves a 289 * reference to, a new latitude object. Otherwise it saves a reference 290 * to {@code newUncertainty}. This means that any changes made to 291 * (a non-null) {@code newUncertainty} by clients after this call 292 * <i>will</i> be reflected in this position.</p> 293 * 294 * @param newUncertainty a new value for the uncertainty of the latitude of 295 * this position. 296 */ 297 public void setLatitudeUncertainty(Latitude newUncertainty) 298 { 299 latitudeUncertainty = 300 (newUncertainty == null) ? new Latitude() : newUncertainty; 301 } 302 303 /** 304 * Returns the uncertainty in the latitude of this position. 305 * <p> 306 * The returned object is guaranteed to be non-null and is also a reference 307 * to the internal uncertainty held by this position. This means any changes 308 * made by clients to the returned object will be reflected in this 309 * position.</p> 310 * 311 * @return the uncertainty in the latitude of this position. 312 */ 313 @XmlElement 314 @Override 315 public Latitude getLatitudeUncertainty() 316 { 317 return latitudeUncertainty; 318 } 319 320 /** 321 * Sets the uncertainty in the distance of this position. 322 * <p> 323 * If {@code newUncertainty} is <i>null</i>, this method creates, and saves a 324 * reference to, a new distance object. Otherwise it saves a reference 325 * to {@code newUncertainty}. This means that any changes made to 326 * (a non-null) {@code newUncertainty} by clients after this call 327 * <i>will</i> be reflected in this position.</p> 328 * 329 * @param newUncertainty a new value for the uncertainty of the distance of 330 * this position. 331 */ 332 public void setDistanceUncertainty(Distance newUncertainty) 333 { 334 distanceUncertainty = 335 (newUncertainty == null) ? new Distance() : newUncertainty; 336 } 337 338 /** 339 * Returns the uncertainty in the distance of this position. 340 * <p> 341 * The returned object is guaranteed to be non-null and is also a reference 342 * to the internal uncertainty held by this position. This means any changes 343 * made by clients to the returned object will be reflected in this 344 * position.</p> 345 * 346 * @return the uncertainty in the distance of this position. 347 */ 348 @XmlElement 349 @Override 350 public Distance getDistanceUncertainty() 351 { 352 return distanceUncertainty; 353 } 354 355 //============================================================================ 356 // 357 //============================================================================ 358 359 /** 360 * Creates and returns a new polynomial position whose time-zero values are 361 * the same as those of this position. 362 * The returned position has a default reference time and a default 363 * valid time interval. 364 * 365 * @return a new polynomial position based on this position. 366 */ 367 public PolynomialPosition toPolynomialPosition() 368 { 369 PolynomialPosition pp = new PolynomialPosition(); 370 371 pp.setCoordinateSystem(getCoordinateSystem()); 372 pp.setEpoch(getEpoch()); 373 374 pp.setDistanceAtTimeZero(getDistance()); 375 pp.setLongitudeAtTimeZero(getLongitude()); 376 pp.setLatitudeAtTimeZero(getLatitude()); 377 378 pp.setDistanceUncertainty(getDistanceUncertainty()); 379 pp.setLongitudeUncertainty(getLongitudeUncertainty()); 380 pp.setLatitudeUncertainty(getLatitudeUncertainty()); 381 382 return pp; 383 } 384 385 //============================================================================ 386 // 387 //============================================================================ 388 389 @Override 390 public String toString() 391 { 392 StringBuilder buff = appendTo(null).append(','); 393 394 buff.append(longitude).append("+/-").append(longitudeUncertainty); 395 buff.append(','); 396 buff.append(latitude).append("+/-").append(latitudeUncertainty); 397 buff.append(','); 398 buff.append(distance).append("+/-").append(distanceUncertainty); 399 400 return buff.toString(); 401 } 402 403 /** 404 * Returns a copy of this sky position. 405 * <p> 406 * If anything goes wrong during the cloning procedure, 407 * a {@code RuntimeException} will be thrown.</p> 408 */ 409 @Override 410 public SimpleSkyPosition clone() 411 { 412 SimpleSkyPosition clone = null; 413 414 try 415 { 416 //This line takes care of the primitive & immutable fields properly 417 clone = (SimpleSkyPosition)super.clone(); 418 419 clone.longitude = this.longitude.clone(); 420 clone.latitude = this.latitude.clone(); 421 clone.distance = this.distance.clone(); 422 423 clone.longitudeUncertainty = this.longitudeUncertainty.clone(); 424 clone.latitudeUncertainty = this.latitudeUncertainty.clone(); 425 clone.distanceUncertainty = this.distanceUncertainty.clone(); 426 } 427 catch (Exception ex) 428 { 429 throw new RuntimeException(ex); 430 } 431 432 return clone; 433 } 434 435 /** Creates and returns a copy of the given sky position. */ 436 static SimpleSkyPosition copy(SkyPosition original, Date time) 437 { 438 SimpleSkyPosition copy = new SimpleSkyPosition(); 439 440 copy.setCoordinateSystem(original.getCoordinateSystem()); 441 copy.setEpoch(original.getEpoch()); 442 443 copy.setLatitude (original.getLatitude(time).clone()); 444 copy.setLongitude(original.getLongitude(time).clone()); 445 copy.setDistance (original.getDistance(time).clone()); 446 447 copy.setLatitudeUncertainty (original.getLatitudeUncertainty().clone()); 448 copy.setLongitudeUncertainty(original.getLongitudeUncertainty().clone()); 449 copy.setDistanceUncertainty (original.getDistanceUncertainty().clone()); 450 451 return copy; 452 } 453 454 /** Returns <i>true</i> if {@code o} is equal to this position. */ 455 @Override 456 public boolean equals(Object o) 457 { 458 //Quick exit if o is this 459 if (o == this) 460 return true; 461 462 //Quick exit if super class determines not equal 463 if (!super.equals(o)) 464 return false; 465 466 //Super class determined o is non-null & of same class 467 SimpleSkyPosition other = (SimpleSkyPosition)o; 468 469 //NOTE: Absence of origin of information here is intentional. 470 471 return other.longitude.equals(this.longitude) && 472 other.latitude.equals (this.latitude ) && 473 other.distance.equals (this.distance ) && 474 475 other.longitudeUncertainty.equals(this.longitudeUncertainty) && 476 other.latitudeUncertainty.equals (this.latitudeUncertainty ) && 477 other.distanceUncertainty.equals (this.distanceUncertainty ); 478 } 479 480 /** Returns a hash code value for this position. */ 481 @Override 482 public int hashCode() 483 { 484 //Taken from the Effective Java book by Joshua Bloch. 485 //The constants 17 & 37 are arbitrary & carry no meaning. 486 487 //You MUST keep this method in synch with equals() 488 489 int result = super.hashCode(); 490 491 result = 37 * result + longitude.hashCode(); 492 result = 37 * result + latitude.hashCode(); 493 result = 37 * result + distance.hashCode(); 494 495 result = 37 * result + longitudeUncertainty.hashCode(); 496 result = 37 * result + latitudeUncertainty.hashCode(); 497 result = 37 * result + distanceUncertainty.hashCode(); 498 499 return result; 500 } 501 }