source: josm/trunk/src/org/openstreetmap/josm/data/projection/AbstractProjection.java@ 10747

Last change on this file since 10747 was 10699, checked in by Don-vip, 8 years ago

fix #13255 - Document AbstractProjection (patch by michael2402) - gsoc-core

  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.projection;
3
4import org.openstreetmap.josm.data.Bounds;
5import org.openstreetmap.josm.data.ProjectionBounds;
6import org.openstreetmap.josm.data.coor.EastNorth;
7import org.openstreetmap.josm.data.coor.LatLon;
8import org.openstreetmap.josm.data.projection.datum.Datum;
9import org.openstreetmap.josm.data.projection.proj.Proj;
10
11/**
12 * Implementation of the Projection interface that represents a coordinate reference system and delegates
13 * the real projection and datum conversion to other classes.
14 *
15 * It handles false easting and northing, central meridian and general scale factor before calling the
16 * delegate projection.
17 *
18 * Forwards lat/lon values to the real projection in units of radians.
19 *
20 * The fields are named after Proj.4 parameters.
21 *
22 * Subclasses of AbstractProjection must set ellps and proj to a non-null value.
23 * In addition, either datum or nadgrid has to be initialized to some value.
24 */
25public abstract class AbstractProjection implements Projection {
26
27 protected Ellipsoid ellps;
28 protected Datum datum;
29 protected Proj proj;
30 protected double x0; /* false easting (in meters) */
31 protected double y0; /* false northing (in meters) */
32 protected double lon0; /* central meridian */
33 protected double pm; /* prime meridian */
34 protected double k0 = 1.0; /* general scale factor */
35 protected double toMeter = 1.0; /* switch from meters to east/north coordinate units */
36
37 private volatile ProjectionBounds projectionBoundsBox;
38
39 /**
40 * Get the base ellipsoid that this projection uses.
41 * @return The {@link Ellipsoid}
42 */
43 public final Ellipsoid getEllipsoid() {
44 return ellps;
45 }
46
47 /**
48 * Gets the datum this projection is based on.
49 * @return The datum
50 */
51 public final Datum getDatum() {
52 return datum;
53 }
54
55 /**
56 * Replies the projection (in the narrow sense)
57 * @return The projection object
58 */
59 public final Proj getProj() {
60 return proj;
61 }
62
63 /**
64 * Gets an east offset that gets applied when converting the coordinate
65 * @return The offset to apply in meter
66 */
67 public final double getFalseEasting() {
68 return x0;
69 }
70
71 /**
72 * Gets an north offset that gets applied when converting the coordinate
73 * @return The offset to apply in meter
74 */
75 public final double getFalseNorthing() {
76 return y0;
77 }
78
79 /**
80 * Gets the meridian that this projection is centered on.
81 * @return The longitude of the meridian.
82 */
83 public final double getCentralMeridian() {
84 return lon0;
85 }
86
87 public final double getScaleFactor() {
88 return k0;
89 }
90
91 /**
92 * Get the factor that converts meters to intended units of east/north coordinates.
93 *
94 * For projected coordinate systems, the semi-major axis of the ellipsoid is
95 * always given in meters, which means the preliminary projection result will
96 * be in meters as well. This factor is used to convert to the intended units
97 * of east/north coordinates (e.g. feet in the US).
98 *
99 * For geographic coordinate systems, the preliminary "projection" result will
100 * be in degrees, so there is no reason to convert anything and this factor
101 * will by 1 by default.
102 *
103 * @return factor that converts meters to intended units of east/north coordinates
104 */
105 public final double getToMeter() {
106 return toMeter;
107 }
108
109 @Override
110 public EastNorth latlon2eastNorth(LatLon ll) {
111 ll = datum.fromWGS84(ll);
112 double[] en = proj.project(Math.toRadians(ll.lat()), Math.toRadians(LatLon.normalizeLon(ll.lon() - lon0 - pm)));
113 return new EastNorth((ellps.a * k0 * en[0] + x0) / toMeter, (ellps.a * k0 * en[1] + y0) / toMeter);
114 }
115
116 @Override
117 public LatLon eastNorth2latlon(EastNorth en) {
118 double[] latlonRad = proj.invproject((en.east() * toMeter - x0) / ellps.a / k0, (en.north() * toMeter - y0) / ellps.a / k0);
119 LatLon ll = new LatLon(Math.toDegrees(latlonRad[0]), LatLon.normalizeLon(Math.toDegrees(latlonRad[1]) + lon0 + pm));
120 return datum.toWGS84(ll);
121 }
122
123 @Override
124 public double getDefaultZoomInPPD() {
125 // this will set the map scaler to about 1000 m
126 return 10;
127 }
128
129 /**
130 * @return The EPSG Code of this CRS, null if it doesn't have one.
131 */
132 public abstract Integer getEpsgCode();
133
134 /**
135 * Default implementation of toCode().
136 * Should be overridden, if there is no EPSG code for this CRS.
137 */
138 @Override
139 public String toCode() {
140 return "EPSG:" + getEpsgCode();
141 }
142
143 protected static final double convertMinuteSecond(double minute, double second) {
144 return (minute/60.0) + (second/3600.0);
145 }
146
147 protected static final double convertDegreeMinuteSecond(double degree, double minute, double second) {
148 return degree + (minute/60.0) + (second/3600.0);
149 }
150
151 @Override
152 public final ProjectionBounds getWorldBoundsBoxEastNorth() {
153 ProjectionBounds result = projectionBoundsBox;
154 if (result == null) {
155 synchronized (this) {
156 result = projectionBoundsBox;
157 if (result == null) {
158 Bounds b = getWorldBoundsLatLon();
159 // add 4 corners
160 result = new ProjectionBounds(latlon2eastNorth(b.getMin()));
161 result.extend(latlon2eastNorth(b.getMax()));
162 result.extend(latlon2eastNorth(new LatLon(b.getMinLat(), b.getMaxLon())));
163 result.extend(latlon2eastNorth(new LatLon(b.getMaxLat(), b.getMinLon())));
164 // and trace along the outline
165 double dLon = (b.getMaxLon() - b.getMinLon()) / 1000;
166 double dLat = (b.getMaxLat() - b.getMinLat()) / 1000;
167 for (double lon = b.getMinLon(); lon < b.getMaxLon(); lon += dLon) {
168 result.extend(latlon2eastNorth(new LatLon(b.getMinLat(), lon)));
169 result.extend(latlon2eastNorth(new LatLon(b.getMaxLat(), lon)));
170 }
171 for (double lat = b.getMinLat(); lat < b.getMaxLat(); lat += dLat) {
172 result.extend(latlon2eastNorth(new LatLon(lat, b.getMinLon())));
173 result.extend(latlon2eastNorth(new LatLon(lat, b.getMaxLon())));
174 }
175 projectionBoundsBox = result;
176 }
177 }
178 }
179 return projectionBoundsBox;
180 }
181}
Note: See TracBrowser for help on using the repository browser.