Skip to content

Commit 15308a4

Browse files
author
Peter
committed
GPX export: avoid adding rounding errors and make it easier to calculate the time via passing the nextlat,nextlon; fix to Directory.remove
1 parent 8cf36b0 commit 15308a4

File tree

7 files changed

+55
-38
lines changed

7 files changed

+55
-38
lines changed

core/src/main/java/com/graphhopper/GraphHopper.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,9 @@ public GraphHopper importOrLoad()
479479
{
480480
if (!load(ghLocation))
481481
{
482+
if (!new File(osmFile).exists())
483+
throw new IllegalStateException("Couldn't load from existing folder: " + ghLocation
484+
+ " but also cannot import from OSM file as it does not exist: " + osmFile);
482485
printInfo();
483486
process(ghLocation, osmFile);
484487
} else

core/src/main/java/com/graphhopper/routing/Path.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,16 +471,16 @@ private void updatePointsAndInstruction( EdgeIteratorState edge, PointList pl )
471471
// add points in opposite direction as adj node is previous
472472
// skip base point => 'i > 0'
473473
int len = pl.size() - 1;
474-
long flags = edge.getFlags();
475474
for (int i = len; i > 0; i--)
476475
{
477476
double lat = pl.getLatitude(i);
478477
double lon = pl.getLongitude(i);
479478
points.add(lat, lon);
480479
}
481-
double dist = edge.getDistance();
482-
prevInstruction.setDistance(dist + prevInstruction.getDistance());
483-
prevInstruction.setMillis(calcMillis(dist, flags) + prevInstruction.getMillis());
480+
double newDist = edge.getDistance();
481+
prevInstruction.setDistance(newDist + prevInstruction.getDistance());
482+
long flags = edge.getFlags();
483+
prevInstruction.setMillis(calcMillis(newDist, flags) + prevInstruction.getMillis());
484484
}
485485
});
486486

core/src/main/java/com/graphhopper/storage/GHDirectory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ void removeByName( String name )
156156
if (da == null)
157157
throw new IllegalStateException("Couldn't remove dataAccess object:" + name);
158158
da.close();
159-
Helper.removeDir(new File(location + name));
159+
if (da.getType().isStoring())
160+
Helper.removeDir(new File(location + name));
160161
}
161162

162163
@Override

core/src/main/java/com/graphhopper/util/Instruction.java

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,13 @@ public class Instruction
3434
private final String name;
3535
private double distance;
3636
private long millis;
37-
private final PointList points;
37+
final PointList points;
3838
private final int pavementType;
3939
private final int waytype;
4040

4141
/**
4242
* The points, distances and times have exactly the same count. The last point of this
43-
* instruction is not duplicated here and should be in the next one. The first distance and time
44-
* entries are measured between the first point and the second one etc.
43+
* instruction is not duplicated here and should be in the next one.
4544
*/
4645
public Instruction( int indication, String name, int waytype, int pavementType, PointList pl )
4746
{
@@ -94,7 +93,7 @@ public Instruction setMillis( long millis )
9493
this.millis = millis;
9594
return this;
9695
}
97-
96+
9897
/**
9998
* Time in millis until no new instruction
10099
*/
@@ -135,27 +134,26 @@ public long getMillis()
135134
* <p>
136135
* @return the time offset to add for the next instruction
137136
*/
138-
public long fillGPXList( List<GPXEntry> list, long time, double prevFactor, double prevLat, double prevLon )
137+
long fillGPXList( List<GPXEntry> list, long time, double nextInstrLat, double nextInstrLon )
139138
{
139+
checkOne();
140140
int len = points.size();
141+
long prevTime = time;
142+
double lat = points.getLatitude(0);
143+
double lon = points.getLongitude(0);
141144
for (int i = 0; i < len; i++)
142145
{
143-
double lat = points.getLatitude(i);
144-
double lon = points.getLongitude(i);
145-
if (!Double.isNaN(prevLat))
146-
{
147-
// Here we assume that the same speed is used until the next instruction.
148-
// If we would calculate all the distances (and times) up front there
149-
// would be a problem where the air-line distance is not the distance returned from the edge
150-
// e.g. in the case if we include elevation data
151-
time += distanceCalc.calcDist(prevLat, prevLon, lat, lon) / prevFactor;
152-
}
153-
list.add(new GPXEntry(lat, lon, time));
154-
prevFactor = distance / millis;
155-
prevLat = lat;
156-
prevLon = lon;
146+
boolean last = i + 1 == len;
147+
double nextLat = last ? nextInstrLat : points.getLatitude(i + 1);
148+
double nextLon = last ? nextInstrLon : points.getLongitude(i + 1);
149+
150+
list.add(new GPXEntry(lat, lon, prevTime));
151+
// TODO in the case of elevation data the air-line distance is probably not precise enough
152+
prevTime = Math.round(prevTime + millis * distanceCalc.calcDist(nextLat, nextLon, lat, lon) / distance);
153+
lat = nextLat;
154+
lon = nextLon;
157155
}
158-
return time;
156+
return time + millis;
159157
}
160158

161159
@Override
@@ -173,4 +171,10 @@ public String toString()
173171
sb.append(')');
174172
return sb.toString();
175173
}
174+
175+
void checkOne()
176+
{
177+
if (points.size() < 1)
178+
throw new IllegalStateException("Instruction must contain at least one point " + toString());
179+
}
176180
}

core/src/main/java/com/graphhopper/util/InstructionList.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,15 +236,19 @@ public List<GPXEntry> createGPXList()
236236

237237
List<GPXEntry> gpxList = new ArrayList<GPXEntry>();
238238
long timeOffset = 0;
239-
double prevLat = Double.NaN, prevLon = Double.NaN;
240-
double prevFactor = 0;
241-
for (Instruction i : this)
239+
for (int i = 0; i < size() - 1; i++)
242240
{
243-
timeOffset = i.fillGPXList(gpxList, timeOffset, prevFactor, prevLat, prevLon);
244-
prevFactor = i.getDistance() / i.getMillis();
245-
prevLat = i.getLastLat();
246-
prevLon = i.getLastLon();
241+
Instruction nextInstr = get(i + 1);
242+
nextInstr.checkOne();
243+
// current instruction does not contain last point which is equals to first point of next instruction:
244+
double nextLat = nextInstr.getFirstLat(), nextLon = nextInstr.getFirstLon();
245+
timeOffset = get(i).fillGPXList(gpxList, timeOffset, nextLat, nextLon);
247246
}
247+
Instruction lastI = get(size() - 1);
248+
if (lastI.points.size() != 1)
249+
throw new IllegalStateException("Last instruction must have exactly one point but was " + lastI.points.size());
250+
double lastLat = lastI.getFirstLat(), lastLon = lastI.getFirstLon();
251+
gpxList.add(new GPXEntry(lastLat, lastLon, timeOffset));
248252
return gpxList;
249253
}
250254

core/src/test/java/com/graphhopper/routing/GraphHopperIT.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ public void testMonacoWithInstructions()
9191
assertEquals(30, times.get(3) / 1000);
9292
assertEquals(87, times.get(4) / 1000);
9393
assertEquals(321, times.get(5) / 1000);
94+
95+
List<GPXEntry> list = rsp.getInstructions().createGPXList();
96+
assertEquals(123, list.size());
97+
final long lastEntryMillis = list.get(list.size() - 1).getMillis();
98+
final long totalResponseMillis = rsp.getMillis();
99+
assertEquals(totalResponseMillis, lastEntryMillis);
100+
94101
} catch (Exception ex)
95102
{
96103
throw new RuntimeException("cannot handle osm file " + osmFile, ex);

core/src/test/java/com/graphhopper/util/InstructionListTest.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import com.graphhopper.routing.util.ShortestWeighting;
2525
import com.graphhopper.storage.Graph;
2626
import com.graphhopper.storage.GraphBuilder;
27-
import gnu.trove.list.array.TDoubleArrayList;
2827
import java.util.Arrays;
2928
import java.util.List;
3029
import java.util.Locale;
@@ -221,12 +220,11 @@ public void testInstructionsWithTimeAndPlace()
221220
assertEquals(5, wayList.size());
222221

223222
List<GPXEntry> gpxList = wayList.createGPXList();
224-
// distances and times are not identical (only similar) as we only guessed the edge distance
225223
assertEquals(34000, p.getDistance(), 1e-1);
226224
assertEquals(34000, sum(wayList.createDistances()), 1e-1);
227225
assertEquals(5, gpxList.size());
228226
assertEquals(1604120, p.getMillis());
229-
assertEquals(2097557, gpxList.get(gpxList.size() - 1).getMillis());
227+
assertEquals(1604120, gpxList.get(gpxList.size() - 1).getMillis());
230228

231229
assertEquals(Instruction.CONTINUE_ON_STREET, wayList.get(0).getIndication());
232230
assertEquals(15, wayList.get(0).getFirstLat(), 1e-3);
@@ -271,9 +269,9 @@ public void testCreateGPX()
271269

272270
assertEquals(0, result.get(0).getMillis());
273271
assertEquals(10391, result.get(1).getMillis());
274-
assertEquals(15602, result.get(2).getMillis());
275-
assertEquals(25449, result.get(3).getMillis());
276-
assertEquals(30559, result.get(4).getMillis());
272+
assertEquals(15000, result.get(2).getMillis());
273+
assertEquals(19000, result.get(3).getMillis());
274+
assertEquals(22000, result.get(4).getMillis());
277275
}
278276

279277
private long flagsForSpeed( EncodingManager encodingManager, int speedKmPerHour )

0 commit comments

Comments
 (0)