Ticket #17131: gpx_distance_v3.patch

File gpx_distance_v3.patch, 9.3 KB (added by taylor.smock, 7 years ago)

Modified to use greatCircleDistance where possible and ant pmd checkstyle has been run

  • src/org/openstreetmap/josm/data/gpx/GpxDistance.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.gpx;
     3
     4import java.util.ArrayList;
     5import java.util.List;
     6import java.util.stream.Collectors;
     7
     8import org.openstreetmap.josm.data.coor.LatLon;
     9import org.openstreetmap.josm.data.osm.Node;
     10import org.openstreetmap.josm.data.osm.OsmPrimitive;
     11import org.openstreetmap.josm.data.osm.Relation;
     12import org.openstreetmap.josm.data.osm.Way;
     13import org.openstreetmap.josm.gui.MainApplication;
     14import org.openstreetmap.josm.gui.layer.GpxLayer;
     15import org.openstreetmap.josm.gui.layer.Layer;
     16import org.openstreetmap.josm.gui.layer.LayerManager;
     17
     18/**
     19 * A class to find the distance between an OsmPrimitive and a GPX point
     20 *
     21 * @author Taylor Smock
     22 *
     23 */
     24public final class GpxDistance {
     25    private GpxDistance() {
     26        // This class should not be instantiated
     27    }
     28
     29    /**
     30     * @param p The OsmPrimitive that we are checking the maximum distance for
     31     * @param maximumDistance The maximum distance from a GPX point to the OsmPrimitive
     32     * @return true if the distance to the closest GPX point is lower than maximumDistance
     33     */
     34    public static boolean isCloseTo(OsmPrimitive p, double maximumDistance) {
     35        double distance = getLowestDistance(p);
     36        return (distance < maximumDistance);
     37    }
     38
     39    /**
     40     * Get the lowest distance from the layers to p
     41     * @param p OsmPrimitive from which to get the lowest distance to a GPX point
     42     * @return the lowest distance from any GpxLayer to p.
     43     */
     44    public static double getLowestDistance(OsmPrimitive p) {
     45        LayerManager layerManager = MainApplication.getLayerManager();
     46        List<Layer> layers = layerManager.getLayers();
     47        double distance = Double.MAX_VALUE;
     48        for (Layer layer : layers) {
     49            double tdistance = getLowestDistance(p, layer);
     50            if (tdistance < distance) distance = tdistance;
     51        }
     52        return distance;
     53    }
     54
     55    /**
     56     * Find the distance between a point and a layer of surveyed points
     57     * @param p OsmPrimitive from which to get the lowest distance to a GPX point
     58     * @param layer Layer from which to get the GPX points (currently, only GpxLayer is supported)
     59     * @return The shortest distance
     60     */
     61    public static double getLowestDistance(OsmPrimitive p, Layer layer) {
     62        if (layer instanceof GpxLayer) {
     63            GpxLayer gpxLayer = (GpxLayer) layer;
     64            GpxData gpxData = gpxLayer.data;
     65            List<WayPoint> trackPoints = gpxData.getTrackPoints().collect(Collectors.toList());
     66            double lowestDistance = Double.MAX_VALUE;
     67            for (WayPoint trackPoint : trackPoints) {
     68                double distance = getDistance(p, trackPoint);
     69                if (distance >= 0.0 && distance < lowestDistance) lowestDistance = distance;
     70            }
     71            return lowestDistance;
     72        }
     73        return Double.MAX_VALUE;
     74    }
     75
     76    /**
     77     * Get the distance between an object and a waypoint
     78     * @param p OsmPrimitive to get the distance to the WayPoint
     79     * @param waypoint WayPoint to get the distance from
     80     * @return The shortest distance between p and waypoint
     81     */
     82    public static double getDistance(OsmPrimitive p, WayPoint waypoint) {
     83        if (p instanceof Node) {
     84            return getDistanceNode((Node) p, waypoint);
     85        } else if (p instanceof Way) {
     86            return getDistanceWay((Way) p, waypoint);
     87        } else if (p instanceof Relation) {
     88            return getDistanceRelation((Relation) p, waypoint);
     89        }
     90        return Double.MAX_VALUE;
     91    }
     92
     93    /**
     94     * Get the shortest distance between a relation and a waypoint
     95     * @param relation Relation to get the distance from
     96     * @param waypoint WayPoint to get the distance to
     97     * @return The distance between the relation and the waypoint
     98     */
     99    public static double getDistanceRelation(Relation relation, WayPoint waypoint) {
     100        double shortestDistance = Double.MAX_VALUE;
     101        List<Node> nodes = new ArrayList<>(relation.getMemberPrimitives(Node.class));
     102        List<Way> ways = new ArrayList<>(relation.getMemberPrimitives(Way.class));
     103        List<Relation> relations = new ArrayList<>(relation.getMemberPrimitives(Relation.class));
     104        if (nodes.isEmpty() && ways.isEmpty() && relations.isEmpty()) return Double.MAX_VALUE;
     105        for (Relation nrelation : relations) {
     106            double distance = getDistanceRelation(nrelation, waypoint);
     107            if (distance < shortestDistance) shortestDistance = distance;
     108        }
     109        for (Way way : ways) {
     110            double distance = getDistanceWay(way, waypoint);
     111            if (distance < shortestDistance) shortestDistance = distance;
     112        }
     113        for (Node node : nodes) {
     114            double distance = getDistanceNode(node, waypoint);
     115            if (distance < shortestDistance) shortestDistance = distance;
     116        }
     117        return shortestDistance;
     118    }
     119
     120    /**
     121     * Get the shortest distance between a way and a waypoint
     122     * @param way Way to get the distance from
     123     * @param waypoint WayPoint to get the distance to
     124     * @return The distance between the way and the waypoint
     125     */
     126    public static double getDistanceWay(Way way, WayPoint waypoint) {
     127        double shortestDistance = Double.MAX_VALUE;
     128        LatLon coords = waypoint.getCoor();
     129        for (int i = 0; i < way.getNodesCount() - 1; i++) {
     130            LatLon first = way.getNode(i).getCoor();
     131            LatLon second = way.getNode(i + 1).getCoor();
     132            double distance = Double.MAX_VALUE;
     133            if (first.isLatLonKnown() && second.isLatLonKnown()) {
     134                double tdistance = ((coords.getX() - first.getX()) * (second.getX() - first.getX())
     135                        + (coords.getY() - first.getY()) * (second.getY() - first.getY()))
     136                        / (Math.pow(second.getX() - first.getX(), 2) + Math.pow(second.getY() - first.getY(), 2));
     137                double x = first.getX() + tdistance * (second.getX() - first.getX());
     138                double y = first.getY() + tdistance * (second.getY() - first.getY());
     139                LatLon npoint = new LatLon(y, x);
     140                distance = npoint.greatCircleDistance(coords);
     141            } else if (first.isLatLonKnown() && !second.isLatLonKnown()) {
     142                distance = getDistanceLatLon(first, waypoint);
     143            } else if (!first.isLatLonKnown() && second.isLatLonKnown()) {
     144                distance = getDistanceLatLon(second, waypoint);
     145            } else if (!first.isLatLonKnown() && !second.isLatLonKnown()) {
     146                distance = Double.MAX_VALUE;
     147            }
     148            if (distance < shortestDistance) shortestDistance = distance;
     149
     150        }
     151        return shortestDistance;
     152    }
     153
     154    /**
     155     * Get the distance between a node and a waypoint
     156     * @param node Node to get the distance from
     157     * @param waypoint WayPoint to get the distance to
     158     * @return The distance between the two points
     159     */
     160    public static double getDistanceNode(Node node, WayPoint waypoint) {
     161        return getDistanceLatLon(node.getCoor(), waypoint);
     162    }
     163
     164    /**
     165     * Get the distance between coordinates (latitude longitude) and a waypoint
     166     * @param latlon LatLon to get the distance from
     167     * @param waypoint WayPoint to get the distance to
     168     * @return The distance between the two points
     169     */
     170    public static double getDistanceLatLon(LatLon latlon, WayPoint waypoint) {
     171        if (latlon == null || waypoint.getCoor() == null) return Double.MAX_VALUE;
     172        return waypoint.getCoor().greatCircleDistance(latlon);
     173    }
     174}
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java

     
    2424import java.util.zip.CRC32;
    2525
    2626import org.openstreetmap.josm.data.coor.LatLon;
     27import org.openstreetmap.josm.data.gpx.GpxDistance;
    2728import org.openstreetmap.josm.data.osm.IPrimitive;
    2829import org.openstreetmap.josm.data.osm.Node;
     30import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2931import org.openstreetmap.josm.data.osm.Way;
    3032import org.openstreetmap.josm.data.osm.search.SearchCompiler;
    3133import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match;
     
    519521        }
    520522
    521523        /**
     524         * Returns the lowest distance between the OSM object and a GPX point
     525         * <p>
     526         * @param env the environment
     527         * @return the distance between the object and the closest gpx point or {@code Double.MAX_VALUE}
     528         */
     529        public static double gpx_distance(final Environment env) { // NO_UCD (unused code)
     530            if (env.osm instanceof OsmPrimitive) {
     531                return GpxDistance.getLowestDistance((OsmPrimitive) env.osm);
     532            } else {
     533                return Double.MAX_VALUE;
     534            }
     535        }
     536
     537        /**
    522538         * Determines whether the object has a tag with the given key.
    523539         * @param env the environment
    524540         * @param key the OSM key