initial commit
This commit is contained in:
commit
c74d331b66
17 changed files with 1699 additions and 0 deletions
147
tut6/src/BoolTreeNode.java
Normal file
147
tut6/src/BoolTreeNode.java
Normal file
|
@ -0,0 +1,147 @@
|
|||
public class BoolTreeNode
|
||||
{
|
||||
private String variable;
|
||||
private BoolTreeNode child1;
|
||||
private BoolTreeNode child2;
|
||||
|
||||
private BoolTreeNode(String variableInput)
|
||||
{
|
||||
variable = variableInput;
|
||||
}
|
||||
|
||||
private BoolTreeNode(BoolTreeNode negated)
|
||||
{
|
||||
child1 = negated;
|
||||
}
|
||||
|
||||
private BoolTreeNode(BoolTreeNode kind1, BoolTreeNode kind2)
|
||||
{
|
||||
child1 = kind1;
|
||||
child2 = kind2;
|
||||
}
|
||||
|
||||
public static BoolTreeNode boolTreeTrueNode()
|
||||
{
|
||||
return new BoolTreeNode("true");
|
||||
}
|
||||
|
||||
public static BoolTreeNode boolTreeFalseNode()
|
||||
{
|
||||
return new BoolTreeNode("false");
|
||||
}
|
||||
|
||||
public static BoolTreeNode boolTreeVariableNode(String variableInput)
|
||||
{
|
||||
if (variableInput == null || variableInput.length() == 0 || variableInput.equals("true") || variableInput.equals("false"))
|
||||
{
|
||||
Utils.error("ungueltiger Name der Variablen");
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BoolTreeNode(variableInput);
|
||||
}
|
||||
|
||||
public static BoolTreeNode boolTreeNotNode(BoolTreeNode negated)
|
||||
{
|
||||
return new BoolTreeNode(negated);
|
||||
}
|
||||
|
||||
public static BoolTreeNode boolTreeAndNode(BoolTreeNode child1, BoolTreeNode child2)
|
||||
{
|
||||
return new BoolTreeNode(child1, child2);
|
||||
}
|
||||
|
||||
public int depth()
|
||||
{
|
||||
if (child2 != null) // konjunktionsknoten
|
||||
{
|
||||
int depth1 = child1.depth();
|
||||
int depth2 = child2.depth();
|
||||
return Utils.max(depth1, depth2) + 1;
|
||||
}
|
||||
|
||||
if (child1 != null) // negationsknoten
|
||||
{
|
||||
return child1.depth() + 1;
|
||||
}
|
||||
|
||||
// variablenknoten
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isLeaf()
|
||||
{
|
||||
return (depth() == 0);
|
||||
}
|
||||
|
||||
public boolean isTrueLeaf()
|
||||
{
|
||||
return isLeaf() && variable.equals("true");
|
||||
}
|
||||
|
||||
public boolean isFalseLeaf()
|
||||
{
|
||||
return isLeaf() && variable.equals("false");
|
||||
}
|
||||
|
||||
public boolean isNegation()
|
||||
{
|
||||
return (child1 != null && child2 == null);
|
||||
}
|
||||
|
||||
public boolean isConjunction()
|
||||
{
|
||||
return (child1 != null && child2 != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wertet den durch diesen Baum dargestellten Booleschen Ausdruck aus.
|
||||
*
|
||||
* @param trueVars Die Namen aller Variablen, die true sind.
|
||||
* @return Den Wert des Ausdruckes.
|
||||
*/
|
||||
public boolean evaluate(String ...trueVars)
|
||||
{
|
||||
if (isLeaf()) // variablenknoten
|
||||
return Utils.evaluateVariable(variable, trueVars);
|
||||
|
||||
if (isConjunction()) // konjunktionsknoten
|
||||
return child1.evaluate(trueVars) && child2.evaluate(trueVars);
|
||||
|
||||
// negationsknoten
|
||||
return !child1.evaluate(trueVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt doppelte Negationen aus dem Baum.
|
||||
*
|
||||
* @return true wenn eine doppelte Negation gefunden wurde und entfernt wurde.
|
||||
*/
|
||||
public boolean removeDoubleNegations()
|
||||
{
|
||||
if (isLeaf())
|
||||
return false;
|
||||
if (isConjunction())
|
||||
return child1.removeDoubleNegations() | child2.removeDoubleNegations();
|
||||
|
||||
// negationsknoten
|
||||
if (!child1.isNegation())
|
||||
return false;
|
||||
BoolTreeNode grandchild = child1.child1;
|
||||
variable = grandchild.variable;
|
||||
child1 = grandchild.child1;
|
||||
child2 = grandchild.child2;
|
||||
child1.removeDoubleNegations();
|
||||
child2.removeDoubleNegations();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String args[])
|
||||
{
|
||||
BoolTreeNode tree = boolTreeAndNode(
|
||||
boolTreeNotNode(boolTreeNotNode(boolTreeVariableNode("a"))),
|
||||
boolTreeNotNode(boolTreeNotNode(boolTreeVariableNode("b"))));
|
||||
System.out.println(tree.removeDoubleNegations());
|
||||
System.out.println("fertig");
|
||||
}
|
||||
}
|
734
tut6/src/Canvas.java
Normal file
734
tut6/src/Canvas.java
Normal file
|
@ -0,0 +1,734 @@
|
|||
/*
|
||||
* HINWEIS:
|
||||
*
|
||||
* Sie brauchen den Java-Code, der in dieser Datei steht, nicht zu lesen oder zu
|
||||
* verstehen. Alle Hinweise, die zur Verwendung der Datei noetig sind, koennen Sie
|
||||
* aus den jeweiligen Aufgabentexten entnehmen.
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.font.*;
|
||||
import java.awt.geom.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* User interface for a Logo-like language. Allows to see the painting process step-by-step.
|
||||
*/
|
||||
public class Canvas {
|
||||
|
||||
/**
|
||||
* The color brown.
|
||||
*/
|
||||
public static final Color BROWN = new Color(160, 82, 45);
|
||||
|
||||
/**
|
||||
* The color green.
|
||||
*/
|
||||
public static final Color GREEN = Color.GREEN;
|
||||
|
||||
/**
|
||||
* Adds the current position to the specified bounds.
|
||||
* @param g The graphics object to draw on.
|
||||
* @param boundsParam The bounds of the canvas.
|
||||
*/
|
||||
private static void addCurrentPos(Graphics2D g, Rectangle boundsParam) {
|
||||
if (boundsParam != null) {
|
||||
Canvas.addToBounds(new Point2D.Float(0f, 0f), boundsParam, g);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a point to the bounds, transformed as in the current graphics object.
|
||||
* @param point The point to add to the bounds.
|
||||
* @param boundsParam The bounds.
|
||||
* @param g The graphics object storing affine transformations.
|
||||
*/
|
||||
private static void addToBounds(Point2D point, Rectangle boundsParam, Graphics2D g) {
|
||||
boundsParam.add(g.getTransform().transform(point, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a rectangle to the bounds, transformed as in the current graphics object.
|
||||
* @param r The rectangle to add to the bounds.
|
||||
* @param boundsParam The bounds.
|
||||
* @param g The graphics object storing affine transformations.
|
||||
*/
|
||||
private static void addToBounds(Rectangle2D r, Rectangle boundsParam, Graphics2D g) {
|
||||
double maxX = r.getMaxX();
|
||||
double maxY = r.getMaxY();
|
||||
double minX = r.getMinX();
|
||||
double minY = r.getMinY();
|
||||
Canvas.addToBounds(new Point2D.Double(maxX, maxY), boundsParam, g);
|
||||
Canvas.addToBounds(new Point2D.Double(maxX, minY), boundsParam, g);
|
||||
Canvas.addToBounds(new Point2D.Double(minX, maxY), boundsParam, g);
|
||||
Canvas.addToBounds(new Point2D.Double(minX, minY), boundsParam, g);
|
||||
}
|
||||
|
||||
/**
|
||||
* The bounds of the canvas.
|
||||
*/
|
||||
protected Rectangle bounds;
|
||||
|
||||
/**
|
||||
* The actions to be executed on the canvas.
|
||||
*/
|
||||
private ArrayList<Canvas.GraphicAction> actions = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The actual drawing on the canvas.
|
||||
*/
|
||||
private final JComponent drawing = new JPanel() {
|
||||
|
||||
/**
|
||||
* For serialization.
|
||||
*/
|
||||
private static final long serialVersionUID = -1665573331455268961L;
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
synchronized (Canvas.this) {
|
||||
return Canvas.this.bounds == null ? new Dimension(100, 100) : Canvas.this.bounds.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
synchronized (Canvas.this) {
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
Rectangle clipBounds = g.getClipBounds();
|
||||
g2.setColor(Color.WHITE);
|
||||
g2.fill(clipBounds);
|
||||
g2.setColor(Color.BLACK);
|
||||
AffineTransform t = g2.getTransform();
|
||||
int drawCounter;
|
||||
// do we have current bounds?
|
||||
if (Canvas.this.bounds == null) {
|
||||
Rectangle newBounds = new Rectangle();
|
||||
Canvas.this.transformations.clear();
|
||||
drawCounter = 0;
|
||||
for (GraphicAction a : Canvas.this.actions) {
|
||||
a.replay(g2, false, newBounds);
|
||||
if (a.drawsSomething()) {
|
||||
drawCounter++;
|
||||
}
|
||||
}
|
||||
Canvas.this.bounds = new Rectangle(newBounds);
|
||||
}
|
||||
// move the drawing inside the screen
|
||||
GraphicAction init = new Move(20 - Canvas.this.bounds.x, 20 - Canvas.this.bounds.y);
|
||||
// draw all lines
|
||||
g2.setTransform(t);
|
||||
Canvas.this.transformations.clear();
|
||||
drawCounter = 0;
|
||||
init.replay(g2, true, null);
|
||||
for (GraphicAction a : Canvas.this.actions) {
|
||||
boolean draw = !(a instanceof DrawTextLabel);
|
||||
a.replay(g2, draw, null);
|
||||
if (a.drawsSomething()) {
|
||||
drawCounter++;
|
||||
}
|
||||
if (drawCounter >= Canvas.this.renderMaxDraws) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// draw all labels
|
||||
g2.setTransform(t);
|
||||
Canvas.this.transformations.clear();
|
||||
drawCounter = 0;
|
||||
init.replay(g2, true, null);
|
||||
for (GraphicAction a : Canvas.this.actions) {
|
||||
boolean draw = (a instanceof DrawTextLabel);
|
||||
a.replay(g2, draw, null);
|
||||
if (a.drawsSomething()) {
|
||||
drawCounter++;
|
||||
}
|
||||
if (drawCounter >= Canvas.this.renderMaxDraws) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The number of actions actually drawing something. Used to step forward and backward through the painting process.
|
||||
*/
|
||||
private int draws;
|
||||
|
||||
/**
|
||||
* Listener to execute the paint actions.
|
||||
*/
|
||||
private final ActionListener handler = new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch (e.getActionCommand()) {
|
||||
case "start":
|
||||
Canvas.this.renderMaxDraws = 0;
|
||||
break;
|
||||
case "next":
|
||||
Canvas.this.renderMaxDraws++;
|
||||
break;
|
||||
case "back":
|
||||
Canvas.this.renderMaxDraws--;
|
||||
break;
|
||||
case "end":
|
||||
Canvas.this.renderMaxDraws = Canvas.this.draws;
|
||||
break;
|
||||
}
|
||||
Canvas.this.step.setText("Schritt: " + Canvas.this.renderMaxDraws);
|
||||
Canvas.this.drawing.repaint();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Current step in the stepwise view of the painting process.
|
||||
*/
|
||||
private int renderMaxDraws = 0;
|
||||
|
||||
/**
|
||||
* Label for showing the current step.
|
||||
*/
|
||||
private final JLabel step = new JLabel("Schritt: " + this.renderMaxDraws);
|
||||
|
||||
/**
|
||||
* Used to (re-)store positions and orientations on the canvas.
|
||||
*/
|
||||
private final Stack<AffineTransform> transformations = new Stack<>();
|
||||
|
||||
/**
|
||||
* The frame to display the canvas.
|
||||
*/
|
||||
private final JFrame ui = new JFrame() {
|
||||
|
||||
/**
|
||||
* For serialization.
|
||||
*/
|
||||
private static final long serialVersionUID = 8620900696432559397L;
|
||||
|
||||
{
|
||||
// set up components
|
||||
final JScrollPane scrollPane = new JScrollPane(Canvas.this.drawing);
|
||||
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
final JPanel panel = new JPanel();
|
||||
final JButton startButton = new JButton("Anfang");
|
||||
startButton.setActionCommand("start");
|
||||
startButton.addActionListener(Canvas.this.handler);
|
||||
final JButton backButton = new JButton("Zurueck");
|
||||
backButton.setActionCommand("back");
|
||||
backButton.addActionListener(Canvas.this.handler);
|
||||
final JButton forwardButton = new JButton("Vor");
|
||||
forwardButton.setActionCommand("next");
|
||||
forwardButton.addActionListener(Canvas.this.handler);
|
||||
final JButton endButton = new JButton("Ende");
|
||||
endButton.setActionCommand("end");
|
||||
endButton.addActionListener(Canvas.this.handler);
|
||||
// configure frame
|
||||
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
// set up layout
|
||||
GroupLayout jPanel1Layout = new GroupLayout(panel);
|
||||
panel.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING
|
||||
).addGap(0, 158, Short.MAX_VALUE)
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING
|
||||
).addGap(0, 36, Short.MAX_VALUE)
|
||||
);
|
||||
GroupLayout layout = new GroupLayout(this.getContentPane());
|
||||
this.getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING
|
||||
).addGroup(
|
||||
GroupLayout.Alignment.TRAILING,
|
||||
layout.createSequentialGroup().addContainerGap().addGroup(
|
||||
layout.createParallelGroup(
|
||||
GroupLayout.Alignment.TRAILING
|
||||
).addComponent(
|
||||
scrollPane,
|
||||
GroupLayout.Alignment.LEADING,
|
||||
GroupLayout.DEFAULT_SIZE,
|
||||
458,
|
||||
Short.MAX_VALUE
|
||||
).addGroup(
|
||||
GroupLayout.Alignment.LEADING,
|
||||
layout.createSequentialGroup().addComponent(
|
||||
startButton
|
||||
).addGap(
|
||||
6,
|
||||
6,
|
||||
6
|
||||
).addComponent(
|
||||
backButton
|
||||
).addGap(
|
||||
6,
|
||||
6,
|
||||
6
|
||||
).addComponent(
|
||||
forwardButton
|
||||
).addGap(
|
||||
6,
|
||||
6,
|
||||
6
|
||||
).addComponent(
|
||||
endButton
|
||||
).addGap(
|
||||
18,
|
||||
18,
|
||||
18
|
||||
).addComponent(
|
||||
Canvas.this.step
|
||||
).addPreferredGap(
|
||||
LayoutStyle.ComponentPlacement.RELATED
|
||||
).addComponent(
|
||||
panel,
|
||||
GroupLayout.DEFAULT_SIZE,
|
||||
GroupLayout.DEFAULT_SIZE,
|
||||
Short.MAX_VALUE
|
||||
)
|
||||
)
|
||||
).addContainerGap()
|
||||
)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING
|
||||
).addGroup(
|
||||
GroupLayout.Alignment.TRAILING,
|
||||
layout.createSequentialGroup().addContainerGap().addComponent(
|
||||
scrollPane,
|
||||
GroupLayout.DEFAULT_SIZE,
|
||||
400,
|
||||
Short.MAX_VALUE
|
||||
).addPreferredGap(
|
||||
LayoutStyle.ComponentPlacement.RELATED
|
||||
).addGroup(
|
||||
layout.createParallelGroup(
|
||||
GroupLayout.Alignment.TRAILING
|
||||
).addComponent(
|
||||
panel,
|
||||
GroupLayout.PREFERRED_SIZE,
|
||||
GroupLayout.DEFAULT_SIZE,
|
||||
GroupLayout.PREFERRED_SIZE
|
||||
).addGroup(
|
||||
layout.createParallelGroup(
|
||||
GroupLayout.Alignment.BASELINE
|
||||
).addComponent(
|
||||
startButton
|
||||
).addComponent(
|
||||
backButton
|
||||
).addComponent(
|
||||
forwardButton
|
||||
).addComponent(
|
||||
endButton
|
||||
).addComponent(
|
||||
Canvas.this.step
|
||||
)
|
||||
)
|
||||
).addContainerGap()
|
||||
)
|
||||
);
|
||||
// make frame visible
|
||||
this.pack();
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Choose the specified color for further painting.
|
||||
* @param c The color to choose.
|
||||
*/
|
||||
public void chooseColor(Color c) {
|
||||
this.addAction(new ChooseColor(c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a line of length {@code length} in the current direction. The current position is moved to the end of the
|
||||
* line.
|
||||
* @param length The length of the line to draw.
|
||||
*/
|
||||
public void drawForward(int length) {
|
||||
this.addAction(new DrawForward(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a box with the text {@code text} at the current position.
|
||||
* @param text The text to draw.
|
||||
*/
|
||||
public void drawTextLabel(String text) {
|
||||
this.addAction(new DrawTextLabel(text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the current position by {@code x} units to the right and {@code y} units down according to the current
|
||||
* orientation (so if the orientation is rotated by 180 degrees, the move goes left and up instead of right and
|
||||
* down). This does not draw anything.
|
||||
* @param x The measure to go right.
|
||||
* @param y The measure to go down.
|
||||
*/
|
||||
public void move(double x, double y) {
|
||||
this.addAction(new Move(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the current position by {@code length} units in the current direction without drawing anything.
|
||||
* @param length The measure to move the current position.
|
||||
*/
|
||||
public void moveForward(int length) {
|
||||
this.addAction(new MoveForward(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current position and orientation to the top-most stored position and orientation. See {@link #push()}.
|
||||
*/
|
||||
public void pop() {
|
||||
this.addAction(new Pop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the current position and orientation.
|
||||
* By a subsequent {@link #pop()}, this position and orientation can be restored.
|
||||
*/
|
||||
public void push() {
|
||||
this.addAction(new Push());
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the shown frame.
|
||||
*/
|
||||
public void refresh() {
|
||||
synchronized (this) {}
|
||||
this.drawing.revalidate();
|
||||
this.ui.revalidate();
|
||||
this.ui.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the current orientation by {@code degrees} degrees (360 degrees form a circle) clockwise.
|
||||
* Negative values turn counter-clockwise.
|
||||
* @param degrees The degrees to turn the orientation.
|
||||
*/
|
||||
public void rotate(int degrees) {
|
||||
this.addAction(new Rotate(degrees));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a filled square of the specified length {@code length} at the current position and with the current
|
||||
* orientation.
|
||||
* @param length The length of the square to draw.
|
||||
*/
|
||||
public void square(double length) {
|
||||
this.addAction(new DrawSquare(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified action to the list of actions to be executed and updates the corresponding counter. Moreover,
|
||||
* the current bounds are deleted.
|
||||
* @param action The action to add.
|
||||
*/
|
||||
private void addAction(GraphicAction action) {
|
||||
synchronized (this) {
|
||||
this.actions.add(action);
|
||||
if (action.drawsSomething()) {
|
||||
this.draws++;
|
||||
}
|
||||
this.bounds = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to choose a color.
|
||||
*/
|
||||
private class ChooseColor extends GraphicAction {
|
||||
|
||||
/**
|
||||
* The color to choose.
|
||||
*/
|
||||
private final Color color;
|
||||
|
||||
/**
|
||||
* @param c The color to choose.
|
||||
*/
|
||||
ChooseColor(Color c) {
|
||||
this.color = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawsSomething() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
g.setColor(this.color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to draw a line forward.
|
||||
*/
|
||||
private class DrawForward extends MoveForward {
|
||||
|
||||
/**
|
||||
* @param length The length of the line to draw.
|
||||
*/
|
||||
DrawForward(int length) {
|
||||
super(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
if (draw) {
|
||||
g.drawLine(0, 0, 0, this.length);
|
||||
}
|
||||
super.replay(g, draw, boundsParam);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to draw a square.
|
||||
*/
|
||||
private class DrawSquare extends GraphicAction {
|
||||
|
||||
/**
|
||||
* The length of the square.
|
||||
*/
|
||||
private final double length;
|
||||
|
||||
/**
|
||||
* @param length The length of the square.
|
||||
*/
|
||||
DrawSquare(double length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
double hl = this.length / 2;
|
||||
Rectangle2D r = new Rectangle2D.Double();
|
||||
r.setFrame(-hl, -hl, this.length, this.length);
|
||||
g.fill(r);
|
||||
if (boundsParam != null) {
|
||||
Canvas.addToBounds(r, boundsParam, g);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to draw a text label.
|
||||
*/
|
||||
private class DrawTextLabel extends GraphicAction {
|
||||
|
||||
/**
|
||||
* The text of the label.
|
||||
*/
|
||||
private final String text;
|
||||
|
||||
/**
|
||||
* @param text The text of the label.
|
||||
*/
|
||||
DrawTextLabel(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
AffineTransform origTrans = g.getTransform();
|
||||
Point2D center = origTrans.transform(new Point2D.Double(0, 0), null);
|
||||
FontRenderContext frc = g.getFontRenderContext();
|
||||
Font f = g.getFont();
|
||||
TextLayout tl = new TextLayout(this.text, f, frc);
|
||||
double w = tl.getBounds().getWidth();
|
||||
double h = tl.getBounds().getHeight();
|
||||
// move the text to the center of the box
|
||||
AffineTransform trans = new AffineTransform();
|
||||
trans.setToTranslation(Math.round(center.getX() - w / 2), Math.round(center.getY() + h / 2));
|
||||
g.setTransform(trans);
|
||||
// draw the box
|
||||
Rectangle r = new Rectangle(0, (int)-h, (int)w, (int)h);
|
||||
if (draw) {
|
||||
Shape textShape = tl.getOutline(new AffineTransform());
|
||||
g.setColor(Color.BLACK);
|
||||
r.grow(4, 4);
|
||||
g.setColor(Color.WHITE);
|
||||
g.fill(r);
|
||||
g.setColor(Color.BLACK);
|
||||
g.draw(r);
|
||||
g.fill(textShape);
|
||||
}
|
||||
if (boundsParam != null) {
|
||||
Canvas.addToBounds(r, boundsParam, g);
|
||||
}
|
||||
// restore original orientation
|
||||
g.setTransform(origTrans);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An action for our canvas.
|
||||
*/
|
||||
private abstract class GraphicAction {
|
||||
|
||||
/**
|
||||
* @return True if this action actually draws something. False otherwise. Needs to be overridden by actions not
|
||||
* drawing something.
|
||||
*/
|
||||
public boolean drawsSomething() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The drawing method used in this canvas.
|
||||
* @param g The graphics object to draw on.
|
||||
* @param draw Flag to indicate whether the drawing action should actually be displayed.
|
||||
* @param boundsParam The bounds of the canvas.
|
||||
*/
|
||||
abstract void replay(Graphics2D g, boolean draw, Rectangle boundsParam);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for moving the current position.
|
||||
*/
|
||||
private class Move extends GraphicAction {
|
||||
|
||||
/**
|
||||
* The measure to move right.
|
||||
*/
|
||||
private final double x;
|
||||
|
||||
/**
|
||||
* The measure to move down.
|
||||
*/
|
||||
private final double y;
|
||||
|
||||
/**
|
||||
* @param x The measure to move right.
|
||||
* @param y The measure to move down.
|
||||
*/
|
||||
Move(double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawsSomething() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
g.translate(this.x, this.y);
|
||||
if (boundsParam != null) {
|
||||
Canvas.addToBounds(new Point2D.Double(this.x, this.y), boundsParam, g);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for moving forward.
|
||||
*/
|
||||
private class MoveForward extends GraphicAction {
|
||||
|
||||
/**
|
||||
* The number of units to move forward.
|
||||
*/
|
||||
final int length;
|
||||
|
||||
/**
|
||||
* @param length The number of units to move forward.
|
||||
*/
|
||||
MoveForward(int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawsSomething() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
Canvas.addCurrentPos(g, boundsParam);
|
||||
AffineTransform t = g.getTransform();
|
||||
t.translate(0, this.length);
|
||||
g.setTransform(t);
|
||||
Canvas.addCurrentPos(g, boundsParam);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for restoring a position and orientation.
|
||||
*/
|
||||
private class Pop extends GraphicAction {
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
g.setTransform(Canvas.this.transformations.pop());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for storing the current position and orientation.
|
||||
*/
|
||||
private class Push extends GraphicAction {
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
Canvas.this.transformations.push(g.getTransform());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for rotation the current orientation.
|
||||
*/
|
||||
private class Rotate extends GraphicAction {
|
||||
|
||||
/**
|
||||
* The degrees to turn the current orientation.
|
||||
*/
|
||||
final int degree;
|
||||
|
||||
/**
|
||||
* @param degree The degrees to turn the current orientation.
|
||||
*/
|
||||
Rotate(int degree) {
|
||||
this.degree = degree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawsSomething() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void replay(Graphics2D g, boolean draw, Rectangle boundsParam) {
|
||||
AffineTransform t = g.getTransform();
|
||||
t.rotate(this.degree / 180.0 * Math.PI);
|
||||
g.setTransform(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
83
tut6/src/Squares.java
Normal file
83
tut6/src/Squares.java
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* Program for drawing a square fractal.
|
||||
*/
|
||||
public class Squares
|
||||
{
|
||||
|
||||
/**
|
||||
* @param args Contains the parameters for the drawing. The first
|
||||
* (mandatory) is the recursion level. The second (optional)
|
||||
* is the base length of the first square. The default value
|
||||
* for this length is 100 if it is not specified. Each
|
||||
* parameter must be positive.
|
||||
*/
|
||||
public static void main(String args[])
|
||||
{
|
||||
int level;
|
||||
int length = 100;
|
||||
switch (args.length)
|
||||
{
|
||||
case 2:
|
||||
length = Integer.parseInt(args[1]);
|
||||
// fall-through
|
||||
case 1:
|
||||
level = Integer.parseInt(args[0]);
|
||||
break;
|
||||
default:
|
||||
System.out.println(
|
||||
"Es muessen zwischen 1 und 2 Parameter angegeben werden "
|
||||
+ "(Level und eventuell Basislaenge)!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (level < 1)
|
||||
{
|
||||
System.out.println("Das Rekursionslevel muss positiv sein!");
|
||||
return;
|
||||
}
|
||||
if (length < 1)
|
||||
{
|
||||
System.out.println("Die Basislaenge muss positiv sein!");
|
||||
return;
|
||||
}
|
||||
Canvas c = new Canvas();
|
||||
Squares.paintFractal(c, level, length);
|
||||
c.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a square fractal with the specified recursion level and base length
|
||||
* on the specified canvas.
|
||||
*
|
||||
* @param c The canvas to draw the tree on.
|
||||
* @param level The current recursion level.
|
||||
* @param length The current length.
|
||||
*/
|
||||
private static void paintFractal(Canvas c, int level, double length)
|
||||
{
|
||||
if (level <= 0)
|
||||
return;
|
||||
|
||||
c.square(length);
|
||||
|
||||
// oben links
|
||||
c.move(-length/2, -length/2);
|
||||
paintFractal(c, level-1, length/2);
|
||||
|
||||
// oben rechts
|
||||
c.move(length, 0);
|
||||
paintFractal(c, level-1, length/2);
|
||||
|
||||
// unten rechts
|
||||
c.move(0, length);
|
||||
paintFractal(c, level-1, length/2);
|
||||
|
||||
// unten links
|
||||
c.move(-length, 0);
|
||||
paintFractal(c, level-1, length/2);
|
||||
|
||||
// zurueck zum mittelpunkt
|
||||
c.move(length/2, -length/2);
|
||||
}
|
||||
|
||||
}
|
69
tut6/src/Utils.java
Normal file
69
tut6/src/Utils.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
import java.awt.*;
|
||||
|
||||
public class Utils {
|
||||
|
||||
private Utils(){}
|
||||
|
||||
/**
|
||||
* Evaluiert eine Variable bei mit wahr angenommenen Variablen
|
||||
* @param elem der Name der zu evaluierenden Variable oder true oder false
|
||||
* @param strings die Namen genau der Variablen, die für diese Evalutaion als wahr angenommen werden
|
||||
* @return true, wenn die Variable zu true evaluiert wird, sonst false
|
||||
*/
|
||||
public static boolean evaluateVariable(String elem, String... strings) {
|
||||
if (elem.equals("true")) {
|
||||
//variable is constant true
|
||||
return true;
|
||||
} else if (elem.equals("false")) {
|
||||
//variable is constant false
|
||||
return false;
|
||||
} else {
|
||||
return contains(elem,strings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt zurück, ob elem in strings enthalten ist
|
||||
* @param elem der String, nach dem gesucht werden soll
|
||||
* @param strings die Strings, die durchsucht werden sollen
|
||||
* @return wenn elem in strings enthalten ist, sonst false
|
||||
*/
|
||||
public static boolean contains(String elem, String... strings) {
|
||||
if (strings == null) {
|
||||
//strings is null, elem cannot be contained
|
||||
return false;
|
||||
}
|
||||
for (String string : strings) {
|
||||
if (string.equals(elem)) {
|
||||
//elem is in strings
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//elem has not been found in strings
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine Fehlermeldung aus.
|
||||
* @param msg die Fehlermeldung, die ausgegeben werden soll
|
||||
*/
|
||||
public static void error(String msg) {
|
||||
System.err.println(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet das Maximum der Argumente.
|
||||
* @param args die Werte, deren Maximum bestimmt werden soll
|
||||
* @return den maximalen Wert aller Argumente
|
||||
*/
|
||||
public static int max(int... args) {
|
||||
if (args.length == 0) {
|
||||
error("Called max without arguments!");
|
||||
}
|
||||
int res = args[0];
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
res = Math.max(res, args[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
Reference in a new issue