/* * Copyright (C) 2014 Alec Dhuse * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package co.foldingmap.map.tile; import co.foldingmap.Logger; import co.foldingmap.map.Layer; import co.foldingmap.map.MapObject; import co.foldingmap.map.MapObjectList; import co.foldingmap.map.MapView; import co.foldingmap.map.vector.LatLonAltBox; import co.foldingmap.map.vector.LatLonBox; import co.foldingmap.xml.XmlOutput; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import javax.swing.JMenuItem; /** * * @author Alec */ public class TileLayer extends Layer { private TileSource tileSource; public TileLayer(TileSource tileSource) { this.layerDescription = tileSource.getDescription(); this.layerName = tileSource.getName(); this.tileSource = tileSource; this.visible = true; } public TileLayer(String name, String description, boolean visible, TileSource tileSource) { this.layerName = name; this.layerDescription = description; this.tileSource = tileSource; this.visible = visible; } /** * Closes this Layer gracefully. */ @Override public void closeLayer() { this.tileSource.closeSource(); } @Override public Layer copy() { Layer layerCopy = new TileLayer(getTileSource()); layerCopy.setName(layerName); layerCopy.setVisible(visible); layerCopy.setParentMap(parentMap); layerCopy.setLayerDescription(layerDescription); return layerCopy; } @Override public void drawLayer(Graphics2D g2, MapView mapView) { BufferedImage image; float longitudeW, longitudeE, tileZoom; float tileX, tileX2, tileY; int size; LatLonBox viewBounds; TileReference currentTileRef, tileRef0, tileRef1; try { if (this.visible) { g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); viewBounds = mapView.getViewBounds(); longitudeE = viewBounds.getEast(); longitudeW = viewBounds.getWest(); tileZoom = Math.round(TileMath.getTileMapZoom(mapView.getZoomLevel())); if (tileZoom > this.tileSource.maxZoom) { tileZoom = tileSource.maxZoom; } else if (tileZoom < this.tileSource.minZoom) { tileZoom = tileSource.minZoom; } //The west bounds is over the IDL if (longitudeW > longitudeE) { longitudeW = -180; } if ((longitudeE < longitudeW) || tileZoom <= 4) { longitudeE = 180; } tileRef0 = TileReference.getTileReference(viewBounds.getNorth(), longitudeW, (int) tileZoom); tileRef1 = TileReference.getTileReference(viewBounds.getSouth(), longitudeE, (int) tileZoom); //determine scale tileX = mapView.getX(tileRef0.getCoordinate(), MapView.NO_WRAP); tileX2 = mapView.getX(tileRef0.getTileOffset(1, 0).getCoordinate(), MapView.NO_WRAP); size = (int) (tileX2 - tileX); tileX = mapView.getX(tileRef1.getCoordinate(), MapView.NO_WRAP); int x = tileRef1.getX(); if (size > 0) { while (tileX > (size * -1)) { tileY = mapView.getY(tileRef1.getCoordinate()); for (int y = tileRef1.getY(); y >= tileRef0.getY(); y--) { currentTileRef = new TileReference(x, y, (int) tileZoom); image = tileSource.getTileImage(currentTileRef); if (image != null) { g2.drawImage(image, (int) tileX, (int) tileY, (int) size, (int) size, null); tileY -= size; } } tileX -= size; x = (x - 1) % ((int) Math.pow(2, tileZoom)); } } } } catch (Exception e) { Logger.log(Logger.ERR, "Error in TileLayer.drawLayer(Graphics2D, MapView) - " + e); } } /** * Returns the boundary that contains all the tiles in this layer. * * @return */ @Override public LatLonAltBox getBoundary() { if (this.getTileSource().getBoundingBox() != null) { return this.getTileSource().getBoundingBox(); } else { return new LatLonAltBox(85.05f, -85.05f, 180f, -180f, 0f, 0f); } } /** * Returns the center longitude for this TileLayer. * * @return */ @Override public float getCenterLongitude() { return (float) this.getTileSource().getBoundingBox().getCenter().getLongitude(); } /** * Returns the center latitude for this TileLAyer. * * @return */ @Override public float getCenterLatitude() { return (float) this.getTileSource().getBoundingBox().getCenter().getLatitude(); } /** * Returns JMenuItems that should be used in the context menu for this Layer * * @return */ @Override public JMenuItem[] getContextMenuItems() { return new JMenuItem[0]; } /** * Returns the TileSource for this TileLayer; * * @return */ public TileSource getTileSource() { return this.tileSource; } @Override public MapObjectList selectObjects(Rectangle2D range) { //TODO: Have the ability to select tiles as MapObjects return new MapObjectList<MapObject>(); } /** * Sets the TileSource for this TileLayer. * * @param tileSource The TileSource used to fetch tiles for this layer. */ public void setTileSource(TileSource tileSource) { this.tileSource = tileSource; } /** * Writes out this TileLayer to FmXML. * * @param xmlWriter */ @Override public void toXML(XmlOutput xmlWriter) { xmlWriter.openTag("TileLayer"); xmlWriter.writeTag("name", layerName); xmlWriter.writeTag("description", layerDescription); xmlWriter.writeTag("visible", Boolean.toString(visible)); //Write out Tile Source tileSource.toXML(xmlWriter); xmlWriter.closeTag("TileLayer"); } }