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

Last change on this file since 15707 was 13784, checked in by pieren, 16 years ago

Fix minor bugs, add the fixed size grab scale configurable, fix pbls in transparency.

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