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;
31 * @author Tuukka Lehtonen
32 * @deprecated this is a demo hack, do not use
34 public class Shp2ImgTileProvider implements ITileProvider {
36 private static final String SHP2IMG_EXECUTABLE = "c:\\ms4w\\tools\\mapserv\\shp2img.exe";
38 private static final String SCHEME = "shp2img";
42 final File mapDirectory;
46 final int tilePixelSize;
48 final String tileSizeString;
50 Rectangle2D extentDegrees;
52 Rectangle2D extentMeters;
60 BufferedImage outOfBoundsImage;
62 public Shp2ImgTileProvider(String mapDirectory, String mapName, int tilePixelSize, Rectangle2D extentDegrees, Rectangle2D extentMeters) {
63 this.mapDirectory = new File(mapDirectory);
64 this.mapName = mapName;
65 this.tilePixelSize = tilePixelSize;
66 this.tileSizeString = String.valueOf(tilePixelSize);
67 this.extentDegrees = extentDegrees;
68 this.extentMeters = extentMeters;
70 this.deWidthRecip = 1.0 / extentDegrees.getWidth();
71 this.deHeightRecip = 1.0 / extentDegrees.getHeight();
73 if (!this.mapDirectory.exists()) {
74 throw new IllegalArgumentException("Map directory '" + mapDirectory + "' does not exist");
77 StringBuilder host = new StringBuilder();
79 String[] segments = mapDirectory.split(File.pathSeparator);
80 for (String seg : segments) {
90 source = new URI(SCHEME, host.toString(), null, null);
91 } catch (URISyntaxException e) {
92 throw new RuntimeException("Shp2ImgTileProvider: Problem in URI generation with mapDirectory="
93 + mapDirectory + ", mapName= " + mapName, e);
96 List<String> envp = new ArrayList<String>();
97 envp.add("GDAL_DATA=c:\\ms4w\\gdaldata");
98 envp.add("GDAL_DRIVER_PATH=c:\\ms4w\\gdalplugins");
99 envp.add("PROJ_LIB=c:\\ms4w\\proj\\nad");
100 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;");
101 ENVP = envp.toArray(new String[0]);
103 // Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("png");
104 // ImageReader reader = readers.next();
108 public URI getSource() {
113 public Rectangle2D getExtent() {
114 // FIXME: should return a clone
115 return extentDegrees;
119 public Image get(TileKey key) throws ProvisionException {
120 // TODO: make this code a utility and externalize the remaining logic as a strategy
121 // This very same code is the same in all ITileProvider implementations.
123 int level = key.getLevel();
127 double xTiles = Math.pow(2, level + 1);
128 double yTiles = Math.pow(2, level);
131 throw new IllegalArgumentException("invalid tile level " + level + " (tile=" + key +")");
132 if (x < 0 || x >= (int) xTiles)
133 throw new IllegalArgumentException("tile x out of bounds " + x + " (tile=" + key +")");
134 if (y < 0 || y >= (int) yTiles)
135 throw new IllegalArgumentException("tile y out of bounds " + y + " (tile=" + key +")");
137 Rectangle2D r = new Rectangle2D.Double();
144 double xdelta = w / xTiles;
145 double ydelta = h / yTiles;
147 double yy = yTiles - y - 1;
156 if (r.intersects(extentDegrees)) {
157 Rectangle2D meters = transformDegreesToMeters(r);
158 // System.out.println("getImage: " + meters.getMinX() + ", " + meters.getMaxX() + ", " + meters.getWidth() + " ... " + meters.getMinY() + ", " + meters.getMaxY() + ", " + meters.getHeight());
160 return getImage(meters);
161 } catch (IOException e) {
162 throw new ProvisionException(e);
166 return getOutOfBoundsImage();
169 private Image getOutOfBoundsImage() {
170 if (outOfBoundsImage != null)
171 return outOfBoundsImage;
173 final int outOfBoundsImageSize = 1;
174 BufferedImage image = new BufferedImage(outOfBoundsImageSize, outOfBoundsImageSize, BufferedImage.TYPE_3BYTE_BGR);
175 Graphics2D g = image.createGraphics();
177 g.setColor(Color.PINK);
178 g.fillRect(0, 0, outOfBoundsImageSize, outOfBoundsImageSize);
179 outOfBoundsImage = image;
186 private Rectangle2D transformDegreesToMeters(Rectangle2D r) {
187 double nx1 = (r.getMinX() - extentDegrees.getMinX()) * deWidthRecip;
188 double ny1 = (r.getMinY() - extentDegrees.getMinY()) * deHeightRecip;
189 double nx2 = (r.getMaxX() - extentDegrees.getMinX()) * deWidthRecip;
190 double ny2 = (r.getMaxY() - extentDegrees.getMinY()) * deHeightRecip;
191 double dw = extentMeters.getWidth();
192 double dh = extentMeters.getHeight();
193 Rectangle2D result = new Rectangle2D.Double();
194 result.setFrameFromDiagonal(
195 extentMeters.getMinX() + nx1 * dw,
196 extentMeters.getMinY() + ny1 * dh,
197 extentMeters.getMinX() + nx2 * dw,
198 extentMeters.getMinY() + ny2 * dh
203 private BufferedImage getImage(Rectangle2D r) throws IOException {
204 double w = r.getWidth();
205 double h = r.getHeight();
206 String tileSizeStringX;
207 String tileSizeStringY;
209 tileSizeStringX = tileSizeString;
210 tileSizeStringY = "" + (int) Math.round(((double)tilePixelSize) * (h/w));
212 tileSizeStringX = "" + (int) Math.round(((double)tilePixelSize) * (w/h));
213 tileSizeStringY = tileSizeString;
216 File tempFile = File.createTempFile("map", ".png");
217 String[] cmd = new String[] {
224 tempFile.getAbsolutePath(),
229 String.valueOf(r.getMinX()),
230 String.valueOf(r.getMinY()),
231 String.valueOf(r.getMaxX()),
232 String.valueOf(r.getMaxY())
236 // System.out.println(System.currentTimeMillis() + " TEMP FILE: " + tempFile);
237 // System.out.println(System.currentTimeMillis() + " EXEC: " + Arrays.toString(cmd));
238 // System.out.println(System.currentTimeMillis() + " EXEC: " + Arrays.toString(ENVP));
239 // System.out.println(System.currentTimeMillis() + " EXEC: " + mapDirectory);
240 Process p = Runtime.getRuntime().exec(cmd, ENVP, mapDirectory);
241 int result = p.waitFor();
242 // System.out.println(System.currentTimeMillis() + " PROCESS EXITED: " + result);
244 throw new ProvisionException(SHP2IMG_EXECUTABLE + " returned error code: " + result);
246 BufferedImage img = ImageIO.read(tempFile);
247 //System.out.println("img = " + img);
249 throw new ProvisionException("Failed to provide image for rectangle: " + r);
251 if (BufferedImage.TYPE_4BYTE_ABGR != img.getType()) {
252 BufferedImage img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
253 img.copyData(img2.getRaster());
258 if (tempFile.exists()) {
259 // System.out.println("DELETING TEMP FILE: " + tempFile);
263 } catch (IOException e) {
264 throw new ProvisionException(e);
265 } catch (InterruptedException e) {
266 throw new ProvisionException(e);
270 public static void main(String[] args) {
272 Rectangle2D degreeExtent = new Rectangle2D.Double();
273 Rectangle2D meterExtent = new Rectangle2D.Double();
274 degreeExtent.setFrameFromDiagonal(24.8, 60.175, 24.84, 60.195);
275 meterExtent.setFrameFromDiagonal(2544800, 6674000, 2546842.4, 6676000);
277 Shp2ImgTileProvider p = new Shp2ImgTileProvider("d:/TerrasolidOtaniemiMalli/ortho", "global.map", 512, degreeExtent, meterExtent);
279 BufferedImage buf = p.getImage(meterExtent);
280 ImageIO.write(buf, "png", new File("d:\\temp\\test.png"));
281 } catch (Throwable e) {