]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.maps/src/org/simantics/maps/tile/Shp2ImgTileProvider.java
Share some projects for Simantics District
[simantics/district.git] / org.simantics.district.maps / src / org / simantics / maps / tile / Shp2ImgTileProvider.java
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 (file)
index 0000000..0431e6f
--- /dev/null
@@ -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<String> envp = new ArrayList<String>();
+        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<ImageReader> 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();
+        }
+    }
+
+}