Create new drawing using Mapsforge.

This commit is contained in:
Mikael Capelle
2018-02-21 19:22:37 +01:00
parent 379784e2ec
commit d5af267227
32 changed files with 1239 additions and 393 deletions

View File

@@ -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");

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<File> 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<org.insa.graph.Point> 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<File> 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: <mapFile>");
}
File demFolder = new File(args[0]);
if (demFolder.exists() && demFolder.isDirectory() && demFolder.canRead()) {
return demFolder;
}
return null;
}
private static List<File> getMapFiles(String[] args) {
if (args.length == 0) {
throw new IllegalArgumentException("missing argument: <mapFile>");
}
List<File> 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();
}
}