Opened 7 years ago
Closed 7 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)
Change History (19)
by , 7 years ago
| Attachment: | gpx_distance.patch added |
|---|
comment:1 by , 7 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 checkstyleand 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 aredistancemethods there you should use rather than make the calculation inGpxDistance
comment:2 by , 7 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.
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
at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55)
at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:145)
at java.base/java.nio.file.Files.readAttributes(Files.java:1763)
at java.base/java.nio.file.FileTreeWalker.getAttributes(FileTreeWalker.java:225)
at java.base/java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:276)
at java.base/java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:322)
at java.base/java.nio.file.Files.walkFileTree(Files.java:2716)
at net.sourceforge.pmd.cache.AbstractAnalysisCache.getClassPathEntries(AbstractAnalysisCache.java:159)
at net.sourceforge.pmd.cache.AbstractAnalysisCache.checkValidity(AbstractAnalysisCache.java:130)
at net.sourceforge.pmd.processor.AbstractPMDProcessor.processFiles(AbstractPMDProcessor.java:102)
at net.sourceforge.pmd.PMD.processFiles(PMD.java:329)
at net.sourceforge.pmd.ant.internal.PMDTaskImpl.doTask(PMDTaskImpl.java:191)
at net.sourceforge.pmd.ant.internal.PMDTaskImpl.execute(PMDTaskImpl.java:275)
at net.sourceforge.pmd.ant.PMDTask.execute(PMDTask.java:50)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at jdk.internal.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:99)
at org.apache.tools.ant.Task.perform(Task.java:350)
at org.apache.tools.ant.Target.execute(Target.java:449)
at org.apache.tools.ant.Target.performTasks(Target.java:470)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1388)
at org.apache.tools.ant.Project.executeTarget(Project.java:1361)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
at org.apache.tools.ant.Main.runBuild(Main.java:834)
at org.apache.tools.ant.Main.startAnt(Main.java:223)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:284)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:101)
[pmd] java.lang.RuntimeException: java.nio.file.NoSuchFileException: /usr/local/share/ant
[pmd] at net.sourceforge.pmd.cache.AbstractAnalysisCache.getClassPathEntries(AbstractAnalysisCache.java:174)
[pmd] at net.sourceforge.pmd.cache.AbstractAnalysisCache.checkValidity(AbstractAnalysisCache.java:130)
[pmd] at net.sourceforge.pmd.processor.AbstractPMDProcessor.processFiles(AbstractPMDProcessor.java:102)
[pmd] at net.sourceforge.pmd.PMD.processFiles(PMD.java:329)
[pmd] at net.sourceforge.pmd.ant.internal.PMDTaskImpl.doTask(PMDTaskImpl.java:191)
[pmd] at net.sourceforge.pmd.ant.internal.PMDTaskImpl.execute(PMDTaskImpl.java:275)
[pmd] at net.sourceforge.pmd.ant.PMDTask.execute(PMDTask.java:50)
[pmd] at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
[pmd] at jdk.internal.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
[pmd] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[pmd] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[pmd] at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:99)
[pmd] at org.apache.tools.ant.Task.perform(Task.java:350)
[pmd] at org.apache.tools.ant.Target.execute(Target.java:449)
[pmd] at org.apache.tools.ant.Target.performTasks(Target.java:470)
[pmd] at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1388)
[pmd] at org.apache.tools.ant.Project.executeTarget(Project.java:1361)
[pmd] at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
[pmd] at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
[pmd] at org.apache.tools.ant.Main.runBuild(Main.java:834)
[pmd] at org.apache.tools.ant.Main.startAnt(Main.java:223)
[pmd] at org.apache.tools.ant.launch.Launcher.run(Launcher.java:284)
[pmd] at org.apache.tools.ant.launch.Launcher.main(Launcher.java:101)
[pmd] Caused by: java.nio.file.NoSuchFileException: /usr/local/share/ant
[pmd] at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
[pmd] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
[pmd] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
[pmd] at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55)
[pmd] at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:145)
[pmd] at java.base/java.nio.file.Files.readAttributes(Files.java:1763)
[pmd] at java.base/java.nio.file.FileTreeWalker.getAttributes(FileTreeWalker.java:225)
[pmd] at java.base/java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:276)
[pmd] at java.base/java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:322)
[pmd] at java.base/java.nio.file.Files.walkFileTree(Files.java:2716)
[pmd] at net.sourceforge.pmd.cache.AbstractAnalysisCache.getClassPathEntries(AbstractAnalysisCache.java:159)
[pmd] ... 22 more
[pmd] null - java.nio.file.NoSuchFileException: /usr/local/share/ant
BUILD FAILED
/Users/tsmock/workspace/josm/core/build.xml:943: java.lang.NullPointerException
at net.sourceforge.pmd.util.StringUtil.appendXmlEscaped(StringUtil.java:214)
at net.sourceforge.pmd.renderers.XMLRenderer.end(XMLRenderer.java:124)
at net.sourceforge.pmd.ant.Formatter.end(Formatter.java:117)
at net.sourceforge.pmd.ant.internal.PMDTaskImpl.doTask(PMDTaskImpl.java:201)
at net.sourceforge.pmd.ant.internal.PMDTaskImpl.execute(PMDTaskImpl.java:275)
at net.sourceforge.pmd.ant.PMDTask.execute(PMDTask.java:50)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at jdk.internal.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:99)
at org.apache.tools.ant.Task.perform(Task.java:350)
at org.apache.tools.ant.Target.execute(Target.java:449)
at org.apache.tools.ant.Target.performTasks(Target.java:470)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1388)
at org.apache.tools.ant.Project.executeTarget(Project.java:1361)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
at org.apache.tools.ant.Main.runBuild(Main.java:834)
at org.apache.tools.ant.Main.startAnt(Main.java:223)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:284)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:101)
Total time: 1 second
iMacs-iMac-6:core tsmock$ which ant /usr/local/bin/ant
by , 7 years ago
| Attachment: | gpx_distance_v2.patch added |
|---|
Patch after feedback (ant pmd checkstyle NOT run)
comment:3 by , 7 years ago
Thanks. In getDistanceWay you should call LatLon.greatCircleDistance instead of the complex calculation. Otherwise looks fine.
comment:4 by , 7 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 , 7 years ago
| Attachment: | gpx_distance_v3.patch added |
|---|
Modified to use greatCircleDistance where possible and ant pmd checkstyle has been run
comment:5 by , 7 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 , 7 years ago
| Milestone: | 18.12 → 19.01 |
|---|
by , 7 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 , 7 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 , 7 years ago
| Attachment: | gpx_distance_v5.patch added |
|---|
Add @since xxx to javadocs and make calls to getCoor() once per object
by , 7 years ago
| Attachment: | GpxDistance_v6.patch added |
|---|
Add tests and fix some bugs that were exposed
by , 7 years ago
| Attachment: | GpxDistance_v6.2.patch added |
|---|
Fix some issues I noticed during testing and start work on method for GeoImage layers
by , 7 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 , 7 years ago
| Milestone: | 19.01 → 19.02 |
|---|
by , 7 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:9 by , 7 years ago
Status update (pursuant https://josm.openstreetmap.de/wiki/DevelopersGuide/PatchGuide)



Possible implementation