Changeset 11858 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2017-04-09T11:08:10+02:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 2 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/imagery/AbstractWMSTileSource.java
r11830 r11858 11 11 import org.openstreetmap.gui.jmapviewer.tilesources.TMSTileSource; 12 12 import org.openstreetmap.gui.jmapviewer.tilesources.TileSourceInfo; 13 import org.openstreetmap.josm.Main;14 13 import org.openstreetmap.josm.data.Bounds; 15 14 import org.openstreetmap.josm.data.ProjectionBounds; … … 32 31 private double[] degreesPerTile; 33 32 private static final float SCALE_DENOMINATOR_ZOOM_LEVEL_1 = 559082264.0287178f; 33 private Projection tileProjection; 34 34 35 35 /** 36 36 * Constructs a new {@code AbstractWMSTileSource}. 37 37 * @param info tile source info 38 * @param tileProjection the tile projection 38 39 */ 39 public AbstractWMSTileSource(TileSourceInfo info) { 40 public AbstractWMSTileSource(TileSourceInfo info, Projection tileProjection) { 40 41 super(info); 42 this.tileProjection = tileProjection; 41 43 } 42 44 … … 48 50 } 49 51 52 public void setTileProjection(Projection tileProjection) { 53 this.tileProjection = tileProjection; 54 initProjection(); 55 } 56 57 public Projection getTileProjection() { 58 return this.tileProjection; 59 } 60 50 61 /** 51 62 * Initializes class with current projection in JOSM. This call is needed every time projection changes. 52 63 */ 53 64 public void initProjection() { 54 initProjection( Main.getProjection());65 initProjection(this.tileProjection); 55 66 } 56 67 … … 99 110 @Override 100 111 public ICoordinate tileXYToLatLon(int x, int y, int zoom) { 101 return Main.getProjection().eastNorth2latlon(getTileEastNorth(x, y, zoom)).toCoordinate();112 return tileProjection.eastNorth2latlon(getTileEastNorth(x, y, zoom)).toCoordinate(); 102 113 } 103 114 … … 112 123 @Override 113 124 public TileXY latLonToTileXY(double lat, double lon, int zoom) { 114 EastNorth enPoint = Main.getProjection().latlon2eastNorth(new LatLon(lat, lon));125 EastNorth enPoint = tileProjection.latlon2eastNorth(new LatLon(lat, lon)); 115 126 return eastNorthToTileXY(enPoint, zoom); 116 127 } … … 144 155 public Point latLonToXY(double lat, double lon, int zoom) { 145 156 double scale = getDegreesPerTile(zoom) / getTileSize(); 146 EastNorth point = Main.getProjection().latlon2eastNorth(new LatLon(lat, lon));157 EastNorth point = tileProjection.latlon2eastNorth(new LatLon(lat, lon)); 147 158 return new Point( 148 159 (int) Math.round((point.east() - anchorPosition.east()) / scale), … … 164 175 public ICoordinate xyToLatLon(int x, int y, int zoom) { 165 176 double scale = getDegreesPerTile(zoom) / getTileSize(); 166 Projection proj = Main.getProjection();167 177 EastNorth ret = new EastNorth( 168 178 anchorPosition.east() + x * scale, 169 179 anchorPosition.north() - y * scale 170 180 ); 171 return proj.eastNorth2latlon(ret).toCoordinate();181 return tileProjection.eastNorth2latlon(ret).toCoordinate(); 172 182 } 173 183 … … 197 207 @Override 198 208 public String getServerCRS() { 199 return Main.getProjection().toCode();209 return this.tileProjection.toCode(); 200 210 } 201 211 } -
trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
r11848 r11858 204 204 /** is the geo reference correct - don't offer offset handling */ 205 205 private boolean isGeoreferenceValid; 206 /** does the EPSG:4326 to mercator woraround work as expected */207 private boolean isEpsg4326To3857Supported;208 206 /** which layers should be activated by default on layer addition. **/ 209 207 private Collection<DefaultLayer> defaultLayers = Collections.emptyList(); … … 244 242 @pref boolean valid_georeference; 245 243 @pref boolean bestMarked; 246 @pref boolean supports_epsg_4326_to_3857_conversion;247 244 // TODO: disabled until change of layers is implemented 248 245 // @pref String default_layers; … … 309 306 310 307 valid_georeference = i.isGeoreferenceValid(); 311 supports_epsg_4326_to_3857_conversion = i.isEpsg4326To3857Supported();312 308 // TODO disabled until change of layers is implemented 313 309 // default_layers = i.defaultLayers.stream().collect(Collectors.joining(",")); … … 439 435 setTileSize(e.tileSize); 440 436 metadataHeaders = e.metadataHeaders; 441 isEpsg4326To3857Supported = e.supports_epsg_4326_to_3857_conversion;442 437 isGeoreferenceValid = e.valid_georeference; 443 438 // TODO disabled until change of layers is implemented … … 476 471 this.noTileChecksums = i.noTileChecksums; 477 472 this.metadataHeaders = i.metadataHeaders; 478 this.isEpsg4326To3857Supported = i.isEpsg4326To3857Supported;479 473 this.isGeoreferenceValid = i.isGeoreferenceValid; 480 474 this.defaultLayers = i.defaultLayers; … … 506 500 Objects.equals(this.url, other.url) && 507 501 Objects.equals(this.bestMarked, other.bestMarked) && 508 Objects.equals(this.isEpsg4326To3857Supported, other.isEpsg4326To3857Supported) &&509 502 Objects.equals(this.isGeoreferenceValid, other.isGeoreferenceValid) && 510 503 Objects.equals(this.cookies, other.cookies) && … … 1141 1134 this.metadataHeaders = metadataHeaders; 1142 1135 } 1143 }1144 1145 /**1146 * Gets the flag if epsg 4326 to 3857 is supported1147 * @return The flag.1148 */1149 public boolean isEpsg4326To3857Supported() {1150 return isEpsg4326To3857Supported;1151 }1152 1153 /**1154 * Sets the flag that epsg 4326 to 3857 is supported1155 * @param isEpsg4326To3857Supported The flag.1156 */1157 public void setEpsg4326To3857Supported(boolean isEpsg4326To3857Supported) {1158 this.isEpsg4326To3857Supported = isEpsg4326To3857Supported;1159 1136 } 1160 1137 -
trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java
r11843 r11858 46 46 private static final LongProperty MAXIMUM_EXPIRES = new LongProperty("imagery.generic.maximum_expires", TimeUnit.DAYS.toMillis(30)); 47 47 private static final LongProperty MINIMUM_EXPIRES = new LongProperty("imagery.generic.minimum_expires", TimeUnit.HOURS.toMillis(1)); 48 pr ivatefinal Tile tile;48 protected final Tile tile; 49 49 private volatile URL url; 50 50 -
trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java
r10990 r11858 19 19 import org.openstreetmap.josm.data.coor.EastNorth; 20 20 import org.openstreetmap.josm.data.coor.LatLon; 21 import org.openstreetmap.josm.data.projection.Projection; 21 22 import org.openstreetmap.josm.gui.layer.WMSLayer; 22 23 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 54 55 * Creates a tile source based on imagery info 55 56 * @param info imagery info 57 * @param tileProjection the tile projection 56 58 */ 57 public TemplatedWMSTileSource(ImageryInfo info) { 58 super(info); 59 public TemplatedWMSTileSource(ImageryInfo info, Projection tileProjection) { 60 super(info, tileProjection); 59 61 this.serverProjections = new TreeSet<>(info.getServerProjections()); 60 62 handleTemplate(); … … 69 71 @Override 70 72 public String getTileUrl(int zoom, int tilex, int tiley) { 71 String myProjCode = Main.getProjection().toCode();73 String myProjCode = getServerCRS(); 72 74 73 75 EastNorth nw = getTileEastNorth(tilex, tiley, zoom); … … 79 81 double s = se.getY(); 80 82 double e = se.getX(); 81 82 if (!serverProjections.contains(myProjCode) && serverProjections.contains("EPSG:4326") && "EPSG:3857".equals(myProjCode)) {83 LatLon swll = Main.getProjection().eastNorth2latlon(new EastNorth(w, s));84 LatLon nell = Main.getProjection().eastNorth2latlon(new EastNorth(e, n));85 myProjCode = "EPSG:4326";86 s = swll.lat();87 w = swll.lon();88 n = nell.lat();89 e = nell.lon();90 }91 83 92 84 if ("EPSG:4326".equals(myProjCode) && !serverProjections.contains(myProjCode) && serverProjections.contains("CRS:84")) { -
trunk/src/org/openstreetmap/josm/data/imagery/WMSCachedTileLoaderJob.java
r8624 r11858 8 8 import org.openstreetmap.gui.jmapviewer.Tile; 9 9 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 10 import org.openstreetmap.josm.Main;11 10 import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; 12 11 … … 40 39 String key = super.getCacheKey(); 41 40 if (key != null) { 42 return key + Main.getProjection().toCode();41 return key + tile.getSource().getServerCRS(); 43 42 } 44 43 return null; -
trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java
r11830 r11858 14 14 import java.util.Collection; 15 15 import java.util.Collections; 16 import java.util.HashSet; 16 import java.util.LinkedHashSet; 17 17 import java.util.List; 18 18 import java.util.Map; … … 20 20 import java.util.Objects; 21 21 import java.util.Optional; 22 import java.util.Set;23 22 import java.util.SortedSet; 24 23 import java.util.Stack; … … 62 61 63 62 /** 64 * Tile Source handling WMS providers 63 * Tile Source handling WMTS providers 65 64 * 66 65 * @author Wiktor Niesiobędzki … … 269 268 private final WMTSDefaultLayer defaultLayer; 270 269 270 private Projection tileProjection; 271 271 272 /** 272 273 * Creates a tile source based on imagery info … … 598 599 */ 599 600 public void initProjection(Projection proj) { 600 // getLayers will return only layers matching the name, if the user already choose the layer 601 // so we will not ask the user again to chose the layer, if he just changes projection 602 Collection<Layer> candidates = getLayers( 603 currentLayer != null ? new WMTSDefaultLayer(currentLayer.identifier, currentLayer.tileMatrixSet.identifier) : defaultLayer, 604 proj.toCode()); 605 606 if (candidates.size() > 1 && defaultLayer != null) { 607 candidates = candidates.stream() 608 .filter(t -> t.tileMatrixSet.identifier.equals(defaultLayer.getTileMatrixSet())) 609 .collect(Collectors.toList()); 610 } 611 if (candidates.size() == 1) { 612 Layer newLayer = candidates.iterator().next(); 613 if (newLayer != null) { 614 this.currentTileMatrixSet = newLayer.tileMatrixSet; 615 this.currentLayer = newLayer; 616 Collection<Double> scales = new ArrayList<>(currentTileMatrixSet.tileMatrix.size()); 617 for (TileMatrix tileMatrix : currentTileMatrixSet.tileMatrix) { 618 scales.add(tileMatrix.scaleDenominator * 0.28e-03); 619 } 620 this.nativeScaleList = new ScaleList(scales); 621 } 622 } else if (candidates.size() > 1) { 623 Main.warn("More than one layer WMTS available: {0} for projection {1} and name {2}. Do not know which to process", 624 candidates.stream().map(x -> x.getUserTitle() + ": " + x.tileMatrixSet.identifier).collect(Collectors.joining(", ")), 625 proj.toCode(), 626 currentLayer != null ? currentLayer.getUserTitle() : defaultLayer 627 ); 628 } 629 this.crsScale = getTileSize() * 0.28e-03 / proj.getMetersPerUnit(); 601 if (proj.equals(tileProjection)) 602 return; 603 List<Layer> matchingLayers = layers.stream().filter( 604 l -> l.identifier.equals(defaultLayer.layerName) && l.tileMatrixSet.crs.equals(proj.toCode())) 605 .collect(Collectors.toList()); 606 if (matchingLayers.size() > 1) { 607 this.currentLayer = matchingLayers.stream().filter( 608 l -> l.tileMatrixSet.identifier.equals(defaultLayer.getTileMatrixSet())) 609 .findFirst().orElse(null); 610 this.tileProjection = proj; 611 } else if (matchingLayers.size() == 1) { 612 this.currentLayer = matchingLayers.get(0); 613 this.tileProjection = proj; 614 } else { 615 // no tile matrix sets with current projection 616 if (this.currentLayer == null) { 617 this.tileProjection = null; 618 for (Layer layer : layers) { 619 if (!layer.identifier.equals(defaultLayer.layerName)) { 620 continue; 621 } 622 Projection pr = Projections.getProjectionByCode(layer.tileMatrixSet.crs); 623 if (pr != null) { 624 this.currentLayer = layer; 625 this.tileProjection = pr; 626 break; 627 } 628 } 629 if (this.currentLayer == null) 630 return; 631 } // else: keep currentLayer and tileProjection as is 632 } 633 this.currentTileMatrixSet = this.currentLayer.tileMatrixSet; 634 Collection<Double> scales = new ArrayList<>(currentTileMatrixSet.tileMatrix.size()); 635 for (TileMatrix tileMatrix : currentTileMatrixSet.tileMatrix) { 636 scales.add(tileMatrix.scaleDenominator * 0.28e-03); 637 } 638 this.nativeScaleList = new ScaleList(scales); 639 this.crsScale = getTileSize() * 0.28e-03 / this.tileProjection.getMetersPerUnit(); 630 640 } 631 641 … … 655 665 // no support for non-square tiles (tileHeight != tileWidth) 656 666 // and for different tile sizes at different zoom levels 657 Collection<Layer> projLayers = getLayers(null, Main.getProjection().toCode());667 Collection<Layer> projLayers = getLayers(null, tileProjection.toCode()); 658 668 if (!projLayers.isEmpty()) { 659 669 return projLayers.iterator().next().tileMatrixSet.tileMatrix.get(0).tileHeight; … … 736 746 TileMatrix matrix = getTileMatrix(zoom); 737 747 if (matrix == null) { 738 return Main.getProjection().getWorldBoundsLatLon().getCenter().toCoordinate();748 return tileProjection.getWorldBoundsLatLon().getCenter().toCoordinate(); 739 749 } 740 750 double scale = matrix.scaleDenominator * this.crsScale; 741 751 EastNorth ret = new EastNorth(matrix.topLeftCorner.east() + x * scale, matrix.topLeftCorner.north() - y * scale); 742 return Main.getProjection().eastNorth2latlon(ret).toCoordinate();752 return tileProjection.eastNorth2latlon(ret).toCoordinate(); 743 753 } 744 754 … … 750 760 } 751 761 752 Projection proj = Main.getProjection(); 753 EastNorth enPoint = proj.latlon2eastNorth(new LatLon(lat, lon)); 762 EastNorth enPoint = tileProjection.latlon2eastNorth(new LatLon(lat, lon)); 754 763 double scale = matrix.scaleDenominator * this.crsScale; 755 764 return new TileXY( … … 766 775 @Override 767 776 public int getTileXMax(int zoom) { 768 return getTileXMax(zoom, Main.getProjection());777 return getTileXMax(zoom, tileProjection); 769 778 } 770 779 771 780 @Override 772 781 public int getTileYMax(int zoom) { 773 return getTileYMax(zoom, Main.getProjection());782 return getTileYMax(zoom, tileProjection); 774 783 } 775 784 … … 781 790 } 782 791 double scale = matrix.scaleDenominator * this.crsScale; 783 EastNorth point = Main.getProjection().latlon2eastNorth(new LatLon(lat, lon));792 EastNorth point = tileProjection.latlon2eastNorth(new LatLon(lat, lon)); 784 793 return new Point( 785 794 (int) Math.round((point.east() - matrix.topLeftCorner.east()) / scale), … … 805 814 } 806 815 double scale = matrix.scaleDenominator * this.crsScale; 807 Projection proj = Main.getProjection();808 816 EastNorth ret = new EastNorth( 809 817 matrix.topLeftCorner.east() + x * scale, 810 818 matrix.topLeftCorner.north() - y * scale 811 819 ); 812 LatLon ll = proj.eastNorth2latlon(ret);820 LatLon ll = tileProjection.eastNorth2latlon(ret); 813 821 return new Coordinate(ll.lat(), ll.lon()); 814 822 } … … 857 865 * @return set of projection codes that this TileSource supports 858 866 */ 859 public Set<String> getSupportedProjections() {860 Set<String> ret = new HashSet<>();867 public Collection<String> getSupportedProjections() { 868 Collection<String> ret = new LinkedHashSet<>(); 861 869 if (currentLayer == null) { 862 870 for (Layer layer: this.layers) { … … 910 918 public ScaleList getNativeScales() { 911 919 return nativeScaleList; 920 } 921 922 public Projection getTileProjection() { 923 return tileProjection; 912 924 } 913 925 … … 978 990 @Override 979 991 public String getServerCRS() { 980 return Main.getProjection().toCode();992 return tileProjection.toCode(); 981 993 } 982 994 } -
trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java
r11746 r11858 875 875 return result; 876 876 } 877 878 @Override 879 public ProjectionBounds getEastNorthBoundsBox(ProjectionBounds box, Projection boxProjection) { 880 final int n = 8; 881 ProjectionBounds result = null; 882 for (int i = 0; i < 4*n; i++) { 883 EastNorth en = latlon2eastNorth(boxProjection.eastNorth2latlon(getPointAlong(i, n, box))); 884 if (result == null) { 885 result = new ProjectionBounds(en); 886 } else { 887 result.extend(en); 888 } 889 } 890 return result; 891 } 877 892 } -
trunk/src/org/openstreetmap/josm/data/projection/Projection.java
r10829 r11858 87 87 88 88 /** 89 * Get a box in east/north space of this projection, that fully contains an 90 * east/north box of another projection. 91 * 92 * Reprojecting a rectangular box from one projection to another may distort/rotate 93 * the shape of the box, so in general one needs to walk along the boundary 94 * in small steps to get a reliable result. 95 * 96 * This is an approximate method. 97 * 98 * @param box the east/north box given in projection <code>boxProjection</code> 99 * @param boxProjection the projection of <code>box</code> 100 * @return an east/north box in this projection, containing the given box 101 */ 102 ProjectionBounds getEastNorthBoundsBox(ProjectionBounds box, Projection boxProjection); 103 104 /** 89 105 * Get the number of meters per unit of this projection. This more 90 106 * defines the scale of the map, than real conversion of unit to meters -
trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java
r11840 r11858 638 638 mvs = mvs.movedTo(mvs.getCenter(), newCenter); 639 639 Point2D enOrigin = mvs.getPointFor(new EastNorth(0, 0)).getInView(); 640 Point2D enOriginAligned = new Point2D.Double(Math.round(enOrigin.getX()), Math.round(enOrigin.getY())); 640 // as a result of the alignment, it is common to round "half integer" values 641 // like 1.49999, which is numerically unstable; add small epsilon to resolve this 642 double EPSILON = 1e-3; 643 Point2D enOriginAligned = new Point2D.Double( 644 Math.round(enOrigin.getX()) + EPSILON, 645 Math.round(enOrigin.getY()) + EPSILON); 641 646 EastNorth enShift = mvs.getForView(enOriginAligned.getX(), enOriginAligned.getY()).getEastNorth(); 642 647 newCenter = newCenter.subtract(enShift); -
trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
r11846 r11858 49 49 import javax.swing.AbstractAction; 50 50 import javax.swing.Action; 51 import javax.swing.BorderFactory;52 51 import javax.swing.JCheckBoxMenuItem; 53 52 import javax.swing.JLabel; … … 57 56 import javax.swing.JPopupMenu; 58 57 import javax.swing.JSeparator; 59 import javax.swing.JTextField;60 58 import javax.swing.Timer; 61 59 … … 88 86 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 89 87 import org.openstreetmap.josm.data.preferences.IntegerProperty; 88 import org.openstreetmap.josm.data.projection.Projection; 89 import org.openstreetmap.josm.data.projection.Projections; 90 90 import org.openstreetmap.josm.gui.ExtendedDialog; 91 91 import org.openstreetmap.josm.gui.MapFrame; … … 96 96 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 97 97 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener; 98 import org.openstreetmap.josm.gui.layer.imagery.ReprojectionTile; 98 99 import org.openstreetmap.josm.gui.layer.imagery.TileAnchor; 99 100 import org.openstreetmap.josm.gui.layer.imagery.TileCoordinateConverter; … … 109 110 import org.openstreetmap.josm.tools.MemoryManager.MemoryHandle; 110 111 import org.openstreetmap.josm.tools.MemoryManager.NotEnoughMemoryException; 112 import org.openstreetmap.josm.tools.Utils; 111 113 112 114 /** … … 185 187 private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this); 186 188 // prepared to be moved to the painter 187 pr ivateTileCoordinateConverter coordinateConverter;189 protected TileCoordinateConverter coordinateConverter; 188 190 189 191 /** … … 346 348 public Object getInfoComponent() { 347 349 JPanel panel = (JPanel) super.getInfoComponent(); 350 List<List<String>> content = new ArrayList<>(); 348 351 EastNorth offset = getDisplaySettings().getDisplacement(); 349 352 if (offset.distanceSq(0, 0) > 1e-10) { 350 panel.add(new JLabel(tr("Offset: ") + offset.east() + ';' + offset.north()), GBC.eol().insets(0, 5, 10, 0)); 353 content.add(Arrays.asList(tr("Offset"), offset.east() + ";" + offset.north())); 354 } 355 if (coordinateConverter.requiresReprojection()) { 356 content.add(Arrays.asList(tr("Tile download projection"), tileSource.getServerCRS())); 357 content.add(Arrays.asList(tr("Tile display projection"), Main.getProjection().toCode())); 358 } 359 content.add(Arrays.asList(tr("Current zoom"), Integer.toString(currentZoomLevel))); 360 for (List<String> entry: content) { 361 panel.add(new JLabel(entry.get(0) + ':'), GBC.std()); 362 panel.add(GBC.glue(5, 0), GBC.std()); 363 panel.add(createTextField(entry.get(1)), GBC.eol().fill(GBC.HORIZONTAL)); 351 364 } 352 365 return panel; … … 363 376 * @return average number of screen pixels per tile pixel 364 377 */ 365 pr ivatedouble getScaleFactor(int zoom) {378 protected double getScaleFactor(int zoom) { 366 379 if (coordinateConverter != null) { 367 380 return coordinateConverter.getScaleFactor(zoom); … … 384 397 */ 385 398 int intResult = (int) Math.round(result + 1 + ZOOM_OFFSET.get() / 1.9); 386 387 intResult = Math.min(intResult, getMaxZoomLvl()); 388 intResult = Math.max(intResult, getMinZoomLvl()); 399 intResult = Utils.clamp(intResult, getMinZoomLvl(), getMaxZoomLvl()); 389 400 return intResult; 390 401 } … … 398 409 private ShowTileInfoAction() { 399 410 super(tr("Show tile info")); 411 setEnabled(clickedTileHolder.getTile() != null); 400 412 } 401 413 402 414 private String getSizeString(int size) { 403 415 return new StringBuilder().append(size).append('x').append(size).toString(); 404 }405 406 private JTextField createTextField(String text) {407 JTextField ret = new JTextField(text);408 ret.setEditable(false);409 ret.setBorder(BorderFactory.createEmptyBorder());410 return ret;411 416 } 412 417 … … 426 431 } 427 432 428 String[][] content = { 429 {"Tile name", clickedTile.getKey()}, 430 {"Tile url", url}, 431 {"Tile size", getSizeString(clickedTile.getTileSource().getTileSize()) }, 432 {"Tile display size", new StringBuilder().append(displaySize.getWidth()) 433 .append('x') 434 .append(displaySize.getHeight()).toString()}, 435 }; 436 437 for (String[] entry: content) { 438 panel.add(new JLabel(tr(entry[0]) + ':'), GBC.std()); 433 List<List<String>> content = new ArrayList<>(); 434 content.add(Arrays.asList(tr("Tile name"), clickedTile.getKey())); 435 content.add(Arrays.asList(tr("Tile URL"), url)); 436 content.add(Arrays.asList(tr("Tile size"), 437 getSizeString(clickedTile.getTileSource().getTileSize()))); 438 content.add(Arrays.asList(tr("Tile display size"), 439 new StringBuilder().append(displaySize.getWidth()) 440 .append('x') 441 .append(displaySize.getHeight()).toString())); 442 if (coordinateConverter.requiresReprojection()) { 443 content.add(Arrays.asList(tr("Reprojection"), 444 clickedTile.getTileSource().getServerCRS() + 445 " -> " + Main.getProjection().toCode())); 446 BufferedImage img = clickedTile.getImage(); 447 if (img != null) { 448 content.add(Arrays.asList(tr("Reprojected tile size"), 449 img.getWidth() + "x" + img.getHeight())); 450 451 } 452 } 453 for (List<String> entry: content) { 454 panel.add(new JLabel(entry.get(0) + ':'), GBC.std()); 439 455 panel.add(GBC.glue(5, 0), GBC.std()); 440 panel.add(createTextField(entry [1]), GBC.eol().fill(GBC.HORIZONTAL));456 panel.add(createTextField(entry.get(1)), GBC.eol().fill(GBC.HORIZONTAL)); 441 457 } 442 458 … … 462 478 private LoadTileAction() { 463 479 super(tr("Load tile")); 480 setEnabled(clickedTileHolder.getTile() != null); 464 481 } 465 482 … … 946 963 Tile tile = getTile(x, y, zoom); 947 964 if (tile == null) { 948 tile = new Tile(tileSource, x, y, zoom); 965 if (coordinateConverter.requiresReprojection()) { 966 tile = new ReprojectionTile(tileSource, x, y, zoom); 967 } else { 968 tile = new Tile(tileSource, x, y, zoom); 969 } 949 970 tileCache.addTile(tile); 950 971 } … … 1021 1042 1022 1043 /** 1023 * Invalidate the layer at a time in the future so t aht the user still sees the interface responsive.1044 * Invalidate the layer at a time in the future so that the user still sees the interface responsive. 1024 1045 */ 1025 1046 private void invalidateLater() { … … 1055 1076 } 1056 1077 1057 /** 1078 /** 1058 1079 * Draw a tile image on screen. 1059 1080 * @param g the Graphics2D … … 1066 1087 AffineTransform imageToScreen = anchorImage.convert(anchorScreen); 1067 1088 Point2D screen0 = imageToScreen.transform(new Point.Double(0, 0), null); 1068 Point2D screen1 = imageToScreen.transform(new Point.Double(toDrawImg.getWidth(), toDrawImg.getHeight()), null); 1089 Point2D screen1 = imageToScreen.transform(new Point.Double( 1090 toDrawImg.getWidth(), toDrawImg.getHeight()), null); 1091 1069 1092 Shape oldClip = null; 1070 1093 if (clip != null) { … … 1085 1108 boolean miss = false; 1086 1109 BufferedImage img = null; 1110 TileAnchor anchorImage = null; 1087 1111 if (!tile.isLoaded() || tile.hasError()) { 1088 1112 miss = true; 1089 1113 } else { 1090 img = getLoadedTileImage(tile); 1091 if (img == null) { 1114 synchronized (tile) { 1115 img = getLoadedTileImage(tile); 1116 anchorImage = getAnchor(tile, img); 1117 } 1118 if (img == null || anchorImage == null) { 1092 1119 miss = true; 1093 1120 } … … 1097 1124 return; 1098 1125 } 1099 TileAnchor anchorImage = new TileAnchor( 1100 new Point.Double(0, 0), 1101 new Point.Double(img.getWidth(), img.getHeight())); 1102 img = applyImageProcessors((BufferedImage) img); 1126 1127 img = applyImageProcessors(img); 1128 1103 1129 TileAnchor anchorScreen = coordinateConverter.getScreenAnchorForTile(tile); 1104 1130 synchronized (paintMutex) { … … 1106 1132 drawImageInside(g, img, anchorImage, anchorScreen, null); 1107 1133 } 1134 if (tile instanceof ReprojectionTile) { 1135 // This means we have a reprojected tile in memory cache, but not at 1136 // current scale. Generally, the positioning of the tile will still 1137 // be correct, but for best image quality, the tile should be 1138 // reprojected to the target scale. The original tile image should 1139 // still be in disk cache, so this is fairly cheap. 1140 if (((ReprojectionTile) tile).needsUpdate(Main.map.mapView.getScale())) { 1141 loadTile(tile, true); 1142 } 1143 } 1144 1108 1145 }, missed::add); 1109 1146 … … 1128 1165 boolean miss = false; 1129 1166 BufferedImage img = null; 1167 TileAnchor anchorImage = null; 1130 1168 if (!tile.isLoaded() || tile.hasError()) { 1131 1169 miss = true; 1132 1170 } else { 1133 img = getLoadedTileImage(tile); 1134 if (img == null) { 1171 synchronized (tile) { 1172 img = getLoadedTileImage(tile); 1173 anchorImage = getAnchor(tile, img); 1174 } 1175 1176 if (img == null || anchorImage == null) { 1135 1177 miss = true; 1136 1178 } … … 1140 1182 continue; 1141 1183 } 1142 TileAnchor anchorImage = new TileAnchor(1143 new Point.Double(0, 0),1144 new Point.Double(img.getWidth(), img.getHeight()));1145 1184 1146 1185 // applying all filters to this layer … … 1159 1198 } 1160 1199 return missedTiles; 1200 } 1201 1202 private TileAnchor getAnchor(Tile tile, BufferedImage image) { 1203 if (tile instanceof ReprojectionTile) { 1204 return ((ReprojectionTile) tile).getAnchor(); 1205 } else { 1206 return new TileAnchor(new Point.Double(0, 0), new Point.Double(image.getWidth(), image.getHeight())); 1207 } 1161 1208 } 1162 1209 … … 1188 1235 } 1189 1236 1190 private void paintTileText(Tile tile, Graphics g, MapView mv) {1237 private void paintTileText(Tile tile, Graphics2D g) { 1191 1238 if (tile == null) { 1192 1239 return; … … 1218 1265 } 1219 1266 1220 int xCursor = -1;1221 int yCursor = -1;1222 1267 if (Main.isDebugEnabled()) { 1223 if (yCursor < tile.getYtile()) { 1224 if (Math.abs(tile.getYtile() % 32) == 31) { 1225 g.fillRect(0, y - 1, mv.getWidth(), 3); 1226 } else { 1227 g.drawLine(0, y, mv.getWidth(), y); 1228 } 1229 //yCursor = t.getYtile(); 1230 } 1231 // This draws the vertical lines for the entire column. Only draw them for the top tile in the column. 1232 if (xCursor < tile.getXtile()) { 1233 if (tile.getXtile() % 32 == 0) { 1234 // level 7 tile boundary 1235 g.fillRect(x - 1, 0, 3, mv.getHeight()); 1236 } else { 1237 g.drawLine(x, 0, x, mv.getHeight()); 1238 } 1239 //xCursor = t.getXtile(); 1240 } 1268 // draw tile outline in semi-transparent red 1269 g.setColor(new Color(255, 0, 0, 50)); 1270 g.draw(coordinateConverter.getScreenQuadrilateralForTile(tile)); 1241 1271 } 1242 1272 } … … 1397 1427 */ 1398 1428 protected TileSet getTileSet(ProjectionBounds bounds, int zoom) { 1399 IProjected topLeftUnshifted = coordinateConverter.shiftDisplayToServer(bounds.getMin()); 1400 IProjected botRightUnshifted = coordinateConverter.shiftDisplayToServer(bounds.getMax()); 1401 TileXY t1 = tileSource.projectedToTileXY(topLeftUnshifted, zoom); 1402 TileXY t2 = tileSource.projectedToTileXY(botRightUnshifted, zoom); 1429 if (zoom == 0) 1430 return new TileSet(); 1431 TileXY t1, t2; 1432 if (coordinateConverter.requiresReprojection()) { 1433 Projection projCurrent = Main.getProjection(); 1434 Projection projServer = Projections.getProjectionByCode(tileSource.getServerCRS()); 1435 bounds = new ProjectionBounds( 1436 new EastNorth(coordinateConverter.shiftDisplayToServer(bounds.getMin())), 1437 new EastNorth(coordinateConverter.shiftDisplayToServer(bounds.getMax()))); 1438 bounds = projServer.getEastNorthBoundsBox(bounds, projCurrent); 1439 t1 = tileSource.projectedToTileXY(bounds.getMin().toProjected(), zoom); 1440 t2 = tileSource.projectedToTileXY(bounds.getMax().toProjected(), zoom); 1441 } else { 1442 IProjected topLeftUnshifted = coordinateConverter.shiftDisplayToServer(bounds.getMin()); 1443 IProjected botRightUnshifted = coordinateConverter.shiftDisplayToServer(bounds.getMax()); 1444 t1 = tileSource.projectedToTileXY(topLeftUnshifted, zoom); 1445 t2 = tileSource.projectedToTileXY(botRightUnshifted, zoom); 1446 } 1403 1447 return new TileSet(t1, t2, zoom); 1404 1448 } … … 1593 1637 // The current zoom tileset should have all of its tiles due to the loadAllTiles(), unless it to tooLarge() 1594 1638 for (Tile t : ts.allExistingTiles()) { 1595 this.paintTileText(t, g , mv);1639 this.paintTileText(t, g); 1596 1640 } 1597 1641 … … 1640 1684 Main.debug("getTileForPixelpos("+px+", "+py+')'); 1641 1685 } 1642 Point clicked = new Point(px, py); 1643 TileSet ts = getVisibleTileSet(); 1644 1645 if (!ts.tooLarge()) { 1646 ts.loadAllTiles(false); // make sure there are tile objects for all tiles 1647 } 1648 Stream<Tile> clickedTiles = ts.allExistingTiles().stream() 1649 .filter(t -> coordinateConverter.getRectangleForTile(t).contains(clicked)); 1650 if (Main.isTraceEnabled()) { 1651 clickedTiles = clickedTiles.peek(t -> Main.trace("Clicked on tile: " + t.getXtile() + ' ' + t.getYtile() + 1652 " currentZoomLevel: " + currentZoomLevel)); 1653 } 1654 return clickedTiles.findAny().orElse(null); 1686 TileXY xy = coordinateConverter.getTileforPixel(px, py, currentZoomLevel); 1687 return getTile(xy.getXIndex(), xy.getYIndex(), currentZoomLevel); 1655 1688 } 1656 1689 -
trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
r11785 r11858 2 2 package org.openstreetmap.josm.gui.layer; 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr;5 4 import static org.openstreetmap.josm.tools.I18n.trc; 6 5 … … 11 10 import java.awt.image.BufferedImageOp; 12 11 import java.util.ArrayList; 12 import java.util.Arrays; 13 import java.util.Collection; 13 14 import java.util.List; 14 15 15 16 import javax.swing.AbstractAction; 16 17 import javax.swing.Action; 18 import javax.swing.BorderFactory; 17 19 import javax.swing.Icon; 18 20 import javax.swing.JCheckBoxMenuItem; … … 24 26 import javax.swing.JPopupMenu; 25 27 import javax.swing.JSeparator; 28 import javax.swing.JTextField; 26 29 27 30 import org.openstreetmap.josm.Main; … … 33 36 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 34 37 import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings; 35 import org.openstreetmap.josm.gui.widgets.UrlLabel;36 38 import org.openstreetmap.josm.tools.GBC; 39 import static org.openstreetmap.josm.tools.I18n.tr; 37 40 import org.openstreetmap.josm.tools.ImageProvider; 38 41 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; … … 146 149 public void mergeFrom(Layer from) { 147 150 } 151 152 public abstract Collection<String> getNativeProjections(); 148 153 149 154 @Override … … 152 157 panel.add(new JLabel(getToolTipText()), GBC.eol()); 153 158 if (info != null) { 154 String url = info.getUrl(); 155 if (url != null) { 156 panel.add(new JLabel(tr("URL: ")), GBC.std().insets(0, 5, 2, 0)); 157 panel.add(new UrlLabel(url), GBC.eol().insets(2, 5, 10, 0)); 159 List<List<String>> content = new ArrayList<>(); 160 content.add(Arrays.asList(tr("Name"), info.getName())); 161 content.add(Arrays.asList(tr("Type"), info.getImageryType().getTypeString().toUpperCase())); 162 content.add(Arrays.asList(tr("URL"), info.getUrl())); 163 content.add(Arrays.asList(tr("Id"), info.getId() == null ? "-" : info.getId())); 164 if (info.getMinZoom() != 0) { 165 content.add(Arrays.asList(tr("Min. zoom"), Integer.toString(info.getMinZoom()))); 166 } 167 if (info.getMaxZoom() != 0) { 168 content.add(Arrays.asList(tr("Max. zoom"), Integer.toString(info.getMaxZoom()))); 169 } 170 if (info.getDescription() != null) { 171 content.add(Arrays.asList(tr("Description"), info.getDescription())); 172 } 173 content.add(Arrays.asList(tr("Native projections"), Utils.join(", ", getNativeProjections()))); 174 for (List<String> entry: content) { 175 panel.add(new JLabel(entry.get(0) + ':'), GBC.std()); 176 panel.add(GBC.glue(5, 0), GBC.std()); 177 panel.add(createTextField(entry.get(1)), GBC.eol().fill(GBC.HORIZONTAL)); 158 178 } 159 179 } 160 180 return panel; 181 } 182 183 protected JTextField createTextField(String text) { 184 JTextField ret = new JTextField(text); 185 ret.setEditable(false); 186 ret.setBorder(BorderFactory.createEmptyBorder()); 187 return ret; 161 188 } 162 189 -
trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java
r11167 r11858 6 6 import java.util.ArrayList; 7 7 import java.util.Collection; 8 import java.util.Collections; 9 import java.util.List; 8 10 9 11 import org.apache.commons.jcs.access.CacheAccess; … … 79 81 80 82 @Override 81 public final boolean isProjectionSupported(Projection proj) { 82 return "EPSG:3857".equals(proj.toCode()) || "EPSG:4326".equals(proj.toCode()); 83 } 84 85 @Override 86 public final String nameSupportedProjections() { 87 return tr("EPSG:4326 and Mercator projection are supported"); 83 public Collection<String> getNativeProjections() { 84 return Collections.singletonList("EPSG:3857"); 88 85 } 89 86 … … 161 158 return new ScaleList(scales); 162 159 } 163 160 } -
trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java
r11848 r11858 7 7 import java.util.ArrayList; 8 8 import java.util.Arrays; 9 import java.util.Collection; 9 10 import java.util.List; 10 import java.util.Set; 11 import java.util.TreeSet; 11 import java.util.Objects; 12 12 13 13 import javax.swing.AbstractAction; … … 28 28 import org.openstreetmap.josm.data.preferences.IntegerProperty; 29 29 import org.openstreetmap.josm.data.projection.Projection; 30 import org.openstreetmap.josm.data.projection.Projections; 30 31 import org.openstreetmap.josm.gui.ExtendedDialog; 31 32 import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings; … … 55 56 private static final String CACHE_REGION_NAME = "WMS"; 56 57 57 private final Set<String> supportedProjections;58 private final List<String> serverProjections; 58 59 59 60 /** … … 66 67 CheckParameterUtil.ensureParameterNotNull(info.getUrl(), "info.url"); 67 68 TemplatedWMSTileSource.checkUrl(info.getUrl()); 68 this.s upportedProjections = newTreeSet<>(info.getServerProjections());69 this.serverProjections = new ArrayList<>(info.getServerProjections()); 69 70 } 70 71 … … 87 88 @Override 88 89 protected AbstractWMSTileSource getTileSource() { 89 AbstractWMSTileSource tileSource = new TemplatedWMSTileSource(info); 90 AbstractWMSTileSource tileSource = new TemplatedWMSTileSource( 91 info, chooseProjection(Main.getProjection())); 90 92 info.setAttribution(tileSource); 91 93 return tileSource; … … 112 114 113 115 @Override 114 public boolean isProjectionSupported(Projection proj) { 115 return supportedProjections == null || supportedProjections.isEmpty() || supportedProjections.contains(proj.toCode()) || 116 (info.isEpsg4326To3857Supported() && supportedProjections.contains("EPSG:4326") 117 && "EPSG:3857".equals(Main.getProjection().toCode())); 118 } 119 120 @Override 121 public String nameSupportedProjections() { 122 StringBuilder ret = new StringBuilder(); 123 for (String e: supportedProjections) { 124 ret.append(e).append(", "); 125 } 126 String appendix = ""; 127 128 if (isReprojectionPossible()) { 129 appendix = ". <p>" + tr("JOSM will use EPSG:4326 to query the server, but results may vary " 130 + "depending on the WMS server") + "</p>"; 131 } 132 return ret.substring(0, ret.length()-2) + appendix; 116 public Collection<String> getNativeProjections() { 117 return serverProjections; 133 118 } 134 119 135 120 @Override 136 121 public void projectionChanged(Projection oldValue, Projection newValue) { 137 // do not call super - we need custom warning dialog 122 Projection tileProjection = chooseProjection(newValue); 123 if (!Objects.equals(tileSource.getTileProjection(), tileProjection)) { 124 tileSource.setTileProjection(tileProjection); 125 } 126 } 138 127 139 if (!isProjectionSupported(newValue)) { 140 String message = 141 "<html><body><p>" + tr("The layer {0} does not support the new projection {1}.", 142 Utils.escapeReservedCharactersHTML(getName()), newValue.toCode()) + 143 "<p style='width: 450px; position: absolute; margin: 0px;'>" + 144 tr("Supported projections are: {0}", nameSupportedProjections()) + "</p>" + 145 "<p>" + tr("Change the projection again or remove the layer."); 146 147 ExtendedDialog warningDialog = new ExtendedDialog(Main.parent, tr("Warning"), new String[]{tr("OK")}). 148 setContent(message). 149 setIcon(JOptionPane.WARNING_MESSAGE); 150 151 if (isReprojectionPossible()) { 152 warningDialog.toggleEnable("imagery.wms.projectionSupportWarnings." + tileSource.getBaseUrl()); 128 private Projection chooseProjection(Projection requested) { 129 if (serverProjections.contains(requested.toCode())) { 130 return requested; 131 } else { 132 for (String code : serverProjections) { 133 Projection proj = Projections.getProjectionByCode(code); 134 if (proj != null) { 135 Main.info(tr("Reprojecting layer {0} from {1} to {2}. For best image quality and performance," 136 + " switch to one of the supported projections: {3}", 137 getName(), proj.toCode(), Main.getProjection().toCode(), Utils.join(", ", getNativeProjections()))); 138 return proj; 139 } 153 140 } 154 warningDialog.showDialog(); 155 } 156 157 if (!newValue.equals(oldValue)) { 158 tileSource.initProjection(newValue); 141 Main.warn(tr("Unable to find supported projection for layer {0}. Using {1}.", getName(), requested.toCode())); 142 return requested; 159 143 } 160 144 } … … 176 160 return AbstractCachedTileSourceLayer.getCache(CACHE_REGION_NAME); 177 161 } 178 179 private boolean isReprojectionPossible() {180 return supportedProjections.contains("EPSG:4326") && "EPSG:3857".equals(Main.getProjection().toCode());181 }182 162 } -
trunk/src/org/openstreetmap/josm/gui/layer/WMTSLayer.java
r11789 r11858 3 3 4 4 import java.io.IOException; 5 import java.util. Set;5 import java.util.Collection; 6 6 7 7 import org.apache.commons.jcs.access.CacheAccess; … … 15 15 import org.openstreetmap.josm.data.projection.Projection; 16 16 import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings; 17 import org.openstreetmap.josm.tools.Utils; 17 18 18 19 /** … … 75 76 return getMaxZoomLvl(); 76 77 } 77 double displayScale = Main.map.mapView.getScale() * Main.getProjection().getMetersPerUnit(); // meter per pixel 78 double displayScale = Main.map.mapView.getScale(); 79 if (coordinateConverter.requiresReprojection()) { 80 displayScale *= Main.getProjection().getMetersPerUnit(); 81 } 78 82 Scale snap = scaleList.getSnapScale(displayScale, false); 79 return Math.max( 80 getMinZoomLvl(), 81 Math.min( 82 snap != null ? snap.getIndex() : getMaxZoomLvl(), 83 getMaxZoomLvl() 84 ) 85 ); 83 return Utils.clamp(snap != null ? snap.getIndex() : getMaxZoomLvl(), 84 getMinZoomLvl(), getMaxZoomLvl()); 86 85 } 87 86 … … 92 91 93 92 @Override 94 public boolean isProjectionSupported(Projection proj) { 95 Set<String> supportedProjections = tileSource.getSupportedProjections(); 96 return supportedProjections.contains(proj.toCode()); 97 } 98 99 @Override 100 public String nameSupportedProjections() { 101 StringBuilder ret = new StringBuilder(); 102 for (String e: tileSource.getSupportedProjections()) { 103 ret.append(e).append(", "); 104 } 105 return ret.length() > 2 ? ret.substring(0, ret.length()-2) : ret.toString(); 93 public Collection<String> getNativeProjections() { 94 return tileSource.getSupportedProjections(); 106 95 } 107 96 -
trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileCoordinateConverter.java
r11846 r11858 12 12 import org.openstreetmap.gui.jmapviewer.interfaces.IProjected; 13 13 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 14 import org.openstreetmap.josm.Main; 14 15 import org.openstreetmap.josm.data.coor.EastNorth; 15 16 import org.openstreetmap.josm.data.coor.LatLon; … … 85 86 */ 86 87 public Point2D getPixelForTile(Tile tile) { 87 return this.getPixelForTile(tile.getXtile(), tile.getYtile(), tile.getZoom()); 88 return getPixelForTile(tile.getXtile(), tile.getYtile(), tile.getZoom()); 89 } 90 91 /** 92 * Convert screen pixel coordinate to tile position at certain zoom level. 93 * @param sx x coordinate (screen pixel) 94 * @param sy y coordinate (screen pixel) 95 * @param zoom zoom level 96 * @return the tile 97 */ 98 public TileXY getTileforPixel(int sx, int sy, int zoom) { 99 if (requiresReprojection()) { 100 LatLon ll = getProjecting().eastNorth2latlonClamped(mapView.getEastNorth(sx, sy)); 101 return tileSource.latLonToTileXY(ll.toCoordinate(), zoom); 102 } else { 103 IProjected p = shiftDisplayToServer(mapView.getEastNorth(sx, sy)); 104 return tileSource.projectedToTileXY(p, zoom); 105 } 88 106 } 89 107 … … 91 109 * Gets the position of the tile inside the map view. 92 110 * @param tile The tile 93 * @return The positon .111 * @return The positon as a rectangle in screen coordinates 94 112 */ 95 113 public Rectangle2D getRectangleForTile(Tile tile) { … … 130 148 */ 131 149 public double getScaleFactor(int zoom) { 132 LatLon topLeft = mapView.getLatLon(0, 0); 133 LatLon botRight = mapView.getLatLon(mapView.getWidth(), mapView.getHeight()); 134 TileXY t1 = tileSource.latLonToTileXY(topLeft.toCoordinate(), zoom); 135 TileXY t2 = tileSource.latLonToTileXY(botRight.toCoordinate(), zoom); 136 150 TileXY t1, t2; 151 if (requiresReprojection()) { 152 LatLon topLeft = mapView.getLatLon(0, 0); 153 LatLon botRight = mapView.getLatLon(mapView.getWidth(), mapView.getHeight()); 154 t1 = tileSource.latLonToTileXY(topLeft.toCoordinate(), zoom); 155 t2 = tileSource.latLonToTileXY(botRight.toCoordinate(), zoom); 156 } else { 157 EastNorth topLeftEN = mapView.getEastNorth(0, 0); 158 EastNorth botRightEN = mapView.getEastNorth(mapView.getWidth(), mapView.getHeight()); 159 t1 = tileSource.projectedToTileXY(topLeftEN.toProjected(), zoom); 160 t2 = tileSource.projectedToTileXY(botRightEN.toProjected(), zoom); 161 } 137 162 int screenPixels = mapView.getWidth()*mapView.getHeight(); 138 163 double tilePixels = Math.abs((t2.getY()-t1.getY())*(t2.getX()-t1.getX())*tileSource.getTileSize()*tileSource.getTileSize()); … … 147 172 */ 148 173 public TileAnchor getScreenAnchorForTile(Tile tile) { 149 IProjected p1 = tileSource.tileXYtoProjected(tile.getXtile(), tile.getYtile(), tile.getZoom()); 150 IProjected p2 = tileSource.tileXYtoProjected(tile.getXtile() + 1, tile.getYtile() + 1, tile.getZoom()); 151 return new TileAnchor(pos(p1).getInView(), pos(p2).getInView()); 174 if (requiresReprojection()) { 175 ICoordinate c1 = tile.getTileSource().tileXYToLatLon(tile); 176 ICoordinate c2 = tile.getTileSource().tileXYToLatLon(tile.getXtile() + 1, tile.getYtile() + 1, tile.getZoom()); 177 return new TileAnchor(pos(c1).getInView(), pos(c2).getInView()); 178 } else { 179 IProjected p1 = tileSource.tileXYtoProjected(tile.getXtile(), tile.getYtile(), tile.getZoom()); 180 IProjected p2 = tileSource.tileXYtoProjected(tile.getXtile() + 1, tile.getYtile() + 1, tile.getZoom()); 181 return new TileAnchor(pos(p1).getInView(), pos(p2).getInView()); 182 } 183 } 184 185 /** 186 * Return true if tiles need to be reprojected from server projection to display projection. 187 * @return true if tiles need to be reprojected from server projection to display projection 188 */ 189 public boolean requiresReprojection() { 190 return !tileSource.getServerCRS().equals(Main.getProjection().toCode()); 152 191 } 153 192 } -
trunk/src/org/openstreetmap/josm/io/imagery/ImageryReader.java
r11575 r11858 458 458 entry.setGeoreferenceValid(Boolean.parseBoolean(accumulator.toString())); 459 459 break; 460 case "epsg4326to3857Supported":461 entry.setEpsg4326To3857Supported(Boolean.parseBoolean(accumulator.toString()));462 break;463 460 default: // Do nothing 464 461 }
Note:
See TracChangeset
for help on using the changeset viewer.