001 package aima.gui.applications.search.map; 002 003 import java.awt.Color; 004 import java.util.ArrayList; 005 import java.util.List; 006 007 import aima.gui.framework.AgentAppFrame; 008 import aima.gui.framework.AgentView; 009 import aima.search.framework.SearchFactory; 010 import aima.search.map.Map; 011 import aima.search.map.Point2D; 012 013 014 /** 015 * Universal frame for experiments with route planning 016 * agents. It configures the agent application frame with some selectors 017 * and an agent view which is designed for cooperation with an 018 * {@link MapAgentModel}. Since items for scenario, agent, destination, 019 * agent, and heuristic selection are application specific, this general 020 * implementation provides items only for search strategy and mode selection. 021 * @author R. Lunde 022 */ 023 public class MapAgentFrame extends AgentAppFrame { 024 public static String SCENARIO_SEL = "ScenarioSelection"; 025 public static String DESTINATION_SEL = "DestinationSelection"; 026 public static String AGENT_SEL = "AgentSelection"; 027 public static String SEARCH_SEL = "SearchSelection"; 028 public static String SEARCH_MODE_SEL = "SearchModeSelection"; 029 public static String HEURISTIC_SEL = "HeuristicSelection"; 030 031 /** Standard constructor. */ 032 public MapAgentFrame() { 033 setSelectors(new String[]{ 034 SCENARIO_SEL, DESTINATION_SEL, AGENT_SEL, 035 SEARCH_SEL, SEARCH_MODE_SEL, HEURISTIC_SEL}, 036 new String[]{ 037 "Select Scenario", "Select Destinations", "Select Agent", 038 "Select Search Strategy", "Select Search Mode", "Select Heuristic"} 039 ); 040 setSelectorItems(SEARCH_SEL, 041 SearchFactory.getInstance().getSearchStrategyNames(), 5); 042 setSelectorItems(SEARCH_MODE_SEL, 043 SearchFactory.getInstance().getSearchModeNames(), 0); 044 setAgentView(new MapAgentView()); 045 setSplitPaneResizeWeight(0.75); 046 setUpdateDelay(500); 047 setSize(1000, 700); 048 } 049 050 051 ////////////////////////////////////////////////////////// 052 // inner classes 053 054 /** 055 * Agent view for map agent applications. This 056 * view requires the used model to be of type 057 * {@link MapAgentModel}. 058 */ 059 class MapAgentView extends AgentView { 060 061 /** Clears the panel and draws the map and the tour history. */ 062 public void paint(java.awt.Graphics g) { 063 super.paint(g); 064 MapAgentModel maModel = (MapAgentModel) model; 065 if (maModel != null && !maModel.isEmpty()) { 066 java.awt.Graphics2D g2 = (java.awt.Graphics2D) g; 067 adjustTransformation(); 068 paintMap(g2); 069 paintTour(g2); 070 for (String loc : maModel.getLocations()) 071 paintLoc(g2, loc); 072 } 073 } 074 075 /** 076 * Adjusts offsets and scale so that the whole map fits on the 077 * view without scrolling. 078 */ 079 private void adjustTransformation() { 080 MapAgentModel maModel = (MapAgentModel) model; 081 List<String> locs = maModel.getLocations(); 082 // adjust coordinates relative to the left upper corner of the graph area 083 double minX = Double.POSITIVE_INFINITY; 084 double minY = Double.POSITIVE_INFINITY; 085 double maxX = Double.NEGATIVE_INFINITY; 086 double maxY = Double.NEGATIVE_INFINITY; 087 for (String loc : locs) { 088 Point2D xy = maModel.getLocCoords(loc); 089 if (xy.getX() < minX) minX = xy.getX(); 090 if (xy.getY() < minY) minY = xy.getY(); 091 if (xy.getX() > maxX) maxX = xy.getX(); 092 if (xy.getY() > maxY) maxY = xy.getY(); 093 } 094 this.setBorder(20, 20, 20, 100); 095 adjustTransformation(minX, minY, maxX, maxY); 096 } 097 098 /** 099 * Represents roads by lines and locations by name-labeled points. 100 */ 101 private void paintMap(java.awt.Graphics2D g2) { 102 MapAgentModel maModel = (MapAgentModel) model; 103 Map envMap = maModel.getEnvMap(); 104 Map agentMap = maModel.getAgentMap(); 105 List<Roadblock> roadblocks = new ArrayList<Roadblock>(); 106 for (String l1 : maModel.getLocations()) { 107 Point2D pt1 = maModel.getLocCoords(l1); 108 List<String> linkedLocs = envMap.getLocationsLinkedTo(l1); 109 for (String l2 : agentMap.getLocationsLinkedTo(l1)) 110 if (!linkedLocs.contains(l2)) 111 linkedLocs.add(l2); 112 for (String l2 : linkedLocs) { 113 Point2D pt2 = maModel.getLocCoords(l2); 114 g2.setColor(Color.lightGray); 115 g2.drawLine(x(pt1), y(pt1), x(pt2), y(pt2)); 116 boolean blockedInEnv = 117 !envMap.getLocationsLinkedTo(l2).contains(l1); 118 boolean blockedInAgent = 119 !agentMap.getLocationsLinkedTo(l2).contains(l1); 120 roadblocks.add(new Roadblock(pt1, pt2, blockedInEnv, blockedInAgent)); 121 if (blockedInEnv && blockedInAgent) { 122 boolean blockedInEnvOtherDir = 123 !envMap.getLocationsLinkedTo(l1).contains(l2); 124 boolean blockedInAgentOtherDir = 125 !agentMap.getLocationsLinkedTo(l1).contains(l2); 126 roadblocks.add(new Roadblock(pt2, pt1, blockedInEnvOtherDir, blockedInAgentOtherDir)); 127 } 128 } 129 } 130 for (Roadblock block : roadblocks) 131 paintRoadblock(g2, block); 132 } 133 134 /** The track of the agent is visualized with red lines. */ 135 private void paintTour(java.awt.Graphics2D g2) { 136 MapAgentModel maModel = (MapAgentModel) model; 137 Point2D lastPt = null; 138 g2.setColor(Color.red); 139 for (String loc : maModel.getTourHistory()) { 140 Point2D pt = maModel.getLocCoords(loc); 141 if (pt != null && lastPt != null) { 142 g2.drawLine(x(pt), y(pt), x(lastPt), y(lastPt)); 143 } 144 lastPt = pt; 145 } 146 } 147 148 /** 149 * Roadblocks are represented by filled rectangles. 150 * Blue denotes, the agent doesn't know it, red dentotes, there is 151 * no roadblock, but the agent thinks so. 152 */ 153 private void paintRoadblock(java.awt.Graphics2D g2, Roadblock block) { 154 if (block.inEnvMap || block.inAgentMap) { 155 int x = (int) (0.2*x(block.pos1)+0.8*x(block.pos2)-4); 156 int y = (int) (0.2*y(block.pos1)+0.8*y(block.pos2)-4); 157 if (!block.inAgentMap) 158 g2.setColor(Color.blue); // agent doesn't know the roadblock 159 else if (!block.inEnvMap) 160 g2.setColor(Color.red); // agent doesn't know the way 161 else 162 g2.setColor(Color.lightGray); 163 g2.fillRect(x, y, 9, 9); 164 } 165 } 166 167 private void paintLoc(java.awt.Graphics2D g2, String loc) { 168 MapAgentModel maModel = (MapAgentModel) model; 169 Point2D pt = maModel.getLocCoords(loc); 170 if (pt != null) { 171 int x = x(pt); 172 int y = y(pt); 173 String info = ""; 174 List<String> history = maModel.getTourHistory(); 175 ArrayList<Integer> list = new ArrayList<Integer>(); 176 for (int i =0; i < history.size(); i++) 177 if (history.get(i).equals(loc)) 178 list.add(i+1); 179 if (!list.isEmpty()) 180 info = list.toString(); 181 if (maModel.hasObjects(loc)) { 182 g2.setColor(Color.green); 183 g2.fillOval(x-5, y-5, 10, 10); 184 } 185 if (maModel.isStart(loc)) { 186 g2.setColor(Color.red); 187 g2.fillOval(x-7, y-7, 14, 14); 188 } 189 if (!history.isEmpty() && loc.equals(history.get(history.size()-1))) { 190 g2.setColor(Color.red); 191 g2.fillOval(x-4, y-4, 8, 8); 192 } 193 if (maModel.hasInfos(loc)) { 194 g2.setColor(Color.blue); 195 g2.drawString("i", x, y+12); 196 } 197 //if (model.isStart(loc)) 198 // g2.setColor(Color.red); 199 //else 200 if (maModel.isDestination(loc)) 201 g2.setColor(Color.green); 202 else if (history.contains(loc)) 203 g2.setColor(Color.black); 204 else 205 g2.setColor(Color.gray); 206 g2.drawString(loc + info, x, y); 207 } 208 } 209 } 210 211 /** 212 * Stores roadblock information. Roadblocks are generally printed after 213 * the road itself so that they always appear in front. 214 */ 215 private static class Roadblock { 216 Point2D pos1; 217 Point2D pos2; 218 boolean inEnvMap; 219 boolean inAgentMap; 220 private Roadblock(Point2D pos1, Point2D pos2, boolean inEnvMap, boolean inAgentMap) { 221 this.pos1 = pos1; 222 this.pos2 = pos2; 223 this.inEnvMap = inEnvMap; 224 this.inAgentMap = inAgentMap; 225 } 226 } 227 }