/* This program is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package org.opentripplanner.graph_builder.impl.shapefile;
import java.util.HashMap;
import java.util.Map;
import org.opengis.feature.simple.SimpleFeature;
import org.opentripplanner.common.model.P2;
import org.opentripplanner.graph_builder.services.shapefile.SimpleFeatureConverter;
/**
* Handles marking certain types of streets/bike lanes as more or less safe for bike trips.
*/
public class CaseBasedBicycleSafetyFeatureConverter implements SimpleFeatureConverter<P2<Double>> {
private String safetyAttributeName;
private String directionAttributeName;
private Map<String, Double> safetyFeatures = new HashMap<String, Double>();
private Map<String, Integer> directions = new HashMap<String, Integer>();
public static final P2<Double> oneone = new P2<Double>(1.0, 1.0);
@Override
public P2<Double> convert(SimpleFeature feature) {
String safetyKey = feature.getAttribute(safetyAttributeName).toString();
Double safetyFeature = safetyFeatures.get(safetyKey);
if (safetyFeature == null)
return oneone;
int directionFeature = 3; // Default to applying the safety feature in both directions
// (useful if the dataset doesn't include direction information)
if (directionAttributeName != null) {
String directionKey = feature.getAttribute(directionAttributeName).toString();
if (directionKey != null) {
directionFeature = directions.get(directionKey.toString());
}
}
return new P2<Double>((directionFeature & 0x1) == 0 ? 1.0 : safetyFeature,
(directionFeature & 0x2) == 0 ? 1.0 : safetyFeature);
}
public CaseBasedBicycleSafetyFeatureConverter(String safetyAttributeName,
String directionAttributeName) {
this.safetyAttributeName = safetyAttributeName;
this.directionAttributeName = directionAttributeName;
}
public CaseBasedBicycleSafetyFeatureConverter() {
}
/**
* @param safetyAttributeName
* The name of the attribute used when calculating the feature's safety.
*/
public void setSafetyAttributeName(String safetyAttributeName) {
this.safetyAttributeName = safetyAttributeName;
}
/**
* @param directionAttributeName
* The name of the attribute used when calculating the direction of the
* street/bikelane for which that the safety feature should apply.
*/
public void setDirectionAttributeName(String directionAttributeName) {
this.directionAttributeName = directionAttributeName;
}
public void setSafety(Map<String, String> safetyValues) {
for (Map.Entry<String, String> entry : safetyValues.entrySet()) {
String attributeValue = entry.getKey();
String featureName = entry.getValue();
Double safety = Double.valueOf(featureName);
addSafety(attributeValue, safety);
}
}
public void addSafety(String attributeValue, Double safety) {
safetyFeatures.put(attributeValue, safety);
}
/**
* Maps the direction value to a number representing the direction that the bike safety feature
* goes. The number is 1 for a safety feature that goes with the road geometry, 2 for a safety
* feature that goes against it, and 3 for a safety feature that goes both ways.
* @param directionValues
*/
public void setDirection(Map<String, String> directionValues) {
for (Map.Entry<String, String> entry : directionValues.entrySet()) {
String attributeValue = entry.getKey();
String featureName = entry.getValue();
Integer direction = Integer.valueOf(featureName);
addDirection(attributeValue, direction);
}
}
public void addDirection(String attributeValue, Integer direction) {
directions.put(attributeValue, direction);
}
}