public void createModel() {
final int count = 1000;
final int width = 3;
+ addStatusSegment(this.positionStep, "");
+
Barrier barrier = new Barrier(this.sheet.createRectangle(new PointRW(
- 500,
- 100), new DimensionRW(600, 100), false, this));
+ 500, 100), new DimensionRW(600, 100), false, this));
barrier.getWidget().setColorBackground(Color.gray);
this.things.add(barrier);
barrier = new Barrier(this.sheet.createRectangle(new PointRW(500, 400),
--- /dev/null
+/**
+ *
+ */
+package jlecture.simulation;
+
+/**
+ * Defines some names for horizontal and vertical alignment.
+ *
+ * @author hm
+ *
+ */
+public enum Alignment {
+ UNDEF, LEFT, RIGHT, CENTER, TOP, MIDDLE, BOTTOM
+}
* the simulator model
* @return a X cross widget
*/
- IWidget createRectangle(PointRW center, DimensionRW dimension,
+ public IWidget createRectangle(PointRW center, DimensionRW dimension,
boolean filled, Model model);
+ /**
+ * Creates a piece of text.
+ *
+ * @param text
+ * the text to show
+ * @param size
+ * the font size (in dots)
+ * @param center
+ * the position of the text. See the following alignments
+ * @param horizontalAlignment
+ * LEFT: the text is left of the center...
+ * @param verticalAlignment
+ * TOP: the text is on the center
+ * @return the created text
+ */
+ public IWidget createText(final String text, final int size,
+ final PointRW center, final Alignment horizontalAlignment,
+ final Alignment verticalAlignment);
+
/**
* Creates a X cross widget.
*
* the simulator model
* @return a X cross widget
*/
- IWidget createXCross(PointRW center, DimensionRW dimension, Model model);
+ public IWidget createXCross(PointRW center, DimensionRW dimension,
+ Model model);
/**
* Returns the width and height of the sheet.
--- /dev/null
+/**
+ *
+ */
+package jlecture.simulation;
+
+/**
+ * Defines a text widget.
+ *
+ * @author hm
+ *
+ */
+public interface ITextWidget extends IWidget {
+ /**
+ * Returns the text of the widget.
+ *
+ * @return the current text
+ */
+ String getText();
+
+ /**
+ * Sets the text of the widget.
+ *
+ * @param text
+ * the new text
+ */
+ void setText(String text);
+}
*/
package jlecture.simulation;
+import java.awt.Color;
import java.awt.Dimension;
+import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
+import java.util.Hashtable;
import java.util.List;
import java.util.Random;
* Counts the number of collisions inside <code>openPosition()</code>.
*/
public int openPositionCollisions = 0;
+ /**
+ * current number of the simulation step.
+ */
+ protected int step = 0;
+ /**
+ * The position of the status line segment displaying the step (in % of the
+ * width)
+ */
+ protected Double positionStep = 0.0;
+
+ /**
+ * Text color of a normal text in the status line.
+ */
+ protected Color colorStatusNormal = Color.black;
+
+ /**
+ * Text color of a warning in the status line.
+ */
+ protected Color colorStatusWarning = Color.cyan;
+
+ /**
+ * Text color of an error message in the status line.
+ */
+ protected Color colorStatusError = Color.red;
+
+ /**
+ * The start time of the simulation (in millisec from 1.1.1970)
+ */
+ private long startTime = 0;
+
+ /**
+ * The status line segments. Allows to change texts.
+ */
+ private final Hashtable<Double, IWidget> statusSegments = new Hashtable<Double, IWidget>();
/**
* Constructor.
this.region = region;
}
+ /**
+ * Shows a text in the status line
+ *
+ * @param xRelative
+ * start position in % from the width
+ * @param text
+ * text to display
+ */
+ public void addStatusSegment(final Double xRelative, final String text) {
+
+ final double x = this.region.x + xRelative / 100.0 * this.region.width;
+ final double y = -this.region.height / 100.0 * 2;
+
+ if (this.statusSegments.contains(xRelative))
+ log(String.format("status segment already exists: %.0f", xRelative));
+ else
+ this.statusSegments.put(xRelative, this.sheet.createText(text, 12,
+ new PointRW(x, y), Alignment.LEFT, Alignment.TOP));
+ }
+
/**
* Checks whether a given object collides with one of the other simulated
* objects.
if (current != exclude) {
final RectangleRW contour = current.widget.getContour();
if (point.x >= contour.x && point.y >= contour.y
- && point.x < contour.x + contour.width
- && point.y < contour.y + contour.height) {
+ && point.x < contour.x + contour.width
+ && point.y < contour.y + contour.height) {
rc = current;
break;
}
count++;
rc.x = this.region.x + this.random.nextDouble() * this.region.width;
rc.y = this.region.x + this.random.nextDouble()
- * this.region.height;
+ * this.region.height;
} while (occupied(rc, null) != null);
this.openPositionCollisions += count - 1;
return rc;
this.sheet = sheet;
}
+ /**
+ * Change the text of a status line segment.
+ *
+ * @param xRelative
+ * identifier of the segment (start position in % of the width)
+ * @param text
+ * the new text
+ * @param color
+ * the new color
+ */
+ public void setStatusSegmentText(final Double xRelative, final String text,
+ final Color color) {
+ final IWidget widget = this.statusSegments.get(xRelative);
+ if (widget == null)
+ log(String.format("status segment does not exist: %.0f", xRelative));
+ else {
+ final ITextWidget textWidget = (ITextWidget) widget;
+ textWidget.setText(text);
+ textWidget.setColor(color);
+ }
+ }
+
/**
* Executes one simulation step.
*
public void simulationStep() {
if (this.isReady) {
this.now = System.currentTimeMillis();
+ if (this.step++ == 0)
+ this.startTime = this.now;
+ else if (this.step % 5 == 0) {
+ final long duration = (this.now - this.startTime) / 1000L;
+ setStatusSegmentText(this.positionStep, String.format(
+ "step %d time: %d sec (%.1f/sec)", this.step, duration,
+ (double) this.step / duration), this.colorStatusNormal);
+ }
// do the moves
for (int ix = this.firstIndexMovables; ix < this.things.size(); ix++) {
final ThingRW thing = this.things.get(ix);
}
}
+ /**
+ * Transforms a real world point to a pixel point.
+ *
+ * <pre>
+ * deltaX = x - xMin
+ * wRW / wPx = deltaXRW / deltaXPx => deltaPx = deltaXRW * wPx / wRW
+ * xPx = xMinPx + deltaXPx, xMinPx = 0
+ * xPx = deltaPx = deltaXRW * wPx / wRW
+ * xPx = (xRW - xMinRW) * (xMaxRW - xMinRW) / xMaxPx
+ * </pre>
+ *
+ * @param pointRW
+ * the point to convert
+ * @param point
+ * OUT: the calculated point
+ */
+ public void transform(final PointRW pointRW, final Point point) {
+ final Dimension dimension = this.sheet.getDimension();
+ point.x = (int) ((pointRW.x - this.region.x) * this.region.width / dimension.width);
+ point.y = dimension.height
+ - (int) ((pointRW.y - this.region.y) * this.region.height / dimension.height);
+ }
+
/**
* Transforms a real world rectangle to a native rectangle.
*
final Dimension dimension = this.sheet.getDimension();
rectangle.x = (int) ((rectangleRW.x - this.region.x)
- * this.region.width / dimension.width);
- rectangle.y = (int) ((rectangleRW.y - this.region.y)
- * this.region.height / dimension.height);
+ * this.region.width / dimension.width);
+ rectangle.y = dimension.height
+ - (int) ((rectangleRW.y - this.region.y) * this.region.height / dimension.height);
rectangle.width = (int) (rectangleRW.width * dimension.width / this.region.width);
rectangle.height = (int) (rectangleRW.height * dimension.height / this.region.height);
}
*
*/
public enum WidgetType {
- UNDEF, RECTANGLE, XCROSS, LINE, POINT
+ UNDEF, RECTANGLE, XCROSS, LINE, POINT, TEXT
}
* @param model
* the simulator model
*/
- public PanelSwing(Model model) {
+ public PanelSwing(final Model model) {
this.model = model;
}
* @param graphics
* the drawing parameter like pencil
*/
- private void doDrawing(Graphics graphics) {
+ private void doDrawing(final Graphics graphics) {
final Graphics2D g2d = (Graphics2D) graphics;
g2d.setColor(this.foreground);
g2d.setBackground(this.background);
-
for (final IWidget item : this.model.getItems()) {
final WidgetSwing item2 = (WidgetSwing) item;
item2.draw(g2d);
}
@Override
- public void paintComponent(Graphics graphics) {
+ public void paintComponent(final Graphics graphics) {
super.paintComponent(graphics);
doDrawing(graphics);
}
import javax.swing.JFrame;
import javax.swing.Timer;
+import jlecture.simulation.Alignment;
import jlecture.simulation.DimensionRW;
import jlecture.simulation.ISheet;
import jlecture.simulation.IWidget;
return new RectangleSwing(center, dimension, filled, model);
}
+ @Override
+ public IWidget createText(final String text, final int size,
+ final PointRW center, final Alignment horizontalAlignment,
+ final Alignment verticalAlignment) {
+ final TextSwing rc = new TextSwing(text, size, center,
+ horizontalAlignment, verticalAlignment, this.model);
+ return rc;
+ }
+
@Override
public IWidget createXCross(final PointRW center,
final DimensionRW dimension, final Model model) {
add(new PanelSwing(this.model));
- setSize(this.dimension.width, this.dimension.height);
+ setSize(this.dimension.width, this.dimension.height * 120 / 100);
if (this.position == null)
// build the window in the center:
--- /dev/null
+/**
+ *
+ */
+package jlecture.swing;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+
+import jlecture.simulation.Alignment;
+import jlecture.simulation.ITextWidget;
+import jlecture.simulation.Model;
+import jlecture.simulation.PointRW;
+import jlecture.simulation.WidgetType;
+
+/**
+ * @author hm
+ *
+ */
+public class TextSwing extends WidgetSwing implements ITextWidget {
+ /**
+ * font size in dots.
+ */
+ private final int size;
+ /**
+ * Text which will be shown.
+ */
+ private String text;
+ /**
+ * The width of the text in pixel.
+ */
+ private int textWidth = 0;
+ /**
+ * The height of the text in pixel.
+ */
+ private int textHeight = 0;
+ /**
+ * the text will be drawn with this font.
+ */
+ Font font = null;
+ /**
+ * Helper to calculate width and height. Will be initialized when a
+ * <code>Graphics</code> is available.
+ */
+ FontMetrics fontMetrics = null;
+ Point nativeCenter = new Point(0, 0);
+ Alignment horizontalAlignment;
+ Alignment verticalAlignment;
+
+ /**
+ * Contructor.
+ *
+ * @param text
+ * the text to show
+ * @param size
+ * the font size in dots
+ * @param center
+ * the text will be centered around this point
+ * @param model
+ * the simulation model
+ */
+ public TextSwing(final String text, final int size, final PointRW center,
+ final Alignment horizontalAlignment, final Alignment verticalAlignment,
+ final Model model) {
+ super(center, model);
+ this.size = size;
+ this.text = text;
+ this.font = new Font("Helvetica", Font.PLAIN, this.size);
+ this.horizontalAlignment = horizontalAlignment;
+ this.verticalAlignment = verticalAlignment;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jlecture.swing.WidgetSwing#calculateContour()
+ */
+ @Override
+ protected void calculateContour() {
+ // TODO Auto-generated method stub
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jlecture.swing.WidgetSwing#draw(java.awt.Graphics2D)
+ */
+ @Override
+ public void draw(final Graphics2D graphics) {
+ if (this.font == null) {
+ this.fontMetrics = graphics.getFontMetrics(this.font);
+ this.textWidth = this.fontMetrics.stringWidth(this.text);
+ this.textHeight = this.fontMetrics.getHeight();
+ }
+ final Color safeColor = graphics.getColor();
+ graphics.setColor(this.color);
+ this.model.transform(this.center, this.nativeCenter);
+ int x, y;
+ switch (this.horizontalAlignment) {
+ case LEFT:
+ x = this.nativeCenter.x;
+ break;
+ case RIGHT:
+ x = this.nativeCenter.x - this.textWidth;
+ break;
+ default:
+ x = this.nativeCenter.x - this.textWidth / 2;
+ break;
+ }
+ switch (this.verticalAlignment) {
+ case TOP:
+ y = this.nativeCenter.y + this.textHeight;
+ break;
+ case BOTTOM:
+ y = this.nativeCenter.y;
+ break;
+ default:
+ y = this.nativeCenter.y - this.textHeight / 2;
+ break;
+ }
+ graphics.drawString(this.text, x, y);
+ graphics.setColor(safeColor);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jlecture.simulation.IWidget#getMaxDimension()
+ */
+ @Override
+ public double getMaxDimension() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getText() {
+ return this.text;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jlecture.simulation.IWidget#getWidgetType()
+ */
+ @Override
+ public WidgetType getWidgetType() {
+ return WidgetType.TEXT;
+ }
+
+ @Override
+ public void setText(final String text) {
+ this.text = text;
+
+ }
+
+}