package de.gaalop.vis2d; import de.gaalop.CodeGenerator; import de.gaalop.CodeGeneratorException; import de.gaalop.OutputFile; import de.gaalop.cfg.ColorNode; import de.gaalop.cfg.ControlFlowGraph; import de.gaalop.cfg.UnknownMacroCall; import de.gaalop.dfg.*; import de.gaalop.vis2d.drawing.*; import java.awt.Color; import java.awt.geom.Rectangle2D; import java.util.*; import javax.swing.JFrame; /** * * @author Christian Steinmetz */ public class Vis2dCodeGen implements CodeGenerator { private static final double EPSILON = 10E-4; public Drawing drawing = new Drawing(); public Rectangle2D.Double world = new Rectangle2D.Double(-5, -5, 10, 10); public MyPanel panel; public DrawVisitorGraphics visitor; public Vis2dUI vis2dUI; private HashMap<String, double[]> values; @Override public Set<OutputFile> generate(ControlFlowGraph in) throws CodeGeneratorException { values = ValueEvaluater.evaluateValues(in); HashMap<String, Color> colors = ColorEvaluater.getColors(in); drawing.objects.clear(); HashMap<String, Multivector> mapMv = MultivectorBuilder.buildMultivectors(in); drawUnknownMacros(in.unknownMacros); for (String s : in.getRenderingExpressions().keySet()) { interpret(mapMv.get(s), colors.get(s)); } vis2dUI = new Vis2dUI(); panel = (MyPanel) vis2dUI.jPanel1; Interaction interaction = new Interaction(this); interaction.initialize(); vis2dUI.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); vis2dUI.setVisible(true); repaintDrawing(); return new HashSet<OutputFile>(); } public void repaintDrawing() { visitor = new DrawVisitorBufferedImage(world, 500, 500); panel.set(drawing, visitor); drawing.draw(visitor); panel.repaint(); } private void interpret(Multivector mv, Color c) { boolean[] nonZero = getNonZeroComponents(mv.entries); if (hasBivecParts16(nonZero)) { //Point pair interpretPointPair(mv, c, nonZero); } else { //Vector double e0 = mv.entries[4]; if (Math.abs(e0) < EPSILON) { //Line double ox = 0; double oy = 0; double dx = 0; double dy = 0; if (Math.abs(mv.entries[2]) < EPSILON) { // parallel to y-axis ox = mv.entries[3] / mv.entries[1]; dy = 1; } else { dx = 1; dy = -mv.entries[1] / mv.entries[2]; oy = mv.entries[3] / mv.entries[2]; } drawing.objects.add(new Gerade2d(ox, oy, dx, dy, c)); } else { //Circle or point x+(0.5*x*x-0.5*r*r)*(einf)+e0 double x = mv.entries[1] / e0; double y = mv.entries[2] / e0; double r = Math.sqrt(Math.abs(2.0 * mv.entries[3] * mv.entries[4] - mv.entries[2] * mv.entries[2] - mv.entries[1] * mv.entries[1])) / Math.abs(mv.entries[4]); if (r < EPSILON) { drawing.objects.add(new Point2d(x, y, c)); } else { if (x*x+y*y-2*mv.entries[3] < 0) { //imaginary radius drawing.objects.add(new CircleDashed2d(x, y, r, c)); } else { //real radius drawing.objects.add(new Circle2d(x, y, r, c)); } } } } } private boolean[] getNonZeroComponents(double[] entries) { boolean[] result = new boolean[entries.length]; for (int i = 0; i < entries.length; i++) { result[i] = (Math.abs(entries[i]) > EPSILON); } return result; } private boolean hasBivecParts16(boolean[] nonZero) { for (int i = 5; i <= 10; i++) if (nonZero[i]) return true; return false; } private void interpretPointPair(Multivector mv, Color c, boolean[] nonZero) { double[] b = mv.entries; double x1 = (b[9] * Math.sqrt(Math.abs((2.0 * b[8] * b[9] + 2.0 * b[6] * b[7]) - b[5] * b[5] + b[10] * b[10])) - b[5] * b[9] + b[10] * b[7]) / (b[9] * b[9] + b[7] * b[7]); // e1 double y1 = (-((b[7] * Math.sqrt(Math.abs((2.0 * b[8] * b[9] + 2.0 * b[6] * b[7]) - b[5] * b[5] + b[10] * b[10])) - b[10] * b[9] - b[5] * b[7]) / (b[9] * b[9] + b[7] * b[7]))); // e2 double x2 = (-(((b[9] * Math.sqrt(Math.abs((2.0 * b[8] * b[9] + 2.0 * b[6] * b[7]) - b[5] * b[5] + b[10] * b[10])) + b[5] * b[9]) - b[10] * b[7]) / (b[9] * b[9] + b[7] * b[7]))); // e1 double y2 = (b[7] * Math.sqrt(Math.abs((2.0 * b[8] * b[9] + 2.0 * b[6] * b[7]) - b[5] * b[5] + b[10] * b[10])) + b[10] * b[9] + b[5] * b[7]) / (b[9] * b[9] + b[7] * b[7]); // e2 if (!(Double.isNaN(x1) || Double.isNaN(y1) || Double.isNaN(x2) || Double.isNaN(y2))) { //2 conformal points drawing.objects.add(new Pointpair2d(x1, y1, x2, y2, c)); } else { //One conformal point and einf if (nonZero[5]) drawing.objects.add(new Point2d(-(b[8] / b[5]), b[6] / b[5], c)); } } private void drawUnknownMacros(LinkedList<UnknownMacroCall> unknownMacros) { for (UnknownMacroCall unknownMacroCall: unknownMacros) { MacroCall macroCall = unknownMacroCall.macroCall; Color color = getColor(unknownMacroCall.colorNode); String name = macroCall.getName(); if (name.equals("DrawArrow")) { drawArrow(macroCall.getArguments(), color); } else if (name.equals("DrawLine")) { drawLine(macroCall.getArguments(), color); } else if (name.equals("DrawTriangle")) { drawTriangle(macroCall.getArguments(), color); } else System.out.println("Unknown macro: "+name); } } private void drawArrow(List<Expression> arguments, Color color) { throw new UnsupportedOperationException("DrawArrow is not implemented yet"); } private double[] getCoordFromMv(Expression mvE) { double[] result = new double[2]; double[] mv = values.get(((Variable) mvE).getName()); result[0] = mv[1] / mv[4]; //x result[1] = mv[2] / mv[4]; //y return result; } private void drawLine(List<Expression> arguments, Color color) { double x1; double y1; double x2; double y2; switch (arguments.size()) { case 2: //Two multivectors representing points double[] startMv = getCoordFromMv(arguments.get(0)); double[] endMv = getCoordFromMv(arguments.get(1)); x1 = startMv[0]; y1 = startMv[1]; x2 = endMv[0]; y2 = endMv[1]; break; case 4: //Four scalar values representing coordinates x1 = getValueOfExpression(arguments.get(0)); y1 = getValueOfExpression(arguments.get(1)); x2 = getValueOfExpression(arguments.get(2)); y2 = getValueOfExpression(arguments.get(3)); break; default: return; } drawing.objects.add(new Stretch2d(x1,y1,x2,y2,color)); } private void drawTriangle(List<Expression> arguments, Color color) { //All arguments are variables (See de.gaalop.algebra.Inliner) double x1; double y1; double x2; double y2; double x3; double y3; switch (arguments.size()) { case 3: //Two multivectors representing points double[] p1 = getCoordFromMv(arguments.get(0)); double[] p2 = getCoordFromMv(arguments.get(1)); double[] p3 = getCoordFromMv(arguments.get(2)); x1 = p1[0]; y1 = p1[1]; x2 = p2[0]; y2 = p2[1]; x3 = p3[0]; y3 = p3[1]; break; case 6: //Four scalar values representing coordinates x1 = getValueOfExpression(arguments.get(0)); y1 = getValueOfExpression(arguments.get(1)); x2 = getValueOfExpression(arguments.get(2)); y2 = getValueOfExpression(arguments.get(3)); x3 = getValueOfExpression(arguments.get(4)); y3 = getValueOfExpression(arguments.get(5)); break; default: return; } drawing.objects.add(new Stretch2d(x1,y1,x2,y2,color)); drawing.objects.add(new Stretch2d(x1,y1,x3,y3,color)); drawing.objects.add(new Stretch2d(x2,y2,x3,y3,color)); } private Color getColor(ColorNode colorNode) { if (colorNode == null) return Color.black; //default color else return new Color( (float) getValueOfExpression(colorNode.getR()), (float) getValueOfExpression(colorNode.getG()), (float) getValueOfExpression(colorNode.getB()), (float) getValueOfExpression(colorNode.getAlpha()) ); } private double getValueOfExpression(Expression e) { if (e instanceof FloatConstant) { return ((FloatConstant) e).getValue(); } else return values.get(((Variable) e).getName())[0]; } }