1 package tim.prune.function.search;
3 import java.io.InputStream;
5 import java.util.ArrayList;
8 import tim.prune.I18nManager;
9 import tim.prune.data.DataPoint;
10 import tim.prune.data.Distance;
11 import tim.prune.data.Field;
12 import tim.prune.data.Latitude;
13 import tim.prune.data.Longitude;
14 import tim.prune.data.SourceInfo;
15 import tim.prune.data.UnitSetLibrary;
16 import tim.prune.load.MediaLinkInfo;
19 * Function to search mapillary for photos
21 public class SearchMapillaryFunction extends GenericDownloaderFunction
23 /** Maximum number of results to get */
24 private static final int MAX_RESULTS = 20;
29 * @param inApp app object
31 public SearchMapillaryFunction(App inApp)
37 public String getNameKey() {
38 return "function.mapillary";
42 protected String getColumnKey(int inColNum)
44 if (inColNum == 0) return "dialog.wikipedia.column.name";
45 return "dialog.wikipedia.column.distance";
49 * Run method, for searching in a separate thread
53 _statusLabel.setText(I18nManager.getText("confirm.running"));
54 // Get coordinates from current point (if any) or from centre of screen
55 double lat = 0.0, lon = 0.0;
56 DataPoint currentPoint = _app.getTrackInfo().getCurrentPoint();
57 if (currentPoint == null)
59 double[] coords = _app.getViewport().getBounds();
60 lat = (coords[0] + coords[2]) / 2.0;
61 lon = (coords[1] + coords[3]) / 2.0;
65 lat = currentPoint.getLatitude().getDouble();
66 lon = currentPoint.getLongitude().getDouble();
70 final String urlString = "http://api.mapillary.com/v1/im/close?lat="
71 + lat + "&lon=" + lon + "&distance=1000&limit=" + MAX_RESULTS;
72 //System.out.println(urlString);
73 InputStream inStream = null;
76 inStream = new URL(urlString).openStream();
77 StringBuilder sb = new StringBuilder();
79 while ((ch = inStream.read()) >= 0)
83 //System.out.println("Got answer: '" + sb.toString() + "'");
85 ArrayList<SearchResult> resultList = new ArrayList<SearchResult>();
86 for (String result : sb.toString().split("\\},\\{"))
88 //System.out.println("Result: '" + result + "'");
89 SearchResult sr = new SearchResult();
90 for (String prop : result.split(","))
92 String key = getKey(prop);
93 if (key == null) {continue;}
94 if (key.equals("key"))
96 final String value = getValue(prop);
97 sr.setDownloadLink("http://images.mapillary.com/" + value + "/thumb-1024.jpg");
98 sr.setWebUrl("http://www.mapillary.com/map/im/" + value);
99 sr.setTrackName(value);
101 else if (key.equals("lat")) {
102 sr.setLatitude(getValue(prop));
104 else if (key.equals("lon")) {
105 sr.setLongitude(getValue(prop));
109 if (sr.getLatitude() != null && sr.getLongitude() != null && sr.getTrackName() != null)
111 // Calculate distance away from current point and set this in sr.setLength
112 DataPoint resultPoint = new DataPoint(new Latitude(sr.getLatitude()), new Longitude(sr.getLongitude()), null);
113 if (resultPoint.isValid() && currentPoint != null && currentPoint.isValid())
115 double radianDist = DataPoint.calculateRadiansBetween(currentPoint, resultPoint);
116 double metresAway = Distance.convertRadiansToDistance(radianDist, UnitSetLibrary.UNITS_METRES);
117 sr.setLength(metresAway);
120 // If there's a valid result, add it to the temporary list
121 if (sr.getTrackName() != null) {
126 // Add all the results to the table model in one go
127 if (!resultList.isEmpty()) {
128 _trackListModel.addTracks(resultList);
131 catch (Exception e) {
132 _errorMessage = e.getClass().getName() + " - " + e.getMessage();
134 // Close stream and ignore errors
137 } catch (Exception e) {}
139 // Set status label according to error or "none found", leave blank if ok
140 if (_errorMessage == null && _trackListModel.isEmpty()) {
141 _errorMessage = I18nManager.getText("dialog.mapillary.nonefound");
143 _statusLabel.setText(_errorMessage == null ? "" : _errorMessage);
147 * From a JSON key:value string, return just the key
148 * @param inString string to parse
149 * @return just the key without the surrounding quotes, or null if not found
151 private static String getKey(String inString)
153 if (inString == null || inString.equals("")) {return null;}
154 final int colonPos = inString.indexOf(':');
155 if (colonPos <= 0) {return null;}
158 while ((c = inString.charAt(startPos)) == '['
159 || c == '{' || c == '\"')
163 int endPos = colonPos;
164 while ((c = inString.charAt(endPos-1)) == '\"')
168 return inString.substring(startPos, endPos);
172 * From a JSON key:value string, return just the value
173 * @param inString string to parse
174 * @return just the value without the surrounding quotes
176 private static String getValue(String inString)
178 final int colonPos = inString.indexOf(':');
179 if (colonPos <= 0 || colonPos >= inString.length()) {return null;}
180 int startPos = colonPos+1;
182 while ((c = inString.charAt(startPos)) == '\"')
186 int endPos = inString.length()-1;
187 while ((c = inString.charAt(endPos-1)) == '\"'
188 || c == '}' || c == ']')
192 return inString.substring(startPos, endPos);
196 protected void loadSelected()
198 // Find the row(s) selected in the table and get the corresponding track
199 int numSelected = _trackTable.getSelectedRowCount();
200 if (numSelected < 1) return;
201 int[] rowNums = _trackTable.getSelectedRows();
203 String[][] pointData = new String[numSelected][];
204 String[] linkArray = new String[numSelected];
206 // Loop over each of the selected points
207 for (int i=0; i<numSelected; i++)
209 pointData[i] = new String[3]; // lat, long, segment
210 int rowNum = rowNums[i];
211 if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
213 SearchResult result = _trackListModel.getTrack(rowNum);
214 //String url = result.getDownloadLink();
215 pointData[i][0] = result.getLatitude();
216 pointData[i][1] = result.getLongitude();
217 pointData[i][2] = "1"; // all points have a new segment
218 linkArray[i] = result.getDownloadLink();
221 // Prepare the data for the app
222 final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.NEW_SEGMENT};
223 _app.autoAppendNextFile();
224 _app.informDataLoaded(fields, pointData, null, new SourceInfo("mapillary", SourceInfo.FILE_TYPE.JSON),
225 null, new MediaLinkInfo(linkArray));