X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.district.maps%2Fsrc%2Forg%2Fsimantics%2Fmaps%2Ftile%2FShp2ImgTileProvider.java;fp=org.simantics.district.maps%2Fsrc%2Forg%2Fsimantics%2Fmaps%2Ftile%2FShp2ImgTileProvider.java;h=0431e6fed1ceb66035acabaf6ceeaada58210914;hb=e9f74f09e0cedb603c0b4de9e542de8dd64a5ce3;hp=0000000000000000000000000000000000000000;hpb=16ee01dc5a40981c58fd5b478b89552e5814e8bb;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.maps/src/org/simantics/maps/tile/Shp2ImgTileProvider.java b/org.simantics.district.maps/src/org/simantics/maps/tile/Shp2ImgTileProvider.java new file mode 100644 index 00000000..0431e6fe --- /dev/null +++ b/org.simantics.district.maps/src/org/simantics/maps/tile/Shp2ImgTileProvider.java @@ -0,0 +1,286 @@ +/******************************************************************************* + * 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(); + } + } + +}