/******************************************************************************* * Copyright (c) 2012 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.maps.tile; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import org.simantics.maps.ProvisionException; /** * @author Tuukka Lehtonen * @deprecated this is a demo hack, do not use */ public class Shp2ImgTileProvider implements ITileProvider { private static final String SHP2IMG_EXECUTABLE = "c:\\ms4w\\tools\\mapserv\\shp2img.exe"; private static final String SCHEME = "shp2img"; final URI source; final File mapDirectory; final String mapName; final int tilePixelSize; final String tileSizeString; Rectangle2D extentDegrees; Rectangle2D extentMeters; double deWidthRecip; double deHeightRecip; String[] ENVP = null; BufferedImage outOfBoundsImage; public Shp2ImgTileProvider(String mapDirectory, String mapName, int tilePixelSize, Rectangle2D extentDegrees, Rectangle2D extentMeters) { this.mapDirectory = new File(mapDirectory); this.mapName = mapName; this.tilePixelSize = tilePixelSize; this.tileSizeString = String.valueOf(tilePixelSize); this.extentDegrees = extentDegrees; this.extentMeters = extentMeters; this.deWidthRecip = 1.0 / extentDegrees.getWidth(); this.deHeightRecip = 1.0 / extentDegrees.getHeight(); if (!this.mapDirectory.exists()) { throw new IllegalArgumentException("Map directory '" + mapDirectory + "' does not exist"); } StringBuilder host = new StringBuilder(); boolean first = true; String[] segments = mapDirectory.split(File.pathSeparator); for (String seg : segments) { if (!first) host.append('.'); first = false; host.append(seg); } host.append('.'); host.append(mapName); try { source = new URI(SCHEME, host.toString(), null, null); } catch (URISyntaxException e) { throw new RuntimeException("Shp2ImgTileProvider: Problem in URI generation with mapDirectory=" + mapDirectory + ", mapName= " + mapName, e); } List envp = new ArrayList(); envp.add("GDAL_DATA=c:\\ms4w\\gdaldata"); envp.add("GDAL_DRIVER_PATH=c:\\ms4w\\gdalplugins"); envp.add("PROJ_LIB=c:\\ms4w\\proj\\nad"); envp.add("PATH=c:\\ms4w\\Apache\\cgi-bin;c:\\ms4w\\tools\\gdal-ogr;c:\\ms4w\\tools\\mapserv;c:\\ms4w\\tools\\shapelib;c:\\ms4w\\proj\\bin;c:\\ms4w\\tools\\shp2tile;c:\\ms4w\\tools\\shpdiff;c:\\ms4w\\tools\\avce00;c:\\ms4w\\tools\\demtools;"); ENVP = envp.toArray(new String[0]); // Iterator readers = ImageIO.getImageReadersByFormatName("png"); // ImageReader reader = readers.next(); } @Override public URI getSource() { return source; } @Override public Rectangle2D getExtent() { // FIXME: should return a clone return extentDegrees; } @Override public Image get(TileKey key) throws ProvisionException { // TODO: make this code a utility and externalize the remaining logic as a strategy // This very same code is the same in all ITileProvider implementations. int level = key.getLevel(); int x = key.getX(); int y = key.getY(); double xTiles = Math.pow(2, level + 1); double yTiles = Math.pow(2, level); if (level < 0) throw new IllegalArgumentException("invalid tile level " + level + " (tile=" + key +")"); if (x < 0 || x >= (int) xTiles) throw new IllegalArgumentException("tile x out of bounds " + x + " (tile=" + key +")"); if (y < 0 || y >= (int) yTiles) throw new IllegalArgumentException("tile y out of bounds " + y + " (tile=" + key +")"); Rectangle2D r = new Rectangle2D.Double(); double minx = -180; double miny = -90; double w = 360; double h = 180; double xdelta = w / xTiles; double ydelta = h / yTiles; double xx = x; double yy = yTiles - y - 1; r.setFrame( minx + xdelta*xx, miny + ydelta*yy, xdelta, ydelta ); if (r.intersects(extentDegrees)) { Rectangle2D meters = transformDegreesToMeters(r); // System.out.println("getImage: " + meters.getMinX() + ", " + meters.getMaxX() + ", " + meters.getWidth() + " ... " + meters.getMinY() + ", " + meters.getMaxY() + ", " + meters.getHeight()); try { return getImage(meters); } catch (IOException e) { throw new ProvisionException(e); } } return getOutOfBoundsImage(); } private Image getOutOfBoundsImage() { if (outOfBoundsImage != null) return outOfBoundsImage; final int outOfBoundsImageSize = 1; BufferedImage image = new BufferedImage(outOfBoundsImageSize, outOfBoundsImageSize, BufferedImage.TYPE_3BYTE_BGR); Graphics2D g = image.createGraphics(); try { g.setColor(Color.PINK); g.fillRect(0, 0, outOfBoundsImageSize, outOfBoundsImageSize); outOfBoundsImage = image; return image; } finally { g.dispose(); } } private Rectangle2D transformDegreesToMeters(Rectangle2D r) { double nx1 = (r.getMinX() - extentDegrees.getMinX()) * deWidthRecip; double ny1 = (r.getMinY() - extentDegrees.getMinY()) * deHeightRecip; double nx2 = (r.getMaxX() - extentDegrees.getMinX()) * deWidthRecip; double ny2 = (r.getMaxY() - extentDegrees.getMinY()) * deHeightRecip; double dw = extentMeters.getWidth(); double dh = extentMeters.getHeight(); Rectangle2D result = new Rectangle2D.Double(); result.setFrameFromDiagonal( extentMeters.getMinX() + nx1 * dw, extentMeters.getMinY() + ny1 * dh, extentMeters.getMinX() + nx2 * dw, extentMeters.getMinY() + ny2 * dh ); return result; } private BufferedImage getImage(Rectangle2D r) throws IOException { double w = r.getWidth(); double h = r.getHeight(); String tileSizeStringX; String tileSizeStringY; if (w > h) { tileSizeStringX = tileSizeString; tileSizeStringY = "" + (int) Math.round(((double)tilePixelSize) * (h/w)); } else { tileSizeStringX = "" + (int) Math.round(((double)tilePixelSize) * (w/h)); tileSizeStringY = tileSizeString; } File tempFile = File.createTempFile("map", ".png"); String[] cmd = new String[] { SHP2IMG_EXECUTABLE, // "-all_debug", // "5", "-m", mapName, "-o", tempFile.getAbsolutePath(), "-s", tileSizeStringX, tileSizeStringY, "-e", String.valueOf(r.getMinX()), String.valueOf(r.getMinY()), String.valueOf(r.getMaxX()), String.valueOf(r.getMaxY()) }; try { try { // System.out.println(System.currentTimeMillis() + " TEMP FILE: " + tempFile); // System.out.println(System.currentTimeMillis() + " EXEC: " + Arrays.toString(cmd)); // System.out.println(System.currentTimeMillis() + " EXEC: " + Arrays.toString(ENVP)); // System.out.println(System.currentTimeMillis() + " EXEC: " + mapDirectory); Process p = Runtime.getRuntime().exec(cmd, ENVP, mapDirectory); int result = p.waitFor(); // System.out.println(System.currentTimeMillis() + " PROCESS EXITED: " + result); if (result != 0) throw new ProvisionException(SHP2IMG_EXECUTABLE + " returned error code: " + result); //Thread.sleep(500); BufferedImage img = ImageIO.read(tempFile); //System.out.println("img = " + img); if (img == null) throw new ProvisionException("Failed to provide image for rectangle: " + r); if (BufferedImage.TYPE_4BYTE_ABGR != img.getType()) { BufferedImage img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR); img.copyData(img2.getRaster()); return img2; } return img; } finally { if (tempFile.exists()) { // System.out.println("DELETING TEMP FILE: " + tempFile); tempFile.delete(); } } } catch (IOException e) { throw new ProvisionException(e); } catch (InterruptedException e) { throw new ProvisionException(e); } } public static void main(String[] args) { try { Rectangle2D degreeExtent = new Rectangle2D.Double(); Rectangle2D meterExtent = new Rectangle2D.Double(); degreeExtent.setFrameFromDiagonal(24.8, 60.175, 24.84, 60.195); meterExtent.setFrameFromDiagonal(2544800, 6674000, 2546842.4, 6676000); Shp2ImgTileProvider p = new Shp2ImgTileProvider("d:/TerrasolidOtaniemiMalli/ortho", "global.map", 512, degreeExtent, meterExtent); BufferedImage buf = p.getImage(meterExtent); ImageIO.write(buf, "png", new File("d:\\temp\\test.png")); } catch (Throwable e) { e.printStackTrace(); } } }