001/* 002MIT License 003 004Copyright (c) 2020 earlygrey 005 006Permission is hereby granted, free of charge, to any person obtaining a copy 007of this software and associated documentation files (the "Software"), to deal 008in the Software without restriction, including without limitation the rights 009to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 010copies of the Software, and to permit persons to whom the Software is 011furnished to do so, subject to the following conditions: 012 013The above copyright notice and this permission notice shall be included in all 014copies or substantial portions of the Software. 015 016THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 017IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 018FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 019AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 020LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 021OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 022SOFTWARE. 023 */ 024package squidpony.squidai.graph; 025 026import squidpony.squidmath.BinaryHeap; 027 028import java.io.Serializable; 029import java.util.ArrayList; 030import java.util.Collection; 031import java.util.HashMap; 032 033/** 034 * An extended version of {@link squidpony.squidmath.BinaryHeap.Node} that also stores a reference to the parent Graph, 035 * a vertex object of type {@code V}, a Map of neighbor Nodes to the appropriate {@link Connection} per Node, an extra 036 * List of those same Connections for faster iteration, and a lot of internal data used by algorithms in this package. 037 * @param <V> the vertex type; often {@link squidpony.squidmath.Coord} 038 * @author earlygrey 039 */ 040public class Node<V> extends BinaryHeap.Node implements Serializable { 041 private static final long serialVersionUID = 1L; 042 043 044 //================================================================================ 045 // Graph structure related members 046 //================================================================================ 047 048 protected final Graph<V> graph; 049 protected final int idHash; 050 protected final V object; 051 protected HashMap<Node<V>, Connection<V>> neighbors = new HashMap<>(); 052 protected ArrayList<Connection<V>> outEdges = new ArrayList<>(); // List for fast iteration 053 054 //================================================================================ 055 // Constructor 056 //================================================================================ 057 058 protected Node(V v, Graph<V> graph) { 059 super(0.0); 060 this.object = v; 061 this.graph = graph; 062 idHash = System.identityHashCode(this); 063 } 064 065 //================================================================================ 066 // Internal methods 067 //================================================================================ 068 069 protected Connection<V> getEdge(Node<V> v) { 070 return neighbors.get(v); 071 } 072 073 protected Connection<V> addEdge(Node<V> v, float weight) { 074 Connection<V> edge = neighbors.get(v); 075 if (edge == null) { 076 edge = graph.obtainEdge(); 077 edge.set(this, v, weight); 078 neighbors.put(v, edge); 079 outEdges.add(edge); 080 return edge; 081 } else { 082 edge.setWeight(weight); 083 } 084 return edge; 085 } 086 protected Connection<V> removeEdge(Node<V> v) { 087 Connection<V> edge = neighbors.remove(v); 088 if (edge == null) return null; 089 // loop backwards to make Graph#removeNode faster 090 for (int j = outEdges.size()-1; j >= 0; j--) { 091 Connection<V> connection = outEdges.get(j); 092 if (connection.equals(edge)) { 093 outEdges.remove(j); 094 break; 095 } 096 } 097 return edge; 098 } 099 100 protected void disconnect() { 101 neighbors.clear(); 102 outEdges.clear(); 103 } 104 105 //================================================================================ 106 // Public Methods 107 //================================================================================ 108 109 public Collection<Connection<V>> getConnections() { 110 return outEdges; 111 } 112 113 public V getObject() { 114 return object; 115 } 116 117 //================================================================================ 118 // Algorithm fields and methods 119 //================================================================================ 120 121 /** 122 * Internal; tracking bit for whether this Node has already been visited during the current algorithm. 123 */ 124 protected boolean visited; 125 /** 126 * Internal; tracking bit for whether this Node has been checked during the current algorithm. 127 */ 128 protected boolean seen; 129 /** 130 * Internal; confirmed distance so far to get to this Node from the start. 131 */ 132 protected double distance; 133 /** 134 * Internal; estimated distance to get from this Node to the goal. 135 */ 136 protected double estimate; 137 /** 138 * Internal; a reference to the previous Node in a BinaryHeap. 139 */ 140 protected Node<V> prev; 141 /** 142 * Internal; a utility field used to store depth in some algorithms. 143 */ 144 protected int i; 145 /** 146 * Internal; a utility field used to distinguish which algorithm last used this Node. 147 */ 148 protected int lastRunID; 149 150 /** 151 * If {@code runID} is not equal to {@link #lastRunID}, this resets the internal fields {@link #visited}, 152 * {@link #seen}, {@link #distance}, {@link #estimate}, {@link #prev}, and {@link #i}, then sets {@link #lastRunID} 153 * to {@code runID}. 154 * @param runID an int that identifies which run of an algorithm is currently active 155 * @return true if anything was reset, or false if {@code runID} is equal to {@link #lastRunID} 156 */ 157 protected boolean resetAlgorithmAttributes(int runID) { 158 if (runID == this.lastRunID) return false; 159 visited = false; 160 prev = null; 161 distance = Float.MAX_VALUE; 162 estimate = 0; 163 i = 0; 164 seen = false; 165 this.lastRunID = runID; 166 return true; 167 } 168 169 //================================================================================ 170 // Misc 171 //================================================================================ 172 173 174 @Override 175 public boolean equals(Object o) { 176 return o == this; 177 } 178 179 180 @Override 181 public int hashCode() { 182 return idHash; 183 } 184 185 @Override 186 public String toString() { 187 return "["+object+"]"; 188 } 189}