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

Last change on this file since 9790 was 9790, checked in by bastiK, 8 years ago

use intended units for east/north coordinates (see #12186)

When east/north coordinates are not in meter, but
feet, ... convert them to correct units.
Currently they are always stored in meters or degrees.
This makes no difference to JOSM internally, but affects
services like WMS/WMTS.
Only relevant for projections with +units=... or +to_meter=...
parameter set to non-default value.

  • Property svn:eol-style set to native
File size: 6.0 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 public final Ellipsoid getEllipsoid() {
40 return ellps;
41 }
42
43 public final Datum getDatum() {
44 return datum;
45 }
46
47 /**
48 * Replies the projection (in the narrow sense)
49 * @return The projection object
50 */
51 public final Proj getProj() {
52 return proj;
53 }
54
55 public final double getFalseEasting() {
56 return x0;
57 }
58
59 public final double getFalseNorthing() {
60 return y0;
61 }
62
63 public final double getCentralMeridian() {
64 return lon0;
65 }
66
67 public final double getScaleFactor() {
68 return k0;
69 }
70
71 /**
72 * Get the factor that converts meters to intended units of east/north coordinates.
73 *
74 * For projected coordinate systems, the semi-major axis of the ellipsoid is
75 * always given in meters, which means the preliminary projection result will
76 * be in meters as well. This factor is used to convert to the intended units
77 * of east/north coordinates (e.g. feet in the US).
78 *
79 * For geographic coordinate systems, the preliminary "projection" result will
80 * be in degrees, so there is no reason to convert anything and this factor
81 * will by 1 by default.
82 *
83 * @return factor that converts meters to intended units of east/north coordinates
84 */
85 public final double getToMeter() {
86 return toMeter;
87 }
88
89 @Override
90 public EastNorth latlon2eastNorth(LatLon ll) {
91 ll = datum.fromWGS84(ll);
92 double[] en = proj.project(Math.toRadians(ll.lat()), Math.toRadians(LatLon.normalizeLon(ll.lon() - lon0 - pm)));
93 return new EastNorth((ellps.a * k0 * en[0] + x0) / toMeter, (ellps.a * k0 * en[1] + y0) / toMeter);
94 }
95
96 @Override
97 public LatLon eastNorth2latlon(EastNorth en) {
98 double[] latlon_rad = proj.invproject((en.east() * toMeter - x0) / ellps.a / k0, (en.north() * toMeter - y0) / ellps.a / k0);
99 LatLon ll = new LatLon(Math.toDegrees(latlon_rad[0]), LatLon.normalizeLon(Math.toDegrees(latlon_rad[1]) + lon0 + pm));
100 return datum.toWGS84(ll);
101 }
102
103 @Override
104 public double getDefaultZoomInPPD() {
105 // this will set the map scaler to about 1000 m
106 return 10;
107 }
108
109 /**
110 * @return The EPSG Code of this CRS, null if it doesn't have one.
111 */
112 public abstract Integer getEpsgCode();
113
114 /**
115 * Default implementation of toCode().
116 * Should be overridden, if there is no EPSG code for this CRS.
117 */
118 @Override
119 public String toCode() {
120 return "EPSG:" + getEpsgCode();
121 }
122
123 protected static final double convertMinuteSecond(double minute, double second) {
124 return (minute/60.0) + (second/3600.0);
125 }
126
127 protected static final double convertDegreeMinuteSecond(double degree, double minute, double second) {
128 return degree + (minute/60.0) + (second/3600.0);
129 }
130
131 @Override
132 public final ProjectionBounds getWorldBoundsBoxEastNorth() {
133 ProjectionBounds result = projectionBoundsBox;
134 if (result == null) {
135 synchronized (this) {
136 result = projectionBoundsBox;
137 if (result == null) {
138 Bounds b = getWorldBoundsLatLon();
139 // add 4 corners
140 result = new ProjectionBounds(latlon2eastNorth(b.getMin()));
141 result.extend(latlon2eastNorth(b.getMax()));
142 result.extend(latlon2eastNorth(new LatLon(b.getMinLat(), b.getMaxLon())));
143 result.extend(latlon2eastNorth(new LatLon(b.getMaxLat(), b.getMinLon())));
144 // and trace along the outline
145 double dLon = (b.getMaxLon() - b.getMinLon()) / 1000;
146 double dLat = (b.getMaxLat() - b.getMinLat()) / 1000;
147 for (double lon = b.getMinLon(); lon < b.getMaxLon(); lon += dLon) {
148 result.extend(latlon2eastNorth(new LatLon(b.getMinLat(), lon)));
149 result.extend(latlon2eastNorth(new LatLon(b.getMaxLat(), lon)));
150 }
151 for (double lat = b.getMinLat(); lat < b.getMaxLat(); lat += dLat) {
152 result.extend(latlon2eastNorth(new LatLon(lat, b.getMinLon())));
153 result.extend(latlon2eastNorth(new LatLon(lat, b.getMaxLon())));
154 }
155 projectionBoundsBox = result;
156 }
157 }
158 }
159 return projectionBoundsBox;
160 }
161}
Note: See TracBrowser for help on using the repository browser.