Package aimax.osm.applications

Source Code of aimax.osm.applications.MiniNaviApp$MyGpsPositionListener

package aimax.osm.applications;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

import aima.core.util.CancelableThread;
import aimax.osm.data.DataResource;
import aimax.osm.data.EntityClassifier;
import aimax.osm.data.OsmMap;
import aimax.osm.data.Position;
import aimax.osm.data.entities.EntityViewInfo;
import aimax.osm.data.entities.MapNode;
import aimax.osm.data.entities.Track;
import aimax.osm.data.impl.DefaultMap;
import aimax.osm.gps.GpsFix;
import aimax.osm.gps.GpsLocator;
import aimax.osm.gps.GpsPositionListener;
import aimax.osm.gps.NmeaReader.MessageToFileListener;
import aimax.osm.routing.RouteCalculator;
import aimax.osm.viewer.AbstractEntityRenderer;
import aimax.osm.viewer.MapStyleFactory;
import aimax.osm.viewer.MapViewFrame;

/**
* Configurable application which shows a map and location information from a
* GPS connection, and additionally provides routing functionality.
* <p>
* This implementation provides a simple reflection-based mechanism which allows
* to replace the standard implementations of all fundamental components by
* other implementations. For example, to replace the route calculator just
* create a class <code>x.y.ZRouteCalculator</code> as subclass of
* <code>RouteCalculator</code> and add in the main method the line
* <code>System.setProperty(MiniNaviApp.MAP_CLASS_PROPERTY, "x.y.ZRouteCalculator</code>
* . Analogously, renderer, entity classifier, and even the map representation
* itself can be replaced. Note, that system properties can also be set by
* VM argument (-Dpropertyname=value).
* </p>
* <p>
* To enable the GPS interface, download the rs232 serial port library from
* http://www.rxtx.org, install it correctly, and rename file
* <code>NmeaSerialPortReader.txt</code> in package <code>aimax.osm.gps</code>
* to <code>NmeaSerialPortReader.java</code>. One possible choice for
* installation is, to add the jar-file to the class path (project properties,
* add jar), to store the DDL locally (e.g. in project-root/lib), and start the
* application with VM argument <code>-Djava.library.path=lib -Xmx1500M</code>.
* </p>
*
* @author Ruediger Lunde
*/
public class MiniNaviApp implements ActionListener {

  protected static Logger LOG = Logger.getLogger("aimax.osm");

  public final static String MAP_CLASS_PROPERTY = "aimax.osm.navi.mapclass";
  public final static String CLASSIFIER_CLASS_PROPERTY = "aimax.osm.navi.classifierclass";
  public final static String RENDERER_CLASS_PROPERTY = "aimax.osm.navi.rendererclass";
  public final static String ROUTECALCULATOR_CLASS_PROPERTY = "aimax.osm.navi.routecalculatorclass";

  public final static String ROUTE_TRACK_NAME = "Route";
  public final static String GPS_TRACK_NAME = "GPS";

  protected MapViewFrame frame;
  protected GpsLocator locator;
  protected MessageToFileListener nmeaLogger;
  protected RouteCalculator routeCalculator;
  protected RoutingThread routingThread;

  protected JComboBox gpsCombo;
  protected JFileChooser gpsFileChooser;
  protected JComboBox waySelection;
  protected JButton calcButton;

  public MiniNaviApp(String[] args) {
    initFrame(args);
    locator = new GpsLocator();
    locator.addGpsPositionListener(new MyGpsPositionListener());
    routeCalculator = (RouteCalculator) createComponent(
        ROUTECALCULATOR_CLASS_PROPERTY, RouteCalculator.class);
    if (routeCalculator == null)
      routeCalculator = new RouteCalculator();

    JToolBar toolbar = frame.getToolbar();
    gpsCombo = new JComboBox(new String[] { "GPS Off", "GPS On",
        "GPS Center", "GPS Cen+Log", "Read Log" });
    gpsCombo.addActionListener(this);
    toolbar.addSeparator();
    toolbar.add(gpsCombo);

    waySelection = new JComboBox(routeCalculator.getWaySelectionOptions());
    toolbar.add(waySelection);
    toolbar.addSeparator();
    calcButton = new JButton("Calculate Route");
    toolbar.add(calcButton);
    calcButton.addActionListener(this);
  }

  protected void initFrame(String[] args) {
    frame = new ConfigurableMapViewFrame(args);
    frame.setTitle("MiniNavi");
  }

  public MapViewFrame getFrame() {
    return frame;
  }

  public OsmMap getMap() {
    return frame.getMap();
  }

  public void showFrame() {
    frame.setSize(800, 600);
    frame.setVisible(true);
  }

  @Override
  public void actionPerformed(ActionEvent event) {
    if (event.getSource() == gpsCombo) {
      getMap().clearTrack(GPS_TRACK_NAME);
      try {
        if (gpsFileChooser == null)
          gpsFileChooser = new JFileChooser();
        if (nmeaLogger != null) {
          nmeaLogger.closeFile();
          locator.getNmeaReader().removeListener(nmeaLogger);
          nmeaLogger = null;
        }
        if (gpsCombo.getSelectedIndex() < 1) { // GPS Off
          locator.closeConnection();
        } else if (gpsCombo.getSelectedIndex() < 4) { // GPS On
          locator.openSerialPortConnection();
          if (locator.isConnected()) {
            if (gpsCombo.getSelectedIndex() == 3
                && gpsFileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
              nmeaLogger = new MessageToFileListener();
              locator.getNmeaReader().addListener(nmeaLogger);
              nmeaLogger.openFile(gpsFileChooser
                  .getSelectedFile());
            }
          } else { // Establishing connection to GPS failed
            gpsCombo.setSelectedIndex(0);
          }
        } else if (gpsFileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) { // simulate
          // GPS
          locator
              .openFileConnection(gpsFileChooser
                  .getSelectedFile());
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    } else if (event.getSource() == calcButton) {
      if (routingThread != null) {
        routingThread.cancel();
      } else {
        List<MapNode> markers = getMap().getMarkers();
        if (!markers.isEmpty()) {
          List<MapNode> routeMarkers = new ArrayList<MapNode>();
          Track gpsTrack = getMap().getTrack(GPS_TRACK_NAME);
          if (gpsTrack != null) {
            routeMarkers.add(gpsTrack.getLastNode());
            routeMarkers.add(markers.get(0));
          } else {
            routeMarkers.addAll(markers);
          }
          routingThread = new RoutingThread(routeMarkers);
          updateEnabledState();
          routingThread.start();
        }
      }
    }
  }

  protected void updateEnabledState() {
    frame.getLoadButton().setEnabled(routingThread == null);
    frame.getSaveButton().setEnabled(routingThread == null);
    calcButton.setText(routingThread == null ? "Calculate Route"
        : "Cancel Calculation");
  }

  protected static Object createComponent(String property, Class<?> oclass) {
    Object result = null;
    String className = System.getProperty(property);
    if (className != null) {
      try {
        Class<?> c = Class.forName(className);
        result = c.newInstance();
        if (!oclass.isInstance(result)) {
          LOG.warning("Component instantiation failed. Class "
              + className + " is not of type "
              + oclass.getCanonicalName() + ".");
        }
      } catch (Exception e) {
        LOG.warning("Component instantiation failed. Class "
            + className + " could not be loaded correctly.");
      }
    }
    return result;
  }

  // ///////////////////////////////////////////////////////////////
  // inner classes

  class RoutingThread extends CancelableThread {
    List<MapNode> routeMarkers;
    List<Position> positions;

    public RoutingThread(List<MapNode> routeMarkers) {
      this.routeMarkers = routeMarkers;
    }

    @Override
    public void interrupt() {
      cancel();
      super.interrupt();
    }

    @Override
    public void run() {
      try {
        positions = routeCalculator.calculateRoute(routeMarkers, frame
            .getMap(), waySelection.getSelectedIndex());
      } catch (Exception e) {
        e.printStackTrace(); // for debugging
      }
      try {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            frame.getMap().createTrack(ROUTE_TRACK_NAME, positions);
            routingThread = null;
            updateEnabledState();
          }
        });
      } catch (Exception e) {
        e.printStackTrace(); // for debugging
      }
    }
  }

  class MyGpsPositionListener implements GpsPositionListener {
    @Override
    public void positionUpdated(GpsFix pos) {
      if (pos.isPosOk()) {
        OsmMap mapData = frame.getMap();
        Track track = mapData.getTrack(GPS_TRACK_NAME);
        MapNode node = null;
        if (track != null)
          node = track.getLastNode();
        if (node == null || pos.getDistKM(node) > 0.01) {
          mapData.addToTrack(GPS_TRACK_NAME, pos);
          if (gpsCombo.getSelectedIndex() == 2
              || gpsCombo.getSelectedIndex() == 3)
            frame.getView().adjustToCenter(pos.getLat(),
                pos.getLon());
        }
      }
    }
  }

  static class ConfigurableMapViewFrame extends MapViewFrame {
    private static final long serialVersionUID = 1L;

    ConfigurableMapViewFrame(String[] args) {
      super(args);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void initMapAndClassifier() {
      OsmMap map = (OsmMap) createComponent(MAP_CLASS_PROPERTY,
          OsmMap.class);
      if (map == null)
        map = new DefaultMap();
      view.setMap(map);
      classifier = (EntityClassifier<EntityViewInfo>) createComponent(
          CLASSIFIER_CLASS_PROPERTY, EntityClassifier.class);
      if (classifier == null)
        classifier = new MapStyleFactory().createDefaultClassifier();
      AbstractEntityRenderer renderer = (AbstractEntityRenderer) createComponent(
          RENDERER_CLASS_PROPERTY, AbstractEntityRenderer.class);
      if (renderer != null)
        view.setRenderer(renderer);
    }
  }

  // ///////////////////////////////////////////////////////////////
  // application starter

  /**
   * Start application with VM arg <code>-Djava.library.path=lib</code> and
   * program arg <code>-screenwidth=xx</code> (with xx the width in cm) or
   * <code>-screensize=yy</code> (with yy measured diagonally in inch).
   */
  public static void main(String[] args) {
    // indicates progress when reading large maps (for testing only)
    Logger.getLogger("aimax.osm").setLevel(Level.FINEST);
    Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);

    Locale.setDefault(Locale.US);
    // System.setProperty(MiniNaviApp.MAP_CLASS_PROPERTY,
    // "rl.osm.data.perst.PerstMap");
    MiniNaviApp demo = new MiniNaviApp(args);
    demo.getFrame().readMap(DataResource.getULMFileResource());
    // demo.getFrame().readMap(new File("maps/ulm.osm"));
    demo.showFrame();
  }
}
TOP

Related Classes of aimax.osm.applications.MiniNaviApp$MyGpsPositionListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.