254 lines
9.2 KiB
Java
254 lines
9.2 KiB
Java
package net.osmand.router;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
|
|
import net.osmand.PlatformUtil;
|
|
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
|
|
import net.osmand.util.Algorithms;
|
|
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
public class RoutingConfiguration {
|
|
|
|
public static final int DEFAULT_MEMORY_LIMIT = 30;
|
|
public final float DEVIATION_RADIUS = 5000;
|
|
public Map<String, String> attributes = new LinkedHashMap<String, String>();
|
|
|
|
// 1. parameters of routing and different tweaks
|
|
// Influence on A* : f(x) + heuristicCoefficient*g(X)
|
|
public float heuristicCoefficient = 1;
|
|
|
|
// 1.1 tile load parameters (should not affect routing)
|
|
public int ZOOM_TO_LOAD_TILES = 16;
|
|
public int memoryLimitation;
|
|
|
|
// 1.2 Build A* graph in backward/forward direction (can affect results)
|
|
// 0 - 2 ways, 1 - direct way, -1 - reverse way
|
|
public int planRoadDirection = 0;
|
|
|
|
// 1.3 Router specific coefficients and restrictions
|
|
public VehicleRouter router = new GeneralRouter(GeneralRouterProfile.CAR, new LinkedHashMap<String, String>());
|
|
public String routerName = "";
|
|
|
|
// 1.4 Used to calculate route in movement
|
|
public Double initialDirection;
|
|
|
|
// 1.5 Recalculate distance help
|
|
public float recalculateDistance = 10000f;
|
|
|
|
|
|
|
|
public static class Builder {
|
|
// Design time storage
|
|
private String defaultRouter = "";
|
|
private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>();
|
|
private Map<String, String> attributes = new LinkedHashMap<String, String>();
|
|
|
|
public RoutingConfiguration build(String router, int memoryLimitMB) {
|
|
return build(router, null, memoryLimitMB, new String[0]);
|
|
}
|
|
|
|
public RoutingConfiguration build(String router, int memoryLimitMB, String[] specialization) {
|
|
return build(router, null, memoryLimitMB, specialization);
|
|
}
|
|
public RoutingConfiguration build(String router, Double direction, int memoryLimitMB, String[] specialization) {
|
|
if (!routers.containsKey(router)) {
|
|
router = defaultRouter;
|
|
}
|
|
RoutingConfiguration i = new RoutingConfiguration();
|
|
if (routers.containsKey(router)) {
|
|
i.router = routers.get(router);
|
|
if (specialization != null) {
|
|
for (String s : specialization) {
|
|
i.router = i.router.specifyParameter(s);
|
|
}
|
|
}
|
|
i.routerName = router;
|
|
}
|
|
attributes.put("routerName", router);
|
|
i.attributes.putAll(attributes);
|
|
i.initialDirection = direction;
|
|
i.recalculateDistance = parseSilentFloat(getAttribute(i.router, "recalculateDistanceHelp"), i.recalculateDistance) ;
|
|
i.heuristicCoefficient = parseSilentFloat(getAttribute(i.router, "heuristicCoefficient"), i.heuristicCoefficient);
|
|
i.ZOOM_TO_LOAD_TILES = parseSilentInt(getAttribute(i.router, "zoomToLoadTiles"), i.ZOOM_TO_LOAD_TILES);
|
|
int desirable = parseSilentInt(getAttribute(i.router, "memoryLimitInMB"), 0);
|
|
if(desirable != 0) {
|
|
i.memoryLimitation = desirable * (1 << 20);
|
|
} else {
|
|
if(memoryLimitMB == 0) {
|
|
memoryLimitMB = DEFAULT_MEMORY_LIMIT;
|
|
}
|
|
i.memoryLimitation = memoryLimitMB * (1 << 20);
|
|
}
|
|
i.planRoadDirection = parseSilentInt(getAttribute(i.router, "planRoadDirection"), i.planRoadDirection);
|
|
|
|
return i;
|
|
}
|
|
|
|
private String getAttribute(VehicleRouter router, String propertyName) {
|
|
String attr = router.getAttribute(propertyName);
|
|
if (attr != null) {
|
|
return attr;
|
|
}
|
|
return attributes.get(propertyName);
|
|
}
|
|
|
|
}
|
|
|
|
private static int parseSilentInt(String t, int v) {
|
|
if (t == null || t.length() == 0) {
|
|
return v;
|
|
}
|
|
return Integer.parseInt(t);
|
|
}
|
|
|
|
|
|
private static float parseSilentFloat(String t, float v) {
|
|
if (t == null || t.length() == 0) {
|
|
return v;
|
|
}
|
|
return Float.parseFloat(t);
|
|
}
|
|
|
|
|
|
private static RoutingConfiguration.Builder DEFAULT;
|
|
|
|
public static RoutingConfiguration.Builder getDefault() {
|
|
if (DEFAULT == null) {
|
|
InputStream resourceAsStream = null;
|
|
try {
|
|
resourceAsStream = RoutingConfiguration.class.getResourceAsStream("routing.xml");
|
|
DEFAULT = parseFromInputStream(resourceAsStream);
|
|
} catch (Exception e) {
|
|
throw new IllegalStateException(e);
|
|
} finally {
|
|
if (resourceAsStream != null) {
|
|
try {
|
|
resourceAsStream.close();
|
|
} catch (IOException ignore) {
|
|
//
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return DEFAULT;
|
|
}
|
|
|
|
public static RoutingConfiguration.Builder parseFromInputStream(InputStream is) throws IOException, XmlPullParserException {
|
|
XmlPullParser parser = PlatformUtil.newXMLPullParser();
|
|
final RoutingConfiguration.Builder config = new RoutingConfiguration.Builder();
|
|
GeneralRouter currentRouter = null;
|
|
String previousKey = null;
|
|
String previousTag = null;
|
|
int tok;
|
|
parser.setInput(is, "UTF-8");
|
|
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
|
|
if (tok == XmlPullParser.START_TAG) {
|
|
String name = parser.getName();
|
|
if ("osmand_routing_config".equals(name)) {
|
|
config.defaultRouter = parser.getAttributeValue("", "defaultProfile");
|
|
} else if ("routingProfile".equals(name)) {
|
|
currentRouter = parseRoutingProfile(parser, config);
|
|
} else if ("attribute".equals(name)) {
|
|
parseAttribute(parser, config, currentRouter);
|
|
previousKey = parser.getAttributeValue("", "name");
|
|
previousTag = name;
|
|
} else if ("specialization".equals(name)) {
|
|
parseSpecialization(parser, currentRouter, previousKey, previousTag);
|
|
} else {
|
|
previousKey = parser.getAttributeValue("", "tag") + "$" + parser.getAttributeValue("", "value");
|
|
previousTag = name;
|
|
if (parseCurrentRule(parser, currentRouter, previousKey, name)) {
|
|
|
|
} else {
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return config;
|
|
}
|
|
|
|
private static boolean parseCurrentRule(XmlPullParser parser, GeneralRouter currentRouter, String key, String name) {
|
|
if ("road".equals(name)) {
|
|
currentRouter.highwayPriorities.put(key, parseSilentFloat(parser.getAttributeValue("", "priority"), 1));
|
|
currentRouter.highwaySpeed.put(key, parseSilentFloat(parser.getAttributeValue("", "speed"), 10));
|
|
return true;
|
|
} else if ("obstacle".equals(name)) {
|
|
float penalty = parseSilentFloat(parser.getAttributeValue("", "penalty"), 0);
|
|
currentRouter.obstacles.put(key, penalty);
|
|
float routingPenalty = parseSilentFloat(parser.getAttributeValue("", "routingPenalty"), penalty);
|
|
currentRouter.routingObstacles.put(key, routingPenalty);
|
|
return true;
|
|
} else if ("avoid".equals(name)) {
|
|
float priority = parseSilentFloat(parser.getAttributeValue("", "decreasedPriority"), 0);
|
|
if (priority == 0) {
|
|
currentRouter.avoid.put(key, priority);
|
|
} else {
|
|
currentRouter.highwayPriorities.put(key, priority);
|
|
}
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static void parseSpecialization(XmlPullParser parser, GeneralRouter currentRouter, String previousKey, String previousTag) {
|
|
String in = parser.getAttributeValue("","input");
|
|
if (previousKey != null) {
|
|
String k = in + ":" + previousKey;
|
|
if (parser.getAttributeValue("","penalty") != null) {
|
|
float penalty = parseSilentFloat(parser.getAttributeValue("","penalty"), 0);
|
|
currentRouter.obstacles.put(k, penalty);
|
|
float routingPenalty = parseSilentFloat(parser.getAttributeValue("","routingPenalty"), penalty );
|
|
currentRouter.routingObstacles.put(k, routingPenalty);
|
|
}
|
|
if (parser.getAttributeValue("","priority") != null) {
|
|
currentRouter.highwayPriorities.put(k, parseSilentFloat(parser.getAttributeValue("","priority"), 0));
|
|
}
|
|
if (parser.getAttributeValue("","speed") != null) {
|
|
currentRouter.highwaySpeed.put(k, parseSilentFloat(parser.getAttributeValue("","speed"), 0));
|
|
}
|
|
if ("attribute".equals(previousTag)) {
|
|
currentRouter.attributes.put(k, parser.getAttributeValue("","value"));
|
|
}
|
|
if ("avoid".equals(previousTag)) {
|
|
float priority = parseSilentFloat(parser.getAttributeValue("","decreasedPriority"), 0);
|
|
if (priority == 0) {
|
|
currentRouter.avoid.put(k, priority);
|
|
} else {
|
|
currentRouter.highwayPriorities.put(k, priority);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config) {
|
|
GeneralRouter currentRouter;
|
|
String currentSelectedRouter = parser.getAttributeValue("", "name");
|
|
Map<String, String> attrs = new LinkedHashMap<String, String>();
|
|
for(int i=0; i< parser.getAttributeCount(); i++) {
|
|
attrs.put(parser.getAttributeName(i), parser.getAttributeValue(i));
|
|
}
|
|
GeneralRouterProfile c = Algorithms.parseEnumValue(GeneralRouterProfile.values(),
|
|
parser.getAttributeValue("", "baseProfile"), GeneralRouterProfile.CAR);
|
|
currentRouter = new GeneralRouter(c, attrs);
|
|
config.routers.put(currentSelectedRouter, currentRouter);
|
|
return currentRouter;
|
|
}
|
|
|
|
private static void parseAttribute(XmlPullParser parser, final RoutingConfiguration.Builder config, GeneralRouter currentRouter) {
|
|
if(currentRouter != null) {
|
|
currentRouter.addAttribute(parser.getAttributeValue("", "name"),
|
|
parser.getAttributeValue("", "value"));
|
|
} else {
|
|
config.attributes.put(parser.getAttributeValue("", "name"),
|
|
parser.getAttributeValue("", "value"));
|
|
}
|
|
}
|
|
|
|
}
|