|
- package de.hems.trafficsim;
-
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.view.SurfaceHolder;
-
- import java.util.ConcurrentModificationException;
- import java.util.List;
-
- /**
- * User interface class rendering the track history on a SurfaceView.
- */
- public class Renderer {
- /**
- * the track to render
- */
- protected Track track;
- /**
- * width of a rectangle representing one vehicle
- */
- protected int pixelPerVehicle;
- /**
- * height of a rectangle representing one vehicle
- */
- protected int pixelPerLine;
- /**
- * amount of pixels per track position which are lost by rounding
- */
- protected float tooShortPerTrackLength;
- /**
- * amount of pixels per height which are lost by rounding
- */
- protected float tooShortPerHeight;
- /**
- * Paint instance of the renderer
- */
- protected Paint paint;
- /**
- * holder of the surface the renderer draws to
- */
- protected SurfaceHolder holder;
- /**
- * width of the surface to draw to
- */
- protected int width;
- /**
- * height of the surface to draw to
- */
- protected int height;
- /**
- * temporary reference to the time records of one simulation step
- */
- private List<VehicleTimeRecord> stepRecords;
- /**
- * temporary reference to the canvas to draw to
- */
- private Canvas canvas;
-
- /**
- * Constuctor for a Renderer.
- *
- * @param track the track to render
- * @param holder the holder of the surface to draw to
- */
- public Renderer(Track track, SurfaceHolder holder) {
- this.track = track;
- this.holder = holder;
- this.paint = new Paint();
- }
-
- /**
- * Updates the dimension information of the renderer.
- *
- * @param width the width of the SurfaceView
- * @param height the height of the SurfaceView
- */
- public void setSize(int width, int height) {
- if (width > 0 && height > 0) {
- this.pixelPerVehicle = width / (int) this.track.getTrackLength();
- this.tooShortPerTrackLength =
- (width - this.pixelPerVehicle * this.track.getTrackLength())
- / this.track.getTrackLength();
- this.pixelPerLine = height / this.track.getHistoryLength();
- this.tooShortPerHeight = (height - this.pixelPerLine * this.track.getHistoryLength())
- / (float) height;
- System.out.println("Viewport: " + width + "x" + height);
- this.width = width;
- this.height = height;
- }
- }
-
- /**
- * Updates the track of the Surface.
- *
- * @param track the new track to render
- */
- public void setTrack(Track track) {
- this.track = track;
- this.setSize(width, height);
- }
-
- /**
- * Utility function which calculates a color from the relation between the current speed of a
- * vehicle and it's maximum speed (from red over yellow to green).
- *
- * @param curVelocity current velocity of the vehicle
- * @param maxVelocity maximum velocity of the vehilce
- * @return color encoded as Android color integer
- */
- protected int getColor(float curVelocity, float maxVelocity) {
- float perc = curVelocity / maxVelocity;
- perc = 1 - perc;
- if (perc <= 0.5) {
- int red = ((int) (2 * perc * 0xFF)) << 16;
- int green = 0xFF << 8;
- int blue = 0;
- return 0xff000000 | red | green | blue;
- } else {
- int red = 0xFF << 16;
- int green = ((int) (0xFF - 0xFF * (perc - 0.5) * 2)) << 8;
- int blue = 0;
- return 0xff000000 | red | green | blue;
- }
- }
-
- /**
- * Draws the current state of the track history to the Surface.
- */
- protected void draw() {
- try {
- if (this.pixelPerVehicle == 0) {
- Rect rect = this.holder.getSurfaceFrame();
- this.setSize(rect.right, rect.bottom);
- }
- canvas = this.holder.lockCanvas();
- synchronized (holder) {
- int y = 0;
- int left = 0;
- int hCompensateStart = 0;
- int hCompensateEnd = 0;
- int vCompensateStart = 0;
- int vCompensateEnd = 0;
- canvas.drawColor(Color.BLACK);
- for (int curStepIdx = this.track.getVtrList().size()-1; curStepIdx >= 0;
- curStepIdx--) {
- try {
- try {
- track.getListSemaphore().acquire();
- } catch (InterruptedException ex) {
- return;
- }
- vCompensateStart = Math.round(y * this.tooShortPerHeight);
- vCompensateEnd = Math.round((y+this.pixelPerLine) * this.tooShortPerHeight);
- stepRecords = this.track.getVtrList().get(curStepIdx);
- int i = 0;
- for (VehicleTimeRecord r : stepRecords) {
- left = (int) (this.pixelPerVehicle * r.getPosition());
- hCompensateStart = Math.round(r.getPosition() * this.tooShortPerTrackLength);
- hCompensateEnd = Math.round((r.getPosition() + this.pixelPerVehicle) * this.tooShortPerTrackLength);
- this.paint.setColor(getColor(r.getVelocity(), r.getMaxVelocity()));
- canvas.drawRect(left + hCompensateStart, y+vCompensateStart,
- left + this.pixelPerVehicle + hCompensateEnd,
- y + pixelPerLine + vCompensateEnd, this.paint);
- i++;
- }
- track.getListSemaphore().release();
- y += pixelPerLine;
- } catch (ConcurrentModificationException ex) {
- System.out.println("Concurrent Exception occured, skipping record");
- y += pixelPerLine;
- }
- }
- }
- } finally {
- if (canvas != null) {
- this.holder.unlockCanvasAndPost(canvas);
- }
- }
- }
- }
|