diff --git a/.classpath b/.classpath index e6ce8ae..a2f75d1 100644 --- a/.classpath +++ b/.classpath @@ -23,5 +23,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project index 87c2087..9a8e431 100644 --- a/.project +++ b/.project @@ -10,14 +10,8 @@ - - org.eclipse.m2e.core.maven2Builder - - - - org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature diff --git a/libs/kxml2-2.3.0.jar b/libs/kxml2-2.3.0.jar new file mode 100644 index 0000000..6470952 Binary files /dev/null and b/libs/kxml2-2.3.0.jar differ diff --git a/libs/mapsforge-core-0.9.1-javadoc.jar b/libs/mapsforge-core-0.9.1-javadoc.jar new file mode 100644 index 0000000..a2a3d4f Binary files /dev/null and b/libs/mapsforge-core-0.9.1-javadoc.jar differ diff --git a/libs/mapsforge-core-0.9.1.jar b/libs/mapsforge-core-0.9.1.jar new file mode 100644 index 0000000..23125a4 Binary files /dev/null and b/libs/mapsforge-core-0.9.1.jar differ diff --git a/libs/mapsforge-map-0.9.1-javadoc.jar b/libs/mapsforge-map-0.9.1-javadoc.jar new file mode 100644 index 0000000..5fe05e1 Binary files /dev/null and b/libs/mapsforge-map-0.9.1-javadoc.jar differ diff --git a/libs/mapsforge-map-0.9.1.jar b/libs/mapsforge-map-0.9.1.jar new file mode 100644 index 0000000..abb4f89 Binary files /dev/null and b/libs/mapsforge-map-0.9.1.jar differ diff --git a/libs/mapsforge-map-awt-0.9.1-javadoc.jar b/libs/mapsforge-map-awt-0.9.1-javadoc.jar new file mode 100644 index 0000000..5f01eaa Binary files /dev/null and b/libs/mapsforge-map-awt-0.9.1-javadoc.jar differ diff --git a/libs/mapsforge-map-awt-0.9.1.jar b/libs/mapsforge-map-awt-0.9.1.jar new file mode 100644 index 0000000..169c154 Binary files /dev/null and b/libs/mapsforge-map-awt-0.9.1.jar differ diff --git a/libs/mapsforge-map-reader-0.9.1-javadoc.jar b/libs/mapsforge-map-reader-0.9.1-javadoc.jar new file mode 100644 index 0000000..783bb46 Binary files /dev/null and b/libs/mapsforge-map-reader-0.9.1-javadoc.jar differ diff --git a/libs/mapsforge-map-reader-0.9.1.jar b/libs/mapsforge-map-reader-0.9.1.jar new file mode 100644 index 0000000..51ad11d Binary files /dev/null and b/libs/mapsforge-map-reader-0.9.1.jar differ diff --git a/libs/mapsforge-poi-0.9.1-javadoc.jar b/libs/mapsforge-poi-0.9.1-javadoc.jar new file mode 100644 index 0000000..0d23e5d Binary files /dev/null and b/libs/mapsforge-poi-0.9.1-javadoc.jar differ diff --git a/libs/mapsforge-poi-0.9.1.jar b/libs/mapsforge-poi-0.9.1.jar new file mode 100644 index 0000000..d778de4 Binary files /dev/null and b/libs/mapsforge-poi-0.9.1.jar differ diff --git a/libs/mapsforge-poi-awt-0.9.1-javadoc.jar b/libs/mapsforge-poi-awt-0.9.1-javadoc.jar new file mode 100644 index 0000000..3c6a872 Binary files /dev/null and b/libs/mapsforge-poi-awt-0.9.1-javadoc.jar differ diff --git a/libs/mapsforge-poi-awt-0.9.1.jar b/libs/mapsforge-poi-awt-0.9.1.jar new file mode 100644 index 0000000..14e1b89 Binary files /dev/null and b/libs/mapsforge-poi-awt-0.9.1.jar differ diff --git a/libs/mapsforge-themes-0.9.1-javadoc.jar b/libs/mapsforge-themes-0.9.1-javadoc.jar new file mode 100644 index 0000000..b40c7e5 Binary files /dev/null and b/libs/mapsforge-themes-0.9.1-javadoc.jar differ diff --git a/libs/mapsforge-themes-0.9.1.jar b/libs/mapsforge-themes-0.9.1.jar new file mode 100644 index 0000000..e91f12b Binary files /dev/null and b/libs/mapsforge-themes-0.9.1.jar differ diff --git a/libs/svg-salamander-1.0-javadoc.jar b/libs/svg-salamander-1.0-javadoc.jar new file mode 100644 index 0000000..e136ad8 Binary files /dev/null and b/libs/svg-salamander-1.0-javadoc.jar differ diff --git a/libs/svg-salamander-1.0.jar b/libs/svg-salamander-1.0.jar new file mode 100644 index 0000000..200eeb0 Binary files /dev/null and b/libs/svg-salamander-1.0.jar differ diff --git a/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentGraphicObserver.java b/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentGraphicObserver.java index 2f24dd9..c5cfa53 100644 --- a/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentGraphicObserver.java +++ b/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentGraphicObserver.java @@ -4,7 +4,6 @@ import java.awt.Color; import java.util.ArrayList; import org.insa.drawing.Drawing; -import org.insa.drawing.graph.GraphDrawing; import org.insa.graph.Node; public class WeaklyConnectedComponentGraphicObserver implements WeaklyConnectedComponentObserver { @@ -15,27 +14,22 @@ public class WeaklyConnectedComponentGraphicObserver implements WeaklyConnectedC // Drawing + Graph drawing private Drawing drawing; - private GraphDrawing gdrawing; // Current index color - private int cindex = 0; + private int cindex = -1; public WeaklyConnectedComponentGraphicObserver(Drawing drawing) { this.drawing = drawing; - this.gdrawing = new GraphDrawing(drawing); - this.drawing.setAutoRepaint(true); } @Override public void notifyStartComponent(Node curNode) { - this.drawing.setColor(COLORS[cindex]); cindex = (cindex + 1) % COLORS.length; } @Override public void notifyNewNodeInComponent(Node node) { - this.gdrawing.drawPoint(node.getPoint(), 5); - this.drawing.repaint(); + this.drawing.drawMarker(node.getPoint(), COLORS[cindex]); } @Override diff --git a/src/main/org/insa/base/MainWindow.java b/src/main/org/insa/base/MainWindow.java index 129e915..01b45dc 100644 --- a/src/main/org/insa/base/MainWindow.java +++ b/src/main/org/insa/base/MainWindow.java @@ -2,6 +2,7 @@ package org.insa.base; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -11,6 +12,8 @@ import java.awt.event.MouseEvent; 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; @@ -47,15 +50,17 @@ import org.insa.algo.shortestpath.ShortestPathSolution; import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver; import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm; import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsData; +import org.insa.drawing.BasicDrawing; +import org.insa.drawing.BlackAndWhiteGraphPalette; import org.insa.drawing.Drawing; -import org.insa.drawing.graph.BlackAndWhiteGraphPalette; -import org.insa.drawing.graph.GraphDrawing; -import org.insa.drawing.graph.PathDrawing; +import org.insa.drawing.MapViewDrawing; import org.insa.graph.Graph; import org.insa.graph.Node; import org.insa.graph.Path; import org.insa.graph.Point; +import org.insa.graph.io.AbstractGraphReader; import org.insa.graph.io.BinaryGraphReader; +import org.insa.graph.io.BinaryGraphReaderV2; import org.insa.graph.io.BinaryPathReader; import org.insa.graph.io.MapMismatchException; import org.insa.graph.io.Openfile; @@ -132,7 +137,8 @@ public class MainWindow extends JFrame { } Point lonlat; try { - lonlat = drawing.getLongitudeLatitude(evt); + // TODO: Fix + lonlat = ((BasicDrawing)drawing).getLongitudeLatitude(evt); } catch (NoninvertibleTransformException e) { // Should never happens in "normal" circumstances... @@ -142,7 +148,7 @@ public class MainWindow extends JFrame { Node node = graph.findClosestNode(lonlat); - new GraphDrawing(drawing).drawPoint(node.getPoint(), 10, Color.BLUE); + drawing.drawMarker(node.getPoint(), Color.BLUE); points.add(node); if (points.size() == nTargetPoints) { callable.call(points); @@ -176,6 +182,9 @@ public class MainWindow extends JFrame { private Drawing drawing; private DrawingClickListener clickAdapter; + // Main panel. + private JSplitPane mainPanel; + // List of item for the top menus. private JMenuItem openMapItem; @@ -219,13 +228,17 @@ public class MainWindow extends JFrame { }); // Create graph area - JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - drawing = new Drawing(); + BasicDrawing drawing = new BasicDrawing(); + // MapViewDrawing drawing = new MapViewDrawing(); + + Component drawingComponent = drawing; + this.drawing = drawing; // Click adapter this.clickAdapter = new DrawingClickListener(); - drawing.addMouseListener(this.clickAdapter); + // drawing.addMouseListener(this.clickAdapter); JTextArea infoPanel = new JTextArea(); infoPanel.setMinimumSize(new Dimension(200, 50)); @@ -236,14 +249,14 @@ public class MainWindow extends JFrame { this.logStream = new JOutputStream(infoPanel); this.printStream = new PrintStream(this.logStream); - sp.setResizeWeight(0.8); + mainPanel.setResizeWeight(0.8); // sp.setEnabled(false); - sp.setDividerSize(5); + mainPanel.setDividerSize(5); - sp.setBackground(Color.WHITE); - sp.add(drawing); - sp.add(new JScrollPane(infoPanel)); - this.add(sp, BorderLayout.CENTER); + mainPanel.setBackground(Color.WHITE); + mainPanel.add(drawingComponent); + mainPanel.add(new JScrollPane(infoPanel)); + this.add(mainPanel, BorderLayout.CENTER); // Top Panel this.add(createTopPanel(), BorderLayout.NORTH); @@ -299,7 +312,7 @@ public class MainWindow extends JFrame { public void run() { ShortestPathSolution solution = spAlgorithm.run(); if (solution != null && solution.isFeasible()) { - new PathDrawing(drawing).drawPath(solution.getPath()); + drawing.drawPath(solution.getPath()); } } }); @@ -317,30 +330,38 @@ public class MainWindow extends JFrame { public void actionPerformed(ActionEvent e) { JFileChooser chooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter( - "Map & compressed map files", "map", "map.gz"); + "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() { - BinaryGraphReader reader; + String path = chooser.getSelectedFile().getAbsolutePath(); + DataInputStream stream; try { - reader = new BinaryGraphReader( - Openfile.open(chooser.getSelectedFile().getAbsolutePath())); + 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(); - new GraphDrawing(drawing).drawGraph(graph); + drawing.drawGraph(graph); for (JMenuItem item: graphLockItems) { item.setEnabled(true); @@ -384,7 +405,7 @@ public class MainWindow extends JFrame { JOptionPane.showMessageDialog(MainWindow.this, "Unable to read path from the selected file."); return ; } - new PathDrawing(drawing).drawPath(currentPath); + drawing.drawPath(currentPath); } } }); @@ -418,9 +439,13 @@ public class MainWindow extends JFrame { launchThread(new Runnable() { @Override public void run() { + if (!(drawing instanceof BasicDrawing)) { + BasicDrawing tmp = new BasicDrawing(); + mainPanel.setLeftComponent(tmp); + drawing = tmp; + } drawing.clear(); - drawing.setAutoRepaint(true); - new GraphDrawing(drawing).drawGraph(graph); + drawing.drawGraph(graph); } }); } @@ -435,18 +460,45 @@ public class MainWindow extends JFrame { launchThread(new Runnable() { @Override public void run() { + if (!(drawing instanceof BasicDrawing)) { + BasicDrawing tmp = new BasicDrawing(); + mainPanel.setLeftComponent(tmp); + drawing = tmp; + } drawing.clear(); - drawing.setAutoRepaint(true); - new GraphDrawing(drawing, new BlackAndWhiteGraphPalette()).drawGraph(graph); + 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"); diff --git a/src/main/org/insa/base/Samples.java b/src/main/org/insa/base/Samples.java new file mode 100644 index 0000000..a08b2cf --- /dev/null +++ b/src/main/org/insa/base/Samples.java @@ -0,0 +1,285 @@ +/* + * Copyright 2010, 2011, 2012, 2013 mapsforge.org + * Copyright 2014 Christian Pesch + * Copyright 2014 Ludwig M Brinckmann + * Copyright 2014-2018 devemux86 + * Copyright 2017 usrusr + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.insa.base; + +import org.insa.graph.Arc; +import org.insa.graph.Graph; +import org.insa.graph.Path; +import org.insa.graph.io.BinaryGraphReader; +import org.insa.graph.io.BinaryPathReader; +import org.insa.graph.io.Openfile; +import org.mapsforge.core.graphics.Color; +import org.mapsforge.core.graphics.GraphicFactory; +import org.mapsforge.core.graphics.Paint; +import org.mapsforge.core.graphics.Style; +import org.mapsforge.core.model.BoundingBox; +import org.mapsforge.core.model.LatLong; +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; +import org.mapsforge.map.awt.view.MapView; +import org.mapsforge.map.datastore.MapDataStore; +import org.mapsforge.map.datastore.MultiMapDataStore; +import org.mapsforge.map.layer.Layers; +import org.mapsforge.map.layer.cache.TileCache; +import org.mapsforge.map.layer.debug.TileCoordinatesLayer; +import org.mapsforge.map.layer.debug.TileGridLayer; +import org.mapsforge.map.layer.download.TileDownloadLayer; +import org.mapsforge.map.layer.download.tilesource.OpenStreetMapMapnik; +import org.mapsforge.map.layer.download.tilesource.TileSource; +import org.mapsforge.map.layer.hills.DiffuseLightShadingAlgorithm; +import org.mapsforge.map.layer.hills.HillsRenderConfig; +import org.mapsforge.map.layer.hills.MemoryCachingHgtReaderTileSource; +import org.mapsforge.map.layer.overlay.Polyline; +import org.mapsforge.map.layer.renderer.TileRendererLayer; +import org.mapsforge.map.model.MapViewPosition; +import org.mapsforge.map.model.Model; +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 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; + + // Square frame buffer + Parameters.SQUARE_FRAME_BUFFER = false; + + 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); + } + + List mapFiles = getMapFiles(args); + final MapView mapView = createMapView(); + final BoundingBox boundingBox = addLayers(mapView, mapFiles, hillsCfg); + + // addAPath(mapView); + + final PreferencesFacade preferencesFacade = new JavaPreferences(Preferences.userNodeForPackage(Samples.class)); + + 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); + } + } + + @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 { + + 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); + + 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())); + } + } + + + mapView.getLayerManager().getLayers().add(line); + } + + private static BoundingBox addLayers(MapView mapView, List mapFiles, HillsRenderConfig hillsRenderConfig) { + Layers layers = mapView.getLayerManager().getLayers(); + + int tileSize = SHOW_RASTER_MAP ? 256 : 512; + + // Tile cache + TileCache tileCache = AwtUtil.createTileCache( + tileSize, + mapView.getModel().frameBufferModel.getOverdrawFactor(), + 1024, + new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString())); + + 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(); + } + + // Debug + if (SHOW_DEBUG_LAYERS) { + layers.add(new TileGridLayer(GRAPHIC_FACTORY, mapView.getModel().displayModel)); + layers.add(new TileCoordinatesLayer(GRAPHIC_FACTORY, mapView.getModel().displayModel)); + } + + return boundingBox; + } + + private static MapView createMapView() { + MapView mapView = new MapView(); + mapView.getMapScaleBar().setVisible(true); + if (SHOW_DEBUG_LAYERS) { + mapView.getFpsCounter().setVisible(true); + } + + return mapView; + } + + @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 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/BasicDrawing.java b/src/main/org/insa/drawing/BasicDrawing.java new file mode 100644 index 0000000..6b67e84 --- /dev/null +++ b/src/main/org/insa/drawing/BasicDrawing.java @@ -0,0 +1,314 @@ +package org.insa.drawing; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.event.MouseEvent; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Point2D; +import java.awt.image.*; +import java.util.ArrayList; +import java.util.Iterator; + +import javax.swing.JPanel; + +import org.insa.graph.Arc; +import org.insa.graph.Graph; +import org.insa.graph.Node; +import org.insa.graph.Path; +import org.insa.graph.Point; + +/** + * Cette implementation de la classe Dessin produit vraiment un affichage + * (au contraire de la classe DessinInvisible). + */ + +public class BasicDrawing extends JPanel implements Drawing { + + /** + * + */ + private static final long serialVersionUID = 96779785877771827L; + + // Default path color. + public static final Color DEFAULT_PATH_COLOR = new Color(255, 0, 255); + + // Default palette. + public static final GraphPalette DEFAULT_PALETTE = new BasicGraphPalette(); + + // Default marker width + private static final int DEFAULT_MARKER_WIDTH = 10; + + // + private final Graphics2D gr; + + private double long1, long2, lat1, lat2; + + // Width and height of the image + private final int width, height; + + private Image image; + private ZoomAndPanListener zoomAndPanListener; + + /** + * Create a new BasicDrawing. + * + */ + public BasicDrawing() { + + this.zoomAndPanListener = new ZoomAndPanListener(this, ZoomAndPanListener.DEFAULT_MIN_ZOOM_LEVEL, 20, 1.2); + this.addMouseListener(zoomAndPanListener); + this.addMouseMotionListener(zoomAndPanListener); + this.addMouseWheelListener(zoomAndPanListener); + + this.width = 2000; + this.height = 1600; + + BufferedImage img = new BufferedImage(this.width, this.height, BufferedImage.TYPE_3BYTE_BGR); + + this.image = img; + this.gr = img.createGraphics(); + + this.zoomAndPanListener.setCoordTransform(this.gr.getTransform()); + + this.long1 = -180; + this.long2 = 180; + this.lat1 = -90; + this.lat2 = 90; + + this.clear(); + this.repaint(); + + } + + @Override + public void paintComponent(Graphics g1) { + Graphics2D g = (Graphics2D)g1; + g.clearRect(0, 0, getWidth(), getHeight()); + g.setTransform(zoomAndPanListener.getCoordTransform()); + g.drawImage(image, 0, 0, this); + } + + protected void setBB(double long1, double long2, double lat1, double lat2) { + + if (long1 > long2 || lat1 > lat2) { + throw new Error("DessinVisible.setBB : mauvaises coordonnees."); + } + + this.long1 = long1; + this.long2 = long2; + this.lat1= lat1; + this.lat2 = lat2; + + double scale = 1 / Math.max(this.width / (double)this.getWidth(), this.height / (double)this.getHeight()); + + this.zoomAndPanListener.getCoordTransform().setToIdentity(); + this.zoomAndPanListener.getCoordTransform().translate((this.getWidth() - this.width * scale) / 2, + (this.getHeight() - this.height * scale) / 2); + this.zoomAndPanListener.getCoordTransform().scale(scale, scale); + this.zoomAndPanListener.setZoomLevel(0); + this.repaint(); + + } + + private int projx(double lon) { + return (int)(width * (lon - this.long1) / (this.long2 - this.long1)) ; + } + + private int projy(double lat) { + return (int)(height * (1 - (lat - this.lat1) / (this.lat2 - this.lat1))) ; + } + + /** + * Return the longitude and latitude corresponding to the given + * position of the MouseEvent. + * + * @param event + * + * @return + */ + public Point getLongitudeLatitude(MouseEvent event) throws NoninvertibleTransformException { + // Get the point using the inverse transform of the Zoom/Pan object, this gives us + // a point within the drawing box (between [0, 0] and [width, height]). + Point2D ptDst = this.zoomAndPanListener.getCoordTransform().inverseTransform(event.getPoint(), null); + + // Inverse the "projection" on x/y to get longitude and latitude. + double lon = ptDst.getX(); + double lat = ptDst.getY(); + lon = (lon / this.width) * (this.long2 - this.long1) + this.long1; + lat = (1 - lat / this.height) * (this.lat2 - this.lat1) + this.lat1; + + // Return a new point. + return new Point(lon, lat); + } + + protected void setWidth(int width) { + this.gr.setStroke(new BasicStroke(width)); + } + + protected void setColor(Color col) { + this.gr.setColor(col); + } + + @Override + public void clear() { + this.gr.setColor(Color.WHITE); + this.gr.fillRect(0, 0, this.width, this.height); + } + + @Override + public void drawLine(Point from, Point to) { + int x1 = this.projx(from.getLongitude()) ; + int x2 = this.projx(to.getLongitude()) ; + int y1 = this.projy(from.getLatitude()) ; + int y2 = this.projy(to.getLatitude()) ; + + gr.drawLine(x1, y1, x2, y2) ; + this.repaint(); + } + + @Override + public void drawLine(Point from, Point to, int width) { + setWidth(width); + drawLine(from, to); + } + + @Override + public void drawLine(Point from, Point to, int width, Color color) { + setWidth(width); + setColor(color); + drawLine(from, to); + } + + @Override + public void drawMarker(Point point) { + drawPoint(point, DEFAULT_MARKER_WIDTH, this.gr.getColor()); + } + + + @Override + public void drawMarker(Point point, Color color) { + setColor(color); + drawMarker(point); + } + + @Override + public void drawPoint(Point point, int width, Color color) { + setWidth(width); + setColor(color); + int x = this.projx(point.getLongitude()) - DEFAULT_MARKER_WIDTH / 2; + int y = this.projy(point.getLatitude()) - DEFAULT_MARKER_WIDTH / 2; + gr.fillOval(x, y, DEFAULT_MARKER_WIDTH, DEFAULT_MARKER_WIDTH); + this.repaint(); + } + + /** + * Draw the given arc. + * + * @param arc Arc to draw. + * @param palette Palette to use to retrieve color and width for arc, + * or null to use current settings. + */ + public void drawArc(Arc arc, GraphPalette palette) { + ArrayList pts = arc.getPoints(); + if (!pts.isEmpty()) { + if (palette != null) { + setColor(palette.getColorForType(arc.getInfo().getType())); + setWidth(palette.getWidthForType(arc.getInfo().getType())); + } + Iterator it1 = pts.iterator(); + Point prev = it1.next(); + while (it1.hasNext()) { + Point curr = it1.next(); + drawLine(prev, curr); + prev = curr; + } + } + } + + /** + * Initialize the drawing for the given graph. + * + * @param graph + */ + public void initialize(Graph graph) { + double minLon = Double.POSITIVE_INFINITY, minLat = Double.POSITIVE_INFINITY, + maxLon = Double.NEGATIVE_INFINITY, maxLat = Double.NEGATIVE_INFINITY; + for (Node node: graph.getNodes()) { + Point pt = node.getPoint(); + if (pt.getLatitude() < minLat) { + minLat = pt.getLatitude(); + } + if (pt.getLatitude() > maxLat) { + maxLat = pt.getLatitude(); + } + if (pt.getLongitude() < minLon) { + minLon = pt.getLongitude(); + } + if (pt.getLongitude() > maxLon) { + maxLon = pt.getLongitude(); + } + } + + double deltaLon = 0.02 * (maxLon - minLon), + deltaLat = 0.02 * (maxLat - minLat); + + setBB(minLon - deltaLon, maxLon + deltaLon, + minLat - deltaLat, maxLat + deltaLat); + } + + @Override + public void drawGraph(Graph graph, GraphPalette palette) { + clear(); + initialize(graph); + for (Node node: graph.getNodes()) { + for (Arc arc: node.getSuccessors()) { + drawArc(arc, palette); + } + } + } + + @Override + public void drawGraph(Graph graph) { + drawGraph(graph, DEFAULT_PALETTE); + } + + @Override + public void drawPath(Path path, Color color, boolean markers) { + setColor(color); + setWidth(2); + for (Arc arc: path.getArcs()) { + drawArc(arc, null); + } + if (markers) { + drawMarker(path.getOrigin().getPoint(), color); + drawMarker(path.getDestination().getPoint(), color); + } + } + + @Override + public void drawPath(Path path, Color color) { + drawPath(path, color, true); + } + + @Override + public void drawPath(Path path) { + drawPath(path, DEFAULT_PATH_COLOR); + } + + @Override + public void drawPath(Path path, boolean markers) { + drawPath(path, DEFAULT_PATH_COLOR, markers); + } + + @SuppressWarnings("unused") + private void putText(Point point, String txt) { + int x = this.projx(point.getLongitude()); + int y = this.projy(point.getLatitude()); + gr.drawString(txt, x, y); + this.repaint(); + } + +} diff --git a/src/main/org/insa/drawing/graph/BasicGraphPalette.java b/src/main/org/insa/drawing/BasicGraphPalette.java similarity index 98% rename from src/main/org/insa/drawing/graph/BasicGraphPalette.java rename to src/main/org/insa/drawing/BasicGraphPalette.java index 5bef312..2d82f04 100644 --- a/src/main/org/insa/drawing/graph/BasicGraphPalette.java +++ b/src/main/org/insa/drawing/BasicGraphPalette.java @@ -1,4 +1,4 @@ -package org.insa.drawing.graph; +package org.insa.drawing; import java.awt.Color; diff --git a/src/main/org/insa/drawing/graph/BlackAndWhiteGraphPalette.java b/src/main/org/insa/drawing/BlackAndWhiteGraphPalette.java similarity index 94% rename from src/main/org/insa/drawing/graph/BlackAndWhiteGraphPalette.java rename to src/main/org/insa/drawing/BlackAndWhiteGraphPalette.java index d2066b6..2d095d5 100644 --- a/src/main/org/insa/drawing/graph/BlackAndWhiteGraphPalette.java +++ b/src/main/org/insa/drawing/BlackAndWhiteGraphPalette.java @@ -1,4 +1,4 @@ -package org.insa.drawing.graph; +package org.insa.drawing; import java.awt.Color; diff --git a/src/main/org/insa/drawing/Drawing.java b/src/main/org/insa/drawing/Drawing.java index ce6c8c9..0ab4927 100644 --- a/src/main/org/insa/drawing/Drawing.java +++ b/src/main/org/insa/drawing/Drawing.java @@ -1,179 +1,119 @@ package org.insa.drawing; -import java.awt.BasicStroke; import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.event.MouseEvent; -import java.awt.geom.NoninvertibleTransformException; -import java.awt.geom.Point2D; -import java.awt.image.*; - -import javax.swing.JPanel; +import org.insa.graph.Graph; +import org.insa.graph.Path; import org.insa.graph.Point; -/** - * Cette implementation de la classe Dessin produit vraiment un affichage - * (au contraire de la classe DessinInvisible). - */ - -public class Drawing extends JPanel { - - /** - * - */ - private static final long serialVersionUID = 96779785877771827L; - - private final Graphics2D gr; - - private double long1, long2, lat1, lat2; - - // Width and height of the image - private final int width, height; - - private Image image; - private ZoomAndPanListener zoomAndPanListener; - - public boolean autoRepaint = true; - - /** - * Cree et affiche une nouvelle fenetre de dessin. - */ - public Drawing() { - - this.zoomAndPanListener = new ZoomAndPanListener(this, ZoomAndPanListener.DEFAULT_MIN_ZOOM_LEVEL, 20, 1.2); - this.addMouseListener(zoomAndPanListener); - this.addMouseMotionListener(zoomAndPanListener); - this.addMouseWheelListener(zoomAndPanListener); - - this.width = 2000; - this.height = 1600; - - BufferedImage img = new BufferedImage(this.width, this.height, BufferedImage.TYPE_3BYTE_BGR); - - this.image = img; - this.gr = img.createGraphics(); - - this.zoomAndPanListener.setCoordTransform(this.gr.getTransform()); - - this.long1 = -180; - this.long2 = 180; - this.lat1 = -90; - this.lat2 = 90; - - this.clear(); - this.repaint(); - - } - - @Override - public void paintComponent(Graphics g1) { - Graphics2D g = (Graphics2D)g1; - g.clearRect(0, 0, getWidth(), getHeight()); - g.setTransform(zoomAndPanListener.getCoordTransform()); - g.drawImage(image, 0, 0, this); - } - - public void setAutoRepaint(boolean autoRepaint) { - this.autoRepaint = autoRepaint; - } - - protected void doAutoPaint() { - if (autoRepaint) { - this.repaint(); - } - } - - public void setWidth(int width) { - this.gr.setStroke(new BasicStroke(width)); - } - - public void setColor(Color col) { - this.gr.setColor(col); - } - - public void clear() { - this.gr.setColor(Color.WHITE); - this.gr.fillRect(0, 0, this.width, this.height); - } - - public void setBB(double long1, double long2, double lat1, double lat2) { - - if (long1 > long2 || lat1 > lat2) { - throw new Error("DessinVisible.setBB : mauvaises coordonnees."); - } - - this.long1 = long1; - this.long2 = long2; - this.lat1= lat1; - this.lat2 = lat2; - - double scale = 1 / Math.max(this.width / (double)this.getWidth(), this.height / (double)this.getHeight()); - - this.zoomAndPanListener.getCoordTransform().setToIdentity(); - this.zoomAndPanListener.getCoordTransform().translate((this.getWidth() - this.width * scale) / 2, - (this.getHeight() - this.height * scale) / 2); - this.zoomAndPanListener.getCoordTransform().scale(scale, scale); - this.zoomAndPanListener.setZoomLevel(0); - this.repaint(); - - } - - private int projx(double lon) { - return (int)(width * (lon - this.long1) / (this.long2 - this.long1)) ; - } - - private int projy(double lat) { - return (int)(height * (1 - (lat - this.lat1) / (this.lat2 - this.lat1))) ; - } +public interface Drawing { /** - * Return the longitude and latitude corresponding to the given - * position of the MouseEvent. - * - * @param event - * - * @return + * Clear the drawing. */ - public Point getLongitudeLatitude(MouseEvent event) throws NoninvertibleTransformException { - // Get the point using the inverse transform of the Zoom/Pan object, this gives us - // a point within the drawing box (between [0, 0] and [width, height]). - Point2D ptDst = this.zoomAndPanListener.getCoordTransform().inverseTransform(event.getPoint(), null); - - // Inverse the "projection" on x/y to get longitude and latitude. - double lon = ptDst.getX(); - double lat = ptDst.getY(); - lon = (lon / this.width) * (this.long2 - this.long1) + this.long1; - lat = (1 - lat / this.height) * (this.lat2 - this.lat1) + this.lat1; - - // Return a new point. - return new Point(lon, lat); - } + public void clear(); - public void drawLine(Point from, Point to) { - int x1 = this.projx(from.getLongitude()) ; - int x2 = this.projx(to.getLongitude()) ; - int y1 = this.projy(from.getLatitude()) ; - int y2 = this.projy(to.getLatitude()) ; - - gr.drawLine(x1, y1, x2, y2) ; - this.doAutoPaint(); - } - - public void drawPoint(Point point, int width) { - int x = this.projx(point.getLongitude()) - width / 2; - int y = this.projy(point.getLatitude()) - width / 2; - gr.fillOval(x, y, width, width); - this.doAutoPaint(); - } - - public void putText(Point point, String txt) { - int x = this.projx(point.getLongitude()); - int y = this.projy(point.getLatitude()); - gr.drawString(txt, x, y); - this.doAutoPaint(); - } + /** + * Draw a line between the two given points with the default color + * and width. + * + * @param from + * @param to + */ + public void drawLine(Point from, Point to); + + /** + * Draw a line between the two given points with the default color + * and the given width. + * + * @param from + * @param to + * @param width + */ + public void drawLine(Point from, Point to, int width); + + /** + * Draw a line between the two given points with the given color + * and the given width. + * + * @param from + * @param to + * @param width + * @param color + */ + public void drawLine(Point from, Point to, int width, Color color); + + /** + * Draw a marker at the given point with the default color. + * + * @param point + */ + public void drawMarker(Point point); + + /** + * Draw the given point with the given color. + * + * @param point + */ + public void drawMarker(Point point, Color color); + + /** + * Draw a point width the given width and color. Do not use this to mark location, + * use drawMarker. + * + * @param point + * @param width + * @param color + */ + public void drawPoint(Point point, int width, Color color); + /** + * Draw the given graph using the given palette. + * + * @param graph + * @param palette + */ + public void drawGraph(Graph graph, GraphPalette palette); + + /** + * Draw the given graph using a default palette specific to the implementation. + * + * @param graph + */ + public void drawGraph(Graph graph); + + /** + * Draw a path using the given color. + * + * @param path + * @param color + * @param markers Show origin and destination markers. + */ + public void drawPath(Path path, Color color, boolean markers); + + /** + * Draw a path using the given color with markers. + * + * @param path + * @param color + */ + public void drawPath(Path path, Color color); + + /** + * Draw a path using a default color specific to the implementation + * + * + * @param path + * @param markers Show origin and destination markers. + */ + public void drawPath(Path path, boolean markers); + + /** + * Draw a path using a default color specific to the implementation + * + * + * @param path + */ + public void drawPath(Path path); + } diff --git a/src/main/org/insa/drawing/graph/GraphPalette.java b/src/main/org/insa/drawing/GraphPalette.java similarity index 95% rename from src/main/org/insa/drawing/graph/GraphPalette.java rename to src/main/org/insa/drawing/GraphPalette.java index 51d8d77..13ae445 100644 --- a/src/main/org/insa/drawing/graph/GraphPalette.java +++ b/src/main/org/insa/drawing/GraphPalette.java @@ -1,4 +1,4 @@ -package org.insa.drawing.graph; +package org.insa.drawing; import java.awt.Color; diff --git a/src/main/org/insa/drawing/MapViewDrawing.java b/src/main/org/insa/drawing/MapViewDrawing.java new file mode 100644 index 0000000..61438af --- /dev/null +++ b/src/main/org/insa/drawing/MapViewDrawing.java @@ -0,0 +1,237 @@ +package org.insa.drawing; + +import java.awt.Color; +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 org.insa.graph.Arc; +import org.insa.graph.Graph; +import org.insa.graph.Path; +import org.insa.graph.Point; +import org.mapsforge.core.graphics.GraphicFactory; +import org.mapsforge.core.graphics.Paint; +import org.mapsforge.core.graphics.Style; +import org.mapsforge.core.model.BoundingBox; +import org.mapsforge.core.model.LatLong; +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.Layers; +import org.mapsforge.map.layer.cache.TileCache; +import org.mapsforge.map.layer.hills.HillsRenderConfig; +import org.mapsforge.map.layer.overlay.Marker; +import org.mapsforge.map.layer.overlay.Polyline; +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 GraphicFactory GRAPHIC_FACTORY = AwtGraphicFactory.INSTANCE; + + // Default tile size. + private static final int DEFAULT_TILE_SIZE = 512; + + // Tile size. + int tileSize; + + public MapViewDrawing() { + setBackground(Color.WHITE); + getMapScaleBar().setVisible(true); + this.tileSize = DEFAULT_TILE_SIZE; + DisplayModel model = getModel().displayModel; + model.setFixedTileSize(tileSize); + model.setBackgroundColor(convertColor(Color.WHITE)); + } + + protected int convertColor(Color color) { + return GRAPHIC_FACTORY.createColor(color.getAlpha(), color.getRed(), + color.getGreen(), color.getBlue()); + } + + private Paint createPaintStroke(int width, Color color) { + Paint paintStroke = AwtGraphicFactory.INSTANCE.createPaint(); + paintStroke.setStyle(Style.STROKE); + if (width != 0) { + paintStroke.setStrokeWidth(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) { + @Override + 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; + } + }; + XmlRenderTheme renderTheme = InternalRenderTheme.DEFAULT; + tileRendererLayer.setXmlRenderTheme(renderTheme); + return tileRendererLayer; + } + + @Override + public void clear() { + getLayerManager().getLayers().clear(); + repaint(); + } + + @Override + public void drawLine(Point from, Point to) { + drawLine(from, to, 0, null); + } + + @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); + } + + @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 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())); + + // Layers + Layers layers = getLayerManager().getLayers(); + + MapDataStore mapDataStore = new MapFile(graphFile); + TileRendererLayer tileRendererLayer = createTileRendererLayer(tileCache, mapDataStore, + getModel().mapViewPosition, null); + layers.add(tileRendererLayer); + BoundingBox boundingBox = mapDataStore.boundingBox(); + + final PreferencesFacade preferencesFacade = new JavaPreferences(Preferences.userNodeForPackage(MapViewDrawing.class)); + final Model model = 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)); + } + } + + @Override + public void drawGraph(Graph graph) { + drawGraph(graph, null); + } + + @Override + public void drawPath(Path path, Color color, boolean markers) { + Paint paintStroke = createPaintStroke(5, 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())); + } + } + getLayerManager().getLayers().add(line); + if (markers) { + 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, boolean markers) { + drawPath(path, DEFAULT_PATH_COLOR, markers); + } + +} diff --git a/src/main/org/insa/drawing/graph/GraphDrawing.java b/src/main/org/insa/drawing/graph/GraphDrawing.java deleted file mode 100644 index e64a001..0000000 --- a/src/main/org/insa/drawing/graph/GraphDrawing.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.insa.drawing.graph; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.Iterator; - -import org.insa.drawing.Drawing; -import org.insa.graph.Arc; -import org.insa.graph.Graph; -import org.insa.graph.Node; -import org.insa.graph.Point; - -public class GraphDrawing { - - // Drawing - private Drawing drawing; - - // Palette - private GraphPalette palette; - - public GraphDrawing(Drawing drawing) { - this.drawing = drawing; - this.palette = new BasicGraphPalette(); - } - - public GraphDrawing(Drawing drawing, GraphPalette palette) { - this.drawing = drawing; - this.palette = palette; - } - - public void drawLine(Point p1, Point p2) { - drawing.drawLine(p1, p2); - } - - public void drawPoint(Point p) { - drawPoint(p, palette.getDefaultPointWidth()); - } - - public void drawPoint(Point p, int width) { - drawing.drawPoint(p, width); - } - - public void drawPoint(Point p, int width, Color c) { - drawing.setColor(c); - drawing.drawPoint(p, width); - } - - /** - * Draw the given arc with automatic color and width depending - * on the road type. - * - * @param arc Arc to draw. - */ - public void drawArc(Arc arc) { - drawArc(arc, true); - } - - /** - * Draw the given arc. - * - * @param arc Arc to draw. - * @param autoColorAndWidth Set to true to set color and width based - * on the road type of the arc. - */ - public void drawArc(Arc arc, boolean autoColorAndWidth) { - ArrayList pts = arc.getPoints(); - if (!pts.isEmpty()) { - if (autoColorAndWidth) { - drawing.setColor(palette.getColorForType(arc.getInfo().getType())); - drawing.setWidth(palette.getWidthForType(arc.getInfo().getType())); - } - Iterator it1 = pts.iterator(); - Point prev = it1.next(); - while (it1.hasNext()) { - Point curr = it1.next(); - drawLine(prev, curr); - prev = curr; - } - } - } - - /** - * Initialize the drawing for the given graph. - * - * @param graph - */ - public void initialize(Graph graph) { - double minLon = Double.POSITIVE_INFINITY, minLat = Double.POSITIVE_INFINITY, - maxLon = Double.NEGATIVE_INFINITY, maxLat = Double.NEGATIVE_INFINITY; - for (Node node: graph.getNodes()) { - Point pt = node.getPoint(); - if (pt.getLatitude() < minLat) { - minLat = pt.getLatitude(); - } - if (pt.getLatitude() > maxLat) { - maxLat = pt.getLatitude(); - } - if (pt.getLongitude() < minLon) { - minLon = pt.getLongitude(); - } - if (pt.getLongitude() > maxLon) { - maxLon = pt.getLongitude(); - } - } - - double deltaLon = 0.02 * (maxLon - minLon), - deltaLat = 0.02 * (maxLat - minLat); - - drawing.setBB(minLon - deltaLon, maxLon + deltaLon, - minLat - deltaLat, maxLat + deltaLat); - } - - - /** - * Clear the drawing and draw the given graph on the drawing. - * - * @param graph Graph to draw. - */ - public void drawGraph(Graph graph) { - - drawing.clear(); - - initialize(graph); - - for (Node node: graph.getNodes()) { - for (Arc arc: node.getSuccessors()) { - drawArc(arc); - } - } - } - -} diff --git a/src/main/org/insa/drawing/graph/PathDrawing.java b/src/main/org/insa/drawing/graph/PathDrawing.java deleted file mode 100644 index 3ff6b03..0000000 --- a/src/main/org/insa/drawing/graph/PathDrawing.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.insa.drawing.graph; - -import java.awt.Color; - -import org.insa.drawing.Drawing; -import org.insa.graph.Arc; -import org.insa.graph.Path; - -public class PathDrawing { - - // Default color - public static final Color DEFAULT_PATH_COLOR = new Color(255, 0, 255); - - // Drawing - private Drawing drawing; - private GraphDrawing graphDrawing; - - /** - * @param drawing - */ - public PathDrawing(Drawing drawing) { - this.drawing = drawing; - this.graphDrawing = new GraphDrawing(drawing); - } - - /** - * Draw the given path with the given color. - * - * @param path - * @param color - */ - public void drawPath(Path path, Color color) { - this.graphDrawing.drawPoint(path.getFirstNode().getPoint(), 4, color); - this.drawing.setColor(color); - this.drawing.setWidth(2); - for (Arc arc: path.getArcs()) { - this.graphDrawing.drawArc(arc, false); - } - this.graphDrawing.drawPoint(path.getLastNode().getPoint(), 4, color); - } - - /** - * Draw the given path with default color. - * - * @param path - */ - public void drawPath(Path path) { - drawPath(path, DEFAULT_PATH_COLOR); - drawing.repaint(); - } - -} diff --git a/src/main/org/insa/graph/io/BinaryGraphReader.java b/src/main/org/insa/graph/io/BinaryGraphReader.java index 8d4eecc..0be885b 100644 --- a/src/main/org/insa/graph/io/BinaryGraphReader.java +++ b/src/main/org/insa/graph/io/BinaryGraphReader.java @@ -61,6 +61,8 @@ public class BinaryGraphReader extends BinaryReader implements AbstractGraphRead @Override public Graph read() throws IOException { + System.out.println(getClass()); + // Read and check magic number and file version. checkMagicNumberOrThrow(dis.readInt()); checkVersionOrThrow(dis.readInt()); diff --git a/src/main/org/insa/graph/io/BinaryGraphReaderV2.java b/src/main/org/insa/graph/io/BinaryGraphReaderV2.java new file mode 100644 index 0000000..597d3a7 --- /dev/null +++ b/src/main/org/insa/graph/io/BinaryGraphReaderV2.java @@ -0,0 +1,170 @@ +package org.insa.graph.io; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; + +import org.insa.graph.Arc; +import org.insa.graph.Graph; +import org.insa.graph.Node; +import org.insa.graph.Point; +import org.insa.graph.RoadInformation; +import org.insa.graph.RoadInformation.RoadType; + +public class BinaryGraphReaderV2 extends BinaryReader implements AbstractGraphReader { + + // Map version and magic number targeted for this reader. + private static final int VERSION = 5; + private static final int MAGIC_NUMBER = 0x208BC3B3; + + /** + * Convert a character to its corresponding road type. + * + * @param ch Character to convert. + * + * @return Road type corresponding to ch. + * + * @see http://wiki.openstreetmap.org/wiki/Highway_tag_usage. + */ + public static RoadType toRoadType(char ch) { + switch (ch) { + case 'a': return RoadType.MOTORWAY; + case 'b': return RoadType.TRUNK; + case 'c': return RoadType.PRIMARY; + case 'd': return RoadType.SECONDARY; + case 'e': return RoadType.MOTORWAY_LINK; + case 'f': return RoadType.TRUNK_LINK; + case 'g': return RoadType.PRIMARY_LINK; + case 'h': return RoadType.SECONDARY_LINK; + case 'i': return RoadType.TERTIARY; + case 'j': return RoadType.RESIDENTIAL; + case 'k': return RoadType.UNCLASSIFIED; + case 'l': return RoadType.ROAD; + case 'm': return RoadType.LIVING_STREET; + case 'n': return RoadType.SERVICE; + case 'o': return RoadType.ROUNDABOUT; + case 'z': return RoadType.COASTLINE; + } + return RoadType.UNCLASSIFIED; + } + + /** + * Create a new BinaryGraphReader using the given DataInputStream. + * + * @param dis + */ + public BinaryGraphReaderV2(DataInputStream dis) { + super(MAGIC_NUMBER, VERSION, dis); + } + + @Override + public Graph read() throws IOException { + + // Read and check magic number and file version. + checkMagicNumberOrThrow(dis.readInt()); + checkVersionOrThrow(dis.readInt()); + + // Read map id. + int mapId = dis.readInt(); + + // Number of descriptors and nodes. + int nbDesc = dis.readInt(); + int nbNodes = dis.readInt(); + + // Number of successors for each nodes. + int[] nbSuccessors = new int[nbNodes]; + + // Construct an array list with initial capacity of nbNodes. + ArrayList nodes = new ArrayList(nbNodes); + + // Read nodes. + for (int node = 0; node < nbNodes; ++node) { + float longitude = ((float)dis.readInt ()) / 1E6f; + float latitude = ((float)dis.readInt ()) / 1E6f; + nbSuccessors[node] = dis.readUnsignedByte(); + nodes.add(new Node(node, new Point(longitude, latitude))); + } + + // Check format. + checkByteOrThrow(255); + + // Read descriptors. + RoadInformation[] descs = new RoadInformation[nbDesc]; + + // Read + for (int descr = 0; descr < nbDesc; ++descr) { + descs[descr] = readRoadInformation(); + } + + // Check format. + checkByteOrThrow(254); + + // Read successors and convert to arcs. + for (int node = 0; node < nbNodes; ++node) { + for (int succ = 0; succ < nbSuccessors[node]; ++succ) { + + // Read target node number. + int destNode = this.read24bits(); + + // Read information number. + int descrNum = this.read24bits(); + + // Length of the arc. + int length = dis.readUnsignedShort(); + + // Number of segments. + int nbSegments = dis.readUnsignedShort(); + + // Chain of points corresponding to the segments. + ArrayList points = new ArrayList(nbSegments + 2); + points.add(nodes.get(node).getPoint()); + + for (int seg = 0; seg < nbSegments; ++seg) { + Point lastPoint = points.get(points.size() - 1); + + float dlon = (dis.readShort()) / 2.0e5f; + float dlat = (dis.readShort()) / 2.0e5f; + + points.add(new Point(lastPoint.getLongitude() + dlon, + lastPoint.getLatitude() + dlat)); + } + + points.add(nodes.get(destNode).getPoint()); + + RoadInformation info = descs[descrNum]; + Node orig = nodes.get(node); + Node dest = nodes.get(destNode); + + // Add successor to initial arc. + new Arc(orig, dest, length, info, points); + + // And reverse arc if its a two-way road. + if (!info.isOneWay()) { + // Add without segments. + ArrayList rPoints = new ArrayList(points); + Collections.reverse(rPoints); + new Arc(dest, orig, length, info, rPoints); + } + + } + } + + // Check format. + checkByteOrThrow(253); + + return new Graph(mapId, nodes); + } + + /** + * Read the next road information from the stream. + * + * @throws IOException + */ + private RoadInformation readRoadInformation() throws IOException { + char type = (char)dis.readUnsignedByte(); + int x = dis.readUnsignedByte() ; + return new RoadInformation(toRoadType(type), (x & 0x80) > 0, (x & 0x7F) * 5, dis.readUTF()); + } + +}