diff --git a/.classpath b/.classpath
index f7d8560..ed0e8f4 100644
--- a/.classpath
+++ b/.classpath
@@ -1,23 +1,42 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index 3a5ba85..2c5af03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.DS_Store
bin
+/target/
diff --git a/.project b/.project
index 9a8e431..87c2087 100644
--- a/.project
+++ b/.project
@@ -10,8 +10,14 @@
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+ org.eclipse.m2e.core.maven2Nature
org.eclipse.jdt.core.javanature
diff --git a/src/main/org/insa/base/MainWindow.java b/src/main/org/insa/base/MainWindow.java
index 4fc986e..d2e1399 100644
--- a/src/main/org/insa/base/MainWindow.java
+++ b/src/main/org/insa/base/MainWindow.java
@@ -11,10 +11,12 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
+import java.lang.reflect.Constructor;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
+import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
@@ -28,13 +30,21 @@ import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
+import javax.swing.UIManager;
import javax.swing.filechooser.FileNameExtensionFilter;
+import org.insa.algo.AbstractSolution;
+import org.insa.algo.shortestpath.BellmanFordAlgorithm;
+import org.insa.algo.shortestpath.ShortestPathAlgorithm;
+import org.insa.algo.shortestpath.ShortestPathGraphicObserver;
+import org.insa.algo.shortestpath.ShortestPathInstance;
+import org.insa.algo.shortestpath.ShortestPathInstance.Mode;
+import org.insa.algo.shortestpath.ShortestPathSolution;
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver;
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentTextObserver;
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsInstance;
-import org.insa.drawing.DrawingVisible;
+import org.insa.drawing.Drawing;
import org.insa.drawing.graph.BlackAndWhiteGraphPalette;
import org.insa.drawing.graph.GraphDrawing;
import org.insa.drawing.graph.PathDrawing;
@@ -48,71 +58,76 @@ import org.insa.graph.io.Openfile;
import com.sun.glass.events.KeyEvent;
public class MainWindow extends JFrame {
-
+
public class JOutputStream extends OutputStream {
- private JTextArea textArea;
+ private JTextArea textArea;
- public JOutputStream(JTextArea textArea) {
- this.textArea = 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());
- }
+ @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());
+ }
}
/**
*
*/
private static final long serialVersionUID = -527660583705140687L;
-
+
/**
*
*/
private static final String WINDOW_TITLE = "BE Graphes INSA";
-
+
/**
*
*/
private static final Dimension DEFAULT_DIMENSION = new Dimension(800, 600);
-
+
// Current graph.
private Graph graph;
-
+
// Current loaded path.
private Path currentPath;
-
+
// List of item for the top menus.
private JMenuItem openMapItem;
-
+
// List of items that cannot be used without a graph
private ArrayList graphItems = new ArrayList();
-
+
// Label containing the map ID of the current graph.
private JLabel mapIdPanel;
+ private JPanel threadPanel;
+
// Log stream and print stream
private JOutputStream logStream;
private PrintStream printStream;
+ // Current running thread
+ private Thread currentThread;
+
/**
*
*/
- private DrawingVisible drawing;
-
+ private Drawing drawing;
+
public MainWindow() {
super(WINDOW_TITLE);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
setLayout(new BorderLayout());
setSize(DEFAULT_DIMENSION);
setJMenuBar(createMenuBar());
-
+
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
int confirmed = JOptionPane.showConfirmDialog(null,
@@ -125,13 +140,13 @@ public class MainWindow extends JFrame {
}
}
});
-
+
// Create graph area
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
-
- drawing = new DrawingVisible();
+
+ drawing = new Drawing();
drawing.setBackground(Color.WHITE);
-
+
JTextArea infoPanel = new JTextArea();
infoPanel.setMinimumSize(new Dimension(200, 50));
// infoPanel.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.GRAY));
@@ -140,36 +155,70 @@ public class MainWindow extends JFrame {
infoPanel.setEditable(false);
this.logStream = new JOutputStream(infoPanel);
this.printStream = new PrintStream(this.logStream);
-
- sp.setResizeWeight(0.8);
- // sp.setEnabled(false);
- sp.setDividerSize(5);
-
- sp.setBackground(Color.WHITE);
+
+ sp.setResizeWeight(0.8);
+ // sp.setEnabled(false);
+ sp.setDividerSize(5);
+
+ sp.setBackground(Color.WHITE);
sp.add(drawing);
sp.add(new JScrollPane(infoPanel));
this.add(sp, BorderLayout.CENTER);
-
+
this.add(createStatusBar(), BorderLayout.SOUTH);
}
+ private void launchThread(Runnable runnable) {
+ currentThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ threadPanel.setVisible(true);
+ runnable.run();
+ threadPanel.setVisible(false);
+ }
+ });
+ currentThread.start();
+ }
+
+ private ShortestPathInstance getShortestPathParameters() {
+ // TODO: Select origin / end nodes.
+ return new ShortestPathInstance(
+ graph, graph.getNodes().get(2), graph.getNodes().get(139), Mode.TIME);
+ }
+
+ private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) {
+ spAlgorithm.addObserver(new ShortestPathGraphicObserver(drawing));
+ // algo.addObserver(new ShortestPathTextObserver(printStream));
+ launchThread(new Runnable() {
+ @Override
+ public void run() {
+ spAlgorithm.run();
+ AbstractSolution solution = spAlgorithm.getLastSolution();
+ if (solution != null && solution.isFeasible()) {
+ new PathDrawing(drawing).drawPath(((ShortestPathSolution)solution).getPath());
+ }
+ }
+ });
+ }
+
+ @SuppressWarnings("restriction")
private JMenuBar createMenuBar() {
// Open Map item...
openMapItem = new JMenuItem("Open Map... ",
- KeyEvent.VK_O);
+ KeyEvent.VK_O);
openMapItem.setAccelerator(KeyStroke.getKeyStroke(
- KeyEvent.VK_O, ActionEvent.ALT_MASK));
+ 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", "map.gz");
- chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
- chooser.setFileFilter(filter);
- if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
- BinaryGraphReader reader;
+ FileNameExtensionFilter filter = new FileNameExtensionFilter(
+ "Map & compressed map files", "map", "map.gz");
+ chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
+ chooser.setFileFilter(filter);
+ if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
+ BinaryGraphReader reader;
try {
reader = new BinaryGraphReader(
Openfile.open(chooser.getSelectedFile().getAbsolutePath()));
@@ -177,38 +226,38 @@ public class MainWindow extends JFrame {
JOptionPane.showMessageDialog(MainWindow.this, "Cannot open the selected file.");
return ;
}
- try {
- graph = reader.read();
- }
- catch (Exception exception) {
+ try {
+ graph = reader.read();
+ }
+ catch (Exception exception) {
JOptionPane.showMessageDialog(MainWindow.this, "Unable to read graph from the selected file.");
return ;
- }
- drawing.clear();
- new GraphDrawing(drawing).drawGraph(graph);
-
- for (JMenuItem item: graphItems) {
- item.setEnabled(true);
- }
- mapIdPanel.setText("Map ID: 0x" + Integer.toHexString(graph.getMapId()));
- }
+ }
+ drawing.clear();
+ new GraphDrawing(drawing).drawGraph(graph);
+
+ for (JMenuItem item: graphItems) {
+ item.setEnabled(true);
+ }
+ mapIdPanel.setText("Map ID: 0x" + Integer.toHexString(graph.getMapId()));
+ }
}
});
-
+
// Open Path item...
JMenuItem openPathItem = new JMenuItem("Open Path... ", KeyEvent.VK_P);
openPathItem.setAccelerator(KeyStroke.getKeyStroke(
- KeyEvent.VK_P, ActionEvent.ALT_MASK));
+ 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;
+ 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()));
@@ -216,23 +265,23 @@ public class MainWindow extends JFrame {
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) {
+ 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 ;
- }
- new PathDrawing(drawing).drawPath(currentPath);
- }
+ }
+ new PathDrawing(drawing).drawPath(currentPath);
+ }
}
});
graphItems.add(openPathItem);
-
+
// Close item
JMenuItem closeItem = new JMenuItem("Quit", KeyEvent.VK_Q);
closeItem.setAccelerator(KeyStroke.getKeyStroke(
@@ -250,7 +299,7 @@ public class MainWindow extends JFrame {
fileMenu.add(openPathItem);
fileMenu.addSeparator();
fileMenu.add(closeItem);
-
+
// Second menu
JMenuItem drawGraphItem = new JMenuItem("Redraw", KeyEvent.VK_R);
drawGraphItem.setAccelerator(KeyStroke.getKeyStroke(
@@ -258,10 +307,14 @@ public class MainWindow extends JFrame {
drawGraphItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- drawing.clear();
- drawing.setAutoRepaint(true);
- new GraphDrawing(drawing).drawGraph(graph);
- drawing.setAutoRepaint(false);
+ launchThread(new Runnable() {
+ @Override
+ public void run() {
+ drawing.clear();
+ drawing.setAutoRepaint(true);
+ new GraphDrawing(drawing).drawGraph(graph);
+ }
+ });
}
});
graphItems.add(drawGraphItem);
@@ -271,40 +324,58 @@ public class MainWindow extends JFrame {
drawGraphBWItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- drawing.clear();
- drawing.setAutoRepaint(true);
- new GraphDrawing(drawing, new BlackAndWhiteGraphPalette()).drawGraph(graph);
- drawing.setAutoRepaint(false);
+ launchThread(new Runnable() {
+ @Override
+ public void run() {
+ drawing.clear();
+ drawing.setAutoRepaint(true);
+ new GraphDrawing(drawing, new BlackAndWhiteGraphPalette()).drawGraph(graph);
+ }
+ });
}
});
graphItems.add(drawGraphBWItem);
-
+
JMenu graphMenu = new JMenu("Graph");
graphMenu.add(drawGraphItem);
graphMenu.add(drawGraphBWItem);
-
+
// 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) {
-
WeaklyConnectedComponentsInstance instance = new WeaklyConnectedComponentsInstance(graph);
WeaklyConnectedComponentsAlgorithm algo = new WeaklyConnectedComponentsAlgorithm(instance);
algo.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing));
-
- (new Thread(algo)).start();
+ // algo.addObserver(new WeaklyConnectedComponentTextObserver(printStream));
+ launchThread(algo);
+ }
+ });
+
+ // Shortest path
+ JMenuItem bellmanItem = new JMenuItem("Shortest Path (Bellman-Ford)");
+ bellmanItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ launchShortestPathThread(new BellmanFordAlgorithm(getShortestPathParameters()));
}
});
graphItems.add(wccItem);
-
+ graphItems.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);
@@ -312,29 +383,60 @@ public class MainWindow extends JFrame {
for (JMenuItem item: graphItems) {
item.setEnabled(false);
}
-
+
return menuBar;
}
-
+
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(), 20));
- statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.X_AXIS));
-
+ statusPanel.setPreferredSize(new Dimension(getWidth(), 34));
+ statusPanel.setLayout(new BorderLayout());
+
mapIdPanel = new JLabel();
mapIdPanel.setHorizontalAlignment(SwingConstants.LEFT);
- statusPanel.add(mapIdPanel);
+ statusPanel.add(mapIdPanel, BorderLayout.WEST);
+
+ JLabel threadInfo = new JLabel("Thread running... ");
+ JButton threadButton = new JButton("Stop");
+ threadButton.addActionListener(new ActionListener() {
+ @SuppressWarnings("deprecation")
+ @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) {
+ currentThread.stop();
+ currentThread = null;
+ threadPanel.setVisible(false);
+ }
+ }
+ }
+ });
+ threadPanel = new JPanel();
+ threadPanel.add(threadInfo);
+ threadPanel.add(threadButton);
+ // threadPanel.setVisible(false);
+ statusPanel.add(threadPanel, BorderLayout.EAST);
return statusPanel;
}
-
+
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/drawing/Drawing.java b/src/main/org/insa/drawing/Drawing.java
index e04d9fc..f19cbd2 100644
--- a/src/main/org/insa/drawing/Drawing.java
+++ b/src/main/org/insa/drawing/Drawing.java
@@ -1,88 +1,170 @@
-package org.insa.drawing ;
+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.image.*;
+
+import javax.swing.JPanel;
/**
- * Classe abstraite pour dessiner a l'ecran.
- * Deux implementations : une sous-classe DessinVisible qui dessine vraiment a l'ecran
- * et une sous-classe DessinInvisible qui ne dessine rien (pour ne pas ralentir les tests avec l'affichage).
+ * Cette implementation de la classe Dessin produit vraiment un affichage
+ * (au contraire de la classe DessinInvisible).
*/
-import java.awt.* ;
+public class Drawing extends JPanel {
-public interface Drawing {
-
/**
- * Enable auto-repaint mode - When this mode is enable, call to
- * drawing function will automatically repaint the drawing, which
- * may be very slow in some case.
- *
- * @param autoRepaint Use true to enable auto-repaint, false to disable.
*
*/
- public void setAutoRepaint(boolean autoRepaint);
+ private static final long serialVersionUID = 96779785877771827L;
+ private final Graphics2D gr;
+
+ private float long1;
+ private float long2;
+ private float lat1;
+ private float lat2;
+
+ // Width and height of the image
+ private final int width, height;
+
+ private boolean bb_is_set ;
+
+ private Image image;
+ private ZoomAndPanListener zoomAndPanListener;
+
+ public boolean autoRepaint = true;
+
/**
- * Repaint the drawing.
- *
+ * Cree et affiche une nouvelle fenetre de dessin.
*/
- public void repaint();
+ 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.bb_is_set = false;
+
+
+ this.long1 = 0.0f;
+ this.long2 = this.width;
+ this.lat1 = 0.0f;
+ this.lat2 = this.height;
+
+ 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);
+ }
- /**
- * Set the pencil width.
- *
- * @param width Width for the pencil.
- *
- */
- public void setWidth(int width);
-
- /**
- * Set the pencil color.
- *
- * @param color Color for the pencil.
- *
- */
- public void setColor(Color col);
-
- /**
- * Clear the drawing.
- */
- public void clear();
+ 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));
+ }
- /**
- * Indique les bornes de la fenetre graphique.
- * Le calcul des coordonnees en pixel se fera automatiquement
- * a l'appel des methodes drawLine et autres.
- *
- * @param long1 longitude du bord gauche
- * @param long2 longitude du bord droit
- * @param lat1 latitude du bord bas
- * @param lat2 latitude du bord haut
- *
- */
- public void setBB(double long1, double long2, double lat1, double lat2);
+ public void setColor(Color col) {
+ this.gr.setColor(col);
+ }
- /**
- * Trace un segment.
- * @param long1 longitude du premier point
- * @param lat1 latitude du premier point
- * @param long2 longitude du second point
- * @param lat2 latitude du second point
- */
- public void drawLine(float long1, float lat1, float long2, float lat2);
+ public void clear() {
+ this.gr.setColor(Color.WHITE);
+ this.gr.fillRect(0, 0, this.width, this.height);
+ }
- /**
- * Trace un point.
- * @param lon longitude du point
- * @param lat latitude du point
- * @param width grosseur du point
- */
- public void drawPoint(float lon, float lat, int width);
+ public void setBB(double long1, double long2, double lat1, double lat2) {
- /**
- * Ecrit du texte a la position indiquee.
- * @param lon longitude du point ou positionner le texte.
- * @param lat latitude du point ou positionner le texte.
- * @param txt le texte a ecrire.
- */
- public void putText(float lon, float lat, String txt);
+ if (long1 > long2 || lat1 > lat2) {
+ throw new Error("DessinVisible.setBB : mauvaises coordonnees.");
+ }
+
+ this.long1 = (float)long1;
+ this.long2 = (float)long2;
+ this.lat1= (float)lat1;
+ this.lat2 = (float)lat2;
+
+ this.bb_is_set = true;
+
+ 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(float lon) {
+ return (int)(width * (lon - this.long1) / (this.long2 - this.long1)) ;
+ }
+
+ private int projy(float lat) {
+ return (int)(height * (1 - (lat - this.lat1) / (this.lat2 - this.lat1))) ;
+ }
+
+ private void checkBB() {
+ if (!this.bb_is_set) {
+ throw new Error("Classe DessinVisible : vous devez invoquer la methode setBB avant de dessiner.") ;
+ }
+ }
+
+ public void drawLine(float long1, float lat1, float long2, float lat2) {
+ this.checkBB() ;
+ int x1 = this.projx(long1) ;
+ int x2 = this.projx(long2) ;
+ int y1 = this.projy(lat1) ;
+ int y2 = this.projy(lat2) ;
+
+ gr.drawLine(x1, y1, x2, y2) ;
+ this.doAutoPaint();
+ }
+
+ public void drawPoint(float lon, float lat, int width) {
+ this.checkBB() ;
+ int x = this.projx(lon) - width / 2 ;
+ int y = this.projy(lat) - width / 2 ;
+ gr.fillOval (x, y, width, width) ;
+ this.doAutoPaint();
+ }
+
+ public void putText(float lon, float lat, String txt) {
+ this.checkBB() ;
+ int x = this.projx(lon) ;
+ int y = this.projy(lat) ;
+ gr.drawString (txt, x, y) ;
+ this.doAutoPaint();
+ }
}