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

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

always normalize longitude before projection and after inverse projection (see #12186)

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