]> gerrit.simantics Code Review - simantics/district.git/blob - 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
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.maps.tile;
13
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;
19 import java.io.File;
20 import java.io.IOException;
21 import java.net.URI;
22 import java.net.URISyntaxException;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import javax.imageio.ImageIO;
27
28 import org.simantics.maps.ProvisionException;
29
30 /**
31  * @author Tuukka Lehtonen
32  * @deprecated this is a demo hack, do not use
33  */
34 public class Shp2ImgTileProvider implements ITileProvider {
35
36     private static final String SHP2IMG_EXECUTABLE = "c:\\ms4w\\tools\\mapserv\\shp2img.exe";
37
38     private static final String SCHEME = "shp2img";
39
40     final URI                   source;
41
42     final File                  mapDirectory;
43
44     final String                mapName;
45
46     final int                   tilePixelSize;
47
48     final String                tileSizeString;
49
50     Rectangle2D                 extentDegrees;
51
52     Rectangle2D                 extentMeters;
53
54     double                      deWidthRecip;
55
56     double                      deHeightRecip;
57
58     String[]                    ENVP               = null;
59
60     BufferedImage               outOfBoundsImage;
61
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;
69
70         this.deWidthRecip = 1.0 / extentDegrees.getWidth();
71         this.deHeightRecip = 1.0 / extentDegrees.getHeight();
72
73         if (!this.mapDirectory.exists()) {
74             throw new IllegalArgumentException("Map directory '" + mapDirectory + "' does not exist");
75         }
76
77         StringBuilder host = new StringBuilder();
78         boolean first = true;
79         String[] segments = mapDirectory.split(File.pathSeparator);
80         for (String seg : segments) {
81             if (!first)
82                 host.append('.');
83             first = false;
84             host.append(seg);
85         }
86         host.append('.');
87         host.append(mapName);
88
89         try {
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);
94         }
95
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]);
102
103 //        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("png");
104 //        ImageReader reader = readers.next();
105     }
106
107     @Override
108     public URI getSource() {
109         return source;
110     }
111
112     @Override
113     public Rectangle2D getExtent() {
114         // FIXME: should return a clone
115         return extentDegrees;
116     }
117
118     @Override
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.
122
123         int level = key.getLevel();
124         int x = key.getX();
125         int y = key.getY();
126
127         double xTiles = Math.pow(2, level + 1);
128         double yTiles = Math.pow(2, level);
129
130         if (level < 0)
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 +")");
136
137         Rectangle2D r = new Rectangle2D.Double();
138
139         double minx = -180;
140         double miny = -90;
141         double w = 360;
142         double h = 180;
143
144         double xdelta = w / xTiles;
145         double ydelta = h / yTiles;
146         double xx = x;
147         double yy = yTiles - y - 1;
148
149         r.setFrame(
150                 minx + xdelta*xx,
151                 miny + ydelta*yy,
152                 xdelta,
153                 ydelta
154         );
155
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());
159             try {
160                 return getImage(meters);
161             } catch (IOException e) {
162                 throw new ProvisionException(e);
163             }
164         }
165
166         return getOutOfBoundsImage();
167     }
168
169     private Image getOutOfBoundsImage() {
170         if (outOfBoundsImage != null)
171             return outOfBoundsImage;
172
173         final int outOfBoundsImageSize = 1;
174         BufferedImage image = new BufferedImage(outOfBoundsImageSize, outOfBoundsImageSize, BufferedImage.TYPE_3BYTE_BGR);
175         Graphics2D g = image.createGraphics();
176         try {
177             g.setColor(Color.PINK);
178             g.fillRect(0, 0, outOfBoundsImageSize, outOfBoundsImageSize);
179             outOfBoundsImage = image;
180             return image;
181         } finally {
182             g.dispose();
183         }
184     }
185
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
199         );
200         return result;
201     }
202
203     private BufferedImage getImage(Rectangle2D r) throws IOException {
204         double w = r.getWidth();
205         double h = r.getHeight();
206         String tileSizeStringX;
207         String tileSizeStringY;
208         if (w > h) {
209             tileSizeStringX = tileSizeString;
210             tileSizeStringY = "" + (int) Math.round(((double)tilePixelSize) * (h/w));
211         } else {
212             tileSizeStringX = "" + (int) Math.round(((double)tilePixelSize) * (w/h));
213             tileSizeStringY = tileSizeString;
214         }
215
216         File tempFile = File.createTempFile("map", ".png");
217         String[] cmd = new String[] {
218                 SHP2IMG_EXECUTABLE,
219 //                "-all_debug",
220 //                "5",
221                 "-m",
222                 mapName,
223                 "-o",
224                 tempFile.getAbsolutePath(),
225                 "-s",
226                 tileSizeStringX,
227                 tileSizeStringY,
228                 "-e",
229                 String.valueOf(r.getMinX()),
230                 String.valueOf(r.getMinY()),
231                 String.valueOf(r.getMaxX()),
232                 String.valueOf(r.getMaxY())
233         };
234         try {
235             try {
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);
243                 if (result != 0)
244                     throw new ProvisionException(SHP2IMG_EXECUTABLE + " returned error code: " + result);
245                 //Thread.sleep(500);
246                 BufferedImage img = ImageIO.read(tempFile);
247                 //System.out.println("img = " + img);
248                 if (img == null)
249                     throw new ProvisionException("Failed to provide image for rectangle: " + r);
250
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());
254                     return img2;
255                 }
256                 return img;
257             } finally {
258                 if (tempFile.exists()) {
259 //                    System.out.println("DELETING TEMP FILE: " + tempFile);
260                     tempFile.delete();
261                 }
262             }
263         } catch (IOException e) {
264             throw new ProvisionException(e);
265         } catch (InterruptedException e) {
266             throw new ProvisionException(e);
267         }
268     }
269
270     public static void main(String[] args) {
271         try {
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);
276
277             Shp2ImgTileProvider p = new Shp2ImgTileProvider("d:/TerrasolidOtaniemiMalli/ortho", "global.map", 512, degreeExtent, meterExtent);
278
279             BufferedImage buf = p.getImage(meterExtent);
280             ImageIO.write(buf, "png", new File("d:\\temp\\test.png"));
281         } catch (Throwable e) {
282             e.printStackTrace();
283         }
284     }
285
286 }