1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.maps.tile;
14 import java.awt.Color;
15 import java.awt.Graphics2D;
16 import java.awt.Image;
17 import java.awt.geom.Rectangle2D;
18 import java.awt.image.BufferedImage;
20 import java.io.IOException;
22 import java.net.URISyntaxException;
23 import java.util.ArrayList;
24 import java.util.List;
26 import javax.imageio.ImageIO;
28 import org.simantics.maps.ProvisionException;
29 import org.simantics.maps.internal.ImageUtil;
32 * @author Tuukka Lehtonen
33 * @deprecated this is a demo hack, do not use
35 public class Shp2ImgTileProvider implements ITileProvider {
37 private static final String SHP2IMG_EXECUTABLE = "c:\\ms4w\\tools\\mapserv\\shp2img.exe";
39 private static final String SCHEME = "shp2img";
43 final File mapDirectory;
47 final int tilePixelSize;
49 final String tileSizeString;
51 Rectangle2D extentDegrees;
53 Rectangle2D extentMeters;
61 BufferedImage outOfBoundsImage;
63 public Shp2ImgTileProvider(String mapDirectory, String mapName, int tilePixelSize, Rectangle2D extentDegrees, Rectangle2D extentMeters) {
64 this.mapDirectory = new File(mapDirectory);
65 this.mapName = mapName;
66 this.tilePixelSize = tilePixelSize;
67 this.tileSizeString = String.valueOf(tilePixelSize);
68 this.extentDegrees = extentDegrees;
69 this.extentMeters = extentMeters;
71 this.deWidthRecip = 1.0 / extentDegrees.getWidth();
72 this.deHeightRecip = 1.0 / extentDegrees.getHeight();
74 if (!this.mapDirectory.exists()) {
75 throw new IllegalArgumentException("Map directory '" + mapDirectory + "' does not exist");
78 StringBuilder host = new StringBuilder();
80 String[] segments = mapDirectory.split(File.pathSeparator);
81 for (String seg : segments) {
91 source = new URI(SCHEME, host.toString(), null, null);
92 } catch (URISyntaxException e) {
93 throw new RuntimeException("Shp2ImgTileProvider: Problem in URI generation with mapDirectory="
94 + mapDirectory + ", mapName= " + mapName, e);
97 List<String> envp = new ArrayList<String>();
98 envp.add("GDAL_DATA=c:\\ms4w\\gdaldata");
99 envp.add("GDAL_DRIVER_PATH=c:\\ms4w\\gdalplugins");
100 envp.add("PROJ_LIB=c:\\ms4w\\proj\\nad");
101 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;");
102 ENVP = envp.toArray(new String[0]);
104 // Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("png");
105 // ImageReader reader = readers.next();
109 public URI getSource() {
114 public Rectangle2D getExtent() {
115 // FIXME: should return a clone
116 return extentDegrees;
120 public Image get(TileKey key) throws ProvisionException {
121 // TODO: make this code a utility and externalize the remaining logic as a strategy
122 // This very same code is the same in all ITileProvider implementations.
124 int level = key.getLevel();
128 double xTiles = Math.pow(2, level + 1);
129 double yTiles = Math.pow(2, level);
132 throw new IllegalArgumentException("invalid tile level " + level + " (tile=" + key +")");
133 if (x < 0 || x >= (int) xTiles)
134 throw new IllegalArgumentException("tile x out of bounds " + x + " (tile=" + key +")");
135 if (y < 0 || y >= (int) yTiles)
136 throw new IllegalArgumentException("tile y out of bounds " + y + " (tile=" + key +")");
138 Rectangle2D r = new Rectangle2D.Double();
145 double xdelta = w / xTiles;
146 double ydelta = h / yTiles;
148 double yy = yTiles - y - 1;
157 if (r.intersects(extentDegrees)) {
158 Rectangle2D meters = transformDegreesToMeters(r);
159 // System.out.println("getImage: " + meters.getMinX() + ", " + meters.getMaxX() + ", " + meters.getWidth() + " ... " + meters.getMinY() + ", " + meters.getMaxY() + ", " + meters.getHeight());
161 return getImage(meters);
162 } catch (IOException e) {
163 throw new ProvisionException(e);
167 return getOutOfBoundsImage();
170 private Image getOutOfBoundsImage() {
171 if (outOfBoundsImage != null)
172 return outOfBoundsImage;
174 final int outOfBoundsImageSize = 1;
175 BufferedImage image = ImageUtil.createScreenCompatibleImage(outOfBoundsImageSize, outOfBoundsImageSize, BufferedImage.OPAQUE);
176 Graphics2D g = image.createGraphics();
178 g.setColor(Color.PINK);
179 g.fillRect(0, 0, outOfBoundsImageSize, outOfBoundsImageSize);
180 outOfBoundsImage = image;
187 private Rectangle2D transformDegreesToMeters(Rectangle2D r) {
188 double nx1 = (r.getMinX() - extentDegrees.getMinX()) * deWidthRecip;
189 double ny1 = (r.getMinY() - extentDegrees.getMinY()) * deHeightRecip;
190 double nx2 = (r.getMaxX() - extentDegrees.getMinX()) * deWidthRecip;
191 double ny2 = (r.getMaxY() - extentDegrees.getMinY()) * deHeightRecip;
192 double dw = extentMeters.getWidth();
193 double dh = extentMeters.getHeight();
194 Rectangle2D result = new Rectangle2D.Double();
195 result.setFrameFromDiagonal(
196 extentMeters.getMinX() + nx1 * dw,
197 extentMeters.getMinY() + ny1 * dh,
198 extentMeters.getMinX() + nx2 * dw,
199 extentMeters.getMinY() + ny2 * dh
204 private BufferedImage getImage(Rectangle2D r) throws IOException {
205 double w = r.getWidth();
206 double h = r.getHeight();
207 String tileSizeStringX;
208 String tileSizeStringY;
210 tileSizeStringX = tileSizeString;
211 tileSizeStringY = "" + (int) Math.round(((double)tilePixelSize) * (h/w));
213 tileSizeStringX = "" + (int) Math.round(((double)tilePixelSize) * (w/h));
214 tileSizeStringY = tileSizeString;
217 File tempFile = File.createTempFile("map", ".png");
218 String[] cmd = new String[] {
225 tempFile.getAbsolutePath(),
230 String.valueOf(r.getMinX()),
231 String.valueOf(r.getMinY()),
232 String.valueOf(r.getMaxX()),
233 String.valueOf(r.getMaxY())
237 // System.out.println(System.currentTimeMillis() + " TEMP FILE: " + tempFile);
238 // System.out.println(System.currentTimeMillis() + " EXEC: " + Arrays.toString(cmd));
239 // System.out.println(System.currentTimeMillis() + " EXEC: " + Arrays.toString(ENVP));
240 // System.out.println(System.currentTimeMillis() + " EXEC: " + mapDirectory);
241 Process p = Runtime.getRuntime().exec(cmd, ENVP, mapDirectory);
242 int result = p.waitFor();
243 // System.out.println(System.currentTimeMillis() + " PROCESS EXITED: " + result);
245 throw new ProvisionException(SHP2IMG_EXECUTABLE + " returned error code: " + result);
247 BufferedImage img = ImageIO.read(tempFile);
248 //System.out.println("img = " + img);
250 throw new ProvisionException("Failed to provide image for rectangle: " + r);
251 return ImageUtil.toScreenCompatibleImage(img);
253 if (tempFile.exists()) {
254 // System.out.println("DELETING TEMP FILE: " + tempFile);
258 } catch (IOException e) {
259 throw new ProvisionException(e);
260 } catch (InterruptedException e) {
261 throw new ProvisionException(e);
265 public static void main(String[] args) {
267 Rectangle2D degreeExtent = new Rectangle2D.Double();
268 Rectangle2D meterExtent = new Rectangle2D.Double();
269 degreeExtent.setFrameFromDiagonal(24.8, 60.175, 24.84, 60.195);
270 meterExtent.setFrameFromDiagonal(2544800, 6674000, 2546842.4, 6676000);
272 Shp2ImgTileProvider p = new Shp2ImgTileProvider("d:/TerrasolidOtaniemiMalli/ortho", "global.map", 512, degreeExtent, meterExtent);
274 BufferedImage buf = p.getImage(meterExtent);
275 ImageIO.write(buf, "png", new File("d:\\temp\\test.png"));
276 } catch (Throwable e) {