Merge pull request #170 from Phyks/exportWaypoints

Export waypoints in formatted tracks
This commit is contained in:
abrensch 2019-07-21 17:04:07 +02:00 committed by GitHub
commit e4c11e6dbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 172 additions and 67 deletions

View file

@ -60,6 +60,9 @@ public final class OsmTrack
public String name = "unset"; public String name = "unset";
protected List<MatchedWaypoint> matchedWaypoints;
public boolean exportWaypoints = false;
public void addNode( OsmPathElement node ) public void addNode( OsmPathElement node )
{ {
nodes.add( 0, node ); nodes.add( 0, node );
@ -175,7 +178,7 @@ public final class OsmTrack
/** /**
* writes the track in binary-format to a file * writes the track in binary-format to a file
* *
* @param filename * @param filename
* the filename to write to * the filename to write to
*/ */
@ -319,8 +322,8 @@ public final class OsmTrack
public void appendTrack( OsmTrack t ) public void appendTrack( OsmTrack t )
{ {
int ourSize = nodes.size(); int ourSize = nodes.size();
float t0 = ourSize > 0 ? nodes.get(ourSize - 1 ).getTime() : 0; float t0 = ourSize > 0 ? nodes.get(ourSize - 1 ).getTime() : 0;
float e0 = ourSize > 0 ? nodes.get(ourSize - 1 ).getEnergy() : 0; float e0 = ourSize > 0 ? nodes.get(ourSize - 1 ).getEnergy() : 0;
for ( int i = 0; i < t.nodes.size(); i++ ) for ( int i = 0; i < t.nodes.size(); i++ )
{ {
if ( i > 0 || ourSize == 0 ) if ( i > 0 || ourSize == 0 )
@ -367,7 +370,7 @@ public final class OsmTrack
/** /**
* writes the track in gpx-format to a file * writes the track in gpx-format to a file
* *
* @param filename * @param filename
* the filename to write to * the filename to write to
*/ */
@ -441,9 +444,9 @@ public final class OsmTrack
if ( turnInstructionMode == 3) // osmand style if ( turnInstructionMode == 3) // osmand style
{ {
float lastRteTime = 0; float lastRteTime = 0;
sb.append(" <rte>\n"); sb.append(" <rte>\n");
sb.append(" <rtept lat=\"").append( formatILat( nodes.get(0).getILat() ) ).append( "\" lon=\"" ) sb.append(" <rtept lat=\"").append( formatILat( nodes.get(0).getILat() ) ).append( "\" lon=\"" )
.append( formatILon( nodes.get(0).getILon() ) ).append( "\">\n" ) .append( formatILon( nodes.get(0).getILon() ) ).append( "\">\n" )
.append ( " <desc>start</desc>\n <extensions>\n"); .append ( " <desc>start</desc>\n <extensions>\n");
@ -475,7 +478,7 @@ public final class OsmTrack
} else { } else {
rteTime = nodes.get(nodes.size() - 1).getTime(); rteTime = nodes.get(nodes.size() - 1).getTime();
} }
if ( rteTime != lastRteTime ) // add timing only if available if ( rteTime != lastRteTime ) // add timing only if available
{ {
double t = rteTime - lastRteTime; double t = rteTime - lastRteTime;
@ -490,7 +493,7 @@ public final class OsmTrack
.append ( " <desc>destination</desc>\n <extensions>\n"); .append ( " <desc>destination</desc>\n <extensions>\n");
sb.append( " <time>0</time>\n" ); sb.append( " <time>0</time>\n" );
sb.append(" <offset>").append( "" + (nodes.size()-1) ).append("</offset>\n </extensions>\n </rtept>\n"); sb.append(" <offset>").append( "" + (nodes.size()-1) ).append("</offset>\n </extensions>\n </rtept>\n");
sb.append("</rte>\n"); sb.append("</rte>\n");
} }
@ -530,6 +533,28 @@ public final class OsmTrack
.append( "</wpt>\n" ); .append( "</wpt>\n" );
} }
} }
if ( exportWaypoints )
{
for( int i=0; i<=matchedWaypoints.size() - 1; i++ )
{
sb.append( " <wpt lon=\"" ).append( formatILon( matchedWaypoints.get(i).waypoint.ilon ) ).append( "\" lat=\"" )
.append( formatILat( matchedWaypoints.get(i).waypoint.ilat ) ).append( "\">\n" )
.append( " <name>" ).append( matchedWaypoints.get(i).name ).append( "</name>\n" );
if(i == 0)
{
sb.append( " <type>from</type>\n" );
}
else if (i == matchedWaypoints.size() - 1)
{
sb.append( " <type>to</type>\n" );
}
else {
sb.append( " <type>via</type>\n" );
}
sb.append( " </wpt>\n" );
}
}
sb.append( " <trk>\n" ); sb.append( " <trk>\n" );
sb.append( " <name>" ).append( name ).append( "</name>\n" ); sb.append( " <name>" ).append( name ).append( "</name>\n" );
if ( turnInstructionMode == 1 ) // trkpt/sym style if ( turnInstructionMode == 1 ) // trkpt/sym style
@ -601,7 +626,7 @@ public final class OsmTrack
sb.append( " <description><![CDATA[If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain]]></description>\n" ); sb.append( " <description><![CDATA[If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain]]></description>\n" );
sb.append( " <LineString>\n" ); sb.append( " <LineString>\n" );
sb.append( " <tessellate>1</tessellate>\n" ); sb.append( " <tessellate>1</tessellate>\n" );
sb.append( " <coordinates> " ); sb.append( " <coordinates>" );
for ( OsmPathElement n : nodes ) for ( OsmPathElement n : nodes )
{ {
@ -612,6 +637,41 @@ public final class OsmTrack
sb.append( " </LineString>\n" ); sb.append( " </LineString>\n" );
sb.append( " </Placemark>\n" ); sb.append( " </Placemark>\n" );
sb.append( " </Folder>\n" ); sb.append( " </Folder>\n" );
if ( exportWaypoints )
{
sb.append( " <Folder>\n" );
sb.append( " <name>start</name>\n" );
sb.append( " <Placemark>\n" );
sb.append( " <name> " + matchedWaypoints.get(0).name + "</name>\n" );
sb.append( " <Point>\n" );
sb.append( " <coordinates>" + formatILon(matchedWaypoints.get(0).waypoint.ilon) + "," + formatILat(matchedWaypoints.get(0).waypoint.ilat) + "</coordinates>\n" );
sb.append( " </Point>\n" );
sb.append( " </Placemark>\n" );
sb.append( " </Folder>\n" );
if (matchedWaypoints.size() > 2) {
sb.append( " <Folder>\n" );
sb.append( " <name>via</name>\n" );
for( int i=1; i<=matchedWaypoints.size() - 2; i++ )
{
sb.append( " <Placemark>\n" );
sb.append( " <name> " + matchedWaypoints.get(i).name + "</name>\n" );
sb.append( " <Point>\n" );
sb.append( " <coordinates>" + formatILon(matchedWaypoints.get(i).waypoint.ilon) + "," + formatILat(matchedWaypoints.get(i).waypoint.ilat) + "</coordinates>\n" );
sb.append( " </Point>\n" );
sb.append( " </Placemark>\n" );
}
sb.append( " </Folder>\n" );
}
sb.append( " <Folder>\n" );
sb.append( " <name>end</name>\n" );
sb.append( " <Placemark>\n" );
sb.append( " <name> " + matchedWaypoints.get(matchedWaypoints.size() - 1).name + "</name>\n" );
sb.append( " <Point>\n" );
sb.append( " <coordinates>" + formatILon(matchedWaypoints.get(matchedWaypoints.size() - 1).waypoint.ilon) + "," + formatILat(matchedWaypoints.get(matchedWaypoints.size() - 1).waypoint.ilat) + "</coordinates>\n" );
sb.append( " </Point>\n" );
sb.append( " </Placemark>\n" );
sb.append( " </Folder>\n" );
}
sb.append( " </Document>\n" ); sb.append( " </Document>\n" );
sb.append( "</kml>\n" ); sb.append( "</kml>\n" );
@ -713,7 +773,46 @@ public final class OsmTrack
sb.append( " ]\n" ); sb.append( " ]\n" );
sb.append( " }\n" ); sb.append( " }\n" );
sb.append( " }\n" ); if ( exportWaypoints )
{
sb.append( " },\n" );
for( int i=0; i<=matchedWaypoints.size() - 1; i++ )
{
sb.append( " {\n" );
sb.append( " \"type\": \"Feature\",\n" );
sb.append( " \"properties\": {\n" );
sb.append( " \"name\": \"" + matchedWaypoints.get(i).name + "\",\n" );
if(i == 0)
{
sb.append( " \"type\": \"from\"\n" );
}
else if (i == matchedWaypoints.size() - 1)
{
sb.append( " \"type\": \"to\"\n" );
}
else
sb.append( " \"type\": \"via\"\n" );
{
}
sb.append( " },\n" );
sb.append( " \"geometry\": {\n" );
sb.append( " \"type\": \"Point\",\n" );
sb.append( " \"coordinates\": [\n" );
sb.append( " " + formatILon(matchedWaypoints.get(i).waypoint.ilon) + ",\n" );
sb.append( " " + formatILat(matchedWaypoints.get(i).waypoint.ilat) + "\n" );
sb.append( " ]\n" );
sb.append( " }\n" );
if (i < matchedWaypoints.size() - 1) {
sb.append( " },\n" );
}
else {
sb.append( " }\n" );
}
}
}
else {
sb.append( " }\n" );
}
sb.append( " ]\n" ); sb.append( " ]\n" );
sb.append( "}\n" ); sb.append( "}\n" );
@ -739,7 +838,7 @@ public final class OsmTrack
{ {
return format1( getTotalSeconds()/60. ) + "m"; return format1( getTotalSeconds()/60. ) + "m";
} }
public String getFormattedTime2() public String getFormattedTime2()
{ {
int seconds = (int)(getTotalSeconds() + 0.5); int seconds = (int)(getTotalSeconds() + 0.5);
@ -789,7 +888,7 @@ public final class OsmTrack
ac[i--] = '-'; ac[i--] = '-';
return new String( ac, i + 1, 11 - i ); return new String( ac, i + 1, 11 - i );
} }
private String format1( double n ) private String format1( double n )
{ {
String s = "" + (long)(n*10 + 0.5); String s = "" + (long)(n*10 + 0.5);

View file

@ -53,7 +53,7 @@ public class RoutingEngine extends Thread
private OsmTrack guideTrack; private OsmTrack guideTrack;
private OsmPathElement matchPath; private OsmPathElement matchPath;
private long startTime; private long startTime;
private long maxRunningTime; private long maxRunningTime;
public SearchBoundary boundary; public SearchBoundary boundary;
@ -129,7 +129,7 @@ public class RoutingEngine extends Thread
} }
catch( IOException io ) catch( IOException io )
{ {
infoLogWriter = null; infoLogWriter = null;
} }
} }
} }
@ -150,7 +150,7 @@ public class RoutingEngine extends Thread
public void doRun( long maxRunningTime ) public void doRun( long maxRunningTime )
{ {
try try
{ {
// delete nogos with waypoints in them // delete nogos with waypoints in them
routingContext.cleanNogolist( waypoints ); routingContext.cleanNogolist( waypoints );
@ -244,7 +244,7 @@ public class RoutingEngine extends Thread
} }
ProfileCache.releaseProfile( routingContext ); ProfileCache.releaseProfile( routingContext );
if ( nodesCache != null ) if ( nodesCache != null )
{ {
if ( hasInfo() && nodesCache != null ) if ( hasInfo() && nodesCache != null )
@ -328,8 +328,8 @@ public class RoutingEngine extends Thread
public void cleanOnOOM() public void cleanOnOOM()
{ {
terminate(); terminate();
} }
private OsmTrack findTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks ) private OsmTrack findTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks )
{ {
for(;;) for(;;)
@ -345,7 +345,7 @@ public class RoutingEngine extends Thread
matchedWaypoints = null; matchedWaypoints = null;
} }
} }
} }
private OsmTrack tryFindTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks ) private OsmTrack tryFindTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks )
{ {
@ -446,6 +446,7 @@ public class RoutingEngine extends Thread
totaltrack.appendTrack( seg ); totaltrack.appendTrack( seg );
lastTracks[i] = seg; lastTracks[i] = seg;
} }
totaltrack.matchedWaypoints = matchedWaypoints;
return totaltrack; return totaltrack;
} }
@ -462,7 +463,7 @@ public class RoutingEngine extends Thread
double[] airDistanceCostFactors = new double[]{ routingContext.pass1coefficient, routingContext.pass2coefficient }; double[] airDistanceCostFactors = new double[]{ routingContext.pass1coefficient, routingContext.pass2coefficient };
boolean isDirty = false; boolean isDirty = false;
IllegalArgumentException dirtyMessage = null; IllegalArgumentException dirtyMessage = null;
if ( nearbyTrack != null ) if ( nearbyTrack != null )
{ {
airDistanceCostFactor = 0.; airDistanceCostFactor = 0.;
@ -473,7 +474,7 @@ public class RoutingEngine extends Thread
catch( IllegalArgumentException iae ) catch( IllegalArgumentException iae )
{ {
if ( terminated ) throw iae; if ( terminated ) throw iae;
// fast partial recalcs: if that timed out, but we had a match, // fast partial recalcs: if that timed out, but we had a match,
// build the concatenation from the partial and the nearby track // build the concatenation from the partial and the nearby track
if ( matchPath != null ) if ( matchPath != null )
@ -495,12 +496,12 @@ public class RoutingEngine extends Thread
for( int cfi = 0; cfi < airDistanceCostFactors.length; cfi++ ) for( int cfi = 0; cfi < airDistanceCostFactors.length; cfi++ )
{ {
airDistanceCostFactor = airDistanceCostFactors[cfi]; airDistanceCostFactor = airDistanceCostFactors[cfi];
if ( airDistanceCostFactor < 0. ) if ( airDistanceCostFactor < 0. )
{ {
continue; continue;
} }
OsmTrack t; OsmTrack t;
try try
{ {
@ -537,7 +538,7 @@ public class RoutingEngine extends Thread
} }
} }
if ( track == null ) throw new IllegalArgumentException( "no track found" ); if ( track == null ) throw new IllegalArgumentException( "no track found" );
boolean wasClean = nearbyTrack != null && !nearbyTrack.isDirty; boolean wasClean = nearbyTrack != null && !nearbyTrack.isDirty;
if ( refTrack == null && !(wasClean && isDirty) ) // do not overwrite a clean with a dirty track if ( refTrack == null && !(wasClean && isDirty) ) // do not overwrite a clean with a dirty track
{ {
@ -578,7 +579,7 @@ public class RoutingEngine extends Thread
logInfo( "NodesCache status before reset=" + nodesCache.formatStatus() ); logInfo( "NodesCache status before reset=" + nodesCache.formatStatus() );
} }
long maxmem = routingContext.memoryclass * 1024L *1024L; // in MB long maxmem = routingContext.memoryclass * 1024L *1024L; // in MB
nodesCache = new NodesCache(segmentDir, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed ); nodesCache = new NodesCache(segmentDir, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed );
islandNodePairs.clearTempPairs(); islandNodePairs.clearTempPairs();
} }
@ -586,7 +587,7 @@ public class RoutingEngine extends Thread
private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, OsmNodeNamed endPos, boolean sameSegmentSearch ) private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, OsmNodeNamed endPos, boolean sameSegmentSearch )
{ {
OsmPath p = getStartPath( n1, n2, new OsmNodeNamed( mwp.waypoint ), endPos ); OsmPath p = getStartPath( n1, n2, new OsmNodeNamed( mwp.waypoint ), endPos );
// special case: start+end on same segment // special case: start+end on same segment
if ( sameSegmentSearch ) if ( sameSegmentSearch )
{ {
@ -627,8 +628,8 @@ public class RoutingEngine extends Thread
return p; return p;
} }
private OsmPath getStartPath( OsmNode n1, OsmNode n2, OsmNodeNamed wp, OsmNodeNamed endPos ) private OsmPath getStartPath( OsmNode n1, OsmNode n2, OsmNodeNamed wp, OsmNodeNamed endPos )
{ {
try try
@ -682,7 +683,7 @@ public class RoutingEngine extends Thread
startLink.addLinkHolder( startPath, null ); startLink.addLinkHolder( startPath, null );
if ( wp != null ) wp.radius = 1.5; if ( wp != null ) wp.radius = 1.5;
return routingContext.createPath( startPath, link, null, guideTrack != null ); return routingContext.createPath( startPath, link, null, guideTrack != null );
} }
finally finally
@ -713,7 +714,7 @@ public class RoutingEngine extends Thread
int maxTotalCost = guideTrack != null ? guideTrack.cost + 5000 : 1000000000; int maxTotalCost = guideTrack != null ? guideTrack.cost + 5000 : 1000000000;
int firstMatchCost = 1000000000; int firstMatchCost = 1000000000;
logInfo( "findtrack with airDistanceCostFactor=" + airDistanceCostFactor ); logInfo( "findtrack with airDistanceCostFactor=" + airDistanceCostFactor );
if (costCuttingTrack != null ) logInfo( "costCuttingTrack.cost=" + costCuttingTrack.cost ); if (costCuttingTrack != null ) logInfo( "costCuttingTrack.cost=" + costCuttingTrack.cost );
@ -727,7 +728,7 @@ public class RoutingEngine extends Thread
OsmNode end1 = null; OsmNode end1 = null;
OsmNode end2 = null; OsmNode end2 = null;
OsmNodeNamed endPos = null; OsmNodeNamed endPos = null;
boolean sameSegmentSearch = false; boolean sameSegmentSearch = false;
OsmNode start1 = nodesCache.getGraphNode( startWp.node1 ); OsmNode start1 = nodesCache.getGraphNode( startWp.node1 );
OsmNode start2 = nodesCache.getGraphNode( startWp.node2 ); OsmNode start2 = nodesCache.getGraphNode( startWp.node2 );
@ -772,10 +773,10 @@ public class RoutingEngine extends Thread
OsmPathElement pe2 = costCuttingTrack.getLink( startNodeId2, startNodeId1 ); OsmPathElement pe2 = costCuttingTrack.getLink( startNodeId2, startNodeId1 );
if ( pe2 != null ) { logInfo( "initialMatch pe2.cost=" + pe2.cost ); if ( pe2 != null ) { logInfo( "initialMatch pe2.cost=" + pe2.cost );
int c = startPath2.cost - pe2.cost; if ( c < 0 ) c = 0; if ( c < firstMatchCost ) firstMatchCost = c; } int c = startPath2.cost - pe2.cost; if ( c < 0 ) c = 0; if ( c < firstMatchCost ) firstMatchCost = c; }
if ( firstMatchCost < 1000000000 ) logInfo( "firstMatchCost from initial match=" + firstMatchCost ); if ( firstMatchCost < 1000000000 ) logInfo( "firstMatchCost from initial match=" + firstMatchCost );
} }
synchronized( openSet ) synchronized( openSet )
{ {
openSet.clear(); openSet.clear();
@ -785,14 +786,14 @@ public class RoutingEngine extends Thread
ArrayList<OsmPath> openBorderList = new ArrayList<OsmPath>(4096); ArrayList<OsmPath> openBorderList = new ArrayList<OsmPath>(4096);
boolean memoryPanicMode = false; boolean memoryPanicMode = false;
boolean needNonPanicProcessing = false; boolean needNonPanicProcessing = false;
for(;;) for(;;)
{ {
if ( terminated ) if ( terminated )
{ {
throw new IllegalArgumentException( "operation killed by thread-priority-watchdog after " + ( System.currentTimeMillis() - startTime)/1000 + " seconds" ); throw new IllegalArgumentException( "operation killed by thread-priority-watchdog after " + ( System.currentTimeMillis() - startTime)/1000 + " seconds" );
} }
if ( maxRunningTime > 0 ) if ( maxRunningTime > 0 )
{ {
long timeout = ( matchPath == null && fastPartialRecalc ) ? maxRunningTime/3 : maxRunningTime; long timeout = ( matchPath == null && fastPartialRecalc ) ? maxRunningTime/3 : maxRunningTime;
@ -827,7 +828,7 @@ public class RoutingEngine extends Thread
path.unregisterUpTree( routingContext ); path.unregisterUpTree( routingContext );
continue; continue;
} }
if ( directWeaving && nodesCache.hasHollowLinkTargets( path.getTargetNode() ) ) if ( directWeaving && nodesCache.hasHollowLinkTargets( path.getTargetNode() ) )
{ {
if ( !memoryPanicMode ) if ( !memoryPanicMode )
@ -837,7 +838,7 @@ public class RoutingEngine extends Thread
// System.out.println( "collecting..." ); // System.out.println( "collecting..." );
int nodesBefore = nodesCache.nodesMap.nodesCreated; int nodesBefore = nodesCache.nodesMap.nodesCreated;
int pathsBefore = openSet.getSize(); int pathsBefore = openSet.getSize();
nodesCache.nodesMap.collectOutreachers(); nodesCache.nodesMap.collectOutreachers();
for(;;) for(;;)
{ {
@ -873,7 +874,7 @@ public class RoutingEngine extends Thread
} }
} }
needNonPanicProcessing = false; needNonPanicProcessing = false;
if ( fastPartialRecalc && matchPath != null && path.cost > 30L*firstMatchCost && !costCuttingTrack.isDirty ) if ( fastPartialRecalc && matchPath != null && path.cost > 30L*firstMatchCost && !costCuttingTrack.isDirty )
{ {
@ -891,7 +892,7 @@ public class RoutingEngine extends Thread
throw new IllegalArgumentException( "early exit for a close recalc" ); throw new IllegalArgumentException( "early exit for a close recalc" );
} }
} }
if ( nodeLimit > 0 ) // check node-limit for target island search if ( nodeLimit > 0 ) // check node-limit for target island search
{ {
if ( --nodeLimit == 0 ) if ( --nodeLimit == 0 )
@ -902,7 +903,7 @@ public class RoutingEngine extends Thread
nodesVisited++; nodesVisited++;
linksProcessed++; linksProcessed++;
OsmLink currentLink = path.getLink(); OsmLink currentLink = path.getLink();
OsmNode sourceNode = path.getSourceNode(); OsmNode sourceNode = path.getSourceNode();
OsmNode currentNode = path.getTargetNode(); OsmNode currentNode = path.getTargetNode();
@ -915,19 +916,19 @@ public class RoutingEngine extends Thread
long currentNodeId = currentNode.getIdFromPos(); long currentNodeId = currentNode.getIdFromPos();
long sourceNodeId = sourceNode.getIdFromPos(); long sourceNodeId = sourceNode.getIdFromPos();
if ( !path.didEnterDestinationArea() ) if ( !path.didEnterDestinationArea() )
{ {
islandNodePairs.addTempPair( sourceNodeId, currentNodeId ); islandNodePairs.addTempPair( sourceNodeId, currentNodeId );
} }
if ( path.treedepth != 1 ) if ( path.treedepth != 1 )
{ {
if ( path.treedepth == 0 ) // hack: sameSegment Paths marked treedepth=0 to pass above check if ( path.treedepth == 0 ) // hack: sameSegment Paths marked treedepth=0 to pass above check
{ {
path.treedepth = 1; path.treedepth = 1;
} }
if ( ( sourceNodeId == endNodeId1 && currentNodeId == endNodeId2 ) if ( ( sourceNodeId == endNodeId1 && currentNodeId == endNodeId2 )
|| ( sourceNodeId == endNodeId2 && currentNodeId == endNodeId1 ) ) || ( sourceNodeId == endNodeId2 && currentNodeId == endNodeId1 ) )
{ {
@ -937,7 +938,7 @@ public class RoutingEngine extends Thread
t.showspeed = routingContext.showspeed; t.showspeed = routingContext.showspeed;
return t; return t;
} }
// check for a match with the cost-cutting-track // check for a match with the cost-cutting-track
if ( costCuttingTrack != null ) if ( costCuttingTrack != null )
{ {
@ -946,13 +947,13 @@ public class RoutingEngine extends Thread
{ {
// remember first match cost for fast termination of partial recalcs // remember first match cost for fast termination of partial recalcs
int parentcost = path.originElement == null ? 0 : path.originElement.cost; int parentcost = path.originElement == null ? 0 : path.originElement.cost;
// hitting start-element of costCuttingTrack? // hitting start-element of costCuttingTrack?
int c = path.cost - parentcost - pe.cost; int c = path.cost - parentcost - pe.cost;
if ( c > 0 ) parentcost += c; if ( c > 0 ) parentcost += c;
if ( parentcost < firstMatchCost ) firstMatchCost = parentcost; if ( parentcost < firstMatchCost ) firstMatchCost = parentcost;
int costEstimate = path.cost int costEstimate = path.cost
+ path.elevationCorrection( routingContext ) + path.elevationCorrection( routingContext )
+ ( costCuttingTrack.cost - pe.cost ); + ( costCuttingTrack.cost - pe.cost );
@ -975,7 +976,7 @@ public class RoutingEngine extends Thread
{ {
((OsmPath)linkHolder).airdistance = -1; // invalidate the entry in the open set; ((OsmPath)linkHolder).airdistance = -1; // invalidate the entry in the open set;
} }
boolean isBidir = currentLink.isBidirectional(); boolean isBidir = currentLink.isBidirectional();
sourceNode.unlinkLink ( currentLink ); sourceNode.unlinkLink ( currentLink );
@ -991,11 +992,11 @@ public class RoutingEngine extends Thread
path.unregisterUpTree( routingContext ); path.unregisterUpTree( routingContext );
continue; continue;
} }
nodesCache.nodesMap.currentMaxCost = maxTotalCost; nodesCache.nodesMap.currentMaxCost = maxTotalCost;
nodesCache.nodesMap.currentPathCost = path.cost; nodesCache.nodesMap.currentPathCost = path.cost;
nodesCache.nodesMap.destination = endPos; nodesCache.nodesMap.destination = endPos;
routingContext.firstPrePath = null; routingContext.firstPrePath = null;
for( OsmLink link = currentNode.firstlink; link != null; link = link.getNext( currentNode) ) for( OsmLink link = currentNode.firstlink; link != null; link = link.getNext( currentNode) )
@ -1105,7 +1106,7 @@ public class RoutingEngine extends Thread
boolean trafficSim = endPos == null; boolean trafficSim = endPos == null;
bestPath.airdistance = trafficSim ? keepPathAirdistance : ( isFinalLink ? 0 : nextNode.calcDistance( endPos ) ); bestPath.airdistance = trafficSim ? keepPathAirdistance : ( isFinalLink ? 0 : nextNode.calcDistance( endPos ) );
boolean inRadius = boundary == null || boundary.isInBoundary( nextNode, bestPath.cost ); boolean inRadius = boundary == null || boundary.isInBoundary( nextNode, bestPath.cost );
if ( inRadius && ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 100 ) ) if ( inRadius && ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 100 ) )
@ -1134,19 +1135,19 @@ public class RoutingEngine extends Thread
} }
} }
} }
path.unregisterUpTree( routingContext ); path.unregisterUpTree( routingContext );
} }
} }
if ( nodesVisited < MAXNODES_ISLAND_CHECK && islandNodePairs.getFreezeCount() < 5 ) if ( nodesVisited < MAXNODES_ISLAND_CHECK && islandNodePairs.getFreezeCount() < 5 )
{ {
throw new RoutingIslandException(); throw new RoutingIslandException();
} }
return null; return null;
} }
private void addToOpenset( OsmPath path ) private void addToOpenset( OsmPath path )
{ {
if ( path.cost >= 0 ) if ( path.cost >= 0 )
@ -1159,7 +1160,7 @@ public class RoutingEngine extends Thread
private OsmTrack compileTrack( OsmPath path, boolean verbose ) private OsmTrack compileTrack( OsmPath path, boolean verbose )
{ {
OsmPathElement element = OsmPathElement.create( path, false ); OsmPathElement element = OsmPathElement.create( path, false );
// for final track, cut endnode // for final track, cut endnode
if ( guideTrack != null ) if ( guideTrack != null )
{ {
@ -1179,7 +1180,7 @@ public class RoutingEngine extends Thread
short ele_start = Short.MIN_VALUE; short ele_start = Short.MIN_VALUE;
short ele_end = Short.MIN_VALUE; short ele_end = Short.MIN_VALUE;
double eleFactor = routingContext.inverseRouting ? -0.25 : 0.25; double eleFactor = routingContext.inverseRouting ? -0.25 : 0.25;
while ( element != null ) while ( element != null )
{ {
@ -1187,7 +1188,7 @@ public class RoutingEngine extends Thread
{ {
element.message = new MessageData(); element.message = new MessageData();
} }
if ( routingContext.inverseRouting ) if ( routingContext.inverseRouting )
{ {
element.setTime( totalTime - element.getTime() ); element.setTime( totalTime - element.getTime() );
@ -1198,9 +1199,9 @@ public class RoutingEngine extends Thread
{ {
track.nodes.add( 0, element ); track.nodes.add( 0, element );
} }
OsmPathElement nextElement = element.origin; OsmPathElement nextElement = element.origin;
short ele = element.getSElev(); short ele = element.getSElev();
if ( ele != Short.MIN_VALUE ) ele_start = ele; if ( ele != Short.MIN_VALUE ) ele_start = ele;
if ( ele_end == Short.MIN_VALUE ) ele_end = ele; if ( ele_end == Short.MIN_VALUE ) ele_end = ele;
@ -1245,7 +1246,7 @@ public class RoutingEngine extends Thread
private OsmTrack mergeTrack( OsmPathElement match, OsmTrack oldTrack ) private OsmTrack mergeTrack( OsmPathElement match, OsmTrack oldTrack )
{ {
logInfo( "**************** merging match=" + match.cost + " with oldTrack=" + oldTrack.cost ); logInfo( "**************** merging match=" + match.cost + " with oldTrack=" + oldTrack.cost );
OsmPathElement element = match; OsmPathElement element = match;
OsmTrack track = new OsmTrack(); OsmTrack track = new OsmTrack();
track.cost = oldTrack.cost; track.cost = oldTrack.cost;
@ -1265,7 +1266,7 @@ public class RoutingEngine extends Thread
{ {
track.nodes.add( n ); track.nodes.add( n );
} }
long id = n.getIdFromPos(); long id = n.getIdFromPos();
if ( id == id1 && lastId == id0 ) if ( id == id1 && lastId == id0 )
{ {
@ -1273,8 +1274,8 @@ public class RoutingEngine extends Thread
} }
lastId = id; lastId = id;
} }
track.buildMap(); track.buildMap();
return track; return track;
} }
@ -1293,7 +1294,7 @@ public class RoutingEngine extends Thread
{ {
extract = new Object[500]; extract = new Object[500];
} }
synchronized( openSet ) synchronized( openSet )
{ {
if ( guideTrack != null ) if ( guideTrack != null )
@ -1308,7 +1309,7 @@ public class RoutingEngine extends Thread
} }
return res; return res;
} }
int size = openSet.getExtract(extract); int size = openSet.getExtract(extract);
int[] res = new int[size * 2]; int[] res = new int[size * 2];
for( int i=0, j=0; i<size; i++ ) for( int i=0, j=0; i<size; i++ )
@ -1347,7 +1348,7 @@ public class RoutingEngine extends Thread
{ {
return foundTrack.plainAscend; return foundTrack.plainAscend;
} }
public String getTime() public String getTime()
{ {
return foundTrack.getFormattedTime2(); return foundTrack.getFormattedTime2();

View file

@ -24,6 +24,7 @@ import java.util.List;
* alternativeidx = [0|1|2|3] (optional, default 0) * alternativeidx = [0|1|2|3] (optional, default 0)
* format = [kml|gpx|geojson] (optional, default gpx) * format = [kml|gpx|geojson] (optional, default gpx)
* trackname = name used for filename and format specific trackname (optional, default brouter) * trackname = name used for filename and format specific trackname (optional, default brouter)
* exportWaypoints = 1 to export them (optional, default is no export)
* *
* Example URLs: * Example URLs:
* {@code http://localhost:17777/brouter?lonlats=8.799297,49.565883|8.811764,49.563606&nogos=&profile=trekking&alternativeidx=0&format=gpx} * {@code http://localhost:17777/brouter?lonlats=8.799297,49.565883|8.811764,49.563606&nogos=&profile=trekking&alternativeidx=0&format=gpx}
@ -118,6 +119,10 @@ public class ServerHandler extends RequestHandler {
if (trackName != null) { if (trackName != null) {
track.name = trackName; track.name = trackName;
} }
String exportWaypointsStr = params.get( "exportWaypoints" );
if (exportWaypointsStr != null && Integer.parseInt(exportWaypointsStr) != 0) {
track.exportWaypoints = true;
}
if (format == null || "gpx".equals(format)) if (format == null || "gpx".equals(format))
{ {