new surrounding check'

This commit is contained in:
afischerdev 2025-03-12 10:09:57 +01:00
parent 1040780c2d
commit 6a8863510d
4 changed files with 314 additions and 9 deletions

View File

@ -0,0 +1,161 @@
package btools.router;
import java.io.File;
import java.util.List;
import btools.codec.DataBuffers;
import btools.codec.MicroCache;
import btools.expressions.BExpressionContextWay;
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 cellsize = 1000000 / 32;
int scale = maxscale;
int count = 0;
int used = 0;
for (int idxLat = -scale; idxLat <= scale; idxLat++) {
for (int idxLon = -scale; idxLon <= scale; idxLon++) {
int tmplon = wp.ilon + cellsize * idxLon;
int tmplat = wp.ilat + cellsize * idxLat;
if (getDirectData(tmplon, tmplat, rc, expctxWay, searchRect, ais)) used++;
count++;
}
}
}
public boolean getDirectData(int inlon, int inlat, RoutingContext rc, BExpressionContextWay expctxWay, OsmNogoPolygon searchRect, List<AreaInfo> ais) {
int lonDegree = inlon / 1000000;
int latDegree = inlat / 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;
lon = 180000000 + (int) (lon * 1000000 + 0.5);
lat = 90000000 + (int) (lat * 1000000 + 0.5);
String filenameBase = slon + "_" + slat;
File file = new File(segmentFolder, filenameBase + ".rd5");
PhysicalFile pf = null;
long maxmem = rc.memoryclass * 1024L * 1024L; // in MB
NodesCache nodesCache = new NodesCache(segmentFolder, expctxWay, rc.forceSecondaryData, maxmem, null, false);
OsmNodesMap nodesMap = new OsmNodesMap();
try {
DataBuffers dataBuffers = new DataBuffers();
pf = new PhysicalFile(file, dataBuffers, -1, -1);
int div = pf.divisor;
OsmFile osmf = new OsmFile(pf, lonDegree, latDegree, dataBuffers);
if (osmf.hasData()) {
int cellsize = 1000000 / div;
int tmplon = inlon; // + cellsize * idxLon;
int tmplat = inlat; // + cellsize * idxLat;
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 = 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) {
return false;
}
MicroCache segment = osmf.createMicroCache(lonIdx, latIdx, dataBuffers, expctxWay, null, true, null);
if (segment != null /*&& segment.getDataSize()>0*/) {
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) {
e.printStackTrace();
} finally {
if (pf != null)
try {
pf.close();
} catch (Exception ee) {
}
nodesCache.close();
nodesCache = null;
}
return false;
}
/*
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);
}
}

View File

@ -485,15 +485,13 @@ public class RoutingEngine extends Thread {
public void doRoundTrip() { public void doRoundTrip() {
try { try {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
MatchedWaypoint wpt1 = new MatchedWaypoint();
wpt1.waypoint = waypoints.get(0);
wpt1.name = "roundtrip";
routingContext.useDynamicDistance = true; routingContext.useDynamicDistance = true;
double searchRadius = (routingContext.roundTripDistance == null ? 1500 :routingContext.roundTripDistance); double searchRadius = (routingContext.roundTripDistance == null ? 1500 :routingContext.roundTripDistance);
double direction = (routingContext.startDirection == null ? -1 :routingContext.startDirection); double direction = (routingContext.startDirection == null ? -1 :routingContext.startDirection);
double directionAdd = (routingContext.roundTripDirectionAdd == null ? ROUNDTRIP_DEFAULT_DIRECTIONADD :routingContext.roundTripDirectionAdd); double directionAdd = (routingContext.roundTripDirectionAdd == null ? ROUNDTRIP_DEFAULT_DIRECTIONADD :routingContext.roundTripDirectionAdd);
if (direction == -1) direction = getRandomDirectionByRouting(waypoints.get(0), searchRadius); //if (direction == -1) direction = getRandomDirectionFromRouting(waypoints.get(0), searchRadius);
if (direction == -1) direction = getRandomDirectionFromData(waypoints.get(0), searchRadius);
if (routingContext.allowSamewayback) { if (routingContext.allowSamewayback) {
int[] pos = CheapRuler.destination(waypoints.get(0).ilon, waypoints.get(0).ilat, searchRadius, direction); int[] pos = CheapRuler.destination(waypoints.get(0).ilon, waypoints.get(0).ilat, searchRadius, direction);
@ -565,7 +563,141 @@ public class RoutingEngine extends Thread {
waypoints.add(onn); waypoints.add(onn);
} }
int getRandomDirectionByRouting(OsmNodeNamed wp, double searchRadius) { 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 = "start_info";
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();
rc.localFunction = "dummy";
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();
List<AreaInfo> ais = new ArrayList<>();
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);
new AreaReader().getDirectAllData(segmentDir, rc, wp, maxscale, rc.expctxWay, searchRect, ais);
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);
}
rc.ai = null;
int angle = ais.get(0).direction;
return angle - 45 + (int) (Math.random()*90);
}
int getRandomDirectionFromRouting(OsmNodeNamed wp, double searchRadius) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@ -698,6 +830,8 @@ public class RoutingEngine extends Thread {
return angle - 45 + (int) (Math.random()*90); return angle - 45 + (int) (Math.random()*90);
} }
private void postElevationCheck(OsmTrack track) { private void postElevationCheck(OsmTrack track) {
OsmPathElement lastPt = null; OsmPathElement lastPt = null;
OsmPathElement startPt = null; OsmPathElement startPt = null;

View File

@ -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;

View File

@ -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) {
}
}
}
} }