Ticket #17131: gpx_distance_v2.patch

File gpx_distance_v2.patch, 9.1 KB (added by taylor.smock, 7 years ago)

Patch after feedback (ant pmd checkstyle NOT 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                distance = Math.abs((second.getY() - first.getY()) * coords.getX() - (second.getX() - first.getX()) * coords.getY()
     135                        + second.getX() * first.getY() - second.getY() - first.getX()) /
     136                        Math.sqrt(Math.pow(second.getY() - first.getY(), 2) + Math.pow(second.getX() - first.getX(), 2));
     137            } else if (first.isLatLonKnown() && !second.isLatLonKnown()) {
     138                distance = getDistanceLatLon(first, waypoint);
     139            } else if (!first.isLatLonKnown() && second.isLatLonKnown()) {
     140                distance = getDistanceLatLon(second, waypoint);
     141            } else if (!first.isLatLonKnown() && !second.isLatLonKnown()) {
     142                distance = Double.MAX_VALUE;
     143            }
     144            if (distance < shortestDistance) shortestDistance = distance;
     145
     146        }
     147        return shortestDistance;
     148    }
     149
     150    /**
     151     * Get the distance between a node and a waypoint
     152     * @param node Node to get the distance from
     153     * @param waypoint WayPoint to get the distance to
     154     * @return The distance between the two points
     155     */
     156    public static double getDistanceNode(Node node, WayPoint waypoint) {
     157        return getDistanceLatLon(node.getCoor(), waypoint);
     158    }
     159
     160    /**
     161     * Get the distance between coordinates (latitude longitude) and a waypoint
     162     * @param latlon LatLon to get the distance from
     163     * @param waypoint WayPoint to get the distance to
     164     * @return The distance between the two points
     165     */
     166    public static double getDistanceLatLon(LatLon latlon, WayPoint waypoint) {
     167        if (latlon == null) return Double.MAX_VALUE;
     168        return waypoint.getCoor().distance(latlon);
     169    }
     170}
  • 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