Merge pull request #759 from afischerdev/roundtrip
New Roundtrip function
This commit is contained in:
commit
063efcc3e1
71
brouter-core/src/main/java/btools/router/AreaInfo.java
Normal file
71
brouter-core/src/main/java/btools/router/AreaInfo.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package btools.router;
|
||||||
|
|
||||||
|
import btools.expressions.BExpressionContext;
|
||||||
|
|
||||||
|
public class AreaInfo {
|
||||||
|
final static int RESULT_TYPE_NONE = 0;
|
||||||
|
final static int RESULT_TYPE_ELEV50 = 1;
|
||||||
|
final static int RESULT_TYPE_GREEN = 4;
|
||||||
|
final static int RESULT_TYPE_RIVER = 5;
|
||||||
|
|
||||||
|
public int direction;
|
||||||
|
public int numForest = -1;
|
||||||
|
public int numRiver = -1;
|
||||||
|
|
||||||
|
public OsmNogoPolygon polygon;
|
||||||
|
|
||||||
|
public int ways = 0;
|
||||||
|
public int greenWays = 0;
|
||||||
|
public int riverWays = 0;
|
||||||
|
public double elevStart = 0;
|
||||||
|
public int elev50 = 0;
|
||||||
|
|
||||||
|
public AreaInfo(int dir) {
|
||||||
|
direction = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkAreaInfo(BExpressionContext expctxWay, double elev, byte[] ab) {
|
||||||
|
ways++;
|
||||||
|
|
||||||
|
double test = elevStart - elev;
|
||||||
|
if (Math.abs(test) < 50) elev50++;
|
||||||
|
|
||||||
|
int[] ld2 = expctxWay.createNewLookupData();
|
||||||
|
expctxWay.decode(ld2, false, ab);
|
||||||
|
|
||||||
|
if (numForest != -1 && ld2[numForest] > 1) {
|
||||||
|
greenWays++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numRiver != -1 && ld2[numRiver] > 1) {
|
||||||
|
riverWays++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getElev50Weight() {
|
||||||
|
if (ways == 0) return 0;
|
||||||
|
return (int) (elev50 * 100. / ways);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGreen() {
|
||||||
|
if (ways == 0) return 0;
|
||||||
|
return (int) (greenWays * 100. / ways);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRiver() {
|
||||||
|
if (ways == 0) return 0;
|
||||||
|
return (int) (riverWays * 100. / ways);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Area ").append(direction).append(" ").append(elevStart).append("m ways ").append(ways);
|
||||||
|
if (ways > 0) {
|
||||||
|
sb.append("\nArea ways <50m ").append(elev50).append(" ").append(getElev50Weight()).append("%");
|
||||||
|
sb.append("\nArea ways green ").append(greenWays).append(" ").append(getGreen()).append("%");
|
||||||
|
sb.append("\nArea ways river ").append(riverWays).append(" ").append(getRiver()).append("%");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
270
brouter-core/src/main/java/btools/router/AreaReader.java
Normal file
270
brouter-core/src/main/java/btools/router/AreaReader.java
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
package btools.router;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import btools.codec.DataBuffers;
|
||||||
|
import btools.codec.MicroCache;
|
||||||
|
import btools.expressions.BExpressionContextWay;
|
||||||
|
import btools.mapaccess.MatchedWaypoint;
|
||||||
|
import btools.mapaccess.NodesCache;
|
||||||
|
import btools.mapaccess.OsmFile;
|
||||||
|
import btools.mapaccess.OsmLink;
|
||||||
|
import btools.mapaccess.OsmNode;
|
||||||
|
import btools.mapaccess.OsmNodesMap;
|
||||||
|
import btools.mapaccess.PhysicalFile;
|
||||||
|
|
||||||
|
public class AreaReader {
|
||||||
|
|
||||||
|
File segmentFolder;
|
||||||
|
|
||||||
|
public void getDirectAllData(File folder, RoutingContext rc, OsmNodeNamed wp, int maxscale, BExpressionContextWay expctxWay, OsmNogoPolygon searchRect, List<AreaInfo> ais) {
|
||||||
|
this.segmentFolder = folder;
|
||||||
|
|
||||||
|
int div = 32;
|
||||||
|
int cellsize = 1000000 / div;
|
||||||
|
int scale = maxscale;
|
||||||
|
int count = 0;
|
||||||
|
int used = 0;
|
||||||
|
boolean checkBorder = maxscale > 7;
|
||||||
|
|
||||||
|
Map<Long, String> tiles = new TreeMap<>();
|
||||||
|
for (int idxLat = -scale; idxLat <= scale; idxLat++) {
|
||||||
|
for (int idxLon = -scale; idxLon <= scale; idxLon++) {
|
||||||
|
if (ignoreCenter(maxscale, idxLon, idxLat)) continue;
|
||||||
|
int tmplon = wp.ilon + cellsize * idxLon;
|
||||||
|
int tmplat = wp.ilat + cellsize * idxLat;
|
||||||
|
int lonDegree = tmplon / 1000000;
|
||||||
|
int latDegree = tmplat / 1000000;
|
||||||
|
int lonMod5 = (int) lonDegree % 5;
|
||||||
|
int latMod5 = (int) latDegree % 5;
|
||||||
|
|
||||||
|
int lon = (int) lonDegree - 180 - lonMod5;
|
||||||
|
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
||||||
|
int lat = (int) latDegree - 90 - latMod5;
|
||||||
|
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
|
||||||
|
String filenameBase = slon + "_" + slat;
|
||||||
|
|
||||||
|
int lonIdx = tmplon / cellsize;
|
||||||
|
int latIdx = tmplat / cellsize;
|
||||||
|
int subIdx = (latIdx - div * latDegree) * div + (lonIdx - div * lonDegree);
|
||||||
|
|
||||||
|
int subLonIdx = (lonIdx - div * lonDegree);
|
||||||
|
int subLatIdx = (latIdx - div * latDegree);
|
||||||
|
|
||||||
|
OsmNogoPolygon dataRect = new OsmNogoPolygon(true);
|
||||||
|
lon = lonDegree * 1000000;
|
||||||
|
lat = latDegree * 1000000;
|
||||||
|
int tmplon2 = lon + cellsize * (subLonIdx);
|
||||||
|
int tmplat2 = lat + cellsize * (subLatIdx);
|
||||||
|
dataRect.addVertex(tmplon2, tmplat2);
|
||||||
|
|
||||||
|
tmplon2 = lon + cellsize * (subLonIdx + 1);
|
||||||
|
tmplat2 = lat + cellsize * (subLatIdx);
|
||||||
|
dataRect.addVertex(tmplon2, tmplat2);
|
||||||
|
|
||||||
|
tmplon2 = lon + cellsize * (subLonIdx + 1);
|
||||||
|
tmplat2 = lat + cellsize * (subLatIdx + 1);
|
||||||
|
dataRect.addVertex(tmplon2, tmplat2);
|
||||||
|
|
||||||
|
tmplon2 = lon + cellsize * (subLonIdx);
|
||||||
|
tmplat2 = lat + cellsize * (subLatIdx + 1);
|
||||||
|
dataRect.addVertex(tmplon2, tmplat2);
|
||||||
|
|
||||||
|
boolean intersects = checkBorder && dataRect.intersects(searchRect.points.get(0).x, searchRect.points.get(0).y, searchRect.points.get(2).x, searchRect.points.get(2).y);
|
||||||
|
if (!intersects && checkBorder)
|
||||||
|
intersects = dataRect.intersects(searchRect.points.get(1).x, searchRect.points.get(1).y, searchRect.points.get(2).x, searchRect.points.get(3).y);
|
||||||
|
if (intersects) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
intersects = searchRect.intersects(dataRect.points.get(0).x, dataRect.points.get(0).y, dataRect.points.get(2).x, dataRect.points.get(2).y);
|
||||||
|
if (!intersects)
|
||||||
|
intersects = searchRect.intersects(dataRect.points.get(1).x, dataRect.points.get(1).y, dataRect.points.get(3).x, dataRect.points.get(3).y);
|
||||||
|
if (!intersects)
|
||||||
|
intersects = containsRect(searchRect, dataRect.points.get(0).x, dataRect.points.get(0).y, dataRect.points.get(2).x, dataRect.points.get(2).y);
|
||||||
|
|
||||||
|
if (!intersects) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tiles.put(((long) tmplon) << 32 | tmplat, filenameBase);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map.Entry<Long, String>> list = new ArrayList<>(tiles.entrySet());
|
||||||
|
Collections.sort(list, new Comparator<>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Map.Entry<Long, String> e1, Map.Entry<Long, String> e2) {
|
||||||
|
return e1.getValue().compareTo(e2.getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
long maxmem = rc.memoryclass * 1024L * 1024L; // in MB
|
||||||
|
NodesCache nodesCache = new NodesCache(segmentFolder, expctxWay, rc.forceSecondaryData, maxmem, null, false);
|
||||||
|
PhysicalFile pf = null;
|
||||||
|
String lastFilenameBase = "";
|
||||||
|
DataBuffers dataBuffers = null;
|
||||||
|
try {
|
||||||
|
for (Map.Entry<Long, String> entry : list) {
|
||||||
|
OsmNode n = new OsmNode(entry.getKey());
|
||||||
|
// System.out.println("areareader set " + n.getILon() + "_" + n.getILat() + " " + entry.getValue());
|
||||||
|
String filenameBase = entry.getValue();
|
||||||
|
if (!filenameBase.equals(lastFilenameBase)) {
|
||||||
|
if (pf != null) pf.close();
|
||||||
|
lastFilenameBase = filenameBase;
|
||||||
|
File file = new File(segmentFolder, filenameBase + ".rd5");
|
||||||
|
dataBuffers = new DataBuffers();
|
||||||
|
|
||||||
|
pf = new PhysicalFile(file, dataBuffers, -1, -1);
|
||||||
|
}
|
||||||
|
if (getDirectData(pf, dataBuffers, n.getILon(), n.getILat(), rc, expctxWay, ais))
|
||||||
|
used++;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("AreaReader: after " + used + "/" + count + " " + e.getMessage());
|
||||||
|
ais.clear();
|
||||||
|
} finally {
|
||||||
|
if (pf != null)
|
||||||
|
try {
|
||||||
|
pf.close();
|
||||||
|
} catch (Exception ee) {
|
||||||
|
}
|
||||||
|
nodesCache.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDirectData(PhysicalFile pf, DataBuffers dataBuffers, int inlon, int inlat, RoutingContext rc, BExpressionContextWay expctxWay, List<AreaInfo> ais) {
|
||||||
|
|
||||||
|
int lonDegree = inlon / 1000000;
|
||||||
|
int latDegree = inlat / 1000000;
|
||||||
|
|
||||||
|
OsmNodesMap nodesMap = new OsmNodesMap();
|
||||||
|
|
||||||
|
try {
|
||||||
|
int div = pf.divisor;
|
||||||
|
|
||||||
|
OsmFile osmf = new OsmFile(pf, lonDegree, latDegree, dataBuffers);
|
||||||
|
if (osmf.hasData()) {
|
||||||
|
int cellsize = 1000000 / div;
|
||||||
|
int tmplon = inlon;
|
||||||
|
int tmplat = inlat;
|
||||||
|
int lonIdx = tmplon / cellsize;
|
||||||
|
int latIdx = tmplat / cellsize;
|
||||||
|
|
||||||
|
MicroCache segment = osmf.createMicroCache(lonIdx, latIdx, dataBuffers, expctxWay, null, true, null);
|
||||||
|
|
||||||
|
if (segment != null) {
|
||||||
|
int size = segment.getSize();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
long id = segment.getIdForIndex(i);
|
||||||
|
OsmNode node = new OsmNode(id);
|
||||||
|
if (segment.getAndClear(id)) {
|
||||||
|
node.parseNodeBody(segment, nodesMap, expctxWay);
|
||||||
|
if (node.firstlink instanceof OsmLink) {
|
||||||
|
for (OsmLink link = node.firstlink; link != null; link = link.getNext(node)) {
|
||||||
|
OsmNode nextNode = link.getTarget(node);
|
||||||
|
if (nextNode.firstlink == null)
|
||||||
|
continue; // don't care about dead ends
|
||||||
|
if (nextNode.firstlink.descriptionBitmap == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (AreaInfo ai : ais) {
|
||||||
|
if (ai.polygon.isWithin(node.ilon, node.ilat)) {
|
||||||
|
ai.checkAreaInfo(expctxWay, node.getElev(), nextNode.firstlink.descriptionBitmap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("AreaReader: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean ignoreCenter(int maxscale, int idxLon, int idxLat) {
|
||||||
|
int centerScale = (int) Math.round(maxscale * .2) - 1;
|
||||||
|
if (centerScale < 0) return false;
|
||||||
|
return idxLon >= -centerScale && idxLon <= centerScale &&
|
||||||
|
idxLat >= -centerScale && idxLat <= centerScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
in this case the polygon is 'only' a rectangle
|
||||||
|
*/
|
||||||
|
boolean containsRect(OsmNogoPolygon searchRect, int p1x, int p1y, int p2x, int p2y) {
|
||||||
|
return searchRect.isWithin((long) p1x, (long) p1y) &&
|
||||||
|
searchRect.isWithin(p2x, p2y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeAreaInfo(String filename, MatchedWaypoint wp, List<AreaInfo> ais) throws Exception {
|
||||||
|
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
|
||||||
|
|
||||||
|
wp.writeToStream(dos);
|
||||||
|
for (AreaInfo ai : ais) {
|
||||||
|
dos.writeInt(ai.direction);
|
||||||
|
dos.writeDouble(ai.elevStart);
|
||||||
|
dos.writeInt(ai.ways);
|
||||||
|
dos.writeInt(ai.greenWays);
|
||||||
|
dos.writeInt(ai.riverWays);
|
||||||
|
dos.writeInt(ai.elev50);
|
||||||
|
}
|
||||||
|
dos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readAreaInfo(File fai, MatchedWaypoint wp, List<AreaInfo> ais) {
|
||||||
|
DataInputStream dis = null;
|
||||||
|
MatchedWaypoint ep = null;
|
||||||
|
try {
|
||||||
|
dis = new DataInputStream(new BufferedInputStream(new FileInputStream(fai)));
|
||||||
|
ep = MatchedWaypoint.readFromStream(dis);
|
||||||
|
if (Math.abs(ep.waypoint.ilon - wp.waypoint.ilon) > 500 &&
|
||||||
|
Math.abs(ep.waypoint.ilat - wp.waypoint.ilat) > 500) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Math.abs(ep.radius - wp.radius) > 500) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
int direction = dis.readInt();
|
||||||
|
AreaInfo ai = new AreaInfo(direction);
|
||||||
|
ai.elevStart = dis.readDouble();
|
||||||
|
ai.ways = dis.readInt();
|
||||||
|
ai.greenWays = dis.readInt();
|
||||||
|
ai.riverWays = dis.readInt();
|
||||||
|
ai.elev50 = dis.readInt();
|
||||||
|
ais.add(ai);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
ais.clear();
|
||||||
|
} finally {
|
||||||
|
if (dis != null) {
|
||||||
|
try {
|
||||||
|
dis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -141,6 +141,10 @@ abstract class OsmPath implements OsmLinkHolder {
|
|||||||
// evaluate the way tags
|
// evaluate the way tags
|
||||||
rc.expctxWay.evaluate(rc.inverseDirection ^ isReverse, description);
|
rc.expctxWay.evaluate(rc.inverseDirection ^ isReverse, description);
|
||||||
|
|
||||||
|
// and check if is useful
|
||||||
|
if (rc.ai != null && rc.ai.polygon.isWithin(lon1, lat1)) {
|
||||||
|
rc.ai.checkAreaInfo(rc.expctxWay, ele1/4., description);
|
||||||
|
}
|
||||||
|
|
||||||
// calculate the costfactor inputs
|
// calculate the costfactor inputs
|
||||||
float costfactor = rc.expctxWay.getCostfactor();
|
float costfactor = rc.expctxWay.getCostfactor();
|
||||||
|
|||||||
@ -36,6 +36,7 @@ public final class RoutingContext {
|
|||||||
public Map<String, String> keyValues;
|
public Map<String, String> keyValues;
|
||||||
|
|
||||||
public String rawTrackPath;
|
public String rawTrackPath;
|
||||||
|
public String rawAreaPath;
|
||||||
|
|
||||||
public String getProfileName() {
|
public String getProfileName() {
|
||||||
String name = localFunction == null ? "unknown" : localFunction;
|
String name = localFunction == null ? "unknown" : localFunction;
|
||||||
@ -79,6 +80,8 @@ public final class RoutingContext {
|
|||||||
public boolean useDynamicDistance;
|
public boolean useDynamicDistance;
|
||||||
public boolean buildBeelineOnRange;
|
public boolean buildBeelineOnRange;
|
||||||
|
|
||||||
|
public AreaInfo ai;
|
||||||
|
|
||||||
private void setModel(String className) {
|
private void setModel(String className) {
|
||||||
if (className == null) {
|
if (className == null) {
|
||||||
pm = new StdModel();
|
pm = new StdModel();
|
||||||
@ -193,6 +196,10 @@ public final class RoutingContext {
|
|||||||
public Integer startDirection;
|
public Integer startDirection;
|
||||||
public boolean startDirectionValid;
|
public boolean startDirectionValid;
|
||||||
public boolean forceUseStartDirection;
|
public boolean forceUseStartDirection;
|
||||||
|
public Integer roundTripDistance;
|
||||||
|
public Integer roundTripDirectionAdd;
|
||||||
|
public Integer roundTripPoints;
|
||||||
|
public boolean allowSamewayback;
|
||||||
|
|
||||||
public CheapAngleMeter anglemeter = new CheapAngleMeter();
|
public CheapAngleMeter anglemeter = new CheapAngleMeter();
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import java.io.PrintWriter;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -21,6 +23,7 @@ import btools.mapaccess.OsmLinkHolder;
|
|||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
import btools.mapaccess.OsmNodePairSet;
|
import btools.mapaccess.OsmNodePairSet;
|
||||||
import btools.mapaccess.OsmPos;
|
import btools.mapaccess.OsmPos;
|
||||||
|
import btools.util.CheapRuler;
|
||||||
import btools.util.CompactLongMap;
|
import btools.util.CompactLongMap;
|
||||||
import btools.util.SortedHeap;
|
import btools.util.SortedHeap;
|
||||||
import btools.util.StackSampler;
|
import btools.util.StackSampler;
|
||||||
@ -31,6 +34,7 @@ public class RoutingEngine extends Thread {
|
|||||||
public final static int BROUTER_ENGINEMODE_SEED = 1;
|
public final static int BROUTER_ENGINEMODE_SEED = 1;
|
||||||
public final static int BROUTER_ENGINEMODE_GETELEV = 2;
|
public final static int BROUTER_ENGINEMODE_GETELEV = 2;
|
||||||
public final static int BROUTER_ENGINEMODE_GETINFO = 3;
|
public final static int BROUTER_ENGINEMODE_GETINFO = 3;
|
||||||
|
public final static int BROUTER_ENGINEMODE_ROUNDTRIP = 4;
|
||||||
|
|
||||||
private NodesCache nodesCache;
|
private NodesCache nodesCache;
|
||||||
private SortedHeap<OsmPath> openSet = new SortedHeap<>();
|
private SortedHeap<OsmPath> openSet = new SortedHeap<>();
|
||||||
@ -48,7 +52,9 @@ public class RoutingEngine extends Thread {
|
|||||||
|
|
||||||
private int engineMode = 0;
|
private int engineMode = 0;
|
||||||
|
|
||||||
private int MAX_STEPS_CHECK = 10;
|
private int MAX_STEPS_CHECK = 500;
|
||||||
|
|
||||||
|
private int ROUNDTRIP_DEFAULT_DIRECTIONADD = 45;
|
||||||
|
|
||||||
private int MAX_DYNAMIC_RANGE = 60000;
|
private int MAX_DYNAMIC_RANGE = 60000;
|
||||||
|
|
||||||
@ -178,6 +184,11 @@ public class RoutingEngine extends Thread {
|
|||||||
}
|
}
|
||||||
doGetInfo();
|
doGetInfo();
|
||||||
break;
|
break;
|
||||||
|
case BROUTER_ENGINEMODE_ROUNDTRIP:
|
||||||
|
if (waypoints.size() < 1)
|
||||||
|
throw new IllegalArgumentException("we need one lat/lon point at least!");
|
||||||
|
doRoundTrip();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("not a valid engine mode");
|
throw new IllegalArgumentException("not a valid engine mode");
|
||||||
}
|
}
|
||||||
@ -189,6 +200,26 @@ public class RoutingEngine extends Thread {
|
|||||||
startTime = System.currentTimeMillis();
|
startTime = System.currentTimeMillis();
|
||||||
long startTime0 = startTime;
|
long startTime0 = startTime;
|
||||||
this.maxRunningTime = maxRunningTime;
|
this.maxRunningTime = maxRunningTime;
|
||||||
|
|
||||||
|
if (routingContext.allowSamewayback) {
|
||||||
|
if (waypoints.size() == 2) {
|
||||||
|
OsmNodeNamed onn = new OsmNodeNamed(new OsmNode(waypoints.get(0).ilon, waypoints.get(0).ilat));
|
||||||
|
onn.name = "to";
|
||||||
|
waypoints.add(onn);
|
||||||
|
} else {
|
||||||
|
waypoints.get(waypoints.size() - 1).name = "via" + (waypoints.size() - 1) + "_center";
|
||||||
|
List<OsmNodeNamed> newpoints = new ArrayList<>();
|
||||||
|
for (int i = waypoints.size() - 2; i >= 0; i--) {
|
||||||
|
// System.out.println("back " + waypoints.get(i));
|
||||||
|
OsmNodeNamed onn = new OsmNodeNamed(new OsmNode(waypoints.get(i).ilon, waypoints.get(i).ilat));
|
||||||
|
onn.name = "via";
|
||||||
|
newpoints.add(onn);
|
||||||
|
}
|
||||||
|
newpoints.get(newpoints.size() - 1).name = "to";
|
||||||
|
waypoints.addAll(newpoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int nsections = waypoints.size() - 1;
|
int nsections = waypoints.size() - 1;
|
||||||
OsmTrack[] refTracks = new OsmTrack[nsections]; // used ways for alternatives
|
OsmTrack[] refTracks = new OsmTrack[nsections]; // used ways for alternatives
|
||||||
OsmTrack[] lastTracks = new OsmTrack[nsections];
|
OsmTrack[] lastTracks = new OsmTrack[nsections];
|
||||||
@ -196,6 +227,10 @@ public class RoutingEngine extends Thread {
|
|||||||
List<String> messageList = new ArrayList<>();
|
List<String> messageList = new ArrayList<>();
|
||||||
for (int i = 0; ; i++) {
|
for (int i = 0; ; i++) {
|
||||||
track = findTrack(refTracks, lastTracks);
|
track = findTrack(refTracks, lastTracks);
|
||||||
|
|
||||||
|
// we are only looking for info
|
||||||
|
if (routingContext.ai != null) return;
|
||||||
|
|
||||||
track.message = "track-length = " + track.distance + " filtered ascend = " + track.ascend
|
track.message = "track-length = " + track.distance + " filtered ascend = " + track.ascend
|
||||||
+ " plain-ascend = " + track.plainAscend + " cost=" + track.cost;
|
+ " plain-ascend = " + track.plainAscend + " cost=" + track.cost;
|
||||||
if (track.energy != 0) {
|
if (track.energy != 0) {
|
||||||
@ -447,6 +482,215 @@ public class RoutingEngine extends Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void doRoundTrip() {
|
||||||
|
try {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
routingContext.useDynamicDistance = true;
|
||||||
|
double searchRadius = (routingContext.roundTripDistance == null ? 1500 :routingContext.roundTripDistance);
|
||||||
|
double direction = (routingContext.startDirection == null ? -1 :routingContext.startDirection);
|
||||||
|
double directionAdd = (routingContext.roundTripDirectionAdd == null ? ROUNDTRIP_DEFAULT_DIRECTIONADD :routingContext.roundTripDirectionAdd);
|
||||||
|
if (direction == -1) direction = getRandomDirectionFromData(waypoints.get(0), searchRadius);
|
||||||
|
|
||||||
|
if (routingContext.allowSamewayback) {
|
||||||
|
int[] pos = CheapRuler.destination(waypoints.get(0).ilon, waypoints.get(0).ilat, searchRadius, direction);
|
||||||
|
MatchedWaypoint wpt2 = new MatchedWaypoint();
|
||||||
|
wpt2.waypoint = new OsmNode(pos[0], pos[1]);
|
||||||
|
wpt2.name = "rt1_" + direction;
|
||||||
|
|
||||||
|
OsmNodeNamed onn = new OsmNodeNamed(new OsmNode(pos[0], pos[1]));
|
||||||
|
onn.name = "rt1";
|
||||||
|
waypoints.add(onn);
|
||||||
|
} else {
|
||||||
|
buildPointsFromCircle(waypoints, direction, searchRadius, routingContext.roundTripPoints == null ? 5 : routingContext.roundTripPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
routingContext.waypointCatchingRange = 250;
|
||||||
|
|
||||||
|
doRouting(0);
|
||||||
|
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
logInfo("round trip execution time = " + (endTime - startTime) / 1000. + " seconds");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.getStackTrace();
|
||||||
|
logException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void buildPointsFromCircle(List<OsmNodeNamed> waypoints, double startAngle, double searchRadius, int points) {
|
||||||
|
//startAngle -= 90;
|
||||||
|
for (int i = 1; i < points; i++) {
|
||||||
|
double anAngle = 90 - (180.0 * i / points);
|
||||||
|
int[] pos = CheapRuler.destination(waypoints.get(0).ilon, waypoints.get(0).ilat, searchRadius, startAngle - anAngle);
|
||||||
|
OsmNodeNamed onn = new OsmNodeNamed(new OsmNode(pos[0], pos[1]));
|
||||||
|
onn.name = "rt" + i;
|
||||||
|
waypoints.add(onn);
|
||||||
|
}
|
||||||
|
|
||||||
|
OsmNodeNamed onn = new OsmNodeNamed(waypoints.get(0));
|
||||||
|
onn.name = "to_rt";
|
||||||
|
waypoints.add(onn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getRandomDirectionFromData(OsmNodeNamed wp, double searchRadius) {
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
int preferredRandomType = 0;
|
||||||
|
boolean consider_elevation = routingContext.expctxWay.getVariableValue("consider_elevation", 0f) == 1f;
|
||||||
|
boolean consider_forest = routingContext.expctxWay.getVariableValue("consider_forest", 0f) == 1f;
|
||||||
|
boolean consider_river = routingContext.expctxWay.getVariableValue("consider_river", 0f) == 1f;
|
||||||
|
if (consider_elevation) {
|
||||||
|
preferredRandomType = AreaInfo.RESULT_TYPE_ELEV50;
|
||||||
|
} else if (consider_forest) {
|
||||||
|
preferredRandomType = AreaInfo.RESULT_TYPE_GREEN;
|
||||||
|
} else if (consider_river) {
|
||||||
|
preferredRandomType = AreaInfo.RESULT_TYPE_RIVER;
|
||||||
|
} else {
|
||||||
|
return (int) (Math.random()*360);
|
||||||
|
}
|
||||||
|
|
||||||
|
MatchedWaypoint wpt1 = new MatchedWaypoint();
|
||||||
|
wpt1.waypoint = wp;
|
||||||
|
wpt1.name = "info";
|
||||||
|
wpt1.radius = searchRadius * 1.5;
|
||||||
|
|
||||||
|
List<AreaInfo> ais = new ArrayList<>();
|
||||||
|
AreaReader areareader = new AreaReader();
|
||||||
|
if (routingContext.rawAreaPath != null) {
|
||||||
|
File fai = new File(routingContext.rawAreaPath);
|
||||||
|
if (fai.exists()) {
|
||||||
|
areareader.readAreaInfo(fai, wpt1, ais);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ais.isEmpty()) {
|
||||||
|
List<MatchedWaypoint> listStart = new ArrayList<>();
|
||||||
|
listStart.add(wpt1);
|
||||||
|
|
||||||
|
List<OsmNodeNamed> wpliststart = new ArrayList<>();
|
||||||
|
wpliststart.add(wp);
|
||||||
|
|
||||||
|
List<OsmNodeNamed> listOne = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int a = 45; a < 360; a += 90) {
|
||||||
|
int[] pos = CheapRuler.destination(wp.ilon, wp.ilat, searchRadius * 1.5, a);
|
||||||
|
OsmNodeNamed onn = new OsmNodeNamed(new OsmNode(pos[0], pos[1]));
|
||||||
|
onn.name = "via" + a;
|
||||||
|
listOne.add(onn);
|
||||||
|
|
||||||
|
MatchedWaypoint wpt = new MatchedWaypoint();
|
||||||
|
wpt.waypoint = onn;
|
||||||
|
wpt.name = onn.name;
|
||||||
|
listStart.add(wpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoutingEngine re = null;
|
||||||
|
RoutingContext rc = new RoutingContext();
|
||||||
|
String name = routingContext.localFunction;
|
||||||
|
int idx = name.lastIndexOf(File.separator);
|
||||||
|
rc.localFunction = idx == -1 ? "dummy" : name.substring(0, idx + 1) + "dummy.brf";
|
||||||
|
|
||||||
|
re = new RoutingEngine(null, null, segmentDir, wpliststart, rc, BROUTER_ENGINEMODE_ROUNDTRIP);
|
||||||
|
rc.useDynamicDistance = true;
|
||||||
|
re.matchWaypointsToNodes(listStart);
|
||||||
|
re.resetCache(true);
|
||||||
|
|
||||||
|
int numForest = rc.expctxWay.getLookupKey("estimated_forest_class");
|
||||||
|
int numRiver = rc.expctxWay.getLookupKey("estimated_river_class");
|
||||||
|
|
||||||
|
OsmNode start1 = re.nodesCache.getStartNode(listStart.get(0).node1.getIdFromPos());
|
||||||
|
|
||||||
|
double elev = (start1 == null ? 0 : start1.getElev()); // listOne.get(0).crosspoint.getElev();
|
||||||
|
|
||||||
|
int maxlon = Integer.MIN_VALUE;
|
||||||
|
int minlon = Integer.MAX_VALUE;
|
||||||
|
int maxlat = Integer.MIN_VALUE;
|
||||||
|
int minlat = Integer.MAX_VALUE;
|
||||||
|
for (OsmNodeNamed on : listOne) {
|
||||||
|
maxlon = Math.max(on.ilon, maxlon);
|
||||||
|
minlon = Math.min(on.ilon, minlon);
|
||||||
|
maxlat = Math.max(on.ilat, maxlat);
|
||||||
|
minlat = Math.min(on.ilat, minlat);
|
||||||
|
}
|
||||||
|
OsmNogoPolygon searchRect = new OsmNogoPolygon(true);
|
||||||
|
searchRect.addVertex(maxlon, maxlat);
|
||||||
|
searchRect.addVertex(maxlon, minlat);
|
||||||
|
searchRect.addVertex(minlon, minlat);
|
||||||
|
searchRect.addVertex(minlon, maxlat);
|
||||||
|
|
||||||
|
for (int a = 0; a < 4; a++) {
|
||||||
|
rc.ai = new AreaInfo(a * 90 + 90);
|
||||||
|
rc.ai.elevStart = elev;
|
||||||
|
rc.ai.numForest = numForest;
|
||||||
|
rc.ai.numRiver = numRiver;
|
||||||
|
|
||||||
|
rc.ai.polygon = new OsmNogoPolygon(true);
|
||||||
|
rc.ai.polygon.addVertex(wp.ilon, wp.ilat);
|
||||||
|
rc.ai.polygon.addVertex(listOne.get(a).ilon, listOne.get(a).ilat);
|
||||||
|
if (a == 3)
|
||||||
|
rc.ai.polygon.addVertex(listOne.get(0).ilon, listOne.get(0).ilat);
|
||||||
|
else
|
||||||
|
rc.ai.polygon.addVertex(listOne.get(a + 1).ilon, listOne.get(a + 1).ilat);
|
||||||
|
|
||||||
|
ais.add(rc.ai);
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxscale = Math.abs(searchRect.points.get(2).x - searchRect.points.get(0).x);
|
||||||
|
maxscale = Math.max(1, Math.round(maxscale / 31250f / 2) + 1);
|
||||||
|
|
||||||
|
areareader.getDirectAllData(segmentDir, rc, wp, maxscale, rc.expctxWay, searchRect, ais);
|
||||||
|
|
||||||
|
if (routingContext.rawAreaPath != null) {
|
||||||
|
try {
|
||||||
|
wpt1.radius = searchRadius * 1.5;
|
||||||
|
areareader.writeAreaInfo(routingContext.rawAreaPath, wpt1, ais);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc.ai = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
logInfo("round trip execution time = " + (System.currentTimeMillis() - start) / 1000. + " seconds");
|
||||||
|
|
||||||
|
// for (AreaInfo ai: ais) {
|
||||||
|
// System.out.println("\n" + ai.toString());
|
||||||
|
//}
|
||||||
|
|
||||||
|
switch (preferredRandomType) {
|
||||||
|
case AreaInfo.RESULT_TYPE_ELEV50:
|
||||||
|
Collections.sort(ais, new Comparator<>() {
|
||||||
|
public int compare(AreaInfo o1, AreaInfo o2) {
|
||||||
|
return o2.getElev50Weight() - o1.getElev50Weight();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case AreaInfo.RESULT_TYPE_GREEN:
|
||||||
|
Collections.sort(ais, new Comparator<>() {
|
||||||
|
public int compare(AreaInfo o1, AreaInfo o2) {
|
||||||
|
return o2.getGreen() - o1.getGreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case AreaInfo.RESULT_TYPE_RIVER:
|
||||||
|
Collections.sort(ais, new Comparator<>() {
|
||||||
|
public int compare(AreaInfo o1, AreaInfo o2) {
|
||||||
|
return o2.getRiver() - o1.getRiver();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (int) (Math.random()*360);
|
||||||
|
}
|
||||||
|
|
||||||
|
int angle = ais.get(0).direction;
|
||||||
|
return angle - 30 + (int) (Math.random() * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void postElevationCheck(OsmTrack track) {
|
private void postElevationCheck(OsmTrack track) {
|
||||||
OsmPathElement lastPt = null;
|
OsmPathElement lastPt = null;
|
||||||
OsmPathElement startPt = null;
|
OsmPathElement startPt = null;
|
||||||
@ -694,7 +938,8 @@ public class RoutingEngine extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (MatchedWaypoint mwp : matchedWaypoints) {
|
for (MatchedWaypoint mwp : matchedWaypoints) {
|
||||||
if (hasInfo() && matchedWaypoints.size() != nUnmatched) logInfo("new wp=" + mwp.waypoint + " " + mwp.crosspoint + (mwp.direct ? " direct" : ""));
|
if (hasInfo() && matchedWaypoints.size() != nUnmatched)
|
||||||
|
logInfo("new wp=" + mwp.waypoint + " " + mwp.crosspoint + (mwp.direct ? " direct" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
routingContext.checkMatchedWaypointAgainstNogos(matchedWaypoints);
|
routingContext.checkMatchedWaypointAgainstNogos(matchedWaypoints);
|
||||||
@ -750,12 +995,26 @@ public class RoutingEngine extends Thread {
|
|||||||
} else {
|
} else {
|
||||||
seg = searchTrack(matchedWaypoints.get(i), matchedWaypoints.get(i + 1), i == matchedWaypoints.size() - 2 ? nearbyTrack : null, refTracks[i]);
|
seg = searchTrack(matchedWaypoints.get(i), matchedWaypoints.get(i + 1), i == matchedWaypoints.size() - 2 ? nearbyTrack : null, refTracks[i]);
|
||||||
wptIndex = i;
|
wptIndex = i;
|
||||||
|
if (engineMode == BROUTER_ENGINEMODE_ROUNDTRIP) {
|
||||||
|
if (i < matchedWaypoints.size() - 2) {
|
||||||
|
OsmNode lastPoint = seg.containsNode(matchedWaypoints.get(i+1).node1) ? matchedWaypoints.get(i+1).node1 : matchedWaypoints.get(i+1).node2;
|
||||||
|
OsmNodeNamed nogo = new OsmNodeNamed(lastPoint);
|
||||||
|
nogo.radius = 5;
|
||||||
|
nogo.name = "nogo" + (i+1);
|
||||||
|
nogo.nogoWeight = 9999.;
|
||||||
|
nogo.isNogo = true;
|
||||||
|
if (routingContext.nogopoints == null) routingContext.nogopoints = new ArrayList<>();
|
||||||
|
routingContext.nogopoints.add(nogo);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (seg == null)
|
if (seg == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (routingContext.ai != null) return null;
|
||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
if (routingContext.correctMisplacedViaPoints && !matchedWaypoints.get(i).direct) {
|
if (routingContext.correctMisplacedViaPoints && !matchedWaypoints.get(i).direct && !routingContext.allowSamewayback) {
|
||||||
changed = snappPathConnection(totaltrack, seg, routingContext.inverseRouting ? matchedWaypoints.get(i + 1) : matchedWaypoints.get(i));
|
changed = snappPathConnection(totaltrack, seg, routingContext.inverseRouting ? matchedWaypoints.get(i + 1) : matchedWaypoints.get(i));
|
||||||
}
|
}
|
||||||
if (wptIndex > 0)
|
if (wptIndex > 0)
|
||||||
@ -785,7 +1044,7 @@ public class RoutingEngine extends Thread {
|
|||||||
|
|
||||||
// check for way back on way point
|
// check for way back on way point
|
||||||
private boolean snappPathConnection(OsmTrack tt, OsmTrack t, MatchedWaypoint startWp) {
|
private boolean snappPathConnection(OsmTrack tt, OsmTrack t, MatchedWaypoint startWp) {
|
||||||
if (!startWp.name.startsWith("via"))
|
if (!startWp.name.startsWith("via") && !startWp.name.startsWith("rt"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int ourSize = tt.nodes.size();
|
int ourSize = tt.nodes.size();
|
||||||
@ -876,16 +1135,12 @@ public class RoutingEngine extends Thread {
|
|||||||
}
|
}
|
||||||
indexback--;
|
indexback--;
|
||||||
indexfore++;
|
indexfore++;
|
||||||
}
|
|
||||||
|
|
||||||
if (routingContext.correctMisplacedViaPointsDistance > 0 &&
|
if (routingContext.correctMisplacedViaPointsDistance > 0 &&
|
||||||
wayDistance > routingContext.correctMisplacedViaPointsDistance) {
|
wayDistance > routingContext.correctMisplacedViaPointsDistance) break;
|
||||||
removeVoiceHintList.clear();
|
|
||||||
removeBackList.clear();
|
|
||||||
removeForeList.clear();
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// time hold
|
// time hold
|
||||||
float atime = 0;
|
float atime = 0;
|
||||||
float aenergy = 0;
|
float aenergy = 0;
|
||||||
@ -1111,6 +1366,7 @@ public class RoutingEngine extends Thread {
|
|||||||
for (int i = 0; i < unmatchedWaypoints.size(); i++) {
|
for (int i = 0; i < unmatchedWaypoints.size(); i++) {
|
||||||
MatchedWaypoint wp = unmatchedWaypoints.get(i);
|
MatchedWaypoint wp = unmatchedWaypoints.get(i);
|
||||||
if (wp.waypoint.calcDistance(wp.crosspoint) > routingContext.waypointCatchingRange) {
|
if (wp.waypoint.calcDistance(wp.crosspoint) > routingContext.waypointCatchingRange) {
|
||||||
|
|
||||||
MatchedWaypoint nmw = new MatchedWaypoint();
|
MatchedWaypoint nmw = new MatchedWaypoint();
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
OsmNodeNamed onn = new OsmNodeNamed(wp.waypoint);
|
OsmNodeNamed onn = new OsmNodeNamed(wp.waypoint);
|
||||||
@ -1153,7 +1409,6 @@ public class RoutingEngine extends Thread {
|
|||||||
}
|
}
|
||||||
wp.crosspoint = new OsmNode(wp.waypoint.ilon, wp.waypoint.ilat);
|
wp.crosspoint = new OsmNode(wp.waypoint.ilon, wp.waypoint.ilat);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
waypoints.add(wp);
|
waypoints.add(wp);
|
||||||
}
|
}
|
||||||
@ -1161,6 +1416,7 @@ public class RoutingEngine extends Thread {
|
|||||||
unmatchedWaypoints.clear();
|
unmatchedWaypoints.clear();
|
||||||
unmatchedWaypoints.addAll(waypoints);
|
unmatchedWaypoints.addAll(waypoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private OsmTrack searchTrack(MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack) {
|
private OsmTrack searchTrack(MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack) {
|
||||||
@ -1222,6 +1478,7 @@ public class RoutingEngine extends Thread {
|
|||||||
OsmTrack t;
|
OsmTrack t;
|
||||||
try {
|
try {
|
||||||
t = findTrack(cfi == 0 ? "pass0" : "pass1", startWp, endWp, track, refTrack, false);
|
t = findTrack(cfi == 0 ? "pass0" : "pass1", startWp, endWp, track, refTrack, false);
|
||||||
|
if (routingContext.ai != null) return t;
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
if (!terminated && matchPath != null) { // timeout, but eventually prepare a dirty ref track
|
if (!terminated && matchPath != null) { // timeout, but eventually prepare a dirty ref track
|
||||||
logInfo("supplying dirty reference track after timeout");
|
logInfo("supplying dirty reference track after timeout");
|
||||||
|
|||||||
@ -202,6 +202,17 @@ public class RoutingParamCollector {
|
|||||||
rctx.forceUseStartDirection = true;
|
rctx.forceUseStartDirection = true;
|
||||||
} else if (key.equals("direction")) {
|
} else if (key.equals("direction")) {
|
||||||
rctx.startDirection = Integer.valueOf(value);
|
rctx.startDirection = Integer.valueOf(value);
|
||||||
|
} else if (key.equals("roundTripDistance")) {
|
||||||
|
rctx.roundTripDistance = Integer.valueOf(value);
|
||||||
|
} else if (key.equals("roundTripDirectionAdd")) {
|
||||||
|
rctx.roundTripDirectionAdd = Integer.valueOf(value);
|
||||||
|
} else if (key.equals("roundTripPoints")) {
|
||||||
|
rctx.roundTripPoints = Integer.valueOf(value);
|
||||||
|
if (rctx.roundTripPoints == null || rctx.roundTripPoints < 3 || rctx.roundTripPoints > 20) {
|
||||||
|
rctx.roundTripPoints = 5;
|
||||||
|
}
|
||||||
|
} else if (key.equals("allowSamewayback")) {
|
||||||
|
rctx.allowSamewayback = Integer.parseInt(value)==1;
|
||||||
} else if (key.equals("alternativeidx")) {
|
} else if (key.equals("alternativeidx")) {
|
||||||
rctx.setAlternativeIdx(Integer.parseInt(value));
|
rctx.setAlternativeIdx(Integer.parseInt(value));
|
||||||
} else if (key.equals("turnInstructionMode")) {
|
} else if (key.equals("turnInstructionMode")) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package btools.router;
|
package btools.router;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -110,4 +111,22 @@ public class OsmNodeNamedTest {
|
|||||||
0.1 * 5
|
0.1 * 5
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDestination() {
|
||||||
|
// Segment ends
|
||||||
|
int lon1, lat1, lon2, lat2;
|
||||||
|
// Circle definition
|
||||||
|
OsmNodeNamed node = new OsmNodeNamed();
|
||||||
|
// Center
|
||||||
|
node.ilon = toOsmLon(0);
|
||||||
|
node.ilat = toOsmLat(0);
|
||||||
|
double startDist = 1000;
|
||||||
|
|
||||||
|
for (int i = 0; i <= 360; i += 45) {
|
||||||
|
int[] pos = CheapRuler.destination(node.ilon, node.ilat, startDist, i);
|
||||||
|
double dist = CheapRuler.distance(node.ilon, node.ilat, pos[0], pos[1]);
|
||||||
|
assertTrue("pos " + pos[0] + " " + pos[1] + " distance (" + dist + ") should be around (" + startDist + ")", dist -1 < startDist && dist +1 > startDist);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import btools.codec.WaypointMatcher;
|
|||||||
import btools.util.ByteDataReader;
|
import btools.util.ByteDataReader;
|
||||||
import btools.util.Crc32;
|
import btools.util.Crc32;
|
||||||
|
|
||||||
final class OsmFile {
|
final public class OsmFile {
|
||||||
private RandomAccessFile is = null;
|
private RandomAccessFile is = null;
|
||||||
private long fileOffset;
|
private long fileOffset;
|
||||||
|
|
||||||
|
|||||||
@ -143,4 +143,14 @@ final public class PhysicalFile {
|
|||||||
elevationType = dis.readByte();
|
elevationType = dis.readByte();
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close(){
|
||||||
|
if (ra != null) {
|
||||||
|
try {
|
||||||
|
ra.close();
|
||||||
|
} catch (Exception ee) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,7 +64,8 @@ public class BRouterService extends Service {
|
|||||||
worker.segmentDir = new File(baseDir, "brouter/segments4");
|
worker.segmentDir = new File(baseDir, "brouter/segments4");
|
||||||
String errMsg = null;
|
String errMsg = null;
|
||||||
|
|
||||||
if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUTING) {
|
if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUTING ||
|
||||||
|
engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUNDTRIP) {
|
||||||
String remoteProfile = params.getString("remoteProfile", null);
|
String remoteProfile = params.getString("remoteProfile", null);
|
||||||
|
|
||||||
if (remoteProfile == null) {
|
if (remoteProfile == null) {
|
||||||
|
|||||||
@ -46,6 +46,7 @@ public class BRouterWorker {
|
|||||||
|
|
||||||
RoutingContext rc = new RoutingContext();
|
RoutingContext rc = new RoutingContext();
|
||||||
rc.rawTrackPath = rawTrackPath;
|
rc.rawTrackPath = rawTrackPath;
|
||||||
|
rc.rawAreaPath = (rawTrackPath != null ? rawTrackPath.substring(0, rawTrackPath.lastIndexOf(File.separator)+1) + "rawAreaInfo.dat" : null);
|
||||||
rc.localFunction = profilePath;
|
rc.localFunction = profilePath;
|
||||||
|
|
||||||
RoutingParamCollector routingParamCollector = new RoutingParamCollector();
|
RoutingParamCollector routingParamCollector = new RoutingParamCollector();
|
||||||
@ -136,7 +137,8 @@ public class BRouterWorker {
|
|||||||
cr.quite = true;
|
cr.quite = true;
|
||||||
cr.doRun(maxRunningTime);
|
cr.doRun(maxRunningTime);
|
||||||
|
|
||||||
if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUTING) {
|
if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUTING ||
|
||||||
|
engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUNDTRIP) {
|
||||||
// store new reference track if any
|
// store new reference track if any
|
||||||
// (can exist for timed-out search)
|
// (can exist for timed-out search)
|
||||||
if (cr.getFoundRawTrack() != null) {
|
if (cr.getFoundRawTrack() != null) {
|
||||||
|
|||||||
@ -222,7 +222,8 @@ public class RouteServer extends Thread implements Comparable<RouteServer> {
|
|||||||
}
|
}
|
||||||
String headers = encodings == null || encodings.indexOf("gzip") < 0 ? null : "Content-Encoding: gzip\n";
|
String headers = encodings == null || encodings.indexOf("gzip") < 0 ? null : "Content-Encoding: gzip\n";
|
||||||
writeHttpHeader(bw, handler.getMimeType(), handler.getFileName(), headers, HTTP_STATUS_OK);
|
writeHttpHeader(bw, handler.getMimeType(), handler.getFileName(), headers, HTTP_STATUS_OK);
|
||||||
if (engineMode == 0) {
|
if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUTING ||
|
||||||
|
engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUNDTRIP) {
|
||||||
if (track != null) {
|
if (track != null) {
|
||||||
if (headers != null) { // compressed
|
if (headers != null) { // compressed
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
@ -235,7 +236,8 @@ public class RouteServer extends Thread implements Comparable<RouteServer> {
|
|||||||
bw.write(handler.formatTrack(track));
|
bw.write(handler.formatTrack(track));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (engineMode == 2) {
|
} else if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_GETELEV ||
|
||||||
|
engineMode == RoutingEngine.BROUTER_ENGINEMODE_GETINFO) {
|
||||||
String s = cr.getFoundInfo();
|
String s = cr.getFoundInfo();
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
bw.write(s);
|
bw.write(s);
|
||||||
|
|||||||
@ -77,4 +77,21 @@ public final class CheapRuler {
|
|||||||
double dlat = (ilat1 - ilat2) * kxky[1];
|
double dlat = (ilat1 - ilat2) * kxky[1];
|
||||||
return Math.sqrt(dlat * dlat + dlon * dlon); // in m
|
return Math.sqrt(dlat * dlat + dlon * dlon); // in m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int[] destination(int lon1, int lat1, double distance, double angle) {
|
||||||
|
|
||||||
|
double[] lonlat2m = getLonLatToMeterScales(lat1);
|
||||||
|
double lon2m = lonlat2m[0];
|
||||||
|
double lat2m = lonlat2m[1];
|
||||||
|
angle = 90. - angle;
|
||||||
|
double st = Math.sin(angle * Math.PI / 180.);
|
||||||
|
double ct = Math.cos(angle * Math.PI / 180.);
|
||||||
|
|
||||||
|
int lon2 = (int) (0.5 + lon1 + ct * distance / lon2m);
|
||||||
|
int lat2 = (int) (0.5 + lat1 + st * distance / lat2m);
|
||||||
|
int[] ret = new int[2];
|
||||||
|
ret[0] = lon2;
|
||||||
|
ret[1] = lat2;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user