package aimax.osm.gui.fx.applications; import java.util.HashSet; import java.util.List; import aima.core.agent.Agent; import aima.core.environment.map.MapAgent; import aima.core.environment.map.MapFunctionFactory; import aima.core.search.framework.SearchForActions; import aima.core.search.framework.evalfunc.HeuristicFunctionFactory; import aima.gui.util.SearchFactory; import aimax.osm.data.EntityClassifier; import aimax.osm.data.entities.EntityViewInfo; import aimax.osm.data.entities.MapNode; import aimax.osm.data.entities.MapWay; import aimax.osm.gui.swing.applications.SearchDemoOsmAgentApp; import aimax.osm.viewer.DefaultEntityRenderer; import aimax.osm.viewer.DefaultEntityViewInfo; import aimax.osm.viewer.MapStyleFactory; import aimax.osm.viewer.UColor; import javafx.scene.layout.Pane; /** * Integrable application which demonstrates how different kinds of search * algorithms perform in a route finding scenario based on a real OSM map. This * implementation extends <code>OsmAgentBaseApp</code> by two aspects: Map * locations corresponding to expanded nodes are highlighted in green. The user * can define several goals by placing more then two markers on the map. * * @author Ruediger Lunde * */ public class OsmRouteFindingAgentApp extends OsmAgentBaseApp { public static void main(String[] args) { launch(args); } /** * Stores those states (Strings with map node ids), whose corresponding * search nodes have been expanded during the last search. */ private static final HashSet<Object> visitedStates = new HashSet<>(); @Override public String getTitle() { return "OSM Route Finding Agent App"; } /** * Defines state view, parameters, and call-back functions and calls the * simulation pane builder to create layout and controller objects. This * implementation modifies the inherited version by changing map renderer * and entity classifier to prepare state space visualization. */ @Override public Pane createRootPane() { Pane root = super.createRootPane(); mapPaneCtrl.setRenderer(new SDMapEntityRenderer()); mapPaneCtrl.getMap().setEntityClassifier(createEntityClassifier()); return root; } /** * The method is called after each parameter selection change. This * implementation clears visited states of the last simulation run, prepares * the map for different kinds of vehicles and clears the currently * displayed track. */ @Override public void initialize() { visitedStates.clear(); super.initialize(); } /** * Factory method which creates a search strategy based on the current * parameter settings. Here, a listener is added to the node expander to * visualize progress during search. A dummy heuristic function is used * because the agent will replace it anyway. */ @Override protected SearchForActions createSearch(List<String> locations) { SearchForActions result = SearchFactory.getInstance().createSearch(simPaneCtrl.getParamValueIndex(PARAM_SEARCH), simPaneCtrl.getParamValueIndex(PARAM_Q_SEARCH_IMPL), MapFunctionFactory.getZeroHeuristicFunction()); result.getNodeExpander().addNodeListener(node -> visitedStates.add(node.getState())); visitedStates.clear(); return result; } /** * Factory method which creates a new agent based on the current parameter * settings. The agent is provided with a heuristic function factory to * adapt to different goals. */ protected Agent createAgent(SearchForActions search, List<String> locations) { HeuristicFunctionFactory hfFactory; if (simPaneCtrl.getParamValueIndex(PARAM_HEURISTIC) == 0) hfFactory = (goal) -> MapFunctionFactory.getZeroHeuristicFunction(); else hfFactory = (goal) -> MapFunctionFactory.getSLDHeuristicFunction(goal, map); return new MapAgent(map, search, locations.subList(1, locations.size()), envViewCtrl::notify, hfFactory); } // helper classes... /** * Variant of the <code>DefaultMapEntityRenderer</code> which highlights way * nodes mentioned in {@link SearchDemoOsmAgentApp#visitedStates}. */ private static class SDMapEntityRenderer extends DefaultEntityRenderer { DefaultEntityViewInfo highlightProp = new MapStyleFactory().createPoiInfo(0, 0, 5, UColor.GREEN, MapStyleFactory.createRectangle(4, UColor.GREEN), false); @Override public void printWay(MapWay way, DefaultEntityViewInfo eprop, boolean asArea) { super.printWay(way, eprop, asArea); if (scale >= highlightProp.minVisibleScale * displayFactor) { for (MapNode node : getWayNodes(way)) if (visitedStates.contains(Long.toString(node.getId()))) printPoint(imageBdr, node, highlightProp, null); } } } /** Demonstrates how to choose a color for a certain track. */ private EntityClassifier<EntityViewInfo> createEntityClassifier() { MapStyleFactory msf = new MapStyleFactory(); // define colors for tracks EntityClassifier<EntityViewInfo> eClassifier = msf.createDefaultClassifier(); eClassifier.addRule("track_type", TRACK_NAME, msf.createTrackInfo(UColor.RED)); return eClassifier; } }