/** * H2GIS is a library that brings spatial support to the H2 Database Engine * <http://www.h2database.com>. H2GIS is developed by CNRS * <http://www.cnrs.fr/>. * * This code is part of the H2GIS project. H2GIS 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; * version 3.0 of the License. * * H2GIS 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 Lesser General Public License * for more details <http://www.gnu.org/licenses/>. * * * For more information, please consult: <http://www.h2gis.org/> * or contact directly: info_at_h2gis.org */ package org.h2gis.network.functions; import java.sql.*; import java.util.HashSet; import java.util.Set; import org.h2.tools.SimpleResultSet; import org.h2gis.api.ScalarFunction; import static org.h2gis.network.functions.GraphConstants.CLOSEST_DEST; import static org.h2gis.network.functions.GraphConstants.DESTINATION; import static org.h2gis.network.functions.GraphConstants.DISTANCE; import static org.h2gis.network.functions.GraphConstants.SOURCE; import static org.h2gis.utilities.TableUtilities.isColumnListConnection; import org.h2gis.utilities.TableLocation; import org.h2gis.utilities.TableUtilities; import org.javanetworkanalyzer.analyzers.AccessibilityAnalyzer; import org.javanetworkanalyzer.data.VAccess; import org.javanetworkanalyzer.model.Edge; import org.javanetworkanalyzer.model.KeyedGraph; /** * Calculates, for each vertex, the closest destination among several possible * destinations, as well as the distance to this destination. * * @author Adam Gogue */ public class ST_Accessibility extends GraphFunction implements ScalarFunction { public static final String REMARKS = "`ST_Accessibility` calculates, for each vertex in a graph, the closest\n" + "destination among several possible destinations as well as the distance to this\n" + "destination. Possible signatures: \n" + "* `ST_Accessibility('input_edges', 'o[ - eo]', 'ds')`\n" + "* `ST_Accessibility('input_edges', 'o[ - eo]', 'dt')`\n" + "* `ST_Accessibility('input_edges', 'o[ - eo]', 'w', 'ds')`\n" + "* `ST_Accessibility('input_edges', 'o[ - eo]', 'w', 'dt')` \n" + "\n" + "where \n" + "* `input_edges` = Edges table produced by `ST_Graph` from table `input`\n" + "* `o` = Global orientation (directed, reversed or undirected)\n" + "* `eo` = Edge orientation (1 = directed, -1 = reversed, 0 = undirected).\n" + " Required if global orientation is directed or reversed.\n" + "* `w` = Name of column containing edge weights as doubles\n" + "* `ds` = Comma-separated Destination string ('dest1, dest2, ...')\n" + "* `dt` = Destination table name (must contain column containing integer vertex\n" + " ids)\n"; /** * Constructor */ public ST_Accessibility() { addProperty(PROP_REMARKS, REMARKS); } @Override public String getJavaStaticMethod() { return "getAccessibility"; } /** * @param connection Connection * @param inputTable Edges table produced by ST_Graph * @param orientation Orientation string * @param arg3 Destination string or destination table * @return Table with closest destination id and distance to closest * destination * @throws SQLException */ public static ResultSet getAccessibility(Connection connection, String inputTable, String orientation, String arg3) throws SQLException { return getAccessibility(connection, inputTable, orientation, null, arg3); } /** * @param connection Connection * @param inputTable Edges table produced by ST_Graph * @param orientation Orientation string * @param weight Weight * @param arg4 Destination string or destination table * @return Table with closest destination id and distance to closest * destination * @throws SQLException */ public static ResultSet getAccessibility(Connection connection, String inputTable, String orientation, String weight, String arg4) throws SQLException { if (isColumnListConnection(connection)) { return prepareResultSet(); } final KeyedGraph<VAccess, Edge> graph = prepareGraph(connection, inputTable, orientation, weight, VAccess.class, Edge.class); // Decide whether this is a destination string or a table string. if (GraphFunctionParser.isDestinationsString(arg4)) { return compute(graph, prepareDestSet(graph, GraphFunctionParser.parseDestinationsString(arg4))); } else { // arg4 is a destination table. return compute(graph, prepareDestSet(connection, graph, arg4)); } } private static ResultSet compute(KeyedGraph<VAccess, Edge> graph, Set<VAccess> destinations) throws SQLException { SimpleResultSet output = prepareResultSet(); new AccessibilityAnalyzer(graph, destinations).compute(); for (VAccess v : graph.vertexSet()) { output.addRow(v.getID(), v.getClosestDestinationId(), v.getDistanceToClosestDestination()); } return output; } private static Set<VAccess> prepareDestSet(KeyedGraph<VAccess, Edge> graph, int[] dests) { Set<VAccess> destinations = new HashSet<VAccess>(); for (int i = 0; i < dests.length; i++) { destinations.add(graph.getVertex(dests[i])); } return destinations; } private static Set<VAccess> prepareDestSet(Connection connection, KeyedGraph<VAccess, Edge> graph, String destTable) throws SQLException { final Statement st = connection.createStatement(); Set<VAccess> destinations = new HashSet<VAccess>(); try { final TableLocation destinationTable = TableUtilities.parseInputTable(connection, destTable); final ResultSet rs = st.executeQuery( "SELECT " + DESTINATION + " FROM " + destinationTable); while (rs.next()) { destinations.add(graph.getVertex(rs.getInt(1))); } } finally { st.close(); } return destinations; } private static SimpleResultSet prepareResultSet() { SimpleResultSet output = new SimpleResultSet(); output.addColumn(SOURCE, Types.INTEGER, 10, 0); output.addColumn(CLOSEST_DEST, Types.INTEGER, 10, 0); output.addColumn(DISTANCE, Types.DOUBLE, 10, 0); return output; } }