OsmAnd/OsmAnd-java/src/net/osmand/router/RoutingConfiguration.java
2014-02-01 22:32:06 +01:00

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"));
}
}
}