001 package aima.search.map; 002 003 import java.util.Collections; 004 import java.util.Hashtable; 005 import java.util.List; 006 007 import aima.util.LabeledGraph; 008 import aima.util.Util; 009 010 /** 011 * Implements a map with locations, distance labeled links between the 012 * locations, straight line distances, and 2d-placement positions of locations. 013 * Locations are represented by strings and travel distances by integer values. 014 * Locations and links can be added dynamically and removed after creation. This 015 * enables to read maps from file or to modify them with respect to newly 016 * obtained knowledge. 017 * 018 * @author R. Lunde 019 */ 020 public class ExtendableMap implements Map { 021 022 /** 023 * Stores map data. Locations are represented as vertices and connections 024 * (links) as directed edges labeled with corresponding travel distances. 025 */ 026 private final LabeledGraph<String, Double> links; 027 028 /** Stores xy-coordinates for each location. */ 029 private final Hashtable<String, Point2D> locationPositions; 030 031 /** Creates an empty map. */ 032 public ExtendableMap() { 033 links = new LabeledGraph<String, Double>(); 034 locationPositions = new Hashtable<String, Point2D>(); 035 } 036 037 /** Removes everything. */ 038 public void clear() { 039 links.clear(); 040 locationPositions.clear(); 041 } 042 043 /** Clears all connections but keeps location position informations. */ 044 public void clearLinks() { 045 links.clear(); 046 } 047 048 /** Returns a list of all locations. */ 049 public List<String> getLocations() { 050 return links.getVertexLabels(); 051 } 052 053 /** Checks whether the given string is the name of a location. */ 054 public boolean isLocation(String str) { 055 return links.isVertexLabel(str); 056 } 057 058 /** 059 * Answers to the question: Where can I get, following one of the 060 * connections starting at the specified location? 061 */ 062 public List<String> getLocationsLinkedTo(String fromLocation) { 063 List<String> result = links.getSuccessors(fromLocation); 064 Collections.sort(result); 065 return result; 066 } 067 068 /** 069 * Returns the travel distance between the two specified locations if they 070 * are linked by a connection and null otherwise. 071 */ 072 public Double getDistance(String fromLocation, String toLocation) { 073 return links.get(fromLocation, toLocation); 074 } 075 076 /** Adds a one-way connection to the map. */ 077 public void addUnidirectionalLink(String fromLocation, String toLocation, 078 Double distance) { 079 links.set(fromLocation, toLocation, distance); 080 } 081 082 /** 083 * Adds a connection which can be traveled in both direction. Internally, 084 * such a connection is represented as two one-way connections. 085 */ 086 public void addBidirectionalLink(String fromLocation, String toLocation, 087 Double distance) { 088 links.set(fromLocation, toLocation, distance); 089 links.set(toLocation, fromLocation, distance); 090 } 091 092 /** 093 * Returns a location which is selected by random. 094 */ 095 public String randomlyGenerateDestination() { 096 return Util.selectRandomlyFromList(getLocations()); 097 } 098 099 /** Removes a one-way connection. */ 100 public void removeUnidirectionalLink(String fromLocation, String toLocation) { 101 links.remove(fromLocation, toLocation); 102 } 103 104 /** Removes the two corresponding one-way connections. */ 105 public void removeBidirectionalLink(String fromLocation, String toLocation) { 106 links.remove(fromLocation, toLocation); 107 links.remove(toLocation, fromLocation); 108 } 109 110 /** 111 * Defines the position of a location as with respect to an orthogonal 112 * coordinate system. 113 */ 114 public void setPosition(String loc, double x, double y) { 115 locationPositions.put(loc, new Point2D(x, y)); 116 } 117 118 /** 119 * Defines the position of a location within the map. Using this method, one 120 * location should be selected as reference position (<code>dist=0</code> 121 * and <code>dir=0</code>) and all the other location should be placed 122 * relative to it. 123 * 124 * @param loc 125 * location name 126 * @param dist 127 * distance to a reference position 128 * @param dir 129 * bearing (compass direction) in which the location is seen from 130 * the reference position 131 */ 132 public void setDistAndDirToRefLocation(String loc, double dist, int dir) { 133 Point2D coords = new Point2D( 134 -Math.sin(dir * Math.PI / 180.0) * dist, 135 Math.cos(dir * Math.PI / 180.0) * dist); 136 links.addVertex(loc); 137 locationPositions.put(loc, coords); 138 } 139 140 /** 141 * Returns an array with two integers describing the the position of the 142 * specified location. 143 */ 144 public Point2D getPosition(String loc) { 145 return locationPositions.get(loc); 146 } 147 148 }