001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/cs/CoordinateSystemFactory.java $ 002 /* 003 * SEAGIS - An OpenSource implementation of OpenGIS specification 004 * (C) 2001, Institut de Recherche pour le D�veloppement 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or (at your option) any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 019 * 020 * 021 * Contacts: 022 * FRANCE: Surveillance de l'Environnement Assist�e par Satellite 023 * Institut de Recherche pour le D�veloppement / US-Espace 024 * mailto:seasnet@teledetection.fr 025 * 026 * CANADA: Observatoire du Saint-Laurent 027 * Institut Maurice-Lamontagne 028 * mailto:osl@osl.gc.ca 029 * 030 * This package contains documentation from OpenGIS specifications. 031 * OpenGIS consortium's work is fully acknowledged here. 032 */ 033 package org.deegree.model.csct.cs; 034 035 // OpenGIS dependencies 036 import java.awt.geom.Point2D; 037 038 import javax.media.jai.ParameterList; 039 040 import org.deegree.model.csct.resources.WeakHashSet; 041 import org.deegree.model.csct.units.Unit; 042 043 /** 044 * Builds up complex objects from simpler objects or values. <code>CoordinateSystemFactory</code> 045 * allows applications to make coordinate systems that cannot be created by a 046 * {@link CoordinateSystemAuthorityFactory}. This factory is very flexible, whereas the authority 047 * factory is easier to use. 048 * 049 * So {@link CoordinateSystemAuthorityFactory} can be used to make 'standard' coordinate systems, 050 * and <code>CoordinateSystemFactory</code> can be used to make "special" coordinate systems. 051 * 052 * For example, the EPSG authority has codes for USA state plane coordinate systems using the NAD83 053 * datum, but these coordinate systems always use meters. EPSG does not have codes for NAD83 state 054 * plane coordinate systems that use feet units. This factory lets an application create such a 055 * hybrid coordinate system. 056 * 057 * @version 1.00 058 * @author OpenGIS (www.opengis.org) 059 * @author Martin Desruisseaux 060 * 061 * @author last edited by: $Author: bezema $ 062 * 063 * @version $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $ 064 * 065 * @see "org.opengis.cs.CS_CoordinateSystemFactory" 066 */ 067 public class CoordinateSystemFactory { 068 /** 069 * Default coordinate system factory. Will be constructed only when first needed. 070 */ 071 private static CoordinateSystemFactory DEFAULT; 072 073 /** 074 * Set of weak references to existing coordinate systems. This set is used in order to return 075 * pre-existing object instead of creating new one. 076 */ 077 private final WeakHashSet pool; 078 079 /** 080 * Construct a new factory with the specified pool. 081 */ 082 private CoordinateSystemFactory( final WeakHashSet pool ) { 083 this.pool = pool; 084 } 085 086 /** 087 * Default constructor. 088 */ 089 protected CoordinateSystemFactory() { 090 this( new WeakHashSet() ); 091 } 092 093 /** 094 * Returns the default coordinate system factory. 095 * 096 * @return the default coordinate system factory. 097 */ 098 public static synchronized CoordinateSystemFactory getDefault() { 099 if ( DEFAULT == null ) { 100 DEFAULT = new CoordinateSystemFactory( Info.pool ); 101 } 102 return DEFAULT; 103 } 104 105 /** 106 * Creates a geographic coordinate system. This coordinate system will use <var>longitude</var>/<var>latitude</var> 107 * ordinates with longitude values increasing east and latitude values increasing north. Angular 108 * units are degrees and prime meridian is Greenwich. 109 * 110 * @param name 111 * Name to give new object. 112 * @param datum 113 * Horizontal datum for created coordinate system. 114 */ 115 public GeographicCoordinateSystem createGeographicCoordinateSystem( final String name, 116 final HorizontalDatum datum ) { 117 return createGeographicCoordinateSystem( name, Unit.DEGREE, datum, PrimeMeridian.GREENWICH, 118 AxisInfo.LONGITUDE, AxisInfo.LATITUDE ); 119 } 120 121 /** 122 * Creates a geographic coordinate system, which could be <var>latitude</var>/<var>longiude</var> 123 * or <var>longitude</var>/<var>latitude</var>. 124 * 125 * @param name 126 * Name to give new object. 127 * @param unit 128 * Angular units for created coordinate system. 129 * @param datum 130 * Horizontal datum for created coordinate system. 131 * @param meridian 132 * Prime Meridian for created coordinate system. 133 * @param axis0 134 * Details of 0th ordinates. 135 * @param axis1 136 * Details of 1st ordinates. 137 * 138 */ 139 public GeographicCoordinateSystem createGeographicCoordinateSystem( 140 final String name, 141 final Unit unit, 142 final HorizontalDatum datum, 143 final PrimeMeridian meridian, 144 final AxisInfo axis0, 145 final AxisInfo axis1 ) { 146 return (GeographicCoordinateSystem) pool.intern( new GeographicCoordinateSystem( name, 147 unit, 148 datum, 149 meridian, 150 axis0, 151 axis1 ) ); 152 } 153 154 /** 155 * Creates a projected coordinate system using the specified geographic system. Projected 156 * coordinates will be in meters, <var>x</var> values increasing east and <var>y</var> values 157 * increasing north. 158 * 159 * @param name 160 * Name to give new object. 161 * @param gcs 162 * Geographic coordinate system to base projection on. 163 * @param projection 164 * Projection from geographic to projected coordinate system. 165 */ 166 public ProjectedCoordinateSystem createProjectedCoordinateSystem( 167 final String name, 168 final GeographicCoordinateSystem gcs, 169 final Projection projection ) { 170 return createProjectedCoordinateSystem( name, gcs, projection, Unit.METRE, AxisInfo.X, 171 AxisInfo.Y ); 172 } 173 174 /** 175 * Creates a projected coordinate system using a projection object. 176 * 177 * @param name 178 * Name to give new object. 179 * @param gcs 180 * Geographic coordinate system to base projection on. 181 * @param projection 182 * Projection from geographic to projected coordinate system. 183 * @param unit 184 * Linear units of returned PCS. 185 * @param axis0 186 * Details of 0th ordinates in returned PCS coordinates. 187 * @param axis1 188 * Details of 1st ordinates in returned PCS coordinates. 189 * 190 */ 191 public ProjectedCoordinateSystem createProjectedCoordinateSystem( 192 final String name, 193 final GeographicCoordinateSystem gcs, 194 final Projection projection, 195 final Unit unit, 196 final AxisInfo axis0, 197 final AxisInfo axis1 ) { 198 return (ProjectedCoordinateSystem) pool.intern( new ProjectedCoordinateSystem( name, gcs, 199 projection, 200 unit, axis0, 201 axis1 ) ); 202 } 203 204 /** 205 * Creates a vertical coordinate system from a datum. Units will be metres and values will be 206 * increasing upward. 207 * 208 * @param name 209 * Name to give new object. 210 * @param datum 211 * Datum to use for new coordinate system. 212 */ 213 public VerticalCoordinateSystem createVerticalCoordinateSystem( final String name, 214 final VerticalDatum datum ) { 215 return createVerticalCoordinateSystem( name, datum, Unit.METRE, AxisInfo.ALTITUDE ); 216 } 217 218 /** 219 * Creates a vertical coordinate system from a datum and linear units. 220 * 221 * @param name 222 * Name to give new object. 223 * @param datum 224 * Datum to use for new coordinate system. 225 * @param unit 226 * Units to use for new coordinate system. 227 * @param axis 228 * Axis to use for new coordinate system. 229 * 230 */ 231 public VerticalCoordinateSystem createVerticalCoordinateSystem( final String name, 232 final VerticalDatum datum, 233 final Unit unit, 234 final AxisInfo axis ) { 235 return (VerticalCoordinateSystem) pool.intern( new VerticalCoordinateSystem( name, datum, 236 unit, axis ) ); 237 } 238 239 /** 240 * Creates a compound coordinate system. 241 * 242 * @param name 243 * Name to give new object. 244 * @param head 245 * Coordinate system to use for earlier ordinates. 246 * @param tail 247 * Coordinate system to use for later ordinates. 248 * 249 */ 250 public CompoundCoordinateSystem createCompoundCoordinateSystem( final String name, 251 final CoordinateSystem head, 252 final CoordinateSystem tail ) { 253 return (CompoundCoordinateSystem) pool.intern( new CompoundCoordinateSystem( name, head, 254 tail ) ); 255 } 256 257 /** 258 * Creates a local coordinate system. The dimension of the local coordinate system is determined 259 * by the size of the axis array. All the axes will have the same units. If you want to make a 260 * coordinate system with mixed units, then you can make a compound coordinate system from 261 * different local coordinate systems. 262 * 263 * @param name 264 * Name to give new object. 265 * @param datum 266 * Local datum to use in created CS. 267 * @param unit 268 * Units to use for all axes in created CS. 269 * @param axes 270 * Axes to use in created CS. 271 * 272 */ 273 public LocalCoordinateSystem createLocalCoordinateSystem( final String name, 274 final LocalDatum datum, 275 final Unit unit, final AxisInfo[] axes ) { 276 return (LocalCoordinateSystem) pool.intern( new LocalCoordinateSystem( name, datum, unit, 277 axes ) ); 278 } 279 280 /** 281 * Creates an ellipsoid from radius values. 282 * 283 * @param name 284 * Name to give new object. 285 * @param semiMajorAxis 286 * Equatorial radius in supplied linear units. 287 * @param semiMinorAxis 288 * Polar radius in supplied linear units. 289 * @param unit 290 * Linear units of ellipsoid axes. 291 * 292 */ 293 public Ellipsoid createEllipsoid( final String name, final double semiMajorAxis, 294 final double semiMinorAxis, final Unit unit ) { 295 return (Ellipsoid) pool.intern( new Ellipsoid( name, semiMajorAxis, semiMinorAxis, unit ) ); 296 } 297 298 /** 299 * Creates an ellipsoid from an major radius, and inverse flattening. 300 * 301 * @param name 302 * Name to give new object. 303 * @param semiMajorAxis 304 * Equatorial radius in supplied linear units. 305 * @param inverseFlattening 306 * Eccentricity of ellipsoid. 307 * @param unit 308 * Linear units of major axis. 309 * 310 */ 311 public Ellipsoid createFlattenedSphere( final String name, final double semiMajorAxis, 312 final double inverseFlattening, final Unit unit ) { 313 return (Ellipsoid) pool.intern( Ellipsoid.createFlattenedSphere( name, semiMajorAxis, 314 inverseFlattening, unit ) ); 315 } 316 317 /** 318 * Creates a prime meridian, relative to Greenwich. 319 * 320 * @param name 321 * Name to give new object. 322 * @param unit 323 * Angular units of longitude. 324 * @param longitude 325 * Longitude of prime meridian in supplied angular units East of Greenwich. 326 * 327 */ 328 public PrimeMeridian createPrimeMeridian( final String name, final Unit unit, 329 final double longitude ) { 330 return (PrimeMeridian) pool.intern( new PrimeMeridian( name, unit, longitude ) ); 331 } 332 333 /** 334 * Creates a projection. The client must ensure that all the linear parameters are expressed in 335 * meters, and all the angular parameters are expressed in degrees. Also, they must supply 336 * <code>"semi_major"</code> and <code>"semi_minor"</code> parameters. The set of legal 337 * parameters and their default values can be queried using 338 * {@link #createProjectionParameterList}. Example: 339 * 340 * <blockquote> 341 * 342 * <pre> 343 * {link ParameterList} param = {@link #createProjectionParameterList createProjectionParameterList}("Transverse_Mercator") 344 * .setParameter("semi_major", 6378206.4) 345 * .setParameter("semi_minor", 6356583.8); 346 * {@link Projection} proj = createProjection("My projection", "Transverse_Mercator", param); 347 * </pre> 348 * 349 * </blockquote> 350 * 351 * @param name 352 * Name to give new object. 353 * @param classification 354 * Classification string for projection (e.g. "Transverse_Mercator"). 355 * @param parameters 356 * Parameters to use for projection. A default set of parameters can be constructed 357 * using <code>{@link #createProjectionParameterList 358 * createProjectionParameterList}(classification)</code> 359 * and initialized using a chain of <code>setParameter(...)</code> calls. 360 * 361 */ 362 public Projection createProjection( final String name, final String classification, 363 final ParameterList parameters ) { 364 return (Projection) pool.intern( new Projection( name, classification, parameters ) ); 365 } 366 367 /** 368 * Convenience method for constructing a projection using the specified ellipsoid. 369 * 370 * @param name 371 * Name to give new object. 372 * @param classification 373 * Classification string for projection (e.g. "Transverse_Mercator"). 374 * @param ellipsoid 375 * Ellipsoid parameter. If non-null, then <code>"semi_major"</code> and 376 * <code>"semi_minor"</code> parameters will be set according. 377 * @param centre 378 * Central meridian and latitude of origin, in degrees. If non-null, then 379 * <code>"central_meridian"</code> and <code>"latitude_of_origin"</code> will be 380 * set according. 381 * @param translation 382 * False easting and northing, in metres. If non-null, then 383 * <code>"false_easting"</code> and <code>"false_northing"</code> will be set 384 * according. 385 */ 386 public Projection createProjection( final String name, final String classification, 387 final Ellipsoid ellipsoid, final Point2D centre, 388 final Point2D translation, final double scaleFactor ) { 389 ParameterList param = createProjectionParameterList( classification ); 390 param = Projection.init( param, ellipsoid, centre, translation, scaleFactor ); 391 return createProjection( name, classification, param ); 392 } 393 394 /** 395 * Returns a default parameter list for the specified projection. 396 * 397 * @param classification 398 * Classification string for projection (e.g. "Transverse_Mercator"). 399 * @return A default parameter list for the supplied projection class. 400 * 401 * @see #createProjection(String, String, ParameterList) 402 */ 403 public ParameterList createProjectionParameterList( final String classification ) { 404 return Projection.getParameterList( classification ); 405 } 406 407 /** 408 * Creates horizontal datum from ellipsoid and Bursa-Wolf parameters. Since this method contains 409 * a set of Bursa-Wolf parameters, the created datum will always have a relationship to WGS84. 410 * If you wish to create a horizontal datum that has no relationship with WGS84, then you can 411 * either specify {@link DatumType.Horizontal#OTHER} as the horizontalDatumType, or create it 412 * via WKT. 413 * 414 * @param name 415 * Name to give new object. 416 * @param type 417 * Type of horizontal datum to create. 418 * @param ellipsoid 419 * Ellipsoid to use in new horizontal datum. 420 * @param toWGS84 421 * Suggested approximate conversion from new datum to WGS84. 422 * 423 */ 424 public HorizontalDatum createHorizontalDatum( final String name, 425 final DatumType.Horizontal type, 426 final Ellipsoid ellipsoid, 427 final WGS84ConversionInfo toWGS84 ) { 428 return (HorizontalDatum) pool.intern( new HorizontalDatum( name, type, ellipsoid, toWGS84 ) ); 429 } 430 431 /** 432 * Creates horizontal datum from an ellipsoid. The datum type will be 433 * {@link DatumType.Horizontal#OTHER}. 434 * 435 * @param name 436 * Name to give new object. 437 * @param ellipsoid 438 * Ellipsoid to use in new horizontal datum. 439 */ 440 public HorizontalDatum createHorizontalDatum( final String name, final Ellipsoid ellipsoid ) { 441 return createHorizontalDatum( name, DatumType.Horizontal.OTHER, ellipsoid, null ); 442 } 443 444 /** 445 * Creates a vertical datum from an enumerated type value. 446 * 447 * @param name 448 * Name to give new object. 449 * @param type 450 * Type of vertical datum to create. 451 * 452 */ 453 public VerticalDatum createVerticalDatum( final String name, final DatumType.Vertical type ) { 454 return (VerticalDatum) pool.intern( new VerticalDatum( name, type ) ); 455 } 456 457 /** 458 * Creates a local datum. 459 * 460 * @param name 461 * Name to give new object. 462 * @param type 463 * Type of local datum to create. 464 * 465 */ 466 public LocalDatum createLocalDatum( final String name, final DatumType.Local type ) { 467 return (LocalDatum) pool.intern( new LocalDatum( name, type ) ); 468 } 469 470 }