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 }