source: osm/applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/DownloadSVGTask.java@ 25889

Last change on this file since 25889 was 25045, checked in by pieren, 14 years ago

Move the grabber single instance from CadastrePlugin singleton to each WMSLayer instance to allow several municipalities grabbing in parallel.

File size: 9.2 KB
Line 
1// License: GPL. v2 and later. Copyright 2008-2009 by Pieren <pieren3@gmail.com> and others
2package cadastre_fr;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.BufferedOutputStream;
7import java.io.BufferedReader;
8import java.io.File;
9import java.io.FileOutputStream;
10import java.io.IOException;
11import java.io.InputStream;
12import java.io.InputStreamReader;
13import java.net.HttpURLConnection;
14import java.net.MalformedURLException;
15import java.net.URL;
16import java.util.ArrayList;
17import java.util.Collection;
18import java.util.Collections;
19import java.util.LinkedList;
20import java.util.List;
21
22import javax.swing.JOptionPane;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.command.AddCommand;
26import org.openstreetmap.josm.command.Command;
27import org.openstreetmap.josm.command.SequenceCommand;
28import org.openstreetmap.josm.data.coor.EastNorth;
29import org.openstreetmap.josm.data.osm.Node;
30import org.openstreetmap.josm.data.osm.Way;
31import org.openstreetmap.josm.gui.PleaseWaitRunnable;
32import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
33import org.openstreetmap.josm.io.OsmTransferException;
34import org.openstreetmap.josm.io.ProgressInputStream;
35/**
36 * Grab the SVG administrative boundaries of the active commune layer (cadastre),
37 * isolate the SVG path of the concerned commune (other municipalities are also
38 * downloaded in the SVG data), convert to OSM nodes and way plus simplify.
39 * Thanks to Frederic Rodrigo for his help.
40 */
41public class DownloadSVGTask extends PleaseWaitRunnable {
42
43 private WMSLayer wmsLayer;
44 private CadastreInterface wmsInterface;
45 private String svg = null;
46 private EastNorthBound viewBox = null;
47 private static String errorMessage;
48
49 public DownloadSVGTask(WMSLayer wmsLayer) {
50 super(tr("Downloading {0}", wmsLayer.getName()));
51
52 this.wmsLayer = wmsLayer;
53 this.wmsInterface = wmsLayer.grabber.getWmsInterface();
54 }
55
56 @Override
57 public void realRun() throws IOException, OsmTransferException {
58 progressMonitor.indeterminateSubTask(tr("Contacting WMS Server..."));
59 errorMessage = null;
60 try {
61 if (wmsInterface.retrieveInterface(wmsLayer)) {
62 svg = grabBoundary(wmsLayer.getCommuneBBox());
63 if (svg == null)
64 return;
65 progressMonitor.indeterminateSubTask(tr("Extract SVG ViewBox..."));
66 getViewBox(svg);
67 if (viewBox == null)
68 return;
69 progressMonitor.indeterminateSubTask(tr("Extract best fitting boundary..."));
70 createWay(svg);
71 }
72 } catch (DuplicateLayerException e) {
73 System.err.println("removed a duplicated layer");
74 } catch (WMSException e) {
75 errorMessage = e.getMessage();
76 wmsLayer.grabber.getWmsInterface().resetCookie();
77 }
78 }
79
80 @Override
81 protected void cancel() {
82 wmsLayer.grabber.getWmsInterface().cancel();
83 }
84
85 @Override
86 protected void finish() {
87 }
88
89 private boolean getViewBox(String svg) {
90 double[] box = new SVGParser().getViewBox(svg);
91 if (box != null) {
92 viewBox = new EastNorthBound(new EastNorth(box[0], box[1]),
93 new EastNorth(box[0]+box[2], box[1]+box[3]));
94 return true;
95 }
96 System.out.println("Unable to parse SVG data (viewBox)");
97 return false;
98 }
99
100 /**
101 * The svg contains more than one commune boundary defined by path elements. So detect
102 * which path element is the best fitting to the viewBox and convert it to OSM objects
103 */
104 private void createWay(String svg) {
105 String[] SVGpaths = new SVGParser().getClosedPaths(svg);
106 ArrayList<Double> fitViewBox = new ArrayList<Double>();
107 ArrayList<ArrayList<EastNorth>> eastNorths = new ArrayList<ArrayList<EastNorth>>();
108 for (int i=0; i< SVGpaths.length; i++) {
109 ArrayList<EastNorth> eastNorth = new ArrayList<EastNorth>();
110 fitViewBox.add( createNodes(SVGpaths[i], eastNorth) );
111 eastNorths.add(eastNorth);
112 }
113 // the smallest fitViewBox indicates the best fitting path in viewBox
114 Double min = Collections.min(fitViewBox);
115 int bestPath = fitViewBox.indexOf(min);
116 List<Node> nodeList = new ArrayList<Node>();
117 for (EastNorth eastNorth : eastNorths.get(bestPath)) {
118 nodeList.add(new Node(Main.proj.eastNorth2latlon(eastNorth)));
119 }
120 Way wayToAdd = new Way();
121 Collection<Command> cmds = new LinkedList<Command>();
122 for (Node node : nodeList) {
123 cmds.add(new AddCommand(node));
124 wayToAdd.addNode(node);
125 }
126 wayToAdd.addNode(wayToAdd.getNode(0)); // close the circle
127
128 // simplify the way
129// double threshold = Double.parseDouble(Main.pref.get("cadastrewms.simplify-way-boundary", "1.0"));
130// new SimplifyWay().simplifyWay(wayToAdd, Main.main.getCurrentDataSet(), threshold);
131
132 cmds.add(new AddCommand(wayToAdd));
133 Main.main.undoRedo.add(new SequenceCommand(tr("Create boundary"), cmds));
134 Main.map.repaint();
135 }
136
137 private double createNodes(String SVGpath, ArrayList<EastNorth> eastNorth) {
138 // looks like "M981283.38 368690.15l143.81 72.46 155.86 ..."
139 String[] coor = SVGpath.split("[MlZ ]"); //coor[1] is x, coor[2] is y
140 double dx = Double.parseDouble(coor[1]);
141 double dy = Double.parseDouble(coor[2]);
142 double minY = Double.MAX_VALUE;
143 double minX = Double.MAX_VALUE;
144 double maxY = Double.MIN_VALUE;
145 double maxX = Double.MIN_VALUE;
146 for (int i=3; i<coor.length; i+=2){
147 double east = dx+=Double.parseDouble(coor[i]);
148 double north = dy+=Double.parseDouble(coor[i+1]);
149 eastNorth.add(new EastNorth(east,north));
150 minX = minX > east ? east : minX;
151 minY = minY > north ? north : minY;
152 maxX = maxX < east ? east : maxX;
153 maxY = maxY < north ? north : maxY;
154 }
155 // flip the image (svg using a reversed Y coordinate system)
156 double pivot = viewBox.min.getY() + (viewBox.max.getY() - viewBox.min.getY()) / 2;
157 for (EastNorth en : eastNorth) {
158 en.setLocation(en.east(), 2 * pivot - en.north());
159 }
160 return Math.abs(minX - viewBox.min.getX())+Math.abs(maxX - viewBox.max.getX())
161 +Math.abs(minY - viewBox.min.getY())+Math.abs(maxY - viewBox.max.getY());
162 }
163
164 private String grabBoundary(EastNorthBound bbox) throws IOException, OsmTransferException {
165 try {
166 URL url = null;
167 url = getURLsvg(bbox);
168 return grabSVG(url);
169 } catch (MalformedURLException e) {
170 throw (IOException) new IOException(tr("CadastreGrabber: Illegal url.")).initCause(e);
171 }
172 }
173
174 private URL getURLsvg(EastNorthBound bbox) throws MalformedURLException {
175 String str = new String(wmsInterface.baseURL+"/scpc/wms?version=1.1&request=GetMap");
176 str += "&layers=";
177 str += "CDIF:COMMUNE";
178 str += "&format=image/svg";
179 str += "&bbox="+bbox.min.east()+",";
180 str += bbox.min.north() + ",";
181 str += bbox.max.east() + ",";
182 str += bbox.max.north();
183 str += "&width="+CadastrePlugin.imageWidth+"&height="+CadastrePlugin.imageHeight;
184 str += "&styles=";
185 str += "COMMUNE_90";
186 System.out.println("URL="+str);
187 return new URL(str.replace(" ", "%20"));
188 }
189
190 private String grabSVG(URL url) throws IOException, OsmTransferException {
191 wmsInterface.urlConn = (HttpURLConnection)url.openConnection();
192 wmsInterface.urlConn.setRequestMethod("GET");
193 wmsInterface.setCookie();
194 InputStream is = new ProgressInputStream(wmsInterface.urlConn, NullProgressMonitor.INSTANCE);
195 File file = new File(CadastrePlugin.cacheDir + "boundary.svg");
196 String svg = new String();
197 try {
198 if (file.exists())
199 file.delete();
200 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file, true));
201 InputStreamReader isr =new InputStreamReader(is);
202 BufferedReader br = new BufferedReader(isr);
203 String line="";
204 while ( null!=(line=br.readLine())){
205 line += "\n";
206 bos.write(line.getBytes());
207 svg += line;
208 }
209 bos.close();
210 } catch (IOException e) {
211 e.printStackTrace(System.out);
212 }
213 is.close();
214 return svg;
215 }
216
217 public static void download(WMSLayer wmsLayer) {
218 if (CadastrePlugin.autoSourcing == false) {
219 JOptionPane.showMessageDialog(Main.parent,
220 tr("Please, enable auto-sourcing and check cadastre millesime."));
221 return;
222 }
223 Main.worker.execute(new DownloadSVGTask(wmsLayer));
224 if (errorMessage != null)
225 JOptionPane.showMessageDialog(Main.parent, errorMessage);
226 }
227
228}
Note: See TracBrowser for help on using the repository browser.