package com.revolsys.geometry.edgegraph; import java.util.Collection; import java.util.HashMap; import java.util.Map; import com.revolsys.geometry.model.Point; /** * A graph comprised of {@link HalfEdge}s. * It supports tracking the vertices in the graph * via edges incident on them, * to allow efficient lookup of edges and vertices. * <p> * This class may be subclassed to use a * different subclass of HalfEdge, * by overriding {@link #newHalfEdge(Point)}. * If additional logic is required to initialize * edges then {@link EdgeGraph#addEdge(Coordinates, Point)} * can be overridden as well. * * @author Martin Davis * */ public class EdgeGraph { private final Map vertexMap = new HashMap(); public EdgeGraph() { } /** * Adds an edge between the coordinates orig and dest * to this graph. * * @param orig the edge origin location * @param dest the edge destination location. * @return the created edge */ public HalfEdge addEdge(final Point orig, final Point dest) { final int cmp = dest.compareTo(orig); // ignore zero-length edges if (cmp == 0) { return null; } /** * Attempt to find the edge already in the graph. * Return it if found. * Otherwise, use a found edge with same origin (if any) to construct new edge. */ final HalfEdge eAdj = (HalfEdge)this.vertexMap.get(orig); HalfEdge eSame = null; if (eAdj != null) { eSame = eAdj.find(dest); } if (eSame != null) { return eSame; } final HalfEdge e = insert(orig, dest, eAdj); return e; } /** * Finds an edge in this graph with the given origin * and destination, if one exists. * * @param orig the origin location * @param dest the destination location. * @return an edge with the given orig and dest, or null if none exists */ public HalfEdge findEdge(final Point orig, final Point dest) { final HalfEdge e = (HalfEdge)this.vertexMap.get(orig); if (e == null) { return null; } return e.find(dest); } public Collection getVertexEdges() { return this.vertexMap.values(); } /** * Inserts an edge not already present into the graph. * * @param orig the edge origin location * @param dest the edge destination location * @param eAdj an existing edge with same orig (if any) * @return the created edge */ private HalfEdge insert(final Point orig, final Point dest, final HalfEdge eAdj) { // edge does not exist, so create it and insert in graph final HalfEdge e = newHalfEdge(orig, dest); if (eAdj != null) { eAdj.insert(e); } else { // add halfedges to to map this.vertexMap.put(orig, e); } final HalfEdge eAdjDest = (HalfEdge)this.vertexMap.get(dest); if (eAdjDest != null) { eAdjDest.insert(e.sym()); } else { this.vertexMap.put(dest, e.sym()); } return e; } /** * Creates a single HalfEdge. * Override to use a different HalfEdge subclass. * * @param orig the origin location * @return a new HalfEdge with the given origin */ protected HalfEdge newHalfEdge(final Point orig) { return new HalfEdge(orig); } private HalfEdge newHalfEdge(final Point p0, final Point p1) { final HalfEdge e0 = newHalfEdge(p0); final HalfEdge e1 = newHalfEdge(p1); HalfEdge.init(e0, e1); return e0; } }