![JAR search and dependency download from the Maven repository](/logo.png)
com.graphhopper.routing.util.CarFlagEncoder Maven / Gradle / Ivy
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.routing.util;
import com.graphhopper.reader.OSMRelation;
import com.graphhopper.reader.OSMWay;
import com.graphhopper.reader.osm.conditional.ConditionalTagsInspector;
import com.graphhopper.reader.osm.conditional.DateRangeParser;
import com.graphhopper.util.Helper;
import com.graphhopper.util.PMap;
import java.util.*;
/**
* Defines bit layout for cars. (speed, access, ferries, ...)
*
* @author Peter Karich
* @author Nop
*/
public class CarFlagEncoder extends AbstractFlagEncoder
{
protected final Map trackTypeSpeedMap = new HashMap();
protected final Set badSurfaceSpeedMap = new HashSet();
/**
* A map which associates string to speed. Get some impression:
* http://www.itoworld.com/map/124#fullscreen
* http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing/Maxspeed
*/
protected final Map defaultSpeedMap = new HashMap();
public CarFlagEncoder()
{
this(5, 5, 0);
}
public CarFlagEncoder( PMap properties )
{
this((int) properties.getLong("speed_bits", 5),
properties.getDouble("speed_factor", 5),
properties.getBool("turn_costs", false) ? 1 : 0);
this.properties = properties;
this.setBlockFords(properties.getBool("block_fords", true));
}
public CarFlagEncoder( String propertiesStr )
{
this(new PMap(propertiesStr));
}
public CarFlagEncoder( int speedBits, double speedFactor, int maxTurnCosts )
{
super(speedBits, speedFactor, maxTurnCosts);
restrictions.addAll(Arrays.asList("motorcar", "motor_vehicle", "vehicle", "access"));
restrictedValues.add("private");
restrictedValues.add("agricultural");
restrictedValues.add("forestry");
restrictedValues.add("no");
restrictedValues.add("restricted");
restrictedValues.add("delivery");
restrictedValues.add("military");
restrictedValues.add("emergency");
intendedValues.add("yes");
intendedValues.add("permissive");
potentialBarriers.add("gate");
potentialBarriers.add("lift_gate");
potentialBarriers.add("kissing_gate");
potentialBarriers.add("swing_gate");
absoluteBarriers.add("bollard");
absoluteBarriers.add("stile");
absoluteBarriers.add("turnstile");
absoluteBarriers.add("cycle_barrier");
absoluteBarriers.add("motorcycle_barrier");
absoluteBarriers.add("block");
absoluteBarriers.add("bus_trap");
absoluteBarriers.add("sump_buster");
trackTypeSpeedMap.put("grade1", 20); // paved
trackTypeSpeedMap.put("grade2", 15); // now unpaved - gravel mixed with ...
trackTypeSpeedMap.put("grade3", 10); // ... hard and soft materials
trackTypeSpeedMap.put("grade4", 5); // ... some hard or compressed materials
trackTypeSpeedMap.put("grade5", 5); // ... no hard materials. soil/sand/grass
badSurfaceSpeedMap.add("cobblestone");
badSurfaceSpeedMap.add("grass_paver");
badSurfaceSpeedMap.add("gravel");
badSurfaceSpeedMap.add("sand");
badSurfaceSpeedMap.add("paving_stones");
badSurfaceSpeedMap.add("dirt");
badSurfaceSpeedMap.add("ground");
badSurfaceSpeedMap.add("grass");
maxPossibleSpeed = 140;
// autobahn
defaultSpeedMap.put("motorway", 100);
defaultSpeedMap.put("motorway_link", 70);
defaultSpeedMap.put("motorroad", 90);
// bundesstraße
defaultSpeedMap.put("trunk", 70);
defaultSpeedMap.put("trunk_link", 65);
// linking bigger town
defaultSpeedMap.put("primary", 65);
defaultSpeedMap.put("primary_link", 60);
// linking towns + villages
defaultSpeedMap.put("secondary", 60);
defaultSpeedMap.put("secondary_link", 50);
// streets without middle line separation
defaultSpeedMap.put("tertiary", 50);
defaultSpeedMap.put("tertiary_link", 40);
defaultSpeedMap.put("unclassified", 30);
defaultSpeedMap.put("residential", 30);
// spielstraße
defaultSpeedMap.put("living_street", 5);
defaultSpeedMap.put("service", 20);
// unknown road
defaultSpeedMap.put("road", 20);
// forestry stuff
defaultSpeedMap.put("track", 15);
conditionalTagsInspector = new ConditionalTagsInspector(DateRangeParser.createCalendar(), restrictions, restrictedValues, intendedValues);
}
@Override
public int getVersion()
{
return 1;
}
/**
* Define the place of the speedBits in the edge flags for car.
*/
@Override
public int defineWayBits( int index, int shift )
{
// first two bits are reserved for route handling in superclass
shift = super.defineWayBits(index, shift);
speedEncoder = new EncodedDoubleValue("Speed", shift, speedBits, speedFactor, defaultSpeedMap.get("secondary"),
maxPossibleSpeed);
return shift + speedEncoder.getBits();
}
protected double getSpeed( OSMWay way )
{
String highwayValue = way.getTag("highway");
Integer speed = defaultSpeedMap.get(highwayValue);
if (speed == null)
throw new IllegalStateException(toString() + ", no speed found for: " + highwayValue + ", tags: " + way);
if (highwayValue.equals("track"))
{
String tt = way.getTag("tracktype");
if (!Helper.isEmpty(tt))
{
Integer tInt = trackTypeSpeedMap.get(tt);
if (tInt != null)
speed = tInt;
}
}
return speed;
}
@Override
public long acceptWay( OSMWay way )
{
// TODO: Ferries have conditionals, like opening hours or are closed during some time in the year
String highwayValue = way.getTag("highway");
if (highwayValue == null)
{
if (way.hasTag("route", ferries))
{
String motorcarTag = way.getTag("motorcar");
if (motorcarTag == null)
motorcarTag = way.getTag("motor_vehicle");
if (motorcarTag == null && !way.hasTag("foot") && !way.hasTag("bicycle") || "yes".equals(motorcarTag))
return acceptBit | ferryBit;
}
return 0;
}
if ("track".equals(highwayValue))
{
String tt = way.getTag("tracktype");
if (tt != null && !tt.equals("grade1") && !tt.equals("grade2") && !tt.equals("grade3"))
return 0;
}
if (!defaultSpeedMap.containsKey(highwayValue))
return 0;
if (way.hasTag("impassable", "yes") || way.hasTag("status", "impassable"))
return 0;
// multiple restrictions needs special handling compared to foot and bike, see also motorcycle
String firstValue = way.getFirstPriorityTag(restrictions);
if (!firstValue.isEmpty())
{
if (restrictedValues.contains(firstValue) && !conditionalTagsInspector.isRestrictedWayConditionallyPermitted(way))
return 0;
if (intendedValues.contains(firstValue))
return acceptBit;
}
// do not drive street cars into fords
if (isBlockFords() && ("ford".equals(highwayValue) || way.hasTag("ford")))
return 0;
if (conditionalTagsInspector.isPermittedWayConditionallyRestricted(way))
return 0;
else
return acceptBit;
}
@Override
public long handleRelationTags( OSMRelation relation, long oldRelationFlags )
{
return oldRelationFlags;
}
@Override
public long handleWayTags( OSMWay way, long allowed, long relationFlags )
{
if (!isAccept(allowed))
return 0;
long flags = 0;
if (!isFerry(allowed))
{
// get assumed speed from highway type
double speed = getSpeed(way);
speed = applyMaxSpeed(way, speed);
// limit speed to max 30 km/h if bad surface
if (speed > 30 && way.hasTag("surface", badSurfaceSpeedMap))
speed = 30;
flags = setSpeed(flags, speed);
boolean isRoundabout = way.hasTag("junction", "roundabout");
if (isRoundabout)
flags = setBool(flags, K_ROUNDABOUT, true);
if (isOneway(way) || isRoundabout)
{
if (isBackwardOneway(way))
flags |= backwardBit;
if (isForwardOneway(way))
flags |= forwardBit;
} else
flags |= directionBitMask;
} else
{
double ferrySpeed = getFerrySpeed(way, defaultSpeedMap.get("living_street"), defaultSpeedMap.get("service"), defaultSpeedMap.get("residential"));
flags = setSpeed(flags, ferrySpeed);
flags |= directionBitMask;
}
return flags;
}
/**
* make sure that isOneway is called before
*/
protected boolean isBackwardOneway( OSMWay way )
{
return way.hasTag("oneway", "-1")
|| way.hasTag("vehicle:forward", "no")
|| way.hasTag("motor_vehicle:forward", "no");
}
/**
* make sure that isOneway is called before
*/
protected boolean isForwardOneway( OSMWay way )
{
return !way.hasTag("oneway", "-1")
&& !way.hasTag("vehicle:forward", "no")
&& !way.hasTag("motor_vehicle:forward", "no");
}
protected boolean isOneway( OSMWay way )
{
return way.hasTag("oneway", oneways)
|| way.hasTag("vehicle:backward")
|| way.hasTag("vehicle:forward")
|| way.hasTag("motor_vehicle:backward")
|| way.hasTag("motor_vehicle:forward");
}
public String getWayInfo( OSMWay way )
{
String str = "";
String highwayValue = way.getTag("highway");
// for now only motorway links
if ("motorway_link".equals(highwayValue))
{
String destination = way.getTag("destination");
if (!Helper.isEmpty(destination))
{
int counter = 0;
for (String d : destination.split(";"))
{
if (d.trim().isEmpty())
continue;
if (counter > 0)
str += ", ";
str += d.trim();
counter++;
}
}
}
if (str.isEmpty())
return str;
// I18N
if (str.contains(","))
return "destinations: " + str;
else
return "destination: " + str;
}
@Override
public String toString()
{
return "car";
}
}