X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.district.maps%2Fsrc%2Forg%2Fsimantics%2Fmaps%2Fsg%2FMapNode.java;h=5bdd2555c7bb373b53a6c34789f13f92fd0ae688;hb=HEAD;hp=e06adcb27e2d82ef8757cc9e4a8e96c6738313fc;hpb=a4395a1da139133059833fb1f909f5033676f8bc;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.maps/src/org/simantics/maps/sg/MapNode.java b/org.simantics.district.maps/src/org/simantics/maps/sg/MapNode.java index e06adcb2..5bdd2555 100644 --- a/org.simantics.district.maps/src/org/simantics/maps/sg/MapNode.java +++ b/org.simantics.district.maps/src/org/simantics/maps/sg/MapNode.java @@ -38,9 +38,12 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.simantics.maps.MapScalingTransform; import org.simantics.maps.WebService; import org.simantics.maps.osm.OSMTileProvider; import org.simantics.maps.pojo.TileJobQueue; +import org.simantics.maps.prefs.MapsClientPreferences; import org.simantics.maps.tile.IFilter; import org.simantics.maps.tile.ITileJobQueue; import org.simantics.maps.tile.ITileListener; @@ -49,6 +52,8 @@ import org.simantics.maps.tile.TileCache; import org.simantics.maps.tile.TileKey; import org.simantics.scenegraph.g2d.G2DNode; import org.simantics.scenegraph.g2d.G2DRenderingHints; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Tuukka Lehtonen @@ -57,12 +62,15 @@ public class MapNode extends G2DNode implements ITileListener { private static final long serialVersionUID = 2490944880914577411L; - private final double MAP_SCALE = 1; - private final int MAX_TILE_LEVEL = 19; + private static final Logger LOGGER = LoggerFactory.getLogger(MapNode.class); + + //private final double MAP_SCALE = 1; + //private final int MAX_TILE_LEVEL = 19; private final int TILE_PIXEL_SIZE = 256; private final int VIEWBOX_QUIET_TIME = 500; protected Boolean enabled = true; + protected Color backgroundColor; enum TileState { NOT_LOADED, @@ -165,16 +173,31 @@ public class MapNode extends G2DNode implements ITileListener { } }; - private int scale; + private IPreferenceChangeListener listener; public void init() { try { - ITileProvider provider = new OSMTileProvider(new WebService("http://localhost:8080/mapbox-studio-osm-bright.tm2/"), TILE_PIXEL_SIZE); + OSMTileProvider provider = new OSMTileProvider(new WebService(computeUrl()), TILE_PIXEL_SIZE); + + listener = event -> { + // if tiles or style change we want to flush the tile cache + if (MapsClientPreferences.P_CURRENT_MBTILES.equals(event.getKey()) || MapsClientPreferences.P_CURRENT_TM2STYLE.equals(event.getKey())) { + if (tileCache != null) { + tileCache.clear(); + } + try { + provider.setWebService(new WebService(computeUrl())); + } catch (MalformedURLException | URISyntaxException e) { + LOGGER.error("Unable to update WebService with new url", e); + } + } + }; + MapsClientPreferences.addPreferenceChangeListenerMapsServer(listener); // Try to load eclipse specific implementation of TileJobQueue, if it doesn't exist, fall back to pojo implementation try { Class proxyClass = (Class) Class.forName("org.simantics.maps.eclipse.TileJobQueue"); - job = (ITileJobQueue)proxyClass.newInstance(); + job = (ITileJobQueue)proxyClass.getDeclaredConstructor().newInstance(); } catch (ClassNotFoundException e1) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { @@ -202,32 +225,55 @@ public class MapNode extends G2DNode implements ITileListener { this.tileCache = new TileCache(job); this.tileCache.addTileListener(this); - } catch (MalformedURLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (URISyntaxException e) { - // TODO Auto-generated catch block - e.printStackTrace(); } catch(Exception e ) { - e.printStackTrace(); + LOGGER.error("Failed to initialize MapNode", e); } } + private static String computeUrl() { + // Construct WebService from client properties + String url; + if (MapsClientPreferences.useBuiltinServer()) + url = MapsClientPreferences.possibleBuiltinServerURL(); + else + url = MapsClientPreferences.tileserverURL(); + if (!url.endsWith("/")) + url = url + "/"; + return url; + } + + @Override + public void cleanup() { + MapsClientPreferences.removePreferenceChangeListenerMapsServer(listener); + tileCache.clear(); + job.clear(); + } + @SyncField("enabled") public void setEnabled(Boolean enabled) { this.enabled = enabled; } + @SyncField("backgroundColor") + public void setBackgroundColor(Color color) { + this.backgroundColor = color; + } + @Override public void render(Graphics2D g2d) { - if (!enabled) - return; - - Graphics2D g = (Graphics2D)g2d.create(); - - AffineTransform tr = (AffineTransform)g.getTransform().clone(); + + AffineTransform ot = g2d.getTransform(); + //System.err.println("ot " + ot); + g2d.transform(transform); + + AffineTransform tr = g2d.getTransform(); + //System.err.println("tr " + tr); +// Graphics2D g = (Graphics2D)g2d.create(); +// AffineTransform tr = (AffineTransform)g.getTransform().clone(); + double scaleX = Math.abs(tr.getScaleX()); + //System.err.println("scaleX : " + scaleX); double scaleY = Math.abs(tr.getScaleY()); if (scaleX <= 0 || scaleY <= 0) { // Make sure that we don't end up in an eternal loop below. @@ -236,72 +282,81 @@ public class MapNode extends G2DNode implements ITileListener { double offsetX = -tr.getTranslateX(); double offsetY = -tr.getTranslateY(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Rectangle2D sp = localToControl(new Rectangle2D.Double(0.0, 0.0, 1.0, 1.0)); - Rectangle2D b = (Rectangle2D)((Rectangle)g.getRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS)).getBounds2D(); // getClipBounds is not accurate enough, use original clipbounds and scale here + Rectangle2D b = (Rectangle2D)((Rectangle)g2d.getRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS)).getBounds2D(); // getClipBounds is not accurate enough, use original clipbounds and scale here Rectangle2D viewbox = new Rectangle2D.Double(offsetX/scaleX, offsetY/scaleY, b.getWidth()/sp.getWidth(), b.getHeight()/sp.getHeight()); //g.getClipBounds(); - if(viewbox == null) return; // FIXME - - double smallerViewboxDimension = viewbox.getWidth() < viewbox.getHeight() ? viewbox.getWidth() * MAP_SCALE : viewbox.getHeight() * MAP_SCALE; - int level = 0; - double tileSize = get360Scaled() * MAP_SCALE*2; - while (level < MAX_TILE_LEVEL) { - double ratio = smallerViewboxDimension / tileSize; - if (ratio >= 0.85) { - break; + if (enabled) { + + int level = MapScalingTransform.zoomLevel(ot); + +// double smallerViewboxDimension = viewbox.getWidth() < viewbox.getHeight() ? viewbox.getWidth() * MAP_SCALE : viewbox.getHeight() * MAP_SCALE; +// int level = 0; +// double tileSize = 360 * MAP_SCALE*2.5; +// while (level < MAX_TILE_LEVEL) { +// double ratio = smallerViewboxDimension / tileSize; +// if (ratio >= 0.85) { +// break; +// } +// tileSize *= 0.5; +// level++; +// } + /* + * To convert y-coordinates to map coordinates in ruler, use: + * double val = (y-offsetY)/scaleY; + * val = Math.toDegrees(Math.atan(Math.sinh(Math.toRadians(val)))); + * String str = formatValue(val); + */ + + double minx = Math.min(180, Math.max(viewbox.getMinX(), -180)); + double maxx = Math.min(180, Math.max(viewbox.getMaxX(), -180)); + + double miny = Math.min(360, Math.max(viewbox.getMinY()+180, 0)); + double maxy = Math.min(360, Math.max(viewbox.getMaxY()+180, 0)); + //System.err.println("minx " + minx + " maxx " + maxx + " miny " + miny + " maxy " + maxy); + g2d.setTransform(new AffineTransform()); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + int levels = (1 << level); + //System.err.println("level " + level); + //System.err.println("levels " + levels); + // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames + int left = (int)Math.floor( (minx + 180) / 360 * (1<= levels) + continue; + for (int ty = top; ty <= bottom; ty++) { + if (ty < 0 || ty >= levels) + continue; + TileKey tile = new TileKey(level, tx, ty); + double y = (double) ty - (double) levels / 2; // In level 0 we have only one tile + + paintTile(tileCache, g2d, tr, tile, tx * tsx - 180, y * tsx, tsx); + } } - tileSize *= 0.5; - level++; - } - - /* - * To convert y-coordinates to map coordinates in ruler, use: - * double val = (y-offsetY)/scaleY; - * val = Math.toDegrees(Math.atan(Math.sinh(Math.toRadians(val)))); - * String str = formatValue(val); - */ - - double minx = Math.min(get180Scaled(), Math.max(viewbox.getMinX(), -get180Scaled())); - double maxx = Math.min(get180Scaled(), Math.max(viewbox.getMaxX(), -get180Scaled())); - - double miny = Math.min(get360Scaled(), Math.max(viewbox.getMinY()+get180Scaled(), 0)); - double maxy = Math.min(get360Scaled(), Math.max(viewbox.getMaxY()+get180Scaled(), 0)); - - g.setTransform(new AffineTransform()); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - int levels = (1 << level); - - // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames - int left = (int)Math.floor( (minx + get180Scaled()) / get360Scaled() * (1<= levels) continue; - for(int ty = top; ty <= bottom; ty++) { - if(ty < 0 || ty >= levels) continue; - TileKey tile = new TileKey(level, tx, ty); - double y = (double)ty - (double)levels/2; // In level 0 we have only one tile - paintTile(tileCache, g, tr, tile, tx*tsx-get180Scaled(), y*tsx, tsx); + // g.dispose(); + + // Check if transform has changed + transformChanged(tr, level); + } else { + if (backgroundColor != null) { + g2d.setTransform(new AffineTransform()); + Rectangle2D controlBounds = (Rectangle2D) g2d.getRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS); + Color color = g2d.getColor(); + g2d.setColor(backgroundColor); + g2d.fill(controlBounds); + g2d.setColor(color); } } - g.dispose(); - - // Check if transform has changed - transformChanged(tr, level); - } - - private double get360Scaled() { - return 360 * scale; - } - - private double get180Scaled() { - return 180 * scale; + g2d.setTransform(ot); } @Override @@ -576,8 +631,4 @@ public class MapNode extends G2DNode implements ITileListener { repaint(); } - public void setScale(int scale) { - this.scale = scale; - } - } \ No newline at end of file