[josm-dev] Change JOSM default projection from EPSG:4326 to Mercartor?
Gabriel Ebner
ge at gabrielebner.at
Fri Nov 30 13:35:20 GMT 2007
On Fri, Nov 30, 2007 at 01:04:55PM +0100, Gabriel Ebner wrote:
> > (Some WMS servers can return Mercator-projected images but the WMS
> > plugin is not smart enough to detect that and request them if it is
> > required. Anyway the Landsat server cannot return Mercator; the image
> > would have to be reprojected by the WMS plugin, and that's rather more
> > difficult than just stretching it a bit...)
>
> If you don't want any anti-aliasing, you just need to rearrange the rows a
> bit, i.e. figure out how high the image is going to be under Mercator, and
> then figure out for every row the corresponding row in the image in longlat
> projection and pick that. Maybe I'll hack up something tonight...
I've hacked up a proof-of-concept implementation now, but I can't really test
it since NASA seems to have shut down general WMS service, and just allows
"Tiled WMS" in order to reduce server load. Tiled WMS is apparently a subset
of WMS that just allows some standardized bboxes and sizes.
Anybody know of a WMS proxy (mapserver?) that can talk Tiled WMS?
In any case, I guess we need a way now to specify the projection of WMS
sources? Large Yahoo tiles look so... different when you reproject them over
again.
Gabriel.
P.S.: In order to try the patch, you'll need a JOSM checkout as of half an
hour ago.
-------------- next part --------------
Index: src/wmsplugin/WMSImage.java
===================================================================
--- src/wmsplugin/WMSImage.java (revision 5828)
+++ src/wmsplugin/WMSImage.java (working copy)
@@ -23,17 +23,22 @@
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.data.projection.Epsg4326;
+import org.openstreetmap.josm.data.projection.Mercator;
import org.openstreetmap.josm.gui.NavigatableComponent;
import org.openstreetmap.josm.io.ProgressInputStream;
public class WMSImage implements Serializable
{
String constURL;
- protected BufferedImage theImage;
protected double grabbedScale;
protected EastNorth topLeft, bottomRight;
double dEast, dNorth;
+ private BufferedImage fetchedImage, projImage;
+ private Projection fetchedProj = new Epsg4326(), proj;
+
public WMSImage(String constURL)
{
this.constURL = constURL;
@@ -46,18 +51,18 @@
dEast = in.readDouble();
dNorth = in.readDouble();
grabbedScale = in.readDouble();
- theImage = (BufferedImage) ImageIO.read(ImageIO.createImageInputStream(in));
+ fetchedImage = (BufferedImage) ImageIO.read(ImageIO.createImageInputStream(in));
}
private void writeObject(ObjectOutputStream out) throws IOException {
- System.out.println("writ" + theImage.getWidth(null));
+ System.out.println("writ" + fetchedImage.getWidth(null));
out.writeObject(constURL);
out.writeObject(topLeft);
out.writeObject(bottomRight);
out.writeDouble(dEast);
out.writeDouble(dNorth);
out.writeDouble(grabbedScale);
- ImageIO.write(theImage, "png", ImageIO.createImageOutputStream(out));
+ ImageIO.write(fetchedImage, "png", ImageIO.createImageOutputStream(out));
}
public void grab(NavigatableComponent nc) throws IOException
@@ -130,7 +135,7 @@
{
InputStream is = new ProgressInputStream(
url.openConnection(), Main.pleaseWaitDlg);
- theImage = ImageIO.read(is);
+ fetchedImage = ImageIO.read(is);
is.close();
Main.map.repaint();
}
@@ -153,25 +158,64 @@
return b;
}
+ private static BufferedImage reprojMerc(
+ BufferedImage img, double minlat, double maxlat) {
+ // Convert the coords into a sensible format.
+ minlat *= Math.PI / 180;
+ maxlat *= Math.PI / 180;
+ double dlat = maxlat - minlat;
+
+ // Convert to mercator.
+ double minmerc = Math.log(Math.tan(Math.PI/4 + minlat/2));
+ double maxmerc = Math.log(Math.tan(Math.PI/4 + maxlat/2));
+ double dmerc = maxmerc - minmerc;
+
+ // Allocate the new image.
+ int gw = img.getWidth(), gh = img.getHeight();
+ int pw = gw, ph = (int) (gh * dmerc / dlat);
+ BufferedImage pimg = new BufferedImage(pw, ph, img.getType());
+
+ // Copy the lines.
+ for (int py = 0; py < ph; py++) {
+ double merc = maxmerc - dmerc * ((double) py) / ph;
+ double lat = 2*Math.atan(Math.exp(merc)) - Math.PI/2;
+ int gy = (int) (gh * (maxlat - lat) / dlat);
+
+ int[] rgb = img.getRGB(0, gy, gw, 1, null, 0, 4*gw);
+ pimg.setRGB(0, py, pw, 1, rgb, 0, 4*pw);
+ }
+
+ return pimg;
+ }
+
public void paint(Graphics g,NavigatableComponent nc)
{
- if (theImage != null)
- {
- double zoomInFactor = grabbedScale / nc.getScale();
+ if (fetchedImage == null) return;
- // Find the image x and y of the supplied bottom left
- // This will be the difference in EastNorth units, divided by the
- // grabbed scale in EastNorth/pixel.
+ if (proj == null || !proj.equals(Main.proj)) {
+ if (Main.proj.equals(fetchedProj)) {
+ projImage = fetchedImage;
+ } else if (Main.proj instanceof Mercator) {
+ double lat1 = Main.proj.eastNorth2latlon(topLeft).lat();
+ double lat2 = Main.proj.eastNorth2latlon(bottomRight).lat();
+ projImage = reprojMerc(fetchedImage,
+ Math.min(lat1, lat2),
+ Math.max(lat1, lat2));
+ proj = Main.proj;
+ } else {
+ // FIXME: We'll need to add every projection that is added to
+ // JOSM here too.
+ projImage = fetchedImage;
+ }
+ }
- int w = theImage.getWidth(null), h=theImage.getHeight(null);
- EastNorth topLeftDisplaced =
- new EastNorth(topLeft.east()+dEast, topLeft.north()+dNorth);
- Point displacement = Main.map.mapView.getPoint(topLeftDisplaced);
- g.drawImage(theImage,displacement.x,displacement.y,
- (int)(displacement.x+w*zoomInFactor),
- (int)(displacement.y+h*zoomInFactor),
- 0,0,w,h,null);
- }
+ Point ulP = Main.map.mapView.getPoint(topLeft.add(dEast, dNorth));
+ Point lrP = Main.map.mapView.getPoint(bottomRight.add(dEast, dNorth));
+ int w = projImage.getWidth(null), h = projImage.getHeight(null);
+ g.drawImage(projImage,
+ ulP.x, ulP.y, lrP.x, lrP.y,
+ 0, 0, w, h,
+ null);
}
}
More information about the josm-dev
mailing list