use of net.osmand.data.TransportSchedule in project OsmAnd-tools by osmandapp.
the class IndexTransportCreator method readSchedule.
private TransportSchedule readSchedule(String ref, List<TransportStop> directStops) throws SQLException {
if (!Algorithms.isEmpty(ref) && gtfsConnection != null && directStops.size() > 0) {
if (gtfsSelectRoute == null) {
// new String[] { "firstStopLat", "firstStopLon", "minLat", "maxLat", "minLon", "maxLon" }
gtfsSelectRoute = gtfsConnection.prepareStatement("SELECT r.route_id, r.route_short_name, r.route_long_name, " + " t.trip_id, t.shape_id, t.service_id, t.firstStopLat, t.firstStopLon from routes r join " + " trips t on t.route_id = r.route_id where route_short_name = ? order by r.route_id asc, t.trip_id asc ");
}
if (gtfsSelectStopTimes == null) {
gtfsSelectStopTimes = gtfsConnection.prepareStatement("SELECT arrival_time, departure_time, stop_id, stop_sequence" + " from stop_times where trip_id = ? order by stop_sequence ");
}
gtfsSelectRoute.setString(1, ref);
ResultSet rs = gtfsSelectRoute.executeQuery();
String routeId = null, routeShortName = null, routeLongName = null;
TransportSchedule schedule = new TransportSchedule();
TIntArrayList timeDeparturesFirst = new TIntArrayList();
while (rs.next()) {
String nrouteId = rs.getString(1);
if (!Algorithms.objectEquals(routeId, nrouteId)) {
routeId = nrouteId;
routeShortName = rs.getString(2);
routeLongName = rs.getString(3);
}
String tripId = rs.getString(4);
// String shapeId = rs.getString(5);
// String serviceId = rs.getString(6);
double firstLat = rs.getDouble(7);
double firstLon = rs.getDouble(8);
double dist = MapUtils.getDistance(directStops.get(0).getLocation(), firstLat, firstLon);
if (dist < DISTANCE_THRESHOLD) {
gtfsSelectStopTimes.setString(1, tripId);
ResultSet nrs = gtfsSelectStopTimes.executeQuery();
TIntArrayList stopIntervals = new TIntArrayList(directStops.size());
TIntArrayList waitIntervals = new TIntArrayList(directStops.size());
int ftime = 0, ptime = 0;
while (nrs.next()) {
int arrivalTime = parseTime(nrs.getString(1));
int depTime = parseTime(nrs.getString(2));
if (arrivalTime == -1 || depTime == -1) {
gtfsStats.errorsTimeParsing++;
continue;
}
if (ftime == 0) {
ftime = ptime = depTime;
} else {
stopIntervals.add(arrivalTime - ptime);
}
waitIntervals.add(depTime - arrivalTime);
ptime = arrivalTime;
}
if (waitIntervals.size() != directStops.size()) {
gtfsStats.errorsTripsStopCounts++;
// failed = true;
} else {
gtfsStats.successTripsParsing++;
if (schedule.avgWaitIntervals.isEmpty()) {
schedule.avgWaitIntervals.addAll(waitIntervals);
} else {
// check wait intervals different
for (int j = 0; j < waitIntervals.size(); j++) {
if (Math.abs(schedule.avgWaitIntervals.getQuick(j) - waitIntervals.getQuick(j)) > 3) {
gtfsStats.avgWaitDiff30Sec++;
break;
}
}
}
if (schedule.avgStopIntervals.isEmpty()) {
schedule.avgStopIntervals.addAll(stopIntervals);
} else {
for (int j = 0; j < stopIntervals.size(); j++) {
if (Math.abs(schedule.avgStopIntervals.getQuick(j) - stopIntervals.getQuick(j)) > 3) {
gtfsStats.avgStopDiff30Sec++;
break;
}
}
}
timeDeparturesFirst.add(ftime);
}
nrs.close();
}
}
if (timeDeparturesFirst.size() > 0) {
timeDeparturesFirst.sort();
int p = 0;
for (int i = 0; i < timeDeparturesFirst.size(); i++) {
int x = timeDeparturesFirst.get(i) - p;
// this is a wrong check cause there should be a check for calendar
if (x > 0) {
schedule.tripIntervals.add(x);
p = timeDeparturesFirst.get(i);
}
}
boolean allZeros = true;
for (int i = 0; i < schedule.avgWaitIntervals.size(); i++) {
if (schedule.avgWaitIntervals.getQuick(i) != 0) {
allZeros = false;
break;
}
}
if (allZeros) {
schedule.avgWaitIntervals.clear();
}
return schedule;
}
}
return null;
}
use of net.osmand.data.TransportSchedule in project OsmAnd-tools by osmandapp.
the class IndexTransportCreator method writeBinaryTransportIndex.
public void writeBinaryTransportIndex(BinaryMapIndexWriter writer, String regionName, Connection mapConnection) throws IOException, SQLException {
try {
closePreparedStatements(transRouteStat, transRouteStopsStat, transStopsStat, transRouteGeometryStat);
mapConnection.commit();
transportStopsTree.flush();
// allow gc to collect it
visitedStops = null;
PreparedStatement selectTransportRouteData = mapConnection.prepareStatement(// $NON-NLS-1$
"SELECT id, dist, name, name_en, ref, operator, type, color FROM transport_route");
PreparedStatement selectTransportData = mapConnection.prepareStatement(// $NON-NLS-1$
"SELECT S.stop, " + // $NON-NLS-1$
" A.latitude, A.longitude, A.name, A.name_en, A.names, A.deleted_routes " + // $NON-NLS-1$
"FROM transport_route_stop S INNER JOIN transport_stop A ON A.id = S.stop WHERE S.route = ? ORDER BY S.ord asc");
PreparedStatement selectTransportRouteGeometry = mapConnection.prepareStatement("SELECT S.geometry " + // $NON-NLS-1$
"FROM transport_route_geometry S WHERE S.route = ? order by S.ind");
long transportIndexOffset = writer.startWriteTransportIndex(regionName);
writer.startWriteTransportRoutes();
// expect that memory would be enough
Map<String, Integer> stringTable = createStringTableForTransport();
Map<Long, Long> transportRoutes = new LinkedHashMap<>();
ResultSet rs = selectTransportRouteData.executeQuery();
List<TransportStop> directStops = new ArrayList<>();
List<TransportStop> reverseStops = new ArrayList<>();
List<byte[]> directGeometry = new ArrayList<>();
while (rs.next()) {
long idRoute = rs.getLong(1);
int dist = rs.getInt(2);
String routeName = rs.getString(3);
String routeEnName = rs.getString(4);
if (routeEnName != null && routeEnName.equals(Junidecode.unidecode(routeName))) {
routeEnName = null;
}
String ref = rs.getString(5);
String operator = rs.getString(6);
String type = rs.getString(7);
String color = rs.getString(8);
selectTransportData.setLong(1, idRoute);
ResultSet rset = selectTransportData.executeQuery();
reverseStops.clear();
directStops.clear();
directGeometry.clear();
while (rset.next()) {
long idStop = rset.getLong(1);
String stopName = rset.getString(4);
String stopEnName = rset.getString(5);
Gson gson = new Gson();
String names = rset.getString(6);
Type t = new TypeToken<Map<String, String>>() {
}.getType();
Map<String, String> map = gson.fromJson(names, t);
if (stopEnName != null && stopEnName.equals(Junidecode.unidecode(stopName))) {
stopEnName = null;
}
TransportStop st = new TransportStop();
st.setNames(map);
st.setId(idStop);
st.setName(stopName);
st.setLocation(rset.getDouble(2), rset.getDouble(3));
if (stopEnName != null) {
st.setEnName(stopEnName);
}
directStops.add(st);
}
selectTransportRouteGeometry.setLong(1, idRoute);
rset = selectTransportRouteGeometry.executeQuery();
while (rset.next()) {
byte[] bytes = rset.getBytes(1);
directGeometry.add(bytes);
}
TransportSchedule schedule = readSchedule(ref, directStops);
long ptr = writer.writeTransportRoute(idRoute, routeName, routeEnName, ref, operator, type, dist, color, directStops, directGeometry, stringTable, transportRoutes, schedule, transportRouteTagValues);
if (isRouteIncomplete(idRoute)) {
incompleteRoutesMap.get(idRoute).setFileOffset((int) ptr);
}
}
rs.close();
selectTransportRouteData.close();
selectTransportData.close();
writer.endWriteTransportRoutes();
PreparedStatement selectTransportStop = mapConnection.prepareStatement(// $NON-NLS-1$
"SELECT A.id, A.latitude, A.longitude, A.name, A.name_en, A.names, A.deleted_routes FROM transport_stop A where A.id = ?");
PreparedStatement selectTransportRouteStop = mapConnection.prepareStatement(// $NON-NLS-1$
"SELECT DISTINCT S.route FROM transport_route_stop S join transport_route R on R.id = S.route WHERE S.stop = ? ORDER BY R.type, R.ref ");
long rootIndex = transportStopsTree.getFileHdr().getRootIndex();
rtree.Node root = transportStopsTree.getReadNode(rootIndex);
Rect rootBounds = calcBounds(root);
if (rootBounds != null) {
writer.startTransportTreeElement(rootBounds.getMinX(), rootBounds.getMaxX(), rootBounds.getMinY(), rootBounds.getMaxY());
writeBinaryTransportTree(root, transportStopsTree, writer, selectTransportStop, selectTransportRouteStop, transportRoutes, stringTable);
writer.endWriteTransportTreeElement();
}
selectTransportStop.close();
selectTransportRouteStop.close();
writer.writeIncompleteTransportRoutes(incompleteRoutesMap.valueCollection(), stringTable, transportIndexOffset);
writer.writeTransportStringTable(stringTable);
writer.endWriteTransportIndex();
writer.flush();
log.info(gtfsStats);
} catch (RTreeException e) {
throw new IllegalStateException(e);
}
}
use of net.osmand.data.TransportSchedule in project Osmand by osmandapp.
the class TransportRouteResult method getTravelTime.
public double getTravelTime() {
double t = 0;
for (TransportRoutePlanner.TransportRouteResultSegment s : segments) {
if (cfg.useSchedule) {
TransportSchedule sts = s.route.getSchedule();
for (int k = s.start; k < s.end; k++) {
t += sts.getAvgStopIntervals()[k] * 10;
}
} else {
t += cfg.getBoardingTime();
t += s.getTravelTime();
}
}
return t;
}
use of net.osmand.data.TransportSchedule in project Osmand by osmandapp.
the class TransportRoutePlanner method convertTransportRoute.
private static TransportRoute convertTransportRoute(NativeTransportRoute nr, TLongObjectHashMap<TransportRoute> convertedRoutesCache, TLongObjectHashMap<TransportStop> convertedStopsCache) {
TransportRoute r = new TransportRoute();
r.setId(nr.id);
r.setLocation(nr.routeLat, nr.routeLon);
r.setName(nr.name);
r.setEnName(nr.enName);
if (nr.namesLng.length > 0 && nr.namesLng.length == nr.namesNames.length) {
for (int i = 0; i < nr.namesLng.length; i++) {
r.setName(nr.namesLng[i], nr.namesNames[i]);
}
}
r.setFileOffset(nr.fileOffset);
r.setForwardStops(convertTransportStops(nr.forwardStops, convertedStopsCache));
r.setRef(nr.ref);
r.setOperator(nr.routeOperator);
r.setType(nr.type);
r.setDist(nr.dist);
r.setColor(nr.color);
if (nr.intervals != null && nr.intervals.length > 0 && nr.avgStopIntervals != null && nr.avgStopIntervals.length > 0 && nr.avgWaitIntervals != null && nr.avgWaitIntervals.length > 0) {
r.setSchedule(new TransportSchedule(new TIntArrayList(nr.intervals), new TIntArrayList(nr.avgStopIntervals), new TIntArrayList(nr.avgWaitIntervals)));
}
for (int i = 0; i < nr.waysIds.length; i++) {
List<Node> wnodes = new ArrayList<>();
for (int j = 0; j < nr.waysNodesLats[i].length; j++) {
wnodes.add(new Node(nr.waysNodesLats[i][j], nr.waysNodesLons[i][j], -1));
}
r.addWay(new Way(nr.waysIds[i], wnodes));
}
if (convertedRoutesCache.get(r.getId()) == null) {
convertedRoutesCache.put(r.getId(), r);
}
return r;
}
use of net.osmand.data.TransportSchedule in project Osmand by osmandapp.
the class TransportRoutePlanner method buildRoute.
public List<TransportRouteResult> buildRoute(TransportRoutingContext ctx, LatLon start, LatLon end) throws IOException, InterruptedException {
ctx.startCalcTime = System.currentTimeMillis();
double totalDistance = MapUtils.getDistance(start, end);
List<TransportRouteSegment> startStops = ctx.getTransportStops(start);
List<TransportRouteSegment> endStops = ctx.getTransportStops(end);
TLongObjectHashMap<TransportRouteSegment> endSegments = new TLongObjectHashMap<TransportRouteSegment>();
for (TransportRouteSegment s : endStops) {
endSegments.put(s.getId(), s);
}
if (startStops.size() == 0) {
return Collections.emptyList();
}
PriorityQueue<TransportRouteSegment> queue = new PriorityQueue<TransportRouteSegment>(startStops.size(), new SegmentsComparator(ctx));
for (TransportRouteSegment r : startStops) {
r.walkDist = (float) MapUtils.getDistance(r.getLocation(), start);
r.distFromStart = r.walkDist / ctx.cfg.walkSpeed;
queue.add(r);
}
double finishTime = ctx.cfg.maxRouteTime;
ctx.finishTimeSeconds = ctx.cfg.finishTimeSeconds;
if (totalDistance > ctx.cfg.maxRouteDistance && ctx.cfg.maxRouteIncreaseSpeed > 0) {
int increaseTime = (int) ((totalDistance - ctx.cfg.maxRouteDistance) * 3.6 / ctx.cfg.maxRouteIncreaseSpeed);
finishTime += increaseTime;
ctx.finishTimeSeconds += increaseTime / 6;
}
double maxTravelTimeCmpToWalk = totalDistance / ctx.cfg.walkSpeed - ctx.cfg.changeTime / 2;
List<TransportRouteSegment> results = new ArrayList<TransportRouteSegment>();
initProgressBar(ctx, start, end);
while (!queue.isEmpty()) {
long beginMs = MEASURE_TIME ? System.currentTimeMillis() : 0;
if (ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) {
return null;
}
TransportRouteSegment segment = queue.poll();
TransportRouteSegment ex = ctx.visitedSegments.get(segment.getId());
if (ex != null) {
if (ex.distFromStart > segment.distFromStart) {
System.err.println(String.format("%.1f (%s) > %.1f (%s)", ex.distFromStart, ex, segment.distFromStart, segment));
}
continue;
}
ctx.visitedRoutesCount++;
ctx.visitedSegments.put(segment.getId(), segment);
if (segment.getDepth() > ctx.cfg.maxNumberOfChanges + 1) {
continue;
}
if (segment.distFromStart > finishTime + ctx.finishTimeSeconds || segment.distFromStart > maxTravelTimeCmpToWalk) {
break;
}
long segmentId = segment.getId();
TransportRouteSegment finish = null;
double minDist = 0;
double travelDist = 0;
double travelTime = 0;
final float routeTravelSpeed = ctx.cfg.getSpeedByRouteType(segment.road.getType());
if (routeTravelSpeed == 0) {
continue;
}
TransportStop prevStop = segment.getStop(segment.segStart);
List<TransportRouteSegment> sgms = new ArrayList<TransportRouteSegment>();
for (int ind = 1 + segment.segStart; ind < segment.getLength(); ind++) {
if (ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) {
return null;
}
segmentId++;
ctx.visitedSegments.put(segmentId, segment);
TransportStop stop = segment.getStop(ind);
// could be geometry size
double segmentDist = MapUtils.getDistance(prevStop.getLocation(), stop.getLocation());
travelDist += segmentDist;
if (ctx.cfg.useSchedule) {
TransportSchedule sc = segment.road.getSchedule();
int interval = sc.avgStopIntervals.get(ind - 1);
travelTime += interval * 10;
} else {
travelTime += ctx.cfg.stopTime + segmentDist / routeTravelSpeed;
}
if (segment.distFromStart + travelTime > finishTime + ctx.finishTimeSeconds) {
break;
}
sgms.clear();
sgms = ctx.getTransportStops(stop.x31, stop.y31, true, sgms);
ctx.visitedStops++;
for (TransportRouteSegment sgm : sgms) {
if (ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) {
return null;
}
if (segment.wasVisited(sgm)) {
continue;
}
TransportRouteSegment nextSegment = new TransportRouteSegment(sgm);
nextSegment.parentRoute = segment;
nextSegment.parentStop = ind;
nextSegment.walkDist = MapUtils.getDistance(nextSegment.getLocation(), stop.getLocation());
nextSegment.parentTravelTime = travelTime;
nextSegment.parentTravelDist = travelDist;
double walkTime = nextSegment.walkDist / ctx.cfg.walkSpeed + ctx.cfg.getChangeTime() + ctx.cfg.getBoardingTime();
nextSegment.distFromStart = segment.distFromStart + travelTime + walkTime;
if (ctx.cfg.useSchedule) {
int tm = (sgm.departureTime - ctx.cfg.scheduleTimeOfDay) * 10;
if (tm >= nextSegment.distFromStart) {
nextSegment.distFromStart = tm;
queue.add(nextSegment);
}
} else {
queue.add(nextSegment);
}
}
TransportRouteSegment finalSegment = endSegments.get(segmentId);
double distToEnd = MapUtils.getDistance(stop.getLocation(), end);
if (finalSegment != null && distToEnd < ctx.cfg.walkRadius) {
if (finish == null || minDist > distToEnd) {
minDist = distToEnd;
finish = new TransportRouteSegment(finalSegment);
finish.parentRoute = segment;
finish.parentStop = ind;
finish.walkDist = distToEnd;
finish.parentTravelTime = travelTime;
finish.parentTravelDist = travelDist;
double walkTime = distToEnd / ctx.cfg.walkSpeed;
finish.distFromStart = segment.distFromStart + travelTime + walkTime;
}
}
prevStop = stop;
}
if (finish != null) {
if (finishTime > finish.distFromStart) {
finishTime = finish.distFromStart;
}
if (finish.distFromStart < finishTime + ctx.finishTimeSeconds && (finish.distFromStart < maxTravelTimeCmpToWalk || results.size() == 0)) {
results.add(finish);
}
}
if (ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) {
throw new InterruptedException("Route calculation interrupted");
}
if (MEASURE_TIME) {
long time = System.currentTimeMillis() - beginMs;
if (time > 10) {
System.out.println(String.format("%d ms ref - %s id - %d", time, segment.road.getRef(), segment.road.getId()));
}
}
updateCalculationProgress(ctx, queue);
}
return prepareResults(ctx, results);
}
Aggregations