| 33 | | return gpxData.getTrackPoints() |
| 34 | | .mapToDouble(tp -> getDistance(p, tp)) |
| 35 | | .filter(x -> x >= 0) |
| 36 | | .min().orElse(Double.MAX_VALUE); |
| | 36 | Collection<GpxTrack> tracks = gpxData.getTracks(); |
| | 37 | TreeMap<GpxTrack, Double> trackDistances = new TreeMap<>(); |
| | 38 | for (GpxTrack track : tracks) { |
| | 39 | Bounds bounds = track.getBounds(); |
| | 40 | double distance = getMinDistanceBounds(p, bounds); |
| | 41 | trackDistances.put(track, distance); |
| | 42 | |
| | 43 | } |
| | 44 | if (trackDistances.containsValue(0.0)) { |
| | 45 | double minDistance = Double.MAX_VALUE; |
| | 46 | for (GpxTrack track : trackDistances.keySet()) { |
| | 47 | if (trackDistances.get(track).equals(0.0)) { |
| | 48 | for (GpxTrackSegment segment : track.getSegments()) { |
| | 49 | for (WayPoint wp : segment.getWayPoints()) { |
| | 50 | double distance = getDistance(p, wp); |
| | 51 | if (distance < minDistance) minDistance = distance; |
| | 52 | } |
| | 53 | } |
| | 54 | } |
| | 55 | } |
| | 56 | return minDistance; |
| | 57 | } else { |
| | 58 | return gpxData.getTrackPoints() |
| | 59 | .mapToDouble(tp -> getDistance(p, tp)) |
| | 60 | .filter(x -> x >= 0) |
| | 61 | .min().orElse(Double.MAX_VALUE); |
| | 62 | } |
| | 174 | |
| | 175 | /** |
| | 176 | * @param p OsmPrimitive to get the lowest distance to its centroid |
| | 177 | * @param bounds The bounds with which we are getting the distance to |
| | 178 | * @return The distance to the bounds (0 if the OsmPrimitive is inside the bounds) |
| | 179 | */ |
| | 180 | public static double getMinDistanceBounds(OsmPrimitive p, Bounds bounds) { |
| | 181 | return getDistanceBounds(p, bounds, true); |
| | 182 | } |
| | 183 | |
| | 184 | /** |
| | 185 | * @param p OsmPrimitive to get the furthest distance to its centroid |
| | 186 | * @param bounds The bounds with which we are getting the distance to |
| | 187 | * @return The furthest distance to the bounds |
| | 188 | */ |
| | 189 | public static double getMaxDistanceBounds(OsmPrimitive p, Bounds bounds) { |
| | 190 | return getDistanceBounds(p, bounds, false); |
| | 191 | } |
| | 192 | |
| | 193 | private static double getDistanceBounds(OsmPrimitive p, Bounds bounds, boolean closest) { |
| | 194 | // If the primitive is within the bounds, return 0 |
| | 195 | if (bounds.toBBox().intersects(p.getBBox()) && closest) return 0; |
| | 196 | |
| | 197 | // The order the corners are added is important! When connected in order, they _must_ form a rectangle. |
| | 198 | ArrayList<Node> corners = new ArrayList<>(); |
| | 199 | corners.add(new Node(bounds.getMax())); |
| | 200 | corners.add(new Node(new LatLon(bounds.getMaxLat(), bounds.getMinLon()))); |
| | 201 | corners.add(new Node(bounds.getMin())); |
| | 202 | corners.add(new Node(new LatLon(bounds.getMinLat(), bounds.getMaxLon()))); |
| | 203 | |
| | 204 | ArrayList<Way> ways = new ArrayList<>(); |
| | 205 | for (int i = 0; i < corners.size(); i++) { |
| | 206 | ways.add(new Way()); |
| | 207 | ways.get(i).addNode(corners.get(i)); |
| | 208 | // Doing % corners.size() avoids requiring an if statement to avoid overflow (which _is_ expected) |
| | 209 | ways.get(i).addNode(corners.get((i + 1) % corners.size())); |
| | 210 | } |
| | 211 | double distance; |
| | 212 | if (closest) distance = Double.MAX_VALUE; |
| | 213 | else distance = Double.MIN_VALUE; |
| | 214 | for (Way way : ways) { |
| | 215 | // Not the best of ideas, but there isn't a method implemented for two ways |
| | 216 | double tdistance = getDistance(way, new WayPoint(p.getBBox().getCenter())); |
| | 217 | if ((closest && tdistance < distance) || (!closest && tdistance > distance)) { |
| | 218 | distance = tdistance; |
| | 219 | } |
| | 220 | } |
| | 221 | return distance; |
| | 222 | } |