183 行
6.3 KiB
Java
183 行
6.3 KiB
Java
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);
|
|
}
|
|
}
|
|
}
|
|
}
|