first .osm format import

- import osm convert it to Drawing and use it as resolved path.
- Not ready , first test over lab/valbonne_oct_2020.osm
This commit is contained in:
philippe lhardy
2020-10-31 15:44:23 +01:00
parent 99716e57d3
commit 8af19bdb59
12 changed files with 17220 additions and 503 deletions

View File

@@ -2,20 +2,14 @@ package org.artisanlogiciel.games.maze.gui;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.*;
import java.util.*;
@@ -27,11 +21,11 @@ import javax.swing.event.ChangeListener;
import org.artisanlogiciel.games.maze.*;
import org.artisanlogiciel.games.maze.persist.MazePersistRaw;
import org.artisanlogiciel.games.maze.solve.DirectionPosition;
import org.artisanlogiciel.games.maze.solve.MazeResolutionListener;
import org.artisanlogiciel.games.maze.solve.SolvingModel;
import org.artisanlogiciel.games.stl.Maze3dParams;
import org.artisanlogiciel.games.stl.Wall3dStream;
import org.artisanlogiciel.osm.OsmReader;
import org.artisanlogiciel.osm.convert.OsmToDrawing;
import org.artisanlogiciel.util.UTF8Control;
import org.artisanlogiciel.graphics.Drawing;
@@ -41,7 +35,9 @@ import org.artisanlogiciel.graphics.SvgWriter;
/**
* Display is Main JFrame for this tool
**/
public class Display extends JFrame {
public class Display extends JFrame
implements StatusListener
{
// to please eclipse, not supposed to be serialized
private static final long serialVersionUID = 8500214871372184418L;
@@ -92,7 +88,7 @@ public class Display extends JFrame {
private MazeComponent createMazeComponent(LabyModel model, int W, int H) {
MazeCellParameters cp = new MazeCellParameters(model.getWidth(), model.getHeight(), W, H, 3, 3);
MazeComponent comp = new MazeComponent(model, cp);
MazeComponent comp = new MazeComponent(model, cp, this);
return comp;
}
@@ -332,7 +328,7 @@ public class Display extends JFrame {
}
void addStatus(String pStatus)
public void addStatus(String pStatus)
{
if ( statusEnable ) {
statusField.setText(pStatus);
@@ -400,6 +396,27 @@ public class Display extends JFrame {
loadImcButton.addActionListener(loadImcAction);
loadMenu.add(loadImcButton);
Action loadOsmAction = new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
//
addStatus("load Osm");
String filename = loadName.getText();
if ((filename.length() > 0)) {
setMazeName(filename);
loadOsm(false);
refresh();
}
}
};
JButton loadOsmButton = new JButton(labels.getString("load" ) + " Osm");
loadOsmButton.addActionListener(loadOsmAction);
loadMenu.add(loadOsmButton);
return loadMenu;
}
@@ -675,6 +692,40 @@ public class Display extends JFrame {
}
}
private void loadOsm(boolean add) {
if ( maze != null ) {
new Thread() {
@Override
public void run() {
File infile = new File(params.getSaveDir(), params.getName() + ".osm");
FileInputStream inputStream = null;
try {
// TODO really use InputStream and not pathname
OsmToDrawing converter = new OsmToDrawing(43.6399000, 7.0058300, 10000,10000);
OsmReader reader = new OsmReader(infile.getCanonicalPath());
reader.read();
Drawing drawing = converter.getDrawing(reader.getWays());
statusEnable = false;
maze.addDrawing(drawing,add);
statusEnable = true;
} catch (IOException io) {
io.printStackTrace(System.err);
statusField.setText("[ERROR] Can't load " + infile.getAbsolutePath());
} finally {
if (inputStream != null) {
// cleanup
try {
inputStream.close();
} catch (Exception any) {
// don't care really
}
}
}
}
}.start();
}
}
private void loadImc(boolean add) {
if ( maze != null ) {
new Thread() {
@@ -720,497 +771,6 @@ public class Display extends JFrame {
return button;
}
private static class MazeCellParameters {
double width = 10; // width of one cell
double height = 10; // height of one cell
int offsetX = 5; // x offset of upper corner left
int offsetY = 5; // y offset of upper corner left
int mapWidth = 0;
int mapHeight = 0;
public MazeCellParameters(int mapw, int maph, int W, int H, int x, int y) {
double w = (W - x) / mapw;
double h = (H - y) / maph;
mapWidth = mapw;
mapHeight = maph;
if (w < 5)
w = 5;
if (h < 5)
h = 5;
setCellSize(w, h);
offsetX = x;
offsetY = y;
}
public void resetMazeWidthHeight(int mapw, int maph) {
mapWidth = mapw;
mapHeight = maph;
}
public void adaptTo(double W, double H) {
double w = (W - offsetX) / mapWidth;
double h = (H - offsetY) / mapHeight;
mapWidth = mapWidth;
mapHeight = mapHeight;
if (w < 5)
w = 5;
if (h < 5)
h = 5;
setCellSize(w, h);
}
public void setCellSize(double w, double h) {
width = w;
height = h;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
public int getOffsetX() {
return offsetX;
}
public int getOffsetY() {
return offsetY;
}
public Dimension getDimension() {
return new Dimension(offsetX + (int) (mapWidth * width),
offsetY + (int) (mapHeight * height));
}
public void drawWalls(Graphics g, int pX, int pY, short walls) {
int x = offsetX + (int) (pX * width);
int y = offsetY + (int) (pY * height);
if ((pY == 0) && ((walls & Brick.UP) == Brick.UP))
g.drawLine(x, y, x + (int) width, y);
if ((walls & Brick.DOWN) == Brick.DOWN)
g.drawLine(x, y + (int) height, x + (int) width, y + (int) height);
if ((walls & Brick.RIGHT) == Brick.RIGHT)
g.drawLine(x + (int) width, y, x + (int) width, y + (int) height);
if ((pX == 0) && ((walls & Brick.LEFT) == Brick.LEFT))
g.drawLine(x, y, x, y + (int) height);
}
public void drawPath(Graphics g, DirectionPosition dp, int pX, int pY, int mX, int mY) {
if (dp != null) {
Position dot = dp.getPosition();
if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
int x = offsetX + (int) (dot.getX() * width);
int y = offsetY + (int) (dot.getY() * height);
short path = dp.getDirection();
int xm = x + (int) (width / 2);
int ym = y + (int) (height / 2);
if ((path & LabyModel.HORIZONTAL) == LabyModel.HORIZONTAL) {
if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
g.drawLine(xm, ym, x + (int) width, ym);
g.drawLine(xm, ym + (int) (height / 4), x + (int) width, ym);
}
// LEFT /_
if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
g.drawLine(x, ym, xm, ym);
g.drawLine(x, ym, xm, ym - (int) (height / 4));
}
}
if ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL) {
if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
g.drawLine(xm, ym, xm, y + (int) height);
g.drawLine(xm - (int) (width / 4), ym, xm, y + (int) height);
}
// UP |\
if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
g.drawLine(xm, ym, xm, y);
g.drawLine(xm + (int) (width / 4), ym, xm, y);
}
}
}
}
}
public void drawDot(Graphics g, Position dot, int pX, int pY, int mX, int mY) {
double radius = (height > width) ? width : height;
int a = (int) (radius / 4);
if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
int x = offsetX + (int) (dot.getX() * width);
int y = offsetY + (int) (dot.getY() * height);
int r2 = (int) ((radius * 3) / 4);
g.drawOval(x + 1, y + 1, r2, r2);
// g.drawLine(x+a,y+a,x+width-a,y+height-a);
// g.drawLine(x+a,y+height-a,x+width-a,y+a);
} else {
int x = offsetX + (int) (pX * width);
int y = offsetY + (int) (pY * height);
g.drawLine(x + 1, y + 1, x + (int) width - 1, y + (int) height - 1);
}
}
}
private class MazeComponent
extends JComponent
implements MazeCreationListener,
MazeResolutionListener,
MouseMotionListener {
private static final long serialVersionUID = 3163272907991176390L;
// WallsProvider map;
LabyModel map;
final MazeCellParameters cp;
Position current = null;
LinkedList<DirectionPosition> solvedPath = null;
LinkedList<DirectionPosition> drawingPath = null;
final Object lockChange = new Object();
// current postion of human resolving
int sX = 0;
int sY = 0;
// goal exit
int gX = -1;
int gY = -1;
Date lastDrag = null;
// FIXME HARCDODED delay after which a draging to draw a continous line is ended, a new line will then start.
long dragTimeout = 200;
// not set by default for debug, will show any path
boolean showAll = false;
// for a given (x,y) pixel return cell position.
// if rightmost position of view not (0,0) this is not working.
Position getPosition(int x, int y) {
int pX = (int) ((double) (x - cp.getOffsetX()) / cp.getWidth());
int pY = (int) ((double) (y - cp.getOffsetY()) / cp.getHeight());
return new Position(pX, pY);
}
@Override
public void mouseDragged(MouseEvent e) {
boolean add = ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0);
Position newPosition = getPosition(e.getX(), e.getY());
Date now = new Date(System.currentTimeMillis());
if (lastDrag == null )
{
resetDrawingPath();
}
else
{
if ( now.getTime() - lastDrag.getTime() > dragTimeout )
{
resetDrawingPath();
addStatus("move timeout");
}
}
lastDrag = now;
addPosition(newPosition,add);
changed(null, null, map);
}
public void resetDrawingPath()
{
drawingPath = null;
}
public void addDrawing(Drawing drawing, boolean add)
{
for (DrawingLine line : drawing.getInternLines())
{
addDrawingLine(line, add);
}
changed(null, null, map);
}
public void addDrawingLine(DrawingLine line, boolean add)
{
resetDrawingPath();
ArrayList<Point> points = line.getPoints();
for (Point p : points)
{
addPosition(new Position(p.x,p.y), add);
}
}
public void addPosition(Position newPosition, boolean add ) {
// should find the cell ...
DirectionPosition last = null;
short path = 0;
if (drawingPath == null) {
drawingPath = new LinkedList<>();
last = new DirectionPosition((short) 0, newPosition);
if ( statusEnable) {
addStatus("Mouse dragged Cell " + newPosition + " Button " + add);
}
drawingPath.addLast(last);
} else {
// setShowAll(true);
DirectionPosition first = drawingPath.getLast();
last = first;
// construct as many move form last to new position as needed.
while (!last.getPosition().equals(newPosition)) {
path = LabyModel.getDirection(last.getPosition(), newPosition);
last.setDirection(path);
// button 1 : add direction; button 2 : rep lace with direction.
if (add) {
map.addDirection(last.getPosition().getX(), last.getPosition().getY(), path);
} else {
map.setDirection(last.getPosition().getX(), last.getPosition().getY(), path);
}
last = last.moveToAdjacentDirection();
drawingPath.addLast(last);
}
if (statusEnable) {
addStatus("Mouse dragged from Cell " + first.getPosition() + "To" + newPosition + " Button " + add);
}
}
}
@Override
public void mouseMoved(MouseEvent e) {
// addStatus("Mouse moved (" + e.getX() + ',' + e.getY() + ')');
Position newPosition = getPosition(e.getX(), e.getY());
if ((newPosition.getX() >= 0) && (newPosition.getY() >= 0)) {
requestFocus();
}
}
public void setShowAll(boolean showall) {
this.showAll = showall;
addStatus(showAll ? "show all" : "X");
}
void checkExit() {
if ((sX == gX) && (sY == gY)) {
addStatus("Exit found by human !");
}
}
private void proceed()
{
// should redraw ...
invalidate();
repaint();
checkExit();
}
void goNorth() {
resetResolution();
if (map.canMoveInDirection(sX, sY,Brick.UP)) {
sY = sY - 1;
proceed();
}
}
void goSouth() {
resetResolution();
if (map.canMoveInDirection(sX, sY,Brick.DOWN)) {
sY = sY + 1;
proceed();
}
}
void goEast() {
resetResolution();
if (map.canMoveInDirection(sX, sY, Brick.RIGHT)) {
sX = sX + 1;
proceed();
}
}
void goWest() {
resetResolution();
if (map.canMoveInDirection(sX, sY, Brick.LEFT)) {
sX = sX - 1;
proceed();
}
}
/**
* width, height of one cell,
* offsetX, offsetY of upper left corner
**/
// public MazeComponent(WallsProvider map, MazeCellParameters cp)
public MazeComponent(LabyModel map, MazeCellParameters cp) {
super();
this.cp = cp;
this.map = map;
setPreferredSize(cp.getDimension());
gX = map.getWidth() - 1;
gY = map.getHeight() - 1;
}
// public void resetWallsProvider(WallsProvider map)
public void resetWallsProvider(LabyModel map) {
this.map = map;
solvedPath = null;
// could be kept
drawingPath = null;
sX = 0;
sY = 0;
cp.resetMazeWidthHeight(map.getWidth(), map.getHeight());
setPreferredSize(cp.getDimension());
}
public void setWallSize(int size) {
cp.setCellSize((double) size, (double) size);
// should redraw ...
invalidate();
repaint();
}
public int getAutoSize() {
Rectangle r = getBounds();
cp.adaptTo((int) r.getWidth(), (int) r.getHeight());
// should redraw ...
invalidate();
repaint();
return 50;
}
public void changed(Position cl, Position cr, WallsProvider map) {
// should redraw ...
invalidate();
repaint();
Object waiter = new Object();
synchronized (waiter) {
try {
waiter.wait(10);
} catch (InterruptedException e) {
System.err.println("Interrupted !");
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = 0;
int y = 0;
short walls = 0;
short path = 0;
// try to display only visible part...
// should compute pX, pY, mX, mY based on clip...
// Shape s=g.getClip();
Rectangle r = g.getClipBounds();
int mX = (int) ((double) r.getWidth() / cp.getWidth());
int mY = (int) ((double) r.getHeight() / cp.getHeight());
int pX = (int) ((double) (r.getX() - cp.getOffsetX()) / cp.getWidth());
int pY = (int) ((double) (r.getY() - cp.getOffsetY()) / cp.getHeight());
if (pX < 0)
pX = 0;
if (pY < 0)
pY = 0;
if (pX >= map.getWidth())
return;
if (pY >= map.getHeight())
return;
mX = mX + pX;
mY = mY + pY;
if (mX > map.getWidth()) {
mX = map.getWidth();
}
if (mY > map.getHeight()) {
mY = map.getHeight();
}
if ((sX == gX) && (sY == gY)) {
g.setColor(Color.red);
} else {
g.setColor(Color.green);
cp.drawDot(g, new Position(gX, gY), pX, pY, mX, mY);
g.setColor(Color.blue);
}
cp.drawDot(g, new Position(sX, sY), pX, pY, mX, mY);
synchronized (lockChange) {
g.setColor(Color.red);
if (current != null) {
cp.drawDot(g, current, pX, pY, mX, mY);
}
if (solvedPath != null) {
for (DirectionPosition resolved : solvedPath) {
// cp.drawDot(g, resolved.getPosition(), pX, pY, mX, mY);
cp.drawPath(g, resolved, pX, pY, mX, mY);
}
}
}
int aX = pX;
int aY = pY;
g.setColor(Color.black);
// draw all walls within clip bounds horiz first then lines
for (; pY < mY; pY++) {
for (pX = 0; pX < mX; pX++) {
walls = map.getWalls(pX, pY);
cp.drawWalls(g, pX, pY, walls);
}
}
if (this.showAll) {
addStatus("*");
pX = aX;
pY = aY;
// draw all path within clip bounds horiz first then lines
for (; pY < mY; pY++) {
for (pX = 0; pX < mX; pX++) {
path = map.getPath(pX, pY);
if ((path & LabyModel.SOLVED) == LabyModel.SOLVED) {
g.setColor(Color.green);
} else {
g.setColor(Color.blue);
}
if (path != 0) {
DirectionPosition dp = new DirectionPosition(path, new Position(pX, pY));
cp.drawPath(g, dp, pX, pY, pX + 1, pY + 1);
}
}
}
}
}
public boolean notifySearch(DirectionPosition pPosition) {
synchronized (lockChange) {
current = pPosition.getPosition();
}
// should redraw ...
invalidate();
repaint();
return true;
}
public void notifySearchError(String error) {
System.err.println(error);
}
public void notifyCompletion(LinkedList<DirectionPosition> solvedPath) {
LinkedList<DirectionPosition> newPath = new LinkedList<>(solvedPath);
addStatus("resolution completed");
synchronized (lockChange) {
this.solvedPath = newPath;
}
// should redraw ...
invalidate();
repaint();
}
public void resetResolution() {
solvedPath = null;
}
}
private static void setupDisplay(LabyModel model, int W, int H, MazeParams params) {
Display display = new Display(model, W, H, params);
}

View File

@@ -0,0 +1,142 @@
package org.artisanlogiciel.games.maze.gui;
import org.artisanlogiciel.games.maze.Brick;
import org.artisanlogiciel.games.maze.LabyModel;
import org.artisanlogiciel.games.maze.Position;
import org.artisanlogiciel.games.maze.solve.DirectionPosition;
import java.awt.*;
public class MazeCellParameters {
double width = 10; // width of one cell
double height = 10; // height of one cell
int offsetX = 5; // x offset of upper corner left
int offsetY = 5; // y offset of upper corner left
int mapWidth = 0;
int mapHeight = 0;
public MazeCellParameters(int mapw, int maph, int W, int H, int x, int y) {
double w = (W - x) / mapw;
double h = (H - y) / maph;
mapWidth = mapw;
mapHeight = maph;
if (w < 5)
w = 5;
if (h < 5)
h = 5;
setCellSize(w, h);
offsetX = x;
offsetY = y;
}
public void resetMazeWidthHeight(int mapw, int maph) {
mapWidth = mapw;
mapHeight = maph;
}
public void adaptTo(double W, double H) {
double w = (W - offsetX) / mapWidth;
double h = (H - offsetY) / mapHeight;
mapWidth = mapWidth;
mapHeight = mapHeight;
if (w < 5)
w = 5;
if (h < 5)
h = 5;
setCellSize(w, h);
}
public void setCellSize(double w, double h) {
width = w;
height = h;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
public int getOffsetX() {
return offsetX;
}
public int getOffsetY() {
return offsetY;
}
public Dimension getDimension() {
return new Dimension(offsetX + (int) (mapWidth * width),
offsetY + (int) (mapHeight * height));
}
public void drawWalls(Graphics g, int pX, int pY, short walls) {
int x = offsetX + (int) (pX * width);
int y = offsetY + (int) (pY * height);
if ((pY == 0) && ((walls & Brick.UP) == Brick.UP))
g.drawLine(x, y, x + (int) width, y);
if ((walls & Brick.DOWN) == Brick.DOWN)
g.drawLine(x, y + (int) height, x + (int) width, y + (int) height);
if ((walls & Brick.RIGHT) == Brick.RIGHT)
g.drawLine(x + (int) width, y, x + (int) width, y + (int) height);
if ((pX == 0) && ((walls & Brick.LEFT) == Brick.LEFT))
g.drawLine(x, y, x, y + (int) height);
}
public void drawPath(Graphics g, DirectionPosition dp, int pX, int pY, int mX, int mY) {
if (dp != null) {
Position dot = dp.getPosition();
if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
int x = offsetX + (int) (dot.getX() * width);
int y = offsetY + (int) (dot.getY() * height);
short path = dp.getDirection();
int xm = x + (int) (width / 2);
int ym = y + (int) (height / 2);
if ((path & LabyModel.HORIZONTAL) == LabyModel.HORIZONTAL) {
if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
g.drawLine(xm, ym, x + (int) width, ym);
g.drawLine(xm, ym + (int) (height / 4), x + (int) width, ym);
}
// LEFT /_
if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
g.drawLine(x, ym, xm, ym);
g.drawLine(x, ym, xm, ym - (int) (height / 4));
}
}
if ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL) {
if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
g.drawLine(xm, ym, xm, y + (int) height);
g.drawLine(xm - (int) (width / 4), ym, xm, y + (int) height);
}
// UP |\
if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
g.drawLine(xm, ym, xm, y);
g.drawLine(xm + (int) (width / 4), ym, xm, y);
}
}
}
}
}
public void drawDot(Graphics g, Position dot, int pX, int pY, int mX, int mY) {
double radius = (height > width) ? width : height;
int a = (int) (radius / 4);
if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
int x = offsetX + (int) (dot.getX() * width);
int y = offsetY + (int) (dot.getY() * height);
int r2 = (int) ((radius * 3) / 4);
g.drawOval(x + 1, y + 1, r2, r2);
// g.drawLine(x+a,y+a,x+width-a,y+height-a);
// g.drawLine(x+a,y+height-a,x+width-a,y+a);
} else {
int x = offsetX + (int) (pX * width);
int y = offsetY + (int) (pY * height);
g.drawLine(x + 1, y + 1, x + (int) width - 1, y + (int) height - 1);
}
}
}

View File

@@ -0,0 +1,367 @@
package org.artisanlogiciel.games.maze.gui;
import org.artisanlogiciel.games.maze.*;
import org.artisanlogiciel.games.maze.solve.DirectionPosition;
import org.artisanlogiciel.games.maze.solve.MazeResolutionListener;
import org.artisanlogiciel.graphics.Drawing;
import org.artisanlogiciel.graphics.DrawingLine;
import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
public class MazeComponent
extends JComponent
implements MazeCreationListener,
MazeResolutionListener,
MouseMotionListener {
private static final long serialVersionUID = 3163272907991176390L;
// WallsProvider map;
LabyModel map;
final MazeCellParameters cp;
Position current = null;
LinkedList<DirectionPosition> solvedPath = null;
LinkedList<DirectionPosition> drawingPath = null;
final Object lockChange = new Object();
// current postion of human resolving
int sX = 0;
int sY = 0;
// goal exit
int gX = -1;
int gY = -1;
Date lastDrag = null;
// FIXME HARCDODED delay after which a draging to draw a continous line is ended, a new line will then start.
long dragTimeout = 200;
// not set by default for debug, will show any path
boolean showAll = false;
StatusListener statusListener;
// for a given (x,y) pixel return cell position.
// if rightmost position of view not (0,0) this is not working.
Position getPosition(int x, int y) {
int pX = (int) ((double) (x - cp.getOffsetX()) / cp.getWidth());
int pY = (int) ((double) (y - cp.getOffsetY()) / cp.getHeight());
return new Position(pX, pY);
}
@Override
public void mouseDragged(MouseEvent e) {
boolean add = ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0);
Position newPosition = getPosition(e.getX(), e.getY());
Date now = new Date(System.currentTimeMillis());
if (lastDrag == null) {
resetDrawingPath();
} else {
if (now.getTime() - lastDrag.getTime() > dragTimeout) {
resetDrawingPath();
statusListener.addStatus("move timeout");
}
}
lastDrag = now;
addPosition(newPosition, add);
changed(null, null, map);
}
public void resetDrawingPath() {
drawingPath = null;
}
public void addDrawing(Drawing drawing, boolean add) {
for (DrawingLine line : drawing.getInternLines()) {
addDrawingLine(line, add);
}
changed(null, null, map);
}
public void addDrawingLine(DrawingLine line, boolean add) {
resetDrawingPath();
ArrayList<Point> points = line.getPoints();
for (Point p : points) {
addPosition(new Position(p.x, p.y), add);
}
}
public void addPosition(Position newPosition, boolean add) {
// should find the cell ...
DirectionPosition last = null;
short path = 0;
if (drawingPath == null) {
drawingPath = new LinkedList<>();
last = new DirectionPosition((short) 0, newPosition);
statusListener.addStatus("Mouse dragged Cell " + newPosition + " Button " + add);
drawingPath.addLast(last);
} else {
// setShowAll(true);
DirectionPosition first = drawingPath.getLast();
last = first;
// construct as many move form last to new position as needed.
while (!last.getPosition().equals(newPosition)) {
path = LabyModel.getDirection(last.getPosition(), newPosition);
last.setDirection(path);
// button 1 : add direction; button 2 : rep lace with direction.
if (add) {
map.addDirection(last.getPosition().getX(), last.getPosition().getY(), path);
} else {
map.setDirection(last.getPosition().getX(), last.getPosition().getY(), path);
}
last = last.moveToAdjacentDirection();
drawingPath.addLast(last);
}
statusListener.addStatus("Mouse dragged from Cell " + first.getPosition() + "To" + newPosition + " Button " + add);
}
}
@Override
public void mouseMoved(MouseEvent e) {
// addStatus("Mouse moved (" + e.getX() + ',' + e.getY() + ')');
Position newPosition = getPosition(e.getX(), e.getY());
if ((newPosition.getX() >= 0) && (newPosition.getY() >= 0)) {
requestFocus();
}
}
public void setShowAll(boolean showall) {
this.showAll = showall;
statusListener.addStatus(showAll ? "show all" : "X");
}
void checkExit() {
if ((sX == gX) && (sY == gY)) {
statusListener.addStatus("Exit found by human !");
}
}
private void proceed() {
// should redraw ...
invalidate();
repaint();
checkExit();
}
void goNorth() {
resetResolution();
if (map.canMoveInDirection(sX, sY, Brick.UP)) {
sY = sY - 1;
proceed();
}
}
void goSouth() {
resetResolution();
if (map.canMoveInDirection(sX, sY, Brick.DOWN)) {
sY = sY + 1;
proceed();
}
}
void goEast() {
resetResolution();
if (map.canMoveInDirection(sX, sY, Brick.RIGHT)) {
sX = sX + 1;
proceed();
}
}
void goWest() {
resetResolution();
if (map.canMoveInDirection(sX, sY, Brick.LEFT)) {
sX = sX - 1;
proceed();
}
}
/**
* width, height of one cell,
* offsetX, offsetY of upper left corner
**/
// public MazeComponent(WallsProvider map, MazeCellParameters cp)
public MazeComponent(LabyModel map, MazeCellParameters cp, StatusListener statusListener) {
super();
this.cp = cp;
this.map = map;
setPreferredSize(cp.getDimension());
gX = map.getWidth() - 1;
gY = map.getHeight() - 1;
this.statusListener = statusListener;
}
// public void resetWallsProvider(WallsProvider map)
public void resetWallsProvider(LabyModel map) {
this.map = map;
solvedPath = null;
// could be kept
drawingPath = null;
sX = 0;
sY = 0;
cp.resetMazeWidthHeight(map.getWidth(), map.getHeight());
setPreferredSize(cp.getDimension());
}
public void setWallSize(int size) {
cp.setCellSize((double) size, (double) size);
// should redraw ...
invalidate();
repaint();
}
public int getAutoSize() {
Rectangle r = getBounds();
cp.adaptTo((int) r.getWidth(), (int) r.getHeight());
// should redraw ...
invalidate();
repaint();
return 50;
}
public void changed(Position cl, Position cr, WallsProvider map) {
// should redraw ...
invalidate();
repaint();
/* what was this ?
Object waiter = new Object();
synchronized (waiter) {
try {
waiter.wait(10);
} catch (InterruptedException e) {
System.err.println("Interrupted !");
}
}
*/
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = 0;
int y = 0;
short walls = 0;
short path = 0;
// try to display only visible part...
// should compute pX, pY, mX, mY based on clip...
// Shape s=g.getClip();
Rectangle r = g.getClipBounds();
int mX = (int) ((double) r.getWidth() / cp.getWidth());
int mY = (int) ((double) r.getHeight() / cp.getHeight());
int pX = (int) ((double) (r.getX() - cp.getOffsetX()) / cp.getWidth());
int pY = (int) ((double) (r.getY() - cp.getOffsetY()) / cp.getHeight());
if (pX < 0)
pX = 0;
if (pY < 0)
pY = 0;
if (pX >= map.getWidth())
return;
if (pY >= map.getHeight())
return;
mX = mX + pX;
mY = mY + pY;
if (mX > map.getWidth()) {
mX = map.getWidth();
}
if (mY > map.getHeight()) {
mY = map.getHeight();
}
if ((sX == gX) && (sY == gY)) {
g.setColor(Color.red);
} else {
g.setColor(Color.green);
cp.drawDot(g, new Position(gX, gY), pX, pY, mX, mY);
g.setColor(Color.blue);
}
cp.drawDot(g, new Position(sX, sY), pX, pY, mX, mY);
synchronized (lockChange) {
g.setColor(Color.red);
if (current != null) {
cp.drawDot(g, current, pX, pY, mX, mY);
}
if (solvedPath != null) {
for (DirectionPosition resolved : solvedPath) {
// cp.drawDot(g, resolved.getPosition(), pX, pY, mX, mY);
cp.drawPath(g, resolved, pX, pY, mX, mY);
}
}
}
int aX = pX;
int aY = pY;
g.setColor(Color.black);
// draw all walls within clip bounds horiz first then lines
for (; pY < mY; pY++) {
for (pX = 0; pX < mX; pX++) {
walls = map.getWalls(pX, pY);
cp.drawWalls(g, pX, pY, walls);
}
}
if (this.showAll) {
statusListener.addStatus("*");
pX = aX;
pY = aY;
// draw all path within clip bounds horiz first then lines
for (; pY < mY; pY++) {
for (pX = 0; pX < mX; pX++) {
path = map.getPath(pX, pY);
if ((path & LabyModel.SOLVED) == LabyModel.SOLVED) {
g.setColor(Color.green);
} else {
g.setColor(Color.blue);
}
if (path != 0) {
DirectionPosition dp = new DirectionPosition(path, new Position(pX, pY));
cp.drawPath(g, dp, pX, pY, pX + 1, pY + 1);
}
}
}
}
}
public boolean notifySearch(DirectionPosition pPosition) {
synchronized (lockChange) {
current = pPosition.getPosition();
}
// should redraw ...
invalidate();
repaint();
return true;
}
public void notifySearchError(String error) {
System.err.println(error);
}
public void notifyCompletion(LinkedList<DirectionPosition> solvedPath) {
LinkedList<DirectionPosition> newPath = new LinkedList<>(solvedPath);
statusListener.addStatus("resolution completed");
synchronized (lockChange) {
this.solvedPath = newPath;
}
// should redraw ...
invalidate();
repaint();
}
public void resetResolution() {
solvedPath = null;
}
}

View File

@@ -0,0 +1,7 @@
package org.artisanlogiciel.games.maze.gui;
public interface StatusListener {
void addStatus(String pStatus);
}