]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/function/search/SearchMapillaryFunction.java
32c58bd8898a93143e65ebfe7b375cfff632969d
[GpsPrune.git] / tim / prune / function / search / SearchMapillaryFunction.java
1 package tim.prune.function.search;
2
3 import java.io.InputStream;
4 import java.net.URL;
5 import java.util.ArrayList;
6
7 import tim.prune.App;
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;
17
18 /**
19  * Function to search mapillary for photos
20  */
21 public class SearchMapillaryFunction extends GenericDownloaderFunction
22 {
23         /** Maximum number of results to get */
24         private static final int MAX_RESULTS = 20;
25
26
27         /**
28          * Constructor
29          * @param inApp app object
30          */
31         public SearchMapillaryFunction(App inApp)
32         {
33                 super(inApp);
34         }
35
36         @Override
37         public String getNameKey() {
38                 return "function.mapillary";
39         }
40
41         @Override
42         protected String getColumnKey(int inColNum)
43         {
44                 if (inColNum == 0) return "dialog.wikipedia.column.name";
45                 return "dialog.wikipedia.column.distance";
46         }
47
48         /**
49          * Run method, for searching in a separate thread
50          */
51         public void run()
52         {
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)
58                 {
59                         double[] coords = _app.getViewport().getBounds();
60                         lat = (coords[0] + coords[2]) / 2.0;
61                         lon = (coords[1] + coords[3]) / 2.0;
62                 }
63                 else
64                 {
65                         lat = currentPoint.getLatitude().getDouble();
66                         lon = currentPoint.getLongitude().getDouble();
67                 }
68
69                 // Construct URL
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;
74                 try
75                 {
76                         inStream = new URL(urlString).openStream();
77                         StringBuilder sb = new StringBuilder();
78                         int ch = 0;
79                         while ((ch = inStream.read()) >= 0)
80                         {
81                                 sb.append((char) ch);
82                         }
83                         //System.out.println("Got answer: '" + sb.toString() + "'");
84
85                         ArrayList<SearchResult> resultList = new ArrayList<SearchResult>();
86                         for (String result : sb.toString().split("\\},\\{"))
87                         {
88                                 //System.out.println("Result: '" + result + "'");
89                                 SearchResult sr = new SearchResult();
90                                 for (String prop : result.split(","))
91                                 {
92                                         String key = getKey(prop);
93                                         if (key == null) {continue;}
94                                         if (key.equals("key"))
95                                         {
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);
100                                         }
101                                         else if (key.equals("lat")) {
102                                                 sr.setLatitude(getValue(prop));
103                                         }
104                                         else if (key.equals("lon")) {
105                                                 sr.setLongitude(getValue(prop));
106                                         }
107                                 }
108
109                                 if (sr.getLatitude() != null && sr.getLongitude() != null && sr.getTrackName() != null)
110                                 {
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())
114                                         {
115                                                 double radianDist = DataPoint.calculateRadiansBetween(currentPoint, resultPoint);
116                                                 double metresAway = Distance.convertRadiansToDistance(radianDist, UnitSetLibrary.UNITS_METRES);
117                                                 sr.setLength(metresAway);
118                                         }
119
120                                         // If there's a valid result, add it to the temporary list
121                                         if (sr.getTrackName() != null) {
122                                                 resultList.add(sr);
123                                         }
124                                 }
125                         }
126                         // Add all the results to the table model in one go
127                         if (!resultList.isEmpty()) {
128                                 _trackListModel.addTracks(resultList);
129                         }
130                 }
131                 catch (Exception e) {
132                         _errorMessage = e.getClass().getName() + " - " + e.getMessage();
133                 }
134                 // Close stream and ignore errors
135                 try {
136                         inStream.close();
137                 } catch (Exception e) {}
138
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");
142                 }
143                 _statusLabel.setText(_errorMessage == null ? "" : _errorMessage);
144         }
145
146         /**
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
150          */
151         private static String getKey(String inString)
152         {
153                 if (inString == null || inString.equals("")) {return null;}
154                 final int colonPos = inString.indexOf(':');
155                 if (colonPos <= 0) {return null;}
156                 int startPos = 0;
157                 char c;
158                 while ((c = inString.charAt(startPos)) == '['
159                         || c == '{' || c == '\"')
160                 {
161                         startPos++;
162                 }
163                 int endPos = colonPos;
164                 while ((c = inString.charAt(endPos-1)) == '\"')
165                 {
166                         endPos--;
167                 }
168                 return inString.substring(startPos, endPos);
169         }
170
171         /**
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
175          */
176         private static String getValue(String inString)
177         {
178                 final int colonPos = inString.indexOf(':');
179                 if (colonPos <= 0 || colonPos >= inString.length()) {return null;}
180                 int startPos = colonPos+1;
181                 char c;
182                 while ((c = inString.charAt(startPos)) == '\"')
183                 {
184                         startPos++;
185                 }
186                 int endPos = inString.length()-1;
187                 while ((c = inString.charAt(endPos-1)) == '\"'
188                         || c == '}' || c == ']')
189                 {
190                         endPos--;
191                 }
192                 return inString.substring(startPos, endPos);
193         }
194
195         @Override
196         protected void loadSelected()
197         {
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();
202
203                 String[][] pointData = new String[numSelected][];
204                 String[]   linkArray = new String[numSelected];
205
206                 // Loop over each of the selected points
207                 for (int i=0; i<numSelected; i++)
208                 {
209                         pointData[i] = new String[3]; // lat, long, segment
210                         int rowNum = rowNums[i];
211                         if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
212                         {
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();
219                         }
220                 }
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));
226
227                 // Close the dialog
228                 _cancelled = true;
229                 _dialog.dispose();
230         }
231 }