Modify

Opened 5 years ago

Closed 5 years ago

#17131 closed enhancement (fixed)

[Patch] mapcss should have the ability to get the distance to a gpx track

Reported by: taylor.smock Owned by: team
Priority: normal Milestone: 19.02
Component: Core validator Version: latest
Keywords: mapcss Cc:

Description

way[highway][!surface][gpx_distance() < 30] {
    throwError: tr("A highway doesn't have a surface type");
}

Attachments (9)

gpx_distance.patch (7.1 KB ) - added by taylor.smock 5 years ago.
Possible implementation
gpx_distance_v2.patch (9.1 KB ) - added by taylor.smock 5 years ago.
Patch after feedback (ant pmd checkstyle NOT run)
gpx_distance_v3.patch (9.3 KB ) - added by taylor.smock 5 years ago.
Modified to use greatCircleDistance where possible and ant pmd checkstyle has been run
gpx_distance_v4.patch (9.7 KB ) - added by taylor.smock 5 years ago.
Now uses Geometry.closestPointToSegment for getting the shortest distance from a point to a way.
gpx_distance_v5.patch (9.9 KB ) - added by taylor.smock 5 years ago.
Add @since xxx to javadocs and make calls to getCoor() once per object
GpxDistance_v6.patch (13.8 KB ) - added by taylor.smock 5 years ago.
Add tests and fix some bugs that were exposed
GpxDistance_v6.2.patch (14.4 KB ) - added by taylor.smock 5 years ago.
Fix some issues I noticed during testing and start work on method for GeoImage layers
GpxDistance_v7.patch (16.5 KB ) - added by taylor.smock 5 years ago.
Creates a new gpxdata object from image gps points where it is not already associated with a gpx track
GpxDistance_v8.patch (17.6 KB ) - added by taylor.smock 5 years ago.
Significantly improve performance by not rebuilding the same fake gpxlayer everytime -- it now stores the fake layer in the GeoImageLayer.

Download all attachments as: .zip

Change History (19)

by taylor.smock, 5 years ago

Attachment: gpx_distance.patch added

Possible implementation

comment:1 by Don-vip, 5 years ago

Milestone: 18.12
Summary: mapcss should have the ability to get the distance to a gpx track[Patch] mapcss should have the ability to get the distance to a gpx track

Thanks for the patch!
Some things to do to include it:

  • please run ant pmd checkstyle and fix all reported issues
  • The methods should be static, there's no need to instantiate an object just to get a list of current layers
  • you can use LayerManager.getLayersOfType(GpxLayer.class)
  • the code must be robust to incomplete primitives (for example: a node without coordinate will throw an NPE here)
  • you don't use any method of org.openstreetmap.josm.tools.Geometry, I'm sure there are distance methods there you should use rather than make the calculation in GpxDistance

comment:2 by taylor.smock, 5 years ago

I think I managed to get the methods to be static, I switched to using LayerManager (but in an odd way due to switching to static methods -- I don't know if it will work), I made the code a bit more robust for incomplete primitives.

As far as org.openstreetmap.josm.tools.Geometry, I didn't see any distance methods in it. I should probably look at moving many (or all) of the methods in GpxDistance to Geometry.

As far as ant pmd checkstyle goes, I couldn't run it. This is probably due to a hardcoded path somewhere in build.xml for ant. I fixed it with ln -s "$(which ant)" /usr/local/share/ant, and the patch no longer has warnings from it.

iMacs-iMac-6:core tsmock$ ant pmd checkstyle
Buildfile: /Users/tsmock/workspace/josm/core/build.xml

init-properties:

pmd:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by net.sourceforge.pmd.ant.Formatter (file:/Users/tsmock/workspace/josm/core/tools/pmd/pmd-core-6.6.0.jar) to field java.io.Console.cs
WARNING: Please consider reporting this to the maintainers of net.sourceforge.pmd.ant.Formatter
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Analysis cache invalidated, rulesets changed.
Incremental analysis can't check execution classpath contents
java.nio.file.NoSuchFileException: /usr/local/share/ant
<TRIMMED>
iMacs-iMac-6:core tsmock$ which ant
/usr/local/bin/ant
Last edited 5 years ago by taylor.smock (previous) (diff)

by taylor.smock, 5 years ago

Attachment: gpx_distance_v2.patch added

Patch after feedback (ant pmd checkstyle NOT run)

comment:3 by Don-vip, 5 years ago

Thanks. In getDistanceWay you should call LatLon.greatCircleDistance instead of the complex calculation. Otherwise looks fine.

comment:4 by taylor.smock, 5 years ago

I'm not certain how to use LatLon.greatCircleDistance to get the distance between a point and a way. It only takes a latlon, right?

So I would do something like this:

                double tdistance = ((coords.getX() - first.getX()) * (second.getX() - first.getX()) + (coords.getY() - first.getY()) * (second.getY() - first.getY()))
                        / (Math.pow(second.getX() - first.getX(), 2) + Math.pow(second.getY() - first.getY(), 2));
                double x = first.getX() + tdistance * (second.getX() - first.getX());
                double y = first.getY() + tdistance * (second.getY() - first.getY());
                LatLon npoint = new LatLon(y, x);
                distance = npoint.greatCircleDistance(coords);

instead of

                distance = Math.abs((second.getY() - first.getY()) * coords.getX() - (second.getX() - first.getX()) * coords.getY()
                        + second.getX() * first.getY() - second.getY() - first.getX()) /
                        Math.sqrt(Math.pow(second.getY() - first.getY(), 2) + Math.pow(second.getX() - first.getX(), 2));

In my local copy, I did modify getDistanceLatLon to use LatLon.greatCircleDistance, since that makes more sense than LatLon.distance for OpenStreetMap.

by taylor.smock, 5 years ago

Attachment: gpx_distance_v3.patch added

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

comment:5 by Don-vip, 5 years ago

I think you could still replace this calculation by a call to Geometry.closestPointToSegment:

    /**
     * Calculates closest point to a line segment.
     * @param segmentP1 First point determining line segment
     * @param segmentP2 Second point determining line segment
     * @param point Point for which a closest point is searched on line segment [P1,P2]
     * @return segmentP1 if it is the closest point, segmentP2 if it is the closest point,
     * a new point if closest point is between segmentP1 and segmentP2.
     * @see #closestPointToLine
     * @since 3650
     */
    public static EastNorth closestPointToSegment(EastNorth segmentP1, EastNorth segmentP2, EastNorth point)

comment:6 by Don-vip, 5 years ago

Milestone: 18.1219.01

by taylor.smock, 5 years ago

Attachment: gpx_distance_v4.patch added

Now uses Geometry.closestPointToSegment for getting the shortest distance from a point to a way.

comment:7 by Don-vip, 5 years ago

OK we're almost there :) Be careful with calling getCoor() method on the same object, several times. It will create a new LatLon instance at each call and thus the code will be memory-hungry, this must be avoided in rendering code by making sure the method is called only once per object:

                    EastNorth first = new EastNorth(way.getNode(i).getCoor().getX(),
                            way.getNode(i).getCoor().getY()); // <--
                    EastNorth second = new EastNorth(way.getNode(i+1).getCoor().getX(),
                            way.getNode(i+1).getCoor().getY()); // <--
                    if (first.isValid() && second.isValid()) {
                        EastNorth closestPoint = Geometry.closestPointToSegment(first, second, enwaypoint);
                        distance = closestPoint.distance(waypoint.getCoor().getX(), waypoint.getCoor().getY()); // <--

Also, please add a @since xxx in javadoc of new public class GpxDistance and new public method ExpressionFactory.gpx_distance. And then we're done :)

by taylor.smock, 5 years ago

Attachment: gpx_distance_v5.patch added

Add @since xxx to javadocs and make calls to getCoor() once per object

by taylor.smock, 5 years ago

Attachment: GpxDistance_v6.patch added

Add tests and fix some bugs that were exposed

by taylor.smock, 5 years ago

Attachment: GpxDistance_v6.2.patch added

Fix some issues I noticed during testing and start work on method for GeoImage layers

by taylor.smock, 5 years ago

Attachment: GpxDistance_v7.patch added

Creates a new gpxdata object from image gps points where it is not already associated with a gpx track

comment:8 by Don-vip, 5 years ago

Milestone: 19.0119.02

by taylor.smock, 5 years ago

Attachment: GpxDistance_v8.patch added

Significantly improve performance by not rebuilding the same fake gpxlayer everytime -- it now stores the fake layer in the GeoImageLayer.

comment:10 by Don-vip, 5 years ago

Resolution: fixed
Status: newclosed

In 14802/josm:

fix #17131 - add mapcss function gpx_distance to get the distance to a gpx track (patch by Taylor Smock, modified)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain team.
as The resolution will be set.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.