From 24eeab7971f64d65e4210ae7cb5ce8b72a424c28 Mon Sep 17 00:00:00 2001 From: Mikael Capelle Date: Fri, 23 Feb 2018 20:39:56 +0100 Subject: [PATCH] Update MapViewer. --- src/main/org/insa/base/MainWindow.java | 1086 +++++++++-------- src/main/org/insa/base/Samples.java | 411 ++++--- src/main/org/insa/drawing/MapViewDrawing.java | 343 +++--- 3 files changed, 936 insertions(+), 904 deletions(-) diff --git a/src/main/org/insa/base/MainWindow.java b/src/main/org/insa/base/MainWindow.java index 01b45dc..28b5c30 100644 --- a/src/main/org/insa/base/MainWindow.java +++ b/src/main/org/insa/base/MainWindow.java @@ -13,7 +13,6 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.geom.NoninvertibleTransformException; import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; @@ -43,9 +42,9 @@ import javax.swing.filechooser.FileNameExtensionFilter; import org.insa.algo.shortestpath.BellmanFordAlgorithm; import org.insa.algo.shortestpath.ShortestPathAlgorithm; -import org.insa.algo.shortestpath.ShortestPathGraphicObserver; import org.insa.algo.shortestpath.ShortestPathData; import org.insa.algo.shortestpath.ShortestPathData.Mode; +import org.insa.algo.shortestpath.ShortestPathGraphicObserver; import org.insa.algo.shortestpath.ShortestPathSolution; import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver; import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm; @@ -67,583 +66,586 @@ import org.insa.graph.io.Openfile; public class MainWindow extends JFrame { - protected class JOutputStream extends OutputStream { - private JTextArea textArea; + protected class JOutputStream extends OutputStream { + private JTextArea textArea; - public JOutputStream(JTextArea textArea) { - this.textArea = textArea; - } - - @Override - public void write(int b) throws IOException { - // redirects data to the text area - textArea.setText(textArea.getText() + String.valueOf((char)b)); - // scrolls the text area to the end of data - textArea.setCaretPosition(textArea.getDocument().getLength()); - // keeps the textArea up to date - textArea.update(textArea.getGraphics()); - } - } - - protected interface CallableWithNodes { - - void call(ArrayList nodes); - - }; - - protected class DrawingClickListener extends MouseAdapter { - - // Enable/Disable. - private boolean enabled = false; - - // List of points. - private ArrayList points = new ArrayList(); - - // Number of points to find before running. - private int nTargetPoints = 0; - - // Callable to call when points are reached. - CallableWithNodes callable = null; - - /** - * @return true if this listener is enabled. - */ - public boolean isEnabled() { - return enabled; - } - - /** - * Enable this listener. - * - * @param nTargetPoints Number of point to found before calling the callable. - */ - public void enable(int nTargetPoints, CallableWithNodes callable) { - this.enabled = true; - this.nTargetPoints = nTargetPoints; - this.points.clear(); - this.callable = callable; - } - - /** - * Disable this listener. - */ - public void disable() { - this.enabled = false; - } - - public void mouseClicked(MouseEvent evt) { - if (!isEnabled()) { - return; - } - Point lonlat; - try { - // TODO: Fix - lonlat = ((BasicDrawing)drawing).getLongitudeLatitude(evt); - } - catch (NoninvertibleTransformException e) { - // Should never happens in "normal" circumstances... - e.printStackTrace(); - return; - } - - Node node = graph.findClosestNode(lonlat); - - drawing.drawMarker(node.getPoint(), Color.BLUE); - points.add(node); - if (points.size() == nTargetPoints) { - callable.call(points); - this.disable(); - } + public JOutputStream(JTextArea textArea) { + this.textArea = textArea; } - }; - - /** - * - */ - private static final long serialVersionUID = -527660583705140687L; - /** - * - */ - private static final String WINDOW_TITLE = "BE Graphes INSA"; - - /** - * - */ - private static final int THREAD_TIMER_DELAY = 1000; // in milliseconds + @Override + public void write(int b) throws IOException { + // redirects data to the text area + textArea.setText(textArea.getText() + String.valueOf((char) b)); + // scrolls the text area to the end of data + textArea.setCaretPosition(textArea.getDocument().getLength()); + // keeps the textArea up to date + textArea.update(textArea.getGraphics()); + } + } - // Current graph. - private Graph graph; + protected interface CallableWithNodes { - // Current loaded path. - private Path currentPath; + void call(ArrayList nodes); - // Drawing and click adapter. - private Drawing drawing; - private DrawingClickListener clickAdapter; - - // Main panel. - private JSplitPane mainPanel; - - // List of item for the top menus. - private JMenuItem openMapItem; + }; - // List of items that cannot be used without a graph - private ArrayList graphLockItems = new ArrayList(); - - // Label containing the map ID of the current graph. - private JLabel mapIdPanel; - - // Thread information - private Instant threadStartTime; - private Timer threadTimer; - private JPanel threadPanel; + protected class DrawingClickListener extends MouseAdapter { - // Log stream and print stream - private JOutputStream logStream; - - @SuppressWarnings("unused") - private PrintStream printStream; - - // Current running thread - private Thread currentThread; + // Enable/Disable. + private boolean enabled = false; - public MainWindow() { - super(WINDOW_TITLE); - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - setLayout(new BorderLayout()); - setJMenuBar(createMenuBar()); + // List of points. + private ArrayList points = new ArrayList(); - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - int confirmed = JOptionPane.showConfirmDialog(null, - "Are you sure you want to close the application?", "Exit Confirmation", - JOptionPane.YES_NO_OPTION); + // Number of points to find before running. + private int nTargetPoints = 0; - if (confirmed == JOptionPane.YES_OPTION) { - dispose(); - System.exit(0); - } - } - }); + // Callable to call when points are reached. + CallableWithNodes callable = null; - // Create graph area - mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + /** + * @return true if this listener is enabled. + */ + public boolean isEnabled() { + return enabled; + } - BasicDrawing drawing = new BasicDrawing(); - // MapViewDrawing drawing = new MapViewDrawing(); - - Component drawingComponent = drawing; - this.drawing = drawing; - - // Click adapter - this.clickAdapter = new DrawingClickListener(); - // drawing.addMouseListener(this.clickAdapter); + /** + * Enable this listener. + * + * @param nTargetPoints Number of point to found before calling the callable. + */ + public void enable(int nTargetPoints, CallableWithNodes callable) { + this.enabled = true; + this.nTargetPoints = nTargetPoints; + this.points.clear(); + this.callable = callable; + } - JTextArea infoPanel = new JTextArea(); - infoPanel.setMinimumSize(new Dimension(200, 50)); - // infoPanel.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.GRAY)); - infoPanel.setBackground(Color.WHITE); - infoPanel.setLineWrap(true); - infoPanel.setEditable(false); - this.logStream = new JOutputStream(infoPanel); - this.printStream = new PrintStream(this.logStream); + /** + * Disable this listener. + */ + public void disable() { + this.enabled = false; + } - mainPanel.setResizeWeight(0.8); - // sp.setEnabled(false); - mainPanel.setDividerSize(5); + public void mouseClicked(MouseEvent evt) { + if (!isEnabled()) { + return; + } + Point lonlat; + try { + // TODO: Fix + lonlat = ((BasicDrawing) drawing).getLongitudeLatitude(evt); + } + catch (NoninvertibleTransformException e) { + // Should never happens in "normal" circumstances... + e.printStackTrace(); + return; + } - mainPanel.setBackground(Color.WHITE); - mainPanel.add(drawingComponent); - mainPanel.add(new JScrollPane(infoPanel)); - this.add(mainPanel, BorderLayout.CENTER); - - // Top Panel - this.add(createTopPanel(), BorderLayout.NORTH); - this.add(createStatusBar(), BorderLayout.SOUTH); - } - - private void restartThreadTimer() { - threadStartTime = Instant.now(); - threadTimer.restart(); - } - - private void stopThreadTimer() { - threadTimer.stop(); - } - - /** - * @param runnable - * @param canInterrupt - */ - private void launchThread(Runnable runnable, boolean canInterrupt) { - if (canInterrupt) { - currentThread = new Thread(new Runnable() { - @Override - public void run() { - restartThreadTimer(); - threadPanel.setVisible(true); - runnable.run(); - clearCurrentThread(); - } - }); - } - else { - currentThread = new Thread(runnable); - } - currentThread.start(); - } - private void launchThread(Runnable runnable) { - launchThread(runnable, true); - } - - - private void clearCurrentThread() { - stopThreadTimer(); - threadPanel.setVisible(false); - currentThread = null; - } - - private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) { - spAlgorithm.addObserver(new ShortestPathGraphicObserver(drawing)); - // algo.addObserver(new ShortestPathTextObserver(printStream)); - launchThread(new Runnable() { - @Override - public void run() { - ShortestPathSolution solution = spAlgorithm.run(); - if (solution != null && solution.isFeasible()) { - drawing.drawPath(solution.getPath()); - } - } - }); - } - - private JMenuBar createMenuBar() { + Node node = graph.findClosestNode(lonlat); - // Open Map item... - openMapItem = new JMenuItem("Open Map... ", - KeyEvent.VK_O); - openMapItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_O, ActionEvent.ALT_MASK)); - openMapItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser chooser = new JFileChooser(); - FileNameExtensionFilter filter = new FileNameExtensionFilter( - "Map & compressed map files", "map", "map2", "map.gz"); - chooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); - chooser.setFileFilter(filter); - if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) { - launchThread(new Runnable() { - @Override - public void run() { - String path = chooser.getSelectedFile().getAbsolutePath(); - DataInputStream stream; - try { - stream = Openfile.open(path); - } catch (IOException e1) { - JOptionPane.showMessageDialog(MainWindow.this, "Cannot open the selected file."); - return ; - } - AbstractGraphReader reader; - if (path.endsWith(".map2")) { - reader = new BinaryGraphReaderV2(stream); - } - else { - reader = new BinaryGraphReader(stream); - } - try { - graph = reader.read(); - } - catch (Exception exception) { - JOptionPane.showMessageDialog(MainWindow.this, "Unable to read graph from the selected file."); - exception.printStackTrace(System.out); - return ; - } - drawing.clear(); - drawing.drawGraph(graph); + drawing.drawMarker(node.getPoint(), Color.BLUE); + points.add(node); + if (points.size() == nTargetPoints) { + callable.call(points); + this.disable(); + } + } + }; - for (JMenuItem item: graphLockItems) { - item.setEnabled(true); - } - mapIdPanel.setText("Map ID: 0x" + Integer.toHexString(graph.getMapId())); - } - }, false); - } - } - }); + /** + * + */ + private static final long serialVersionUID = -527660583705140687L; - // Open Path item... - JMenuItem openPathItem = new JMenuItem("Open Path... ", KeyEvent.VK_P); - openPathItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_P, ActionEvent.ALT_MASK)); - openPathItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser chooser = new JFileChooser(); - FileNameExtensionFilter filter = new FileNameExtensionFilter( - "Path & compressed path files", "path", "path.gz"); - chooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); - chooser.setFileFilter(filter); - if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) { - BinaryPathReader reader; - try { - reader = new BinaryPathReader( - Openfile.open(chooser.getSelectedFile().getAbsolutePath())); - } catch (IOException e1) { - JOptionPane.showMessageDialog(MainWindow.this, "Cannot open the selected file."); - return ; - } - try { - currentPath = reader.readPath(graph); - } - catch (MapMismatchException exception) { - JOptionPane.showMessageDialog(MainWindow.this, "The selected file does not contain a path for the current graph."); - return; - } - catch (Exception exception) { - JOptionPane.showMessageDialog(MainWindow.this, "Unable to read path from the selected file."); - return ; - } - drawing.drawPath(currentPath); - } - } - }); - graphLockItems.add(openPathItem); + /** + * + */ + private static final String WINDOW_TITLE = "BE Graphes INSA"; - // Close item - JMenuItem closeItem = new JMenuItem("Quit", KeyEvent.VK_Q); - closeItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_Q, ActionEvent.ALT_MASK)); - closeItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - MainWindow.this.dispatchEvent(new WindowEvent(MainWindow.this, WindowEvent.WINDOW_CLOSING)); - } - }); + /** + * + */ + private static final int THREAD_TIMER_DELAY = 1000; // in milliseconds - //Build the first menu. - JMenu fileMenu = new JMenu("File"); - fileMenu.add(openMapItem); - fileMenu.add(openPathItem); - fileMenu.addSeparator(); - fileMenu.add(closeItem); + // Current graph. + private Graph graph; - // Second menu - JMenuItem drawGraphItem = new JMenuItem("Redraw", KeyEvent.VK_R); - drawGraphItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_R, ActionEvent.ALT_MASK)); - drawGraphItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - launchThread(new Runnable() { - @Override - public void run() { - if (!(drawing instanceof BasicDrawing)) { - BasicDrawing tmp = new BasicDrawing(); - mainPanel.setLeftComponent(tmp); - drawing = tmp; - } - drawing.clear(); - drawing.drawGraph(graph); - } - }); - } - }); - graphLockItems.add(drawGraphItem); - JMenuItem drawGraphBWItem = new JMenuItem("Redraw (B&W)", KeyEvent.VK_B); - drawGraphBWItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_B, ActionEvent.ALT_MASK)); - drawGraphBWItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - launchThread(new Runnable() { - @Override - public void run() { - if (!(drawing instanceof BasicDrawing)) { - BasicDrawing tmp = new BasicDrawing(); - mainPanel.setLeftComponent(tmp); - drawing = tmp; - } - drawing.clear(); - drawing.drawGraph(graph, new BlackAndWhiteGraphPalette()); - } - }); - } - }); - graphLockItems.add(drawGraphBWItem); - JMenuItem drawGraphMapsforgeItem = new JMenuItem("Redraw (Map)", KeyEvent.VK_M); - drawGraphMapsforgeItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_M, ActionEvent.ALT_MASK)); - drawGraphMapsforgeItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - launchThread(new Runnable() { - @Override - public void run() { - if (!(drawing instanceof MapViewDrawing)) { - MapViewDrawing tmp = new MapViewDrawing(); - mainPanel.setLeftComponent(tmp); - drawing = tmp; - } - drawing.clear(); - drawing.drawGraph(graph, new BlackAndWhiteGraphPalette()); - } - }); - } - }); - graphLockItems.add(drawGraphMapsforgeItem); + // Current loaded path. + private Path currentPath; - JMenu graphMenu = new JMenu("Graph"); - graphMenu.add(drawGraphItem); - graphMenu.add(drawGraphBWItem); - graphMenu.addSeparator(); - graphMenu.add(drawGraphMapsforgeItem); + // Drawing and click adapter. + private Drawing drawing; + private DrawingClickListener clickAdapter; - // Algo menu - JMenu algoMenu = new JMenu("Algorithms"); + // Main panel. + private JSplitPane mainPanel; - // Weakly connected components - JMenuItem wccItem = new JMenuItem("Weakly Connected Components"); - wccItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - WeaklyConnectedComponentsData instance = new WeaklyConnectedComponentsData(graph); - WeaklyConnectedComponentsAlgorithm algo = new WeaklyConnectedComponentsAlgorithm(instance); - algo.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing)); - // algo.addObserver(new WeaklyConnectedComponentTextObserver(printStream)); - launchThread(new Runnable() { - @Override - public void run() { - algo.run(); - } - }); - } - }); + // List of item for the top menus. + private JMenuItem openMapItem; - // Shortest path - JMenuItem bellmanItem = new JMenuItem("Shortest Path (Bellman-Ford)"); - bellmanItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - int idx = JOptionPane.showOptionDialog(MainWindow.this, - "Which mode do you want?", "Mode selection", - JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, - null, Mode.values(), Mode.LENGTH); - - if (idx != -1) { - Mode mode = Mode.values()[idx]; - clickAdapter.enable(2, new CallableWithNodes() { - @Override - public void call(ArrayList nodes) { - launchShortestPathThread(new BellmanFordAlgorithm( - new ShortestPathData(graph, nodes.get(0), nodes.get(1), mode))); - } - }); - } - } - }); - graphLockItems.add(wccItem); - graphLockItems.add(bellmanItem); + // List of items that cannot be used without a graph + private ArrayList graphLockItems = new ArrayList(); - algoMenu.add(wccItem); - algoMenu.addSeparator(); - algoMenu.add(bellmanItem); - // algoMenu.add(djikstraItem); - // algoMenu.add(aStarItem); + // Label containing the map ID of the current graph. + private JLabel mapIdPanel; - // Create the menu bar. - JMenuBar menuBar = new JMenuBar(); + // Thread information + private Instant threadStartTime; + private Timer threadTimer; + private JPanel threadPanel; - menuBar.add(fileMenu); - menuBar.add(graphMenu); - menuBar.add(algoMenu); + // Log stream and print stream + private JOutputStream logStream; - for (JMenuItem item: graphLockItems) { - item.setEnabled(false); - } - - return menuBar; - } - - @SuppressWarnings("deprecation") - private void stopCurrentThread() { - // Should not be used in production code, but here I have no idea how - // to do this properly... Cannot use .interrupt() because it would requires - // the algorithm to watch the ThreadInteruption exception. - currentThread.stop(); - } + @SuppressWarnings("unused") + private PrintStream printStream; - private JPanel createStatusBar() { - // create the status bar panel and shove it down the bottom of the frame - JPanel statusPanel = new JPanel(); - statusPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY)); - statusPanel.setPreferredSize(new Dimension(getWidth(), 38)); - statusPanel.setLayout(new BorderLayout()); + // Current running thread + private Thread currentThread; - mapIdPanel = new JLabel(); - mapIdPanel.setHorizontalAlignment(SwingConstants.LEFT); - statusPanel.add(mapIdPanel, BorderLayout.WEST); - - JLabel threadInfo = new JLabel("Thread running... "); - JLabel threadTimerLabel = new JLabel("00:00:00"); - JButton threadButton = new JButton("Stop"); - threadButton.addActionListener(new ActionListener() { + public MainWindow() { + super(WINDOW_TITLE); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + setLayout(new BorderLayout()); + setJMenuBar(createMenuBar()); - @Override - public void actionPerformed(ActionEvent e) { - if (currentThread != null && currentThread.isAlive()) { - int confirmed = JOptionPane.showConfirmDialog(null, - "Are you sure you want to kill the running thread?", "Kill Confirmation", - JOptionPane.YES_NO_OPTION); - if (confirmed == JOptionPane.YES_OPTION) { - stopCurrentThread(); - clearCurrentThread(); - threadPanel.setVisible(false); - } - } - } - }); - - threadTimer = new Timer(THREAD_TIMER_DELAY, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Duration elapsed = Duration.between(threadStartTime, Instant.now()); - long seconds = elapsed.getSeconds(); - threadTimerLabel.setText(String.format( - "%02d:%02d:%02d", seconds/3600, seconds/60 % 60, seconds % 60)); - } - }); - threadTimer.setInitialDelay(0); - - threadPanel = new JPanel(); - threadPanel.add(threadInfo); - threadPanel.add(threadTimerLabel); - threadPanel.add(threadButton); - threadPanel.setVisible(false); - statusPanel.add(threadPanel, BorderLayout.EAST); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + int confirmed = JOptionPane.showConfirmDialog(null, + "Are you sure you want to close the application?", "Exit Confirmation", + JOptionPane.YES_NO_OPTION); - return statusPanel; - } + if (confirmed == JOptionPane.YES_OPTION) { + dispose(); + System.exit(0); + } + } + }); - protected JPanel createTopPanel() { - JPanel topPanel = new JPanel(); - - return topPanel; - } - - public static void main(final String[] args) { + // Create graph area + mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - // Try to set system look and feel. - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) ; - } - catch (Exception e) { } + BasicDrawing drawing = new BasicDrawing(); + // MapViewDrawing drawing = new MapViewDrawing(); - MainWindow w = new MainWindow(); - w.setExtendedState(JFrame.MAXIMIZED_BOTH); - w.setVisible(true); - } + Component drawingComponent = drawing; + this.drawing = drawing; + // Click adapter + this.clickAdapter = new DrawingClickListener(); + // drawing.addMouseListener(this.clickAdapter); + + JTextArea infoPanel = new JTextArea(); + infoPanel.setMinimumSize(new Dimension(200, 50)); + // infoPanel.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.GRAY)); + infoPanel.setBackground(Color.WHITE); + infoPanel.setLineWrap(true); + infoPanel.setEditable(false); + this.logStream = new JOutputStream(infoPanel); + this.printStream = new PrintStream(this.logStream); + + mainPanel.setResizeWeight(0.8); + // sp.setEnabled(false); + mainPanel.setDividerSize(5); + + mainPanel.setBackground(Color.WHITE); + mainPanel.add(drawingComponent); + mainPanel.add(new JScrollPane(infoPanel)); + this.add(mainPanel, BorderLayout.CENTER); + + // Top Panel + this.add(createTopPanel(), BorderLayout.NORTH); + this.add(createStatusBar(), BorderLayout.SOUTH); + } + + private void restartThreadTimer() { + threadStartTime = Instant.now(); + threadTimer.restart(); + } + + private void stopThreadTimer() { + threadTimer.stop(); + } + + /** + * @param runnable + * @param canInterrupt + */ + private void launchThread(Runnable runnable, boolean canInterrupt) { + if (canInterrupt) { + currentThread = new Thread(new Runnable() { + @Override + public void run() { + restartThreadTimer(); + threadPanel.setVisible(true); + runnable.run(); + clearCurrentThread(); + } + }); + } + else { + currentThread = new Thread(runnable); + } + currentThread.start(); + } + + private void launchThread(Runnable runnable) { + launchThread(runnable, true); + } + + private void clearCurrentThread() { + stopThreadTimer(); + threadPanel.setVisible(false); + currentThread = null; + } + + private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) { + spAlgorithm.addObserver(new ShortestPathGraphicObserver(drawing)); + // algo.addObserver(new ShortestPathTextObserver(printStream)); + launchThread(new Runnable() { + @Override + public void run() { + ShortestPathSolution solution = spAlgorithm.run(); + if (solution != null && solution.isFeasible()) { + drawing.drawPath(solution.getPath()); + } + } + }); + } + + private JMenuBar createMenuBar() { + + // Open Map item... + openMapItem = new JMenuItem("Open Map... ", KeyEvent.VK_O); + openMapItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK)); + openMapItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = new JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter( + "Map & compressed map files", "map", "map2", "mapgr", "map.gz"); + chooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); + chooser.setFileFilter(filter); + if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) { + launchThread(new Runnable() { + @Override + public void run() { + String path = chooser.getSelectedFile().getAbsolutePath(); + DataInputStream stream; + try { + stream = Openfile.open(path); + } + catch (IOException e1) { + JOptionPane.showMessageDialog(MainWindow.this, + "Cannot open the selected file."); + return; + } + AbstractGraphReader reader; + if (path.endsWith(".map2") || path.endsWith("mapgr")) { + reader = new BinaryGraphReaderV2(stream); + } + else { + reader = new BinaryGraphReader(stream); + } + try { + graph = reader.read(); + } + catch (Exception exception) { + JOptionPane.showMessageDialog(MainWindow.this, + "Unable to read graph from the selected file."); + exception.printStackTrace(System.out); + return; + } + drawing.clear(); + drawing.drawGraph(graph); + + for (JMenuItem item: graphLockItems) { + item.setEnabled(true); + } + mapIdPanel + .setText("Map ID: 0x" + Integer.toHexString(graph.getMapId())); + } + }, false); + } + } + }); + + // Open Path item... + JMenuItem openPathItem = new JMenuItem("Open Path... ", KeyEvent.VK_P); + openPathItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.ALT_MASK)); + openPathItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = new JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter( + "Path & compressed path files", "path", "path.gz"); + chooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); + chooser.setFileFilter(filter); + if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) { + BinaryPathReader reader; + try { + reader = new BinaryPathReader( + Openfile.open(chooser.getSelectedFile().getAbsolutePath())); + } + catch (IOException e1) { + JOptionPane.showMessageDialog(MainWindow.this, + "Cannot open the selected file."); + return; + } + try { + currentPath = reader.readPath(graph); + } + catch (MapMismatchException exception) { + JOptionPane.showMessageDialog(MainWindow.this, + "The selected file does not contain a path for the current graph."); + return; + } + catch (Exception exception) { + JOptionPane.showMessageDialog(MainWindow.this, + "Unable to read path from the selected file."); + return; + } + drawing.drawPath(currentPath); + } + } + }); + graphLockItems.add(openPathItem); + + // Close item + JMenuItem closeItem = new JMenuItem("Quit", KeyEvent.VK_Q); + closeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.ALT_MASK)); + closeItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + MainWindow.this.dispatchEvent( + new WindowEvent(MainWindow.this, WindowEvent.WINDOW_CLOSING)); + } + }); + + // Build the first menu. + JMenu fileMenu = new JMenu("File"); + fileMenu.add(openMapItem); + fileMenu.add(openPathItem); + fileMenu.addSeparator(); + fileMenu.add(closeItem); + + // Second menu + JMenuItem drawGraphItem = new JMenuItem("Redraw", KeyEvent.VK_R); + drawGraphItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.ALT_MASK)); + drawGraphItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + launchThread(new Runnable() { + @Override + public void run() { + if (!(drawing instanceof BasicDrawing)) { + BasicDrawing tmp = new BasicDrawing(); + mainPanel.setLeftComponent(tmp); + drawing = tmp; + } + drawing.clear(); + drawing.drawGraph(graph); + } + }); + } + }); + graphLockItems.add(drawGraphItem); + JMenuItem drawGraphBWItem = new JMenuItem("Redraw (B&W)", KeyEvent.VK_B); + drawGraphBWItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.ALT_MASK)); + drawGraphBWItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + launchThread(new Runnable() { + @Override + public void run() { + if (!(drawing instanceof BasicDrawing)) { + BasicDrawing tmp = new BasicDrawing(); + mainPanel.setLeftComponent(tmp); + drawing = tmp; + } + drawing.clear(); + drawing.drawGraph(graph, new BlackAndWhiteGraphPalette()); + } + }); + } + }); + graphLockItems.add(drawGraphBWItem); + JMenuItem drawGraphMapsforgeItem = new JMenuItem("Redraw (Map)", KeyEvent.VK_M); + drawGraphMapsforgeItem + .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.ALT_MASK)); + drawGraphMapsforgeItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + launchThread(new Runnable() { + @Override + public void run() { + if (!(drawing instanceof MapViewDrawing)) { + MapViewDrawing tmp = new MapViewDrawing(); + mainPanel.setLeftComponent(tmp); + drawing = tmp; + } + drawing.clear(); + drawing.drawGraph(graph, new BlackAndWhiteGraphPalette()); + } + }); + } + }); + graphLockItems.add(drawGraphMapsforgeItem); + + JMenu graphMenu = new JMenu("Graph"); + graphMenu.add(drawGraphItem); + graphMenu.add(drawGraphBWItem); + graphMenu.addSeparator(); + graphMenu.add(drawGraphMapsforgeItem); + + // Algo menu + JMenu algoMenu = new JMenu("Algorithms"); + + // Weakly connected components + JMenuItem wccItem = new JMenuItem("Weakly Connected Components"); + wccItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + WeaklyConnectedComponentsData instance = new WeaklyConnectedComponentsData(graph); + WeaklyConnectedComponentsAlgorithm algo = new WeaklyConnectedComponentsAlgorithm( + instance); + algo.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing)); + // algo.addObserver(new WeaklyConnectedComponentTextObserver(printStream)); + launchThread(new Runnable() { + @Override + public void run() { + algo.run(); + } + }); + } + }); + + // Shortest path + JMenuItem bellmanItem = new JMenuItem("Shortest Path (Bellman-Ford)"); + bellmanItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int idx = JOptionPane.showOptionDialog(MainWindow.this, "Which mode do you want?", + "Mode selection", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, + null, Mode.values(), Mode.LENGTH); + + if (idx != -1) { + Mode mode = Mode.values()[idx]; + clickAdapter.enable(2, new CallableWithNodes() { + @Override + public void call(ArrayList nodes) { + launchShortestPathThread(new BellmanFordAlgorithm( + new ShortestPathData(graph, nodes.get(0), nodes.get(1), mode))); + } + }); + } + } + }); + graphLockItems.add(wccItem); + graphLockItems.add(bellmanItem); + + algoMenu.add(wccItem); + algoMenu.addSeparator(); + algoMenu.add(bellmanItem); + // algoMenu.add(djikstraItem); + // algoMenu.add(aStarItem); + + // Create the menu bar. + JMenuBar menuBar = new JMenuBar(); + + menuBar.add(fileMenu); + menuBar.add(graphMenu); + menuBar.add(algoMenu); + + for (JMenuItem item: graphLockItems) { + item.setEnabled(false); + } + + return menuBar; + } + + @SuppressWarnings("deprecation") + private void stopCurrentThread() { + // Should not be used in production code, but here I have no idea how + // to do this properly... Cannot use .interrupt() because it would requires + // the algorithm to watch the ThreadInteruption exception. + currentThread.stop(); + } + + private JPanel createStatusBar() { + // create the status bar panel and shove it down the bottom of the frame + JPanel statusPanel = new JPanel(); + statusPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY)); + statusPanel.setPreferredSize(new Dimension(getWidth(), 38)); + statusPanel.setLayout(new BorderLayout()); + + mapIdPanel = new JLabel(); + mapIdPanel.setHorizontalAlignment(SwingConstants.LEFT); + statusPanel.add(mapIdPanel, BorderLayout.WEST); + + JLabel threadInfo = new JLabel("Thread running... "); + JLabel threadTimerLabel = new JLabel("00:00:00"); + JButton threadButton = new JButton("Stop"); + threadButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (currentThread != null && currentThread.isAlive()) { + int confirmed = JOptionPane.showConfirmDialog(null, + "Are you sure you want to kill the running thread?", + "Kill Confirmation", JOptionPane.YES_NO_OPTION); + if (confirmed == JOptionPane.YES_OPTION) { + stopCurrentThread(); + clearCurrentThread(); + threadPanel.setVisible(false); + } + } + } + }); + + threadTimer = new Timer(THREAD_TIMER_DELAY, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Duration elapsed = Duration.between(threadStartTime, Instant.now()); + long seconds = elapsed.getSeconds(); + threadTimerLabel.setText(String.format("%02d:%02d:%02d", seconds / 3600, + seconds / 60 % 60, seconds % 60)); + } + }); + threadTimer.setInitialDelay(0); + + threadPanel = new JPanel(); + threadPanel.add(threadInfo); + threadPanel.add(threadTimerLabel); + threadPanel.add(threadButton); + threadPanel.setVisible(false); + statusPanel.add(threadPanel, BorderLayout.EAST); + + return statusPanel; + } + + protected JPanel createTopPanel() { + JPanel topPanel = new JPanel(); + + return topPanel; + } + + public static void main(final String[] args) { + + // Try to set system look and feel. + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch (Exception e) { + } + + MainWindow w = new MainWindow(); + w.setExtendedState(JFrame.MAXIMIZED_BOTH); + w.setVisible(true); + } } diff --git a/src/main/org/insa/base/Samples.java b/src/main/org/insa/base/Samples.java index a08b2cf..720eee8 100644 --- a/src/main/org/insa/base/Samples.java +++ b/src/main/org/insa/base/Samples.java @@ -18,6 +18,20 @@ */ package org.insa.base; +import java.awt.Dimension; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.prefs.Preferences; + +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.WindowConstants; + import org.insa.graph.Arc; import org.insa.graph.Graph; import org.insa.graph.Path; @@ -34,7 +48,6 @@ import org.mapsforge.core.model.MapPosition; import org.mapsforge.core.model.Point; import org.mapsforge.core.util.LatLongUtils; import org.mapsforge.core.util.Parameters; -import org.mapsforge.core.util.Utils; import org.mapsforge.map.awt.graphics.AwtGraphicFactory; import org.mapsforge.map.awt.util.AwtUtil; import org.mapsforge.map.awt.util.JavaPreferences; @@ -59,227 +72,231 @@ import org.mapsforge.map.model.common.PreferencesFacade; import org.mapsforge.map.reader.MapFile; import org.mapsforge.map.rendertheme.InternalRenderTheme; -import java.awt.Dimension; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import java.util.prefs.Preferences; - -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.WindowConstants; - public final class Samples { - private static final GraphicFactory GRAPHIC_FACTORY = AwtGraphicFactory.INSTANCE; - private static final boolean SHOW_DEBUG_LAYERS = false; - private static final boolean SHOW_RASTER_MAP = false; + private static final GraphicFactory GRAPHIC_FACTORY = AwtGraphicFactory.INSTANCE; + private static final boolean SHOW_DEBUG_LAYERS = false; + private static final boolean SHOW_RASTER_MAP = false; - private static final String MESSAGE = "Are you sure you want to exit the application?"; - private static final String TITLE = "Confirm close"; + private static final String MESSAGE = "Are you sure you want to exit the application?"; + private static final String TITLE = "Confirm close"; - /** - * Starts the {@code Samples}. - * - * @param args command line args: expects the map files as multiple parameters - * with possible SRTM hgt folder as 1st argument. - * @throws Exception - */ - public static void main(String[] args) throws Exception { - - // Multithreaded map rendering - Parameters.NUMBER_OF_THREADS = 2; + /** + * Starts the {@code Samples}. + * + * @param args + * command line args: expects the map files as multiple parameters + * with possible SRTM hgt folder as 1st argument. + * @throws Exception + */ + public static void main(String[] args) throws Exception { - // Square frame buffer - Parameters.SQUARE_FRAME_BUFFER = false; + // Multithreaded map rendering + Parameters.NUMBER_OF_THREADS = 2; - HillsRenderConfig hillsCfg = null; - File demFolder = getDemFolder(args); - if (demFolder != null) { - MemoryCachingHgtReaderTileSource tileSource = new MemoryCachingHgtReaderTileSource(demFolder, new DiffuseLightShadingAlgorithm(), AwtGraphicFactory.INSTANCE); - tileSource.setEnableInterpolationOverlap(true); - hillsCfg = new HillsRenderConfig(tileSource); - hillsCfg.indexOnThread(); - args = Arrays.copyOfRange(args, 1, args.length); - } + // Square frame buffer + Parameters.SQUARE_FRAME_BUFFER = false; - List mapFiles = getMapFiles(args); - final MapView mapView = createMapView(); - final BoundingBox boundingBox = addLayers(mapView, mapFiles, hillsCfg); - - // addAPath(mapView); + HillsRenderConfig hillsCfg = null; + File demFolder = getDemFolder(args); + if (demFolder != null) { + MemoryCachingHgtReaderTileSource tileSource = new MemoryCachingHgtReaderTileSource( + demFolder, new DiffuseLightShadingAlgorithm(), AwtGraphicFactory.INSTANCE); + tileSource.setEnableInterpolationOverlap(true); + hillsCfg = new HillsRenderConfig(tileSource); + hillsCfg.indexOnThread(); + args = Arrays.copyOfRange(args, 1, args.length); + } - final PreferencesFacade preferencesFacade = new JavaPreferences(Preferences.userNodeForPackage(Samples.class)); + List mapFiles = getMapFiles(args); + final MapView mapView = createMapView(); + final BoundingBox boundingBox = addLayers(mapView, mapFiles, hillsCfg); - final JFrame frame = new JFrame(); - frame.setTitle("Mapsforge Samples"); - frame.add(mapView); - frame.pack(); - frame.setSize(new Dimension(800, 600)); - frame.setLocationRelativeTo(null); - frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - frame.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - int result = JOptionPane.showConfirmDialog(frame, MESSAGE, TITLE, JOptionPane.YES_NO_OPTION); - if (result == JOptionPane.YES_OPTION) { - mapView.getModel().save(preferencesFacade); - mapView.destroyAll(); - AwtGraphicFactory.clearResourceMemoryCache(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - } - } + // addAPath(mapView); - @Override - public void windowOpened(WindowEvent e) { - final Model model = mapView.getModel(); - model.init(preferencesFacade); - if (model.mapViewPosition.getZoomLevel() == 0 || !boundingBox.contains(model.mapViewPosition.getCenter())) { - byte zoomLevel = LatLongUtils.zoomForBounds(model.mapViewDimension.getDimension(), boundingBox, model.displayModel.getTileSize()); - model.mapViewPosition.setMapPosition(new MapPosition(boundingBox.getCenterPoint(), zoomLevel)); - } - } - }); - frame.setVisible(true); - } - - private static void addAPath(MapView mapView) throws Exception { + final PreferencesFacade preferencesFacade = new JavaPreferences( + Preferences.userNodeForPackage(Samples.class)); - Graph gr = (new BinaryGraphReader(Openfile.open("Maps/midip.map"))).read(); - Path path = (new BinaryPathReader(Openfile.open("Paths/chemin_0x400_119963_96676.path"))).readPath(gr); - - Paint paintStroke = AwtGraphicFactory.INSTANCE.createPaint(); - paintStroke.setColor(Color.GREEN); - paintStroke.setStrokeWidth(3); - paintStroke.setStyle(Style.STROKE); + final JFrame frame = new JFrame(); + frame.setTitle("Mapsforge Samples"); + frame.add(mapView); + frame.pack(); + frame.setSize(new Dimension(800, 600)); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + int result = JOptionPane.showConfirmDialog(frame, MESSAGE, TITLE, + JOptionPane.YES_NO_OPTION); + if (result == JOptionPane.YES_OPTION) { + mapView.getModel().save(preferencesFacade); + mapView.destroyAll(); + AwtGraphicFactory.clearResourceMemoryCache(); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + } + } - Polyline line = new Polyline(paintStroke, AwtGraphicFactory.INSTANCE); + @Override + public void windowOpened(WindowEvent e) { + final Model model = mapView.getModel(); + model.init(preferencesFacade); + if (model.mapViewPosition.getZoomLevel() == 0 + || !boundingBox.contains(model.mapViewPosition.getCenter())) { + byte zoomLevel = LatLongUtils.zoomForBounds( + model.mapViewDimension.getDimension(), boundingBox, + model.displayModel.getTileSize()); + model.mapViewPosition.setMapPosition( + new MapPosition(boundingBox.getCenterPoint(), zoomLevel)); + } + } + }); + frame.setVisible(true); + } - for (Arc arc: path.getArcs()) { - ArrayList points = arc.getPoints(); - for (int i = 0; i < points.size(); ++i) { - line.getLatLongs().add(new LatLong(points.get(i).getLatitude(), points.get(i).getLongitude())); - } - } - - - mapView.getLayerManager().getLayers().add(line); - } + private static void addAPath(MapView mapView) throws Exception { - private static BoundingBox addLayers(MapView mapView, List mapFiles, HillsRenderConfig hillsRenderConfig) { - Layers layers = mapView.getLayerManager().getLayers(); + Graph gr = (new BinaryGraphReader(Openfile.open("Maps/midip.map"))).read(); + Path path = (new BinaryPathReader(Openfile.open("Paths/chemin_0x400_119963_96676.path"))) + .readPath(gr); - int tileSize = SHOW_RASTER_MAP ? 256 : 512; + Paint paintStroke = AwtGraphicFactory.INSTANCE.createPaint(); + paintStroke.setColor(Color.GREEN); + paintStroke.setStrokeWidth(3); + paintStroke.setStyle(Style.STROKE); - // Tile cache - TileCache tileCache = AwtUtil.createTileCache( - tileSize, - mapView.getModel().frameBufferModel.getOverdrawFactor(), - 1024, - new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString())); + Polyline line = new Polyline(paintStroke, AwtGraphicFactory.INSTANCE); - final BoundingBox boundingBox; - if (SHOW_RASTER_MAP) { - // Raster - mapView.getModel().displayModel.setFixedTileSize(tileSize); - TileSource tileSource = OpenStreetMapMapnik.INSTANCE; - TileDownloadLayer tileDownloadLayer = createTileDownloadLayer(tileCache, mapView.getModel().mapViewPosition, tileSource); - layers.add(tileDownloadLayer); - tileDownloadLayer.start(); - mapView.setZoomLevelMin(tileSource.getZoomLevelMin()); - mapView.setZoomLevelMax(tileSource.getZoomLevelMax()); - boundingBox = new BoundingBox(LatLongUtils.LATITUDE_MIN, LatLongUtils.LONGITUDE_MIN, LatLongUtils.LATITUDE_MAX, LatLongUtils.LONGITUDE_MAX); - } else { - // Vector - mapView.getModel().displayModel.setFixedTileSize(tileSize); - MultiMapDataStore mapDataStore = new MultiMapDataStore(MultiMapDataStore.DataPolicy.RETURN_ALL); - for (File file : mapFiles) { - mapDataStore.addMapDataStore(new MapFile(file), false, false); - } - TileRendererLayer tileRendererLayer = createTileRendererLayer(tileCache, mapDataStore, mapView.getModel().mapViewPosition, hillsRenderConfig); - layers.add(tileRendererLayer); - boundingBox = mapDataStore.boundingBox(); - } + for (Arc arc : path.getArcs()) { + ArrayList points = arc.getPoints(); + for (int i = 0; i < points.size(); ++i) { + line.getLatLongs().add( + new LatLong(points.get(i).getLatitude(), points.get(i).getLongitude())); + } + } - // Debug - if (SHOW_DEBUG_LAYERS) { - layers.add(new TileGridLayer(GRAPHIC_FACTORY, mapView.getModel().displayModel)); - layers.add(new TileCoordinatesLayer(GRAPHIC_FACTORY, mapView.getModel().displayModel)); - } + mapView.getLayerManager().getLayers().add(line); + } - return boundingBox; - } + private static BoundingBox addLayers(MapView mapView, List mapFiles, + HillsRenderConfig hillsRenderConfig) { + Layers layers = mapView.getLayerManager().getLayers(); - private static MapView createMapView() { - MapView mapView = new MapView(); - mapView.getMapScaleBar().setVisible(true); - if (SHOW_DEBUG_LAYERS) { - mapView.getFpsCounter().setVisible(true); - } + int tileSize = SHOW_RASTER_MAP ? 256 : 512; - return mapView; - } + // Tile cache + TileCache tileCache = AwtUtil.createTileCache(tileSize, + mapView.getModel().frameBufferModel.getOverdrawFactor(), 1024, + new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString())); - @SuppressWarnings("unused") - private static TileDownloadLayer createTileDownloadLayer(TileCache tileCache, MapViewPosition mapViewPosition, TileSource tileSource) { - return new TileDownloadLayer(tileCache, mapViewPosition, tileSource, GRAPHIC_FACTORY) { - @Override - public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) { - System.out.println("Tap on: " + tapLatLong); - return true; - } - }; - } + final BoundingBox boundingBox; + if (SHOW_RASTER_MAP) { + // Raster + mapView.getModel().displayModel.setFixedTileSize(tileSize); + TileSource tileSource = OpenStreetMapMapnik.INSTANCE; + TileDownloadLayer tileDownloadLayer = createTileDownloadLayer(tileCache, + mapView.getModel().mapViewPosition, tileSource); + layers.add(tileDownloadLayer); + tileDownloadLayer.start(); + mapView.setZoomLevelMin(tileSource.getZoomLevelMin()); + mapView.setZoomLevelMax(tileSource.getZoomLevelMax()); + boundingBox = new BoundingBox(LatLongUtils.LATITUDE_MIN, LatLongUtils.LONGITUDE_MIN, + LatLongUtils.LATITUDE_MAX, LatLongUtils.LONGITUDE_MAX); + } + else { + // Vector + mapView.getModel().displayModel.setFixedTileSize(tileSize); + MultiMapDataStore mapDataStore = new MultiMapDataStore( + MultiMapDataStore.DataPolicy.RETURN_ALL); + for (File file : mapFiles) { + mapDataStore.addMapDataStore(new MapFile(file), false, false); + } + TileRendererLayer tileRendererLayer = createTileRendererLayer(tileCache, mapDataStore, + mapView.getModel().mapViewPosition, hillsRenderConfig); + layers.add(tileRendererLayer); + boundingBox = mapDataStore.boundingBox(); + } - private static TileRendererLayer createTileRendererLayer(TileCache tileCache, MapDataStore mapDataStore, MapViewPosition mapViewPosition, HillsRenderConfig hillsRenderConfig) { - TileRendererLayer tileRendererLayer = new TileRendererLayer(tileCache, mapDataStore, mapViewPosition, false, true, false, GRAPHIC_FACTORY, hillsRenderConfig) { - @Override - public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) { - System.out.println("Tap on: " + tapLatLong); - return true; - } - }; - tileRendererLayer.setXmlRenderTheme(InternalRenderTheme.DEFAULT); - return tileRendererLayer; - } + // Debug + if (SHOW_DEBUG_LAYERS) { + layers.add(new TileGridLayer(GRAPHIC_FACTORY, mapView.getModel().displayModel)); + layers.add(new TileCoordinatesLayer(GRAPHIC_FACTORY, mapView.getModel().displayModel)); + } - private static File getDemFolder(String[] args) { - if (args.length == 0) { - throw new IllegalArgumentException("missing argument: "); - } + return boundingBox; + } - File demFolder = new File(args[0]); - if (demFolder.exists() && demFolder.isDirectory() && demFolder.canRead()) { - return demFolder; - } - return null; - } + private static MapView createMapView() { + MapView mapView = new MapView(); + mapView.getMapScaleBar().setVisible(true); + if (SHOW_DEBUG_LAYERS) { + mapView.getFpsCounter().setVisible(true); + } - private static List getMapFiles(String[] args) { - if (args.length == 0) { - throw new IllegalArgumentException("missing argument: "); - } + return mapView; + } - List result = new ArrayList<>(); - for (String arg : args) { - File mapFile = new File(arg); - if (!mapFile.exists()) { - throw new IllegalArgumentException("file does not exist: " + mapFile); - } else if (!mapFile.isFile()) { - throw new IllegalArgumentException("not a file: " + mapFile); - } else if (!mapFile.canRead()) { - throw new IllegalArgumentException("cannot read file: " + mapFile); - } - result.add(mapFile); - } - return result; - } + @SuppressWarnings("unused") + private static TileDownloadLayer createTileDownloadLayer(TileCache tileCache, + MapViewPosition mapViewPosition, TileSource tileSource) { + return new TileDownloadLayer(tileCache, mapViewPosition, tileSource, GRAPHIC_FACTORY) { + @Override + public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) { + System.out.println("Tap on: " + tapLatLong); + return true; + } + }; + } - private Samples() { - throw new IllegalStateException(); - } + private static TileRendererLayer createTileRendererLayer(TileCache tileCache, + MapDataStore mapDataStore, MapViewPosition mapViewPosition, + HillsRenderConfig hillsRenderConfig) { + TileRendererLayer tileRendererLayer = new TileRendererLayer(tileCache, mapDataStore, + mapViewPosition, false, true, false, GRAPHIC_FACTORY, hillsRenderConfig) { + @Override + public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) { + System.out.println("Tap on: " + tapLatLong); + return true; + } + }; + tileRendererLayer.setXmlRenderTheme(InternalRenderTheme.DEFAULT); + return tileRendererLayer; + } + + private static File getDemFolder(String[] args) { + if (args.length == 0) { + throw new IllegalArgumentException("missing argument: "); + } + + File demFolder = new File(args[0]); + if (demFolder.exists() && demFolder.isDirectory() && demFolder.canRead()) { + return demFolder; + } + return null; + } + + private static List getMapFiles(String[] args) { + if (args.length == 0) { + throw new IllegalArgumentException("missing argument: "); + } + + List result = new ArrayList<>(); + for (String arg : args) { + File mapFile = new File(arg); + if (!mapFile.exists()) { + throw new IllegalArgumentException("file does not exist: " + mapFile); + } + else if (!mapFile.isFile()) { + throw new IllegalArgumentException("not a file: " + mapFile); + } + else if (!mapFile.canRead()) { + throw new IllegalArgumentException("cannot read file: " + mapFile); + } + result.add(mapFile); + } + return result; + } + + private Samples() { + throw new IllegalStateException(); + } } \ No newline at end of file diff --git a/src/main/org/insa/drawing/MapViewDrawing.java b/src/main/org/insa/drawing/MapViewDrawing.java index 24ae2d2..5c08be5 100644 --- a/src/main/org/insa/drawing/MapViewDrawing.java +++ b/src/main/org/insa/drawing/MapViewDrawing.java @@ -4,12 +4,13 @@ import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseWheelEvent; import java.io.File; -import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.UUID; -import java.util.prefs.Preferences; + +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileNameExtensionFilter; import org.insa.graph.Arc; import org.insa.graph.Graph; @@ -24,10 +25,8 @@ import org.mapsforge.core.model.MapPosition; import org.mapsforge.core.util.LatLongUtils; import org.mapsforge.map.awt.graphics.AwtGraphicFactory; import org.mapsforge.map.awt.util.AwtUtil; -import org.mapsforge.map.awt.util.JavaPreferences; import org.mapsforge.map.awt.view.MapView; import org.mapsforge.map.datastore.MapDataStore; -import org.mapsforge.map.layer.Layer; import org.mapsforge.map.layer.Layers; import org.mapsforge.map.layer.cache.TileCache; import org.mapsforge.map.layer.hills.HillsRenderConfig; @@ -37,109 +36,119 @@ import org.mapsforge.map.layer.renderer.TileRendererLayer; import org.mapsforge.map.model.DisplayModel; import org.mapsforge.map.model.MapViewPosition; import org.mapsforge.map.model.Model; -import org.mapsforge.map.model.common.Observer; -import org.mapsforge.map.model.common.PreferencesFacade; import org.mapsforge.map.reader.MapFile; import org.mapsforge.map.rendertheme.InternalRenderTheme; import org.mapsforge.map.rendertheme.XmlRenderTheme; -import com.google.common.util.concurrent.SettableFuture; - public class MapViewDrawing extends MapView implements Drawing { - /** - * - */ - private static final long serialVersionUID = 8606967833704938092L; - - // Default path color. - public static final Color DEFAULT_PATH_COLOR = new Color(66, 134, 244); - - // Graphic factory. + /** + * + */ + private static final long serialVersionUID = 8606967833704938092L; + + // Default path color. + public static final Color DEFAULT_PATH_COLOR = new Color(66, 134, 244); + + // Graphic factory. private static final GraphicFactory GRAPHIC_FACTORY = AwtGraphicFactory.INSTANCE; - + // Default tile size. private static final int DEFAULT_TILE_SIZE = 512; - - // Tile size. - int tileSize; - - ArrayList extraLayers; - public MapViewDrawing() { - setBackground(Color.WHITE); - getMapScaleBar().setVisible(true); - this.tileSize = DEFAULT_TILE_SIZE; - DisplayModel model = getModel().displayModel; + // Tile size. + int tileSize; + + ArrayList extraLayers; + + public MapViewDrawing() { + getMapScaleBar().setVisible(true); + this.tileSize = DEFAULT_TILE_SIZE; + DisplayModel model = getModel().displayModel; model.setFixedTileSize(tileSize); - model.setBackgroundColor(convertColor(Color.WHITE)); - + // model.setBackgroundColor(convertColor(Color.WHITE)); + extraLayers = new ArrayList(); addMouseWheelListener(new MouseAdapter() { @Override public void mouseWheelMoved(MouseWheelEvent e) { byte zoomLevelDiff = (byte) -e.getWheelRotation(); for (Paint p: extraLayers) { - p.setStrokeWidth(p.getStrokeWidth() + zoomLevelDiff); + p.setStrokeWidth(p.getStrokeWidth() + zoomLevelDiff); } } - }); - } - - protected int convertColor(Color color) { - return GRAPHIC_FACTORY.createColor(color.getAlpha(), color.getRed(), - color.getGreen(), color.getBlue()); - } - - private int getStrokeWidth(int width) { - byte zoomLevel = getModel().mapViewPosition.getZoomLevel(); - return width * (2 - (8 - zoomLevel)); - } - - private Paint createPaintStroke(int width, Color color) { - Paint paintStroke = AwtGraphicFactory.INSTANCE.createPaint(); - paintStroke.setStyle(Style.STROKE); - if (width != 0) { - paintStroke.setStrokeWidth(getStrokeWidth(width)); - } - if (color != null) { - paintStroke.setColor(convertColor(color)); - } - return paintStroke; - } - - /** - * - * @param color - * @return - */ - private static File getMapsforgeFileFromGraph(Graph graph) { - // TODO: Find a way to change this... - Map idToNames = new HashMap(); - idToNames.put(0x100, "insa"); - idToNames.put(0x101, "insa"); - idToNames.put(0x110, "paris"); - idToNames.put(0x200, "mayotte"); - idToNames.put(0x250, "newzealand"); - idToNames.put(0x300, "reunion"); - idToNames.put(0x400, "midip"); - idToNames.put(0x410, "morbihan"); - - File file = null; - if (idToNames.containsKey(graph.getMapId())) { - file = new File("Maps/" + idToNames.get(graph.getMapId()) + ".mapfg"); - } - return file; - } - - protected LatLong convertPoint(Point point) { - return new LatLong(point.getLatitude(), point.getLongitude()); - } - - private static TileRendererLayer createTileRendererLayer(TileCache tileCache, MapDataStore mapDataStore, MapViewPosition mapViewPosition, HillsRenderConfig hillsRenderConfig) { - TileRendererLayer tileRendererLayer = new TileRendererLayer(tileCache, mapDataStore, mapViewPosition, false, true, false, GRAPHIC_FACTORY, hillsRenderConfig) { + }); + } + + protected int convertColor(Color color) { + return GRAPHIC_FACTORY.createColor(color.getAlpha(), color.getRed(), color.getGreen(), + color.getBlue()); + } + + private int getStrokeWidth(int width) { + byte zoomLevel = getModel().mapViewPosition.getZoomLevel(); + return width * (2 - (8 - zoomLevel)); + } + + private Paint createPaintStroke(int width, Color color) { + Paint paintStroke = AwtGraphicFactory.INSTANCE.createPaint(); + paintStroke.setStyle(Style.STROKE); + if (width != 0) { + paintStroke.setStrokeWidth(getStrokeWidth(width)); + } + if (color != null) { + paintStroke.setColor(convertColor(color)); + } + return paintStroke; + } + + /** + * + * @param color + * @return + */ + private File getMapsforgeFileFromGraph(Graph graph) { + // TODO: Find a way to change this... + Map idToNames = new HashMap(); + idToNames.put(0x100, "insa"); + idToNames.put(0x110, "paris"); + idToNames.put(0x200, "mayotte"); + idToNames.put(0x250, "newzealand"); + idToNames.put(0x300, "reunion"); + idToNames.put(0x400, "midip"); + idToNames.put(0x410, "morbihan"); + + File file = null; + if (idToNames.containsKey(graph.getMapId())) { + file = new File("Maps/" + idToNames.get(graph.getMapId()) + ".mapfg"); + if (!file.exists()) { + file = new File("Maps/new/" + idToNames.get(graph.getMapId()) + ".mapfg"); + } + } + + if (file == null || !file.exists()) { + JFileChooser fileChooser = new JFileChooser("Maps/"); + fileChooser.setFileFilter(new FileNameExtensionFilter("mapsforge files", "" + "mapfg")); + if (fileChooser.showOpenDialog(this.getParent()) == JFileChooser.APPROVE_OPTION) { + file = fileChooser.getSelectedFile(); + } + } + + return file; + } + + protected LatLong convertPoint(Point point) { + return new LatLong(point.getLatitude(), point.getLongitude()); + } + + private static TileRendererLayer createTileRendererLayer(TileCache tileCache, + MapDataStore mapDataStore, MapViewPosition mapViewPosition, + HillsRenderConfig hillsRenderConfig) { + TileRendererLayer tileRendererLayer = new TileRendererLayer(tileCache, mapDataStore, + mapViewPosition, false, true, false, GRAPHIC_FACTORY, hillsRenderConfig) { @Override - public boolean onTap(LatLong tapLatLong, org.mapsforge.core.model.Point layerXY, org.mapsforge.core.model.Point tapXY) { + public boolean onTap(LatLong tapLatLong, org.mapsforge.core.model.Point layerXY, + org.mapsforge.core.model.Point tapXY) { System.out.println("Tap on: " + tapLatLong); return true; } @@ -148,112 +157,116 @@ public class MapViewDrawing extends MapView implements Drawing { tileRendererLayer.setXmlRenderTheme(renderTheme); return tileRendererLayer; } - - @Override - public void clear() { - getLayerManager().getLayers().clear(); - extraLayers.clear(); - repaint(); - } - @Override - public void drawLine(Point from, Point to) { - drawLine(from, to, 0, null); - } + @Override + public void clear() { + getLayerManager().getLayers().clear(); + extraLayers.clear(); + repaint(); + } - @Override - public void drawLine(Point from, Point to, int width) { - drawLine(from, to, width, null); - } + @Override + public void drawLine(Point from, Point to) { + drawLine(from, to, 0, null); + } - @Override - public void drawLine(Point from, Point to, int width, Color color) { - Paint paintStroke = createPaintStroke(width, color); + @Override + public void drawLine(Point from, Point to, int width) { + drawLine(from, to, width, null); + } + + @Override + public void drawLine(Point from, Point to, int width, Color color) { + Paint paintStroke = createPaintStroke(width, color); Polyline line = new Polyline(paintStroke, AwtGraphicFactory.INSTANCE); line.getLatLongs().add(convertPoint(from)); line.getLatLongs().add(convertPoint(to)); - getLayerManager().getLayers().add(line); + getLayerManager().getLayers().add(line); } - - @Override - public void drawMarker(Point point) { - drawMarker(point, null); - } - @Override - public void drawMarker(Point point, Color color) { - Marker marker = new Marker(convertPoint(point), GRAPHIC_FACTORY.createBitmap(10, 20), 1, 2); - getLayerManager().getLayers().add(marker); - } - - @Override - public void drawPoint(Point point, int width, Color color) { - // TODO: Maybe do something? - } + @Override + public void drawMarker(Point point) { + drawMarker(point, null); + } - @Override - public void drawGraph(Graph graph, GraphPalette palette) { - - File graphFile = getMapsforgeFileFromGraph(graph); + @Override + public void drawMarker(Point point, Color color) { + Marker marker = new Marker(convertPoint(point), GRAPHIC_FACTORY.createBitmap(10, 20), 1, 2); + getLayerManager().getLayers().add(marker); + } + + @Override + public void drawPoint(Point point, int width, Color color) { + // TODO: Maybe do something? + } + + @Override + public void drawGraph(Graph graph, GraphPalette palette) { + + File graphFile = getMapsforgeFileFromGraph(graph); // Tile cache - TileCache tileCache = AwtUtil.createTileCache( - tileSize, getModel().frameBufferModel.getOverdrawFactor(), - 1024, new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString())); - + TileCache tileCache = AwtUtil.createTileCache(tileSize, + getModel().frameBufferModel.getOverdrawFactor(), 1024, + new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString())); + // Layers Layers layers = getLayerManager().getLayers(); MapDataStore mapDataStore = new MapFile(graphFile); - TileRendererLayer tileRendererLayer = createTileRendererLayer(tileCache, mapDataStore, - getModel().mapViewPosition, null); + TileRendererLayer tileRendererLayer = createTileRendererLayer(tileCache, mapDataStore, + getModel().mapViewPosition, null); layers.add(tileRendererLayer); BoundingBox boundingBox = mapDataStore.boundingBox(); - + final Model model = getModel(); - if (model.mapViewPosition.getZoomLevel() == 0 || !boundingBox.contains(model.mapViewPosition.getCenter())) { - byte zoomLevel = LatLongUtils.zoomForBounds(model.mapViewDimension.getDimension(), boundingBox, model.displayModel.getTileSize()); - model.mapViewPosition.setMapPosition(new MapPosition(boundingBox.getCenterPoint(), zoomLevel)); + if (model.mapViewPosition.getZoomLevel() == 0 + || !boundingBox.contains(model.mapViewPosition.getCenter())) { + byte zoomLevel = LatLongUtils.zoomForBounds(model.mapViewDimension.getDimension(), + boundingBox, model.displayModel.getTileSize()); + model.mapViewPosition + .setMapPosition(new MapPosition(boundingBox.getCenterPoint(), zoomLevel)); model.mapViewPosition.setZoomLevelMin(zoomLevel); } - } + } - @Override - public void drawGraph(Graph graph) { - drawGraph(graph, null); - } + @Override + public void drawGraph(Graph graph) { + drawGraph(graph, null); + } - @Override - public void drawPath(Path path, Color color, boolean markers) { - Paint paintStroke = createPaintStroke(1, DEFAULT_PATH_COLOR); - Polyline line = new Polyline(paintStroke, AwtGraphicFactory.INSTANCE); + @Override + public void drawPath(Path path, Color color, boolean markers) { + Paint paintStroke = createPaintStroke(1, DEFAULT_PATH_COLOR); + Polyline line = new Polyline(paintStroke, AwtGraphicFactory.INSTANCE); for (Arc arc: path.getArcs()) { - ArrayList points = arc.getPoints(); - for (int i = 0; i < points.size(); ++i) { - line.getLatLongs().add(new LatLong(points.get(i).getLatitude(), points.get(i).getLongitude())); - } + ArrayList points = arc.getPoints(); + for (int i = 0; i < points.size(); ++i) { + line.getLatLongs().add( + new LatLong(points.get(i).getLatitude(), points.get(i).getLongitude())); + } } getLayerManager().getLayers().add(line); extraLayers.add(paintStroke); if (markers) { - drawMarker(path.getOrigin().getPoint()); - drawMarker(path.getDestination().getPoint()); + drawMarker(path.getOrigin().getPoint()); + drawMarker(path.getDestination().getPoint()); } - } - - @Override - public void drawPath(Path path, Color color) { - drawPath(path, color, true); - } + } - @Override - public void drawPath(Path path) { - drawPath(path, DEFAULT_PATH_COLOR, true); - } + @Override + public void drawPath(Path path, Color color) { + drawPath(path, color, true); + } + + @Override + public void drawPath(Path path) { + drawPath(path, DEFAULT_PATH_COLOR, true); + } + + @Override + public void drawPath(Path path, boolean markers) { + drawPath(path, DEFAULT_PATH_COLOR, markers); + } - @Override - public void drawPath(Path path, boolean markers) { - drawPath(path, DEFAULT_PATH_COLOR, markers); - } - }