package at.ac.tuwien.dbai.alternation.gui.example; import java.awt.Color; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Point; import java.util.Iterator; import java.util.Vector; import at.ac.tuwien.dbai.alternation.examples.CatAndMouse2; import at.ac.tuwien.dbai.alternation.examples.Graph; import at.ac.tuwien.dbai.alternation.examples.CatAndMouse2.Worktape; import at.ac.tuwien.dbai.alternation.examples.Graph.Node; import at.ac.tuwien.dbai.alternation.gui.DefaultFormat; public class CatAndMouseTest { /** * This class fills the worktape-canvas for CatAndMouse. It shows the * position of the mouse and the cat and illustrates the possible ways each * one can take. * * To initialise the class a <code>Graph<Integer></code>-Object is needed * to read out nodes and edges. * * @author Stefan Weiser * */ private static class CatAndMouse2FormatMath extends DefaultFormat<CatAndMouse2.Inputtape, CatAndMouse2.Worktape> { Graph<Integer> graph; CatAndMouse2FormatMath(Graph<Integer> graph) { this.graph = graph; } @Override public String getLongInformation(Worktape worktape, String state) { return worktape.toString(); } @Override public String getShortInformation(Worktape worktape, String state) { java.util.StringTokenizer tokens = new java.util.StringTokenizer( worktape.toString(), "; "); String returnString = tokens.nextToken() + "\n" + tokens.nextToken(); return returnString; } @Override public void paintWorktape(Worktape worktape, String state, Graphics g, Dimension size) { super.paintWorktape(worktape, state, g, size); Color mouseColor = Color.YELLOW; Color catColor = Color.RED; Color catEatMouseColor = Color.ORANGE; Color goal = Color.GREEN; g.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 16)); g.setColor(mouseColor); g.drawString("Mouse", 0, 18); g.setColor(catColor); g.drawString("Cat", 0, 36); g.setColor(goal); g.drawString("Goal", 0, 54); g.setFont(new java.awt.Font("Arial", java.awt.Font.PLAIN, 20)); g.setColor(Color.BLACK); // Defining the coordinates of each point Vector<Coordinate> points = new Vector<Coordinate>(); if (size.width > 510) { points.add(new Coordinate(((size.width - 60) / 6) * 0 + 30, size.height / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 1 + 30, (size.height / 2) / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 1 + 30, (size.height / 2) / 2 + size.height / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 2 + 30, size.height / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 3 + 30, (size.height / 2) / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 3 + 30, (size.height / 2) / 2 + size.height / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 4 + 30, size.height / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 5 + 30, (size.height / 2) / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 5 + 30, (size.height / 2) / 2 + size.height / 2, 30, 30)); points.add(new Coordinate(((size.width - 60) / 6) * 6 + 30, size.height / 2, 30, 30)); } else { points.add(new Coordinate(30, size.height / 2, 30, 30)); points.add(new Coordinate(110, (size.height / 2) / 2, 30, 30)); points.add(new Coordinate(110, (size.height / 2) / 2 + size.height / 2, 30, 30)); points.add(new Coordinate(190, size.height / 2, 30, 30)); points.add(new Coordinate(270, (size.height / 2) / 2, 30, 30)); points.add(new Coordinate(270, (size.height / 2) / 2 + size.height / 2, 30, 30)); points.add(new Coordinate(350, size.height / 2, 30, 30)); points.add(new Coordinate(430, (size.height / 2) / 2, 30, 30)); points.add(new Coordinate(430, (size.height / 2) / 2 + size.height / 2, 30, 30)); points.add(new Coordinate(510, size.height / 2, 30, 30)); } // Draw Arrows Iterator<Integer> iterator = graph.iterator(); while (iterator.hasNext()) { Node<Integer> node = graph.get(iterator.next()); Iterator<Node<Integer>> childIterator = node.getChildren(). iterator(); while (childIterator.hasNext()) { Node<Integer> child = childIterator.next(); drawArrow(g, 15, points.get(node.getObject() - 1), points .get(child.getObject() - 1)); } } // Draw Points FontMetrics fm = g.getFontMetrics(); for (int i = 0; i < points.capacity(); i++) { Color thisColor; if (worktape.catPosition.getObject() == worktape.mousePosition .getObject() && worktape.mousePosition.getObject() == i + 1) thisColor = catEatMouseColor; else if (worktape.catPosition.getObject() == i + 1) thisColor = catColor; else if (worktape.mousePosition.getObject() == i + 1) thisColor = mouseColor; else if (i + 1 == points.capacity()) thisColor = goal; else thisColor = Color.LIGHT_GRAY; if (thisColor != null) { g.setColor(thisColor); g.fillRect(points.get(i).x - points.get(i).width / 2, points.get(i).y - points.get(i).height / 2, points .get(i).width, points.get(i).height); g.setColor(Color.BLACK); } g.drawRect(points.get(i).x - points.get(i).width / 2, points .get(i).y - points.get(i).height / 2, points.get(i).width, points .get(i).height); int slen = fm.stringWidth("" + (i + 1)); g.drawString("" + (i + 1), points.get(i).x - points.get(i).width / 2 + points.get(i).width / 2 - slen / 2, points.get(i).y - points.get(i).height / 2 + 22); } } /** * Draws an arrow from point p1 to point p2. * * @param g * the <code>Graphics</code>-Object where to draw the arrow. * @param alpha * the angle of the arrowhead * @param p1 * the first point * @param p2 * the second point */ private void drawArrow(Graphics g, int alpha, CatAndMouseTest.CatAndMouse2FormatMath.Coordinate p1, CatAndMouseTest.CatAndMouse2FormatMath.Coordinate p2) { Point intPoint = getIntersection(p1, p2); if (intPoint == null) { System.err.println("Intersection = null"); intPoint = new Point(p2.x, p2.y); } g.drawLine(p1.x, p1.y, intPoint.x, intPoint.y); if (alpha > 90) alpha = 90; else if (alpha < 0) alpha = 0; boolean kleinerWinkel = false; double h = Math.sqrt(Math.pow(intPoint.x - p1.x, 2) + Math.pow(intPoint.y - p1.y, 2)); double beta1 = Math.toDegrees(Math.asin(Math.sqrt(Math.pow( intPoint.x - p1.x, 2)) / h)); double gamma = beta1 - alpha; double deltaX = Math.sin(Math.toRadians(gamma)) * 20; double deltaY = Math.sqrt(Math.pow(20, 2) - Math.pow(deltaX, 2)); double beta2 = Math.toDegrees(Math.acos(Math.sqrt(Math.pow( intPoint.x - p1.x, 2)) / h)); int x1 = intPoint.x; int x2 = 0; int x3 = 0; int y1 = intPoint.y; int y2 = 0; int y3 = 0; // to right top if (p1.x < p2.x && p1.y > p2.y) { x2 = (int) (intPoint.x - deltaX); y2 = (int) (intPoint.y + deltaY); gamma = beta2 - alpha; if (gamma < 0) { gamma = alpha - beta2; kleinerWinkel = true; } deltaX = Math.cos(Math.toRadians(gamma)) * 20; deltaY = Math.sqrt(Math.pow(20, 2) - Math.pow(deltaX, 2)); x3 = (int) (intPoint.x - deltaX); if (kleinerWinkel) y3 = (int) (intPoint.y - deltaY); else y3 = (int) (intPoint.y + deltaY); } // to right bottom else if (p1.x < p2.x && p1.y < p2.y) { x2 = (int) (intPoint.x - deltaX); y2 = (int) (intPoint.y - deltaY); gamma = beta2 - alpha; if (gamma < 0) { gamma = alpha - beta2; kleinerWinkel = true; } deltaX = Math.cos(Math.toRadians(gamma)) * 20; deltaY = Math.sqrt(Math.pow(20, 2) - Math.pow(deltaX, 2)); x3 = (int) (intPoint.x - deltaX); if (kleinerWinkel) y3 = (int) (intPoint.y + deltaY); else y3 = (int) (intPoint.y - deltaY); } // to left bottom else if (p1.x > p2.x && p1.y < p2.y) { x2 = (int) (intPoint.x + deltaX); y2 = (int) (intPoint.y - deltaY); gamma = alpha - beta2; if (gamma < 0) { gamma = beta2 - alpha; kleinerWinkel = true; } deltaX = Math.cos(Math.toRadians(gamma)) * 20; deltaY = Math.sqrt(Math.pow(20, 2) - Math.pow(deltaX, 2)); x3 = (int) (intPoint.x + deltaX); if (kleinerWinkel) y3 = (int) (intPoint.y - deltaY); else y3 = (int) (intPoint.y + deltaY); } // to left top else if (p1.x > p2.x && p1.y > p2.y) { x2 = (int) (intPoint.x + deltaX); y2 = (int) (intPoint.y + deltaY); gamma = alpha - beta2; if (gamma < 0) { gamma = beta2 - alpha; kleinerWinkel = true; } deltaX = Math.cos(Math.toRadians(gamma)) * 20; deltaY = Math.sqrt(Math.pow(20, 2) - Math.pow(deltaX, 2)); x3 = (int) (intPoint.x + deltaX); if (kleinerWinkel) y3 = (int) (intPoint.y + deltaY); else y3 = (int) (intPoint.y - deltaY); } // horicontal else if (p1.y == p2.y) { deltaX = Math.cos(Math.toRadians(alpha)) * 20; deltaY = Math.sqrt(Math.pow(20, 2) - Math.pow(deltaX, 2)); if (p1.x < intPoint.x) { x2 = (int) (intPoint.x - deltaX); y2 = (int) (intPoint.y - deltaY); x3 = (int) (intPoint.x - deltaX); y3 = (int) (intPoint.y + deltaY); } else { x2 = (int) (intPoint.x + deltaX); y2 = (int) (intPoint.y - deltaY); x3 = (int) (intPoint.x + deltaX); y3 = (int) (intPoint.y + deltaY); } } // vertical else if (p1.x == p2.x) { deltaX = Math.sin(Math.toRadians(alpha)) * 20; deltaY = Math.sqrt(Math.pow(20, 2) - Math.pow(deltaX, 2)); if (p1.y < intPoint.y) { x2 = (int) (intPoint.x - deltaX); y2 = (int) (intPoint.y - deltaY); x3 = (int) (intPoint.x + deltaX); y3 = (int) (intPoint.y - deltaY); } else { x2 = (int) (intPoint.x - deltaX); y2 = (int) (intPoint.y + deltaY); x3 = (int) (intPoint.x + deltaX); y3 = (int) (intPoint.y + deltaY); } } int[] xCoordinates = { x1, x2, x3 }; int[] yCoordinates = { y1, y2, y3 }; g.fillPolygon(xCoordinates, yCoordinates, 3); } /** * Calculates the intersection point between the connecting line and the * edge of the endpoint (p2). * * @param p1 * the first point * @param p2 * the second point * @return the intersection point */ private Point getIntersection( CatAndMouseTest.CatAndMouse2FormatMath.Coordinate p1, CatAndMouseTest.CatAndMouse2FormatMath.Coordinate p2) { int deltaX; int deltaY; int signumX = 1; int signumY = 1; int xk = p1.x; int yk = p1.y; int twoDeltaY; int diffDelta; int p; if (p1.x == p2.x) { if (p1.y < p2.y) return new Point(p1.x, p2.y - p2.height / 2); else return new Point(p1.x, p2.y + p2.height / 2); } if (p1.y == p2.y) { if (p1.x < p2.x) return new Point(p2.x - p2.width / 2, p1.y); else return new Point(p2.x + p2.width / 2, p1.y); } // Berechnung deltaX bzw. deltaY // Bestimmung, ob Inkrementierung oder Dekrementierung if (p2.x >= p1.x) deltaX = p2.x - p1.x; else { deltaX = p1.x - p2.x; signumX = -1; } if (p2.y >= p1.y) deltaY = p2.y - p1.y; else { deltaY = p1.y - p2.y; signumY = -1; } twoDeltaY = 2 * deltaY; diffDelta = 2 * deltaY - 2 * deltaX; p = 2 * deltaY - deltaX; if (deltaX > deltaY) { // Winkel <45 for (int i = 1; i < deltaX; i++) { if (p < 0) { xk += signumX; if (p2.x - p2.width / 2 == xk || p2.x + p2.width / 2 == xk) return new Point(xk, yk); p = p + twoDeltaY; } else { xk += signumX; yk += signumY; if (p2.x - p2.width / 2 == xk || p2.x + p2.width / 2 == xk) return new Point(xk, yk); p = p + diffDelta; } } } else { // Winkel >=45 for (int i = 1; i < deltaY; i++) { if (p < 0) { yk += signumY; if (p2.y - p2.height / 2 == yk || p2.y - p2.height / 2 == yk) return new Point(xk, yk); p = p + twoDeltaY; } else { xk += signumX; yk += signumY; if (p2.y - p2.height / 2 == yk || p2.y - p2.height / 2 == yk) return new Point(xk, yk); p = p + diffDelta; } } } return null; } @Override public void resetWorktape(Graphics g, int width, int height) { super.resetWorktape(g, width, height); } /** * This class represents the coordinates of the point of CatAndMouse. It * contains the Coordinates of the point (x,y) and width and height of * each point. * * @author Stefan Weiser * */ private static class Coordinate { private final int x; private final int y; private final int width; private final int height; /** * Defines the Coordinates and the Dimension of CatAndMouse-points. */ private Coordinate(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } } } /** * @param args */ public static void main(String[] args) { Graph<Integer> graph = new Graph<Integer>(); int n = 10; for (int i = 1; i <= n; i++) { graph.addNode(i); } graph.addEdge(1, 2); graph.addEdge(1, 3); graph.addEdge(2, 1); graph.addEdge(2, 6); graph.addEdge(3, 4); graph.addEdge(4, 1); graph.addEdge(4, 5); graph.addEdge(5, 6); graph.addEdge(5, 7); graph.addEdge(5, 8); graph.addEdge(6, 8); graph.addEdge(7, 8); graph.addEdge(7, 9); graph.addEdge(8, 7); graph.addEdge(8, 10); graph.addEdge(9, 10); Graph.Node<Integer> mouseStart = graph.get(1); Graph.Node<Integer> catStart = graph.get(2); Graph.Node<Integer> goal = graph.get(10); CatAndMouse2 catAndMouseAtm= new CatAndMouse2(); catAndMouseAtm.compute(graph, catStart, mouseStart, goal); CatAndMouse2FormatMath format = new CatAndMouse2FormatMath(graph); format.setFormat(130, 55, 30, 30); new at.ac.tuwien.dbai.alternation.gui.MainFrame<CatAndMouse2.Inputtape, CatAndMouse2.Worktape>( catAndMouseAtm.getComputationTree(), format, 5); } }