All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.routing.core.OverlayGraph Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
/* 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 (props, 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 . */

package org.opentripplanner.routing.core;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;

import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.graph.Vertex;


/**
 * Allows adding supplemental edges to existing vertices in another graph. Useful for CH, and
 * potentially for "extraEdges".
 * 
 * @author andrewbyrd
 */
public class OverlayGraph implements Serializable {

    private static final long serialVersionUID = 20111106L; // YYYYMMDD

    private static final int INITIAL_EDGELIST_CAPACITY = 5;

    private IdentityHashMap> outgoing;

    private IdentityHashMap> incoming;

    /**
     * Create an empty OverlayGraph.
     */
    public OverlayGraph() {
        outgoing = new IdentityHashMap>();
        incoming = new IdentityHashMap>();
    }

    /**
     * Copy contents of a Graph into this OverlayGraph
     */
    public OverlayGraph(Graph g) {
        this();
        for (Vertex v : g.getVertices()) {
            for (Edge e : v.getOutgoing())
                this.addOutgoing(v, e);
            for (Edge e : v.getIncoming())
                this.addIncoming(v, e);
        }
    }

    public void addOutgoing(Vertex fromv, Edge e) {
        List fromOutgoing = outgoing.get(fromv);
        if (fromOutgoing == null) {
            fromOutgoing = new ArrayList(INITIAL_EDGELIST_CAPACITY);
            outgoing.put(fromv, fromOutgoing);
        }
        if (!fromOutgoing.contains(e))
            fromOutgoing.add(e);
    }

    public void addIncoming(Vertex tov, Edge e) {
        List toIncoming = incoming.get(tov);
        if (toIncoming == null) {
            toIncoming = new ArrayList(INITIAL_EDGELIST_CAPACITY);
            incoming.put(tov, toIncoming);
        }
        if (!toIncoming.contains(e))
            toIncoming.add(e);
    }

    public void removeOutgoing(Vertex fromv, Edge e) {
        List fromOutgoing = outgoing.get(fromv);
        if (fromOutgoing != null) {
            fromOutgoing.remove(e);
        }
    }

    public void removeIncoming(Vertex tov, Edge e) {
        List toIncoming = incoming.get(tov);
        if (toIncoming != null) {
            toIncoming.remove(e);
        }
    }

    public void addEdge(Edge e) {
        Vertex fromv = e.getFromVertex();
        Vertex tov = e.getToVertex();
        addOutgoing(fromv, e);
        addIncoming(tov, e);
    }

    public void removeEdge(Edge e) {
        Vertex fromv = e.getFromVertex();
        Vertex tov = e.getToVertex();
        removeOutgoing(fromv, e);
        removeIncoming(tov, e);
    }

    public List getOutgoing(Vertex v) {
        List ret = outgoing.get(v);
        if (ret == null)
            ret = Collections.emptyList();
        return ret;
    }

    public List getIncoming(Vertex v) {
        List ret = incoming.get(v);
        if (ret == null)
            ret = Collections.emptyList();
        return ret;
    }

    /**
     * A single edge can appear once or twice. (CH graphs might have only outgoing or only incoming
     * edges.) Avoid double-counting.
     */
    public int countEdges() {
        HashSet eset = new HashSet(1000);
        for (List l : outgoing.values())
            for (Edge e : l)
                eset.add(e);

        for (List l : incoming.values())
            for (Edge e : l)
                eset.add(e);

        return eset.size();
    }

    /**
     * A single Vertex can appear once or twice. (CH graphs might have only outgoing or only
     * incoming edges.) Avoid double-counting.
     */
    public Collection getVertices() {
        HashSet sv = new HashSet();
        sv.addAll(outgoing.keySet());
        sv.addAll(incoming.keySet());
        return sv;
    }

    /**
     * A single Vertex can appear once or twice. (CH graphs might have only outgoing or only
     * incoming edges.) Avoid double-counting. This is very inefficient.
     */
    public int countVertices() {
        return getVertices().size();
    }

    // need to make sure lists are never null - Vertex
    // beware concurrentModification of lists.
    // public void removeVertex(Vertex vertex) {
    // List toRemove = outgoing.remove(vertex);
    // toRemove.addAll(incoming.remove(vertex));
    // for (Edge e : toRemove)
    // if (e instanceof Edge)
    // removeEdge((Edge)e);
    // }

    public void removeVertex(Vertex vertex) {
        outgoing.remove(vertex);
        incoming.remove(vertex);
    }

    public int getDegreeIn(Vertex v) {
        List l = incoming.get(v);
        if (l == null)
            return 0;
        else
            return l.size();
    }

    public int getDegreeOut(Vertex v) {
        List l = outgoing.get(v);
        if (l == null)
            return 0;
        else
            return l.size();
    }

    public boolean containsVertex(Vertex vertex) {
        return outgoing.containsKey(vertex) || incoming.containsKey(vertex);
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        for (List le : outgoing.values())
            ((ArrayList)le).trimToSize();
        for (List le : incoming.values())
            ((ArrayList)le).trimToSize();
        out.defaultWriteObject();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy