/*
* Copyright 2013 Serdar.
*
* Licensed 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 de.fub.maps.project.plugins.mapmatcher;
import de.fub.agg2graph.structs.GPSSegment;
import de.fub.agg2graph.structs.ILocation;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
/**
* MapMatcher interface, which will be used by the navigation graph
* OSMMapEvaluator.
*
* @author Serdar
*/
public interface MapMatcher {
/**
* finds the match for the specified {@code road}. The method iterates
* through all roads in the {@code roadNetwork} and finds the most fitting
* road. A Road can contain one or more points
*
* @param roadTobeMatched the segment to be matched
* @param roadNetwork the network in which the match is to be found.
* @return A MapMatchResult that contains one or more gps points if there
* was a match, otherwise null.
*/
public List<MapMatchSegment> findMatch(Collection<GPSSegment> roadTobeMatched, Collection<GPSSegment> roadNetwork);
/**
* Factory class to localize all registered MapMatcher instances.
*/
public static class Factory {
private static final Object MUTEX = new Object();
/**
* Returns the default MapMatcher instance of type
* PointToPointMapMatcher.
*
* @return MapMatcher instance or null if the the type was not correctly
* registered via <code>@ServiceProvider</code>.
*/
public static MapMatcher getDefault() {
MapMatcher mapMatcher = null;
try {
mapMatcher = find(PointToPointMapMatcher.class.getName());
} catch (MapMatcherNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
return mapMatcher;
}
/**
* Finds all registered MapMatcher types and creates an instance of each
* type and returns these via a list.
*
* @return a collection of MapMatcher instances.
*/
public static Collection<? extends MapMatcher> findAll() {
Set<Class<? extends MapMatcher>> allClasses = Lookup.getDefault().lookupResult(MapMatcher.class).allClasses();
List<MapMatcher> instances = new ArrayList<MapMatcher>(allClasses.size());
for (Class<? extends MapMatcher> clazz : allClasses) {
try {
instances.add(clazz.newInstance());
} catch (InstantiationException ex) {
Exceptions.printStackTrace(ex);
} catch (IllegalAccessException ex) {
Exceptions.printStackTrace(ex);
}
}
return instances;
}
/**
* Creates an instance of an MapMatcher of the specified qualified name.
*
* @param qualifiedName
* @return returns an MapMatcher instance.
* @throws
* de.fub.maps.project.plugins.mapmatcher.MapMatcher.MapMatcherNotFoundException
* if the type of the qualified name could not be found of instanciated.
*/
public static MapMatcher find(String qualifiedName) throws MapMatcherNotFoundException {
synchronized (MUTEX) {
MapMatcher mapMatcher = null;
for (MapMatcher matcher : findAll()) {
if (matcher.getClass().getName().equals(qualifiedName)) {
mapMatcher = matcher;
break;
}
}
if (mapMatcher == null) {
throw new MapMatcherNotFoundException(MessageFormat.format("Couldn'T find instance {0}! Please check whether the type is registered via @ServiceProvider annotation.", qualifiedName));
}
return mapMatcher;
}
}
}
public static class MapMatcherNotFoundException extends Exception {
private static final long serialVersionUID = 1L;
public MapMatcherNotFoundException() {
}
public MapMatcherNotFoundException(String message) {
super(message);
}
public MapMatcherNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public MapMatcherNotFoundException(Throwable cause) {
super(cause);
}
}
/**
* The result type of an MapMatcher instance.
*/
public static class MapMatchResult {
private ILocation tobeMatchedPoint;
private ILocation matchedPoint;
private double distance;
public MapMatchResult(ILocation tobeMatchedPoint, ILocation matchedPoint, double distance) {
this.tobeMatchedPoint = tobeMatchedPoint;
this.matchedPoint = matchedPoint;
this.distance = distance;
}
public ILocation getTobeMatchedPoint() {
return tobeMatchedPoint;
}
public ILocation getMatchedPoint() {
return matchedPoint;
}
public double getDistance() {
return distance;
}
}
/**
* A MapMatchSegment
*/
public static class MapMatchSegment {
private List<MapMatchResult> segment = new ArrayList<MapMatchResult>();
public MapMatchSegment() {
}
public List<MapMatchResult> getSegment() {
return segment;
}
public double getMapMatchCost() {
double cost = Double.MAX_VALUE;
double costSum = 0;
if (!getSegment().isEmpty()) {
for (MapMatchResult mapMatchResult : getSegment()) {
costSum += mapMatchResult.getDistance();
}
cost = costSum / getSegment().size();
}
return cost;
}
}
}