/** * Copyright (C) 2012, Emergya (http://www.emergya.es) * * @author <a href="mailto:marias@emergya.com">MarĂ­a Arias de Reyna</a> * * This file is part of GoFleet * * This software is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This software 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA * * As a special exception, if you link this library with other files to * produce an executable, this library does not by itself cause the * resulting executable to be covered by the GNU General Public License. * This exception does not however invalidate any other reasons why the * executable file might be covered by the GNU General Public License. */ package org.emergya.backtrackTSP; import java.io.IOException; import java.text.ParseException; import java.util.HashMap; import java.util.Locale; import java.util.Map; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import net.opengis.gml.v_3_1_1.DirectPositionType; import net.opengis.gml.v_3_1_1.PointType; import net.opengis.xls.v_1_2_0.AbstractLocationType; import net.opengis.xls.v_1_2_0.DetermineRouteRequestType; import net.opengis.xls.v_1_2_0.DetermineRouteResponseType; import net.opengis.xls.v_1_2_0.PositionType; import net.opengis.xls.v_1_2_0.RoutePlanType; import net.opengis.xls.v_1_2_0.WayPointListType; import net.opengis.xls.v_1_2_0.WayPointType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.emergya.osrm.OSRM; import org.gofleet.openLS.tsp.TSPStop; import com.vividsolutions.jts.geom.Point; public class DistanceMatrix { private Map<Key, Double> distances = new HashMap<Key, Double>(); private static Log LOG = LogFactory.getLog(DistanceMatrix.class); private OSRM osrm; private org.gofleet.configuration.Configuration configuration; public DistanceMatrix() { this.osrm = new OSRM(); } public DistanceMatrix(OSRM osrm, org.gofleet.configuration.Configuration configuration) { super(); this.osrm = osrm; this.configuration = configuration; } public Double distance(BacktrackStop from, BacktrackStop to) throws InterruptedException { Key k = new Key(from.id, to.id); Double d = null; synchronized (distances) { d = distances.get(k); } if (d != null) { return d; } else { if (LOG.isDebugEnabled()) LOG.debug("DistanceMatrix.distance(" + k + ")"); return calculateDistance(from, to, k); } } private Double calculateDistance(TSPStop from, TSPStop to, Key k) throws InterruptedException { String host_port = "localhost:5000"; String http = "http"; if (configuration != null) { if (configuration.get("OSRM_SSL", "off").equals("on")) http = "https"; host_port = configuration.get("OSRM_HOST", "localhost:5000"); } DetermineRouteRequestType param = new DetermineRouteRequestType(); if (param.getRoutePlan() == null) param.setRoutePlan(new RoutePlanType()); if (param.getRoutePlan().getWayPointList() == null) param.getRoutePlan().setWayPointList(new WayPointListType()); WayPointListType waypointList = param.getRoutePlan().getWayPointList(); WayPointType start = getWayPoint(from.getPosition()); WayPointType end = getWayPoint(to.getPosition()); waypointList.setStartPoint(start); waypointList.setEndPoint(end); try { DetermineRouteResponseType res = (DetermineRouteResponseType) osrm .routePlan(param, host_port, http, Locale.ROOT); double cost = res.getRouteSummary().getTotalDistance().getValue() .doubleValue(); synchronized (distances) { distances.put(k, cost); } return cost; } catch (IOException e) { LOG.error("Error extracting distance from " + from + " to " + to); return Double.MAX_VALUE; } catch (ParseException e) { LOG.error("Error extracting distance from " + from + " to " + to); return Double.MAX_VALUE; } catch (JAXBException e) { LOG.error("Error extracting distance from " + from + " to " + to); return Double.MAX_VALUE; } } @SuppressWarnings("restriction") private WayPointType getWayPoint(Point position) { WayPointType point = new WayPointType(); point.setStop(Boolean.TRUE); PositionType postype = new PositionType(); PointType pointtype = new PointType(); DirectPositionType directPosition = new DirectPositionType(); directPosition.setSrsName("EPSG:" + position.getSRID()); directPosition.getValue().add(position.getX()); directPosition.getValue().add(position.getY()); pointtype.setPos(directPosition); postype.setPoint(pointtype); JAXBElement<? extends AbstractLocationType> value = new JAXBElement<PositionType>( new QName("http://www.opengis.net/gml", "pos", "gml"), PositionType.class, postype); point.setLocation(value); return point; } } class Key { protected Key(Integer from, Integer to) { super(); this.from = from; this.to = to; } private Integer from; private Integer to; public Integer getFrom() { return from; } public void setFrom(Integer from) { this.from = from; } public Integer getTo() { return to; } public void setTo(Integer to) { this.to = to; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((from == null) ? 0 : from.hashCode()); result = prime * result + ((to == null) ? 0 : to.hashCode()); return result; } @Override public boolean equals(Object obj) { if (!(obj instanceof Key)) return false; Key other = (Key) obj; return other.getFrom().equals(this.from) && other.getTo().equals(this.to); } @Override public String toString() { return "{ K<" + this.getFrom() + "->" + this.getTo() + ">}"; } }