package com.revolsys.swing.map.layer.webmercatortilecache;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.revolsys.collection.map.MapEx;
import com.revolsys.datatype.DataType;
import com.revolsys.geometry.model.BoundingBox;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.logging.Logs;
import com.revolsys.swing.Icons;
import com.revolsys.swing.SwingUtil;
import com.revolsys.swing.component.BasePanel;
import com.revolsys.swing.component.ValueField;
import com.revolsys.swing.field.TextField;
import com.revolsys.swing.layout.GroupLayouts;
import com.revolsys.swing.map.Viewport2D;
import com.revolsys.swing.map.layer.AbstractTiledImageLayer;
import com.revolsys.swing.map.layer.BaseMapLayerGroup;
import com.revolsys.swing.map.layer.MapTile;
import com.revolsys.swing.menu.MenuFactory;
import com.revolsys.swing.menu.Menus;
import com.revolsys.util.CaseConverter;
import com.revolsys.util.Property;
public class WebMercatorTileCacheLayer extends AbstractTiledImageLayer {
public static final GeometryFactory GEOMETRY_FACTORY = GeometryFactory.floating3(4326);
private static final BoundingBox MAX_BOUNDING_BOX = GEOMETRY_FACTORY.newBoundingBox(-180, -85,
180, 85);
private static void actionAddLayer(final BaseMapLayerGroup parent) {
final ValueField dialog = new ValueField();
dialog.setTitle("Add Web Mercator Tile Cache Layer");
SwingUtil.addLabel(dialog, "URL");
final TextField urlField = new TextField("url", 50);
dialog.add(urlField);
GroupLayouts.makeColumns(dialog, 2, true, true);
dialog.setSaveAction(() -> {
final String url = urlField.getText();
if (Property.hasValue(url)) {
final WebMercatorTileCacheLayer layer = new WebMercatorTileCacheLayer();
layer.setUrl(url);
layer.setVisible(true);
parent.addLayer(layer);
}
});
dialog.showDialog();
}
public static void mapObjectFactoryInit() {
final MenuFactory baseMapsMenu = MenuFactory.getMenu(BaseMapLayerGroup.class);
Menus.addMenuItem(baseMapsMenu, "group", "Add Web Mercator Tile Cache Layer",
Icons.getIconWithBadge("map", "add"), WebMercatorTileCacheLayer::actionAddLayer, false);
}
private WebMercatorTileCacheClient client;
private String url;
public WebMercatorTileCacheLayer() {
super("webMercatorTileCacheLayer");
}
public WebMercatorTileCacheLayer(final Map<String, Object> properties) {
this();
setProperties(properties);
}
@Override
public boolean equals(final Object other) {
if (other instanceof WebMercatorTileCacheLayer) {
final WebMercatorTileCacheLayer layer = (WebMercatorTileCacheLayer)other;
if (DataType.equal(layer.getUrl(), getUrl())) {
return true;
}
}
return false;
}
@Override
public BoundingBox getBoundingBox() {
return MAX_BOUNDING_BOX;
}
public WebMercatorTileCacheClient getClient() {
return this.client;
}
@Override
public List<MapTile> getOverlappingMapTiles(final Viewport2D viewport) {
final List<MapTile> tiles = new ArrayList<>();
try {
final double metresPerPixel = viewport.getUnitsPerPixel();
final int zoomLevel = this.client.getZoomLevel(metresPerPixel);
final double resolution = getResolution(viewport);
final BoundingBox geographicBoundingBox = viewport.getBoundingBox()
.convert(GEOMETRY_FACTORY)
.intersection(MAX_BOUNDING_BOX);
final double minX = geographicBoundingBox.getMinX();
final double minY = geographicBoundingBox.getMinY();
final double maxX = geographicBoundingBox.getMaxX();
final double maxY = geographicBoundingBox.getMaxY();
// Tiles start at the North-West corner of the map
final int minTileY = this.client.getTileY(zoomLevel, maxY);
final int maxTileY = this.client.getTileY(zoomLevel, minY);
final int minTileX = this.client.getTileX(zoomLevel, minX);
final int maxTileX = this.client.getTileX(zoomLevel, maxX);
for (int tileY = minTileY; tileY <= maxTileY; tileY++) {
for (int tileX = minTileX; tileX <= maxTileX; tileX++) {
final WebMercatorTileCacheMapTile tile = new WebMercatorTileCacheMapTile(this, zoomLevel,
resolution, tileX, tileY);
tiles.add(tile);
}
}
} catch (final Throwable e) {
Logs.error(this, "Error getting tile envelopes", e);
}
return tiles;
}
@Override
public double getResolution(final Viewport2D viewport) {
final double metresPerPixel = viewport.getUnitsPerPixel();
final int zoomLevel = this.client.getZoomLevel(metresPerPixel);
return this.client.getResolution(zoomLevel);
}
public String getUrl() {
return this.url;
}
@Override
protected boolean initializeDo() {
this.client = new WebMercatorTileCacheClient(this.url);
return true;
}
@Override
protected ValueField newPropertiesTabGeneralPanelSource(final BasePanel parent) {
final ValueField panel = super.newPropertiesTabGeneralPanelSource(parent);
final String url = getUrl();
SwingUtil.addLabelledReadOnlyTextField(panel, "URL", url);
GroupLayouts.makeColumns(panel, 2, true);
return panel;
}
public void setUrl(final String url) {
final Object oldValue = this.url;
if (Property.hasValue(url)) {
if (url.endsWith("/")) {
this.url = url;
} else {
this.url = url + "/";
}
if (getName() == null) {
setName(
CaseConverter.toCapitalizedWords(url.replaceAll("http(s)?://", "").replaceAll("/", " ")));
}
}
firePropertyChange("url", oldValue, url);
}
@Override
public MapEx toMap() {
final MapEx map = super.toMap();
map.put("type", "openStreetMap");
addToMap(map, "url", this.url);
return map;
}
}