/*
* Licensed Materials - Property of Rogue Wave Software, Inc.
* © Copyright Rogue Wave Software, Inc. 2014, 2017
* © Copyright IBM Corp. 2009, 2014
* © Copyright ILOG 1996, 2009
* All Rights Reserved.
*
* Note to U.S. Government Users Restricted Rights:
* The Software and Documentation were developed at private expense and
* are "Commercial Items" as that term is defined at 48 CFR 2.101,
* consisting of "Commercial Computer Software" and
* "Commercial Computer Software Documentation", as such terms are
* used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
* as applicable.
*/
package demo.triplebuffering;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.ImageObserver;
import ilog.views.IlvGraphic;
import ilog.views.IlvGraphicUtil;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.IlvTransformer;
/**
* A graphic object showing the track of a plane.
*/
public class Track extends IlvGraphic implements ImageObserver {
/**
* Name of the plane.
*/
private String name;
/**
* The logo of the company.
*/
private Image image;
/**
* Speed of the plane.
*/
private int speed;
/**
* Altitude of the plane.
*/
private int altitude;
/**
* Position of the plane in manager's coordinate system.
*/
private IlvPoint position;
/**
* Position of the speed vector of the plane.
*/
private IlvPoint speedPosition;
/**
* Position of the destination of the plane.
*/
private IlvPoint destination;
/**
* Are last positions displayed.
*/
private boolean showLastPositions = true;
/**
* Are last positions displayed using alpha composition.
*/
public static boolean transparentLastPositions = true;
/**
* Are last positions displayed using antialising.
*/
public static boolean antialiasedLastPositions = true;
/**
* Is the speed vector displayed.
*/
private boolean showSpeed = true;
/**
* Are the labels displayed.
*/
private boolean showLabels = true;
/**
* Is the logo displayed.
*/
private boolean showLogo = true;
/**
* Is the route of the plane displayed.
*/
private boolean showRoute;
/**
* The warning distance.
*/
private double warningDistance;
/**
* A cache for the width of the name.
*/
private int nameWidth;
/**
* A cache for the width of the speed label.
*/
private int speedLabelWidth;
/**
* A cache for the width of the altitude label.
*/
private int altitudeLabelWidth;
/**
* Number of positions of the track displayed.
*/
private static final int TRACKMAXLASTPOSITION = 6;
/**
* Last positions of the plane.
*/
private IlvPoint[] lastPositions = new IlvPoint[TRACKMAXLASTPOSITION];
/**
* Font to display labels.
*/
private Font font;
/**
* A cache for the height of the font.
*/
private double fontHeight;
/**
* Colors of the plane.
*/
private Color color, takeOffColor, landingColor;
/**
* The label for altitude.
*/
private String altitudeStr = "0";
/**
* The label for speed.
*/
private String speedStr = "0";
/**
* Highquality rendering for the logo image. Set to false because it seems
* this is useful mainly if the image gets resized or rotated, which is not
* the case here.
*/
private static final boolean HIGHQUALITY_IMAGE = false;
/**
* Last positions drawn as rectangles.
*/
private static final int LAST_POSITION_RECT = 0;
/**
* Last positions drawn as ovals.
*/
private static final int LAST_POSITION_OVAL = 1;
/**
* The drawing style for showing the last positions.
*/
private int _lastPositionDrawingStyle = LAST_POSITION_OVAL;
/**
* A factor used when computing alpha transparency.
*/
private static final float LAST_POS_ALFA_FACTOR = (1.f / TRACKMAXLASTPOSITION) * .8f;
/**
* Distance between successive /** Creates an initializes a Track.
*/
public Track(String name, Image image, IlvPoint position, IlvPoint destination, Font font, Color color,
Color takeOffColor, Color landingColor) {
this.name = name;
this.image = image;
setFont(font);
this.color = color;
this.takeOffColor = takeOffColor;
this.landingColor = landingColor;
init(position, destination);
}
/**
* Initializes the positions.
*/
public void init(IlvPoint position, IlvPoint destination) {
this.position = new IlvPoint(position);
for (int i = 0; i < TRACKMAXLASTPOSITION; ++i)
lastPositions[i] = new IlvPoint(position);
speedPosition = new IlvPoint(position);
this.destination = new IlvPoint(destination);
}
/**
* Returns the name of the plane.
*/
public String getTrackName() {
return name;
}
/**
* Changes the name of the plane.
*/
public void setTrackName(String s) {
name = s;
IlvRect r = IlvGraphicUtil.GetStringBounds(name, font, false);
nameWidth = (int) r.width;
}
/**
* Returns the current position of the plane.
*/
public IlvPoint getPosition() {
return new IlvPoint(position);
}
/**
* Changes the position of the plane.
*/
public void setPosition(double x, double y) {
// Shift last positions
int i;
for (i = 0; i < TRACKMAXLASTPOSITION - 1; ++i)
lastPositions[i].move(lastPositions[i + 1].x, lastPositions[i + 1].y);
speedPosition.move(x, y);
speedPosition.translate(position.x - lastPositions[TRACKMAXLASTPOSITION - 1].x,
position.y - lastPositions[TRACKMAXLASTPOSITION - 1].y);
lastPositions[i].move(position.x, position.y);
position.move(x, y);
}
/**
* Translates the plane's position.
*/
public void translatePosition(double dx, double dy) {
setPosition(position.x + dx, position.y + dy);
}
/**
* Returns the destination of the plane.
*/
public IlvPoint getDestination() {
return new IlvPoint(destination);
}
/**
* Returns the position of the speed vector of the plane.
*/
public IlvPoint getSpeedPosition() {
return new IlvPoint(speedPosition);
}
/**
* Indicates wheither last positions are displayed.
*/
public boolean isShowingLastPositions() {
return showLastPositions;
}
/**
* Displays or hides the last positions of the plane.
*/
public void setShowingLastPositions(boolean value) {
showLastPositions = value;
}
/**
* Indicates wheither the speed is displayed.
*/
public boolean isShowingSpeed() {
return showSpeed;
}
/**
* Displays or hides the speed vector of the plane.
*/
public void setShowingSpeed(boolean value) {
showSpeed = value;
}
/**
* Indicates wheither the labels are displayed.
*/
public boolean isShowingLabels() {
return showLabels;
}
/**
* Displays or hides the labels of the plane.
*/
public void setShowingLabels(boolean value) {
showLabels = value;
}
/**
* Indicates wheither the logo is displayed.
*/
public boolean isShowingLogo() {
return showLogo;
}
/**
* Displays or hides the logo of the plane.
*/
public void setShowingLogo(boolean value) {
showLogo = value;
}
/**
* Indicates wheither the route is displayed.
*/
public boolean isShowingRoute() {
return showRoute;
}
/**
* Displays or hides the route of the plane.
*/
public void setShowingRoute(boolean value) {
showRoute = value;
}
/**
* Returns the speed of the plane.
*/
public int getSpeed() {
return speed;
}
/**
* Changes the speed of the plane.
*/
public void setSpeed(int val) {
speed = val;
speedStr = String.valueOf(speed);
IlvRect r = IlvGraphicUtil.GetStringBounds(speedStr, font, false);
speedLabelWidth = (int) r.width;
}
/**
* Returns the altitude of the plane.
*/
public int getAltitude() {
return altitude;
}
/**
* Changes the altitude of the plane.
*/
public void setAltitude(int val) {
altitude = val;
altitudeStr = String.valueOf(altitude);
IlvRect r = IlvGraphicUtil.GetStringBounds(altitudeStr, font, false);
altitudeLabelWidth = (int) r.width;
}
/**
* Returns the warning distance of the plane.
*/
public double getWarningDistance() {
return warningDistance;
}
/**
* Changes the warning distance of the plane.
*/
public void setWarningDistance(double val) {
warningDistance = val;
}
/**
* Returns the font of the labels.
*/
public Font getFont() {
return font;
}
/**
* Changes the font of the labels.
*/
public void setFont(Font font) {
this.font = font;
IlvRect r = IlvGraphicUtil.GetStringBounds(name, font, false);
nameWidth = (int) r.width;
fontHeight = r.height;
r = IlvGraphicUtil.GetStringBounds(speedStr, font, false);
speedLabelWidth = (int) r.width;
r = IlvGraphicUtil.GetStringBounds(altitudeStr, font, false);
altitudeLabelWidth = (int) r.width;
}
/**
* Returns the color used during take off.
*/
public Color getTakeOffColor() {
return takeOffColor;
}
/**
* Changes the color used during take off.
*/
public void setTakeOffColor(Color color) {
takeOffColor = color;
}
/**
* Returns the color used when landing.
*/
public Color getLandingColor() {
return landingColor;
}
/**
* Changes the color used when landing.
*/
public void setLandingColor(Color pal) {
landingColor = pal;
}
/**
* Returns true if the plane has landed.
*/
public boolean hasLanded() {
return position.equals(destination);
}
/**
* Sets the position to the destination.
*/
public void land() {
setPosition(destination.x, destination.y);
}
private static final int DELTA = 5;
private static final int DELTAX = 10;
private static final int DELTAY = 0;
/**
* Draws the track.
*/
Override
public void draw(Graphics g, IlvTransformer t) {
Graphics2D dst = (Graphics2D) g;
Color color = this.color;
if (lastPositions[0].equals(lastPositions[1]))
color = takeOffColor;
else if (CloseTo(position, destination, warningDistance))
color = landingColor;
IlvPoint p = new IlvPoint();
IlvPoint point = new IlvPoint(position);
// Draw position
if (t != null)
t.apply(point);
IlvRect rect = new IlvRect(point.x - DELTA, point.y - DELTA, 2 * DELTA, 2 * DELTA);
dst.setColor(color);
dst.drawOval((int) rect.x, (int) rect.y, (int) rect.width, (int) rect.height);
// Draw last positions
if (isShowingLastPositions()) {
if (antialiasedLastPositions)
dst.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double d = 2;
for (int i = 0; i < TRACKMAXLASTPOSITION; ++i, ++d) {
p.move(lastPositions[i].x, lastPositions[i].y);
if (t != null)
t.apply(p);
rect.reshape(p.x - d, p.y - d, 2 * d, 2 * d);
if (transparentLastPositions) {
float alpha = .2f + i * LAST_POS_ALFA_FACTOR;
dst.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
}
if (_lastPositionDrawingStyle == LAST_POSITION_RECT)
dst.draw(rect);
else // LAST_POSITION_OVAL (slower, but nicer)
dst.drawOval(rect.xFloor(), rect.yFloor(), rect.widthFloor(), rect.heightFloor());
}
if (transparentLastPositions)
dst.setComposite(AlphaComposite.SrcOver);
if (antialiasedLastPositions)
dst.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
}
// Draw Logo
if (image != null && isShowingLogo()) {
rect.move(point.x - rect.width / 2, point.y - rect.height / 2);
IlvGraphicUtil.DrawImage(dst, rect, image, null, this, HIGHQUALITY_IMAGE);
}
// Draw Speed
if (isShowingSpeed()) {
p.move(speedPosition.x, speedPosition.y);
if (t != null)
t.apply(p);
dst.drawLine((int) point.x, (int) point.y, (int) p.x, (int) p.y);
}
// Draw Labels
if (isShowingLabels()) {
double h = fontHeight;
p.move(point.x + DELTAX, point.y);
dst.setFont(font);
dst.drawString(name, (int) p.x, (int) p.y);
p.y += DELTAY + h;
dst.drawString(speedStr, (int) p.x, (int) p.y);
p.y += DELTAY + h;
dst.drawString(altitudeStr, (int) p.x, (int) p.y);
}
// Draw the rest of the route
if (isShowingRoute() && !hasLanded()) {
p.move(destination.x, destination.y);
if (t != null)
t.apply(p);
dst.setColor(landingColor);
dst.drawLine((int) point.x, (int) point.y, (int) p.x, (int) p.y);
}
}
/**
* Redraws the object when the image is fully loaded. Implementation of the
* method of ImageObserver.
*/
Override
public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) {
if (img == image) {
if ((flags & ERROR) != 0) {
image = null;
reDraw();
}
if ((flags & ALLBITS) != 0)
reDraw();
if ((flags & FRAMEBITS) != 0)
reDraw();
return (flags & (ALLBITS | ERROR)) == 0;
} else
return false;
}
/**
* Returns the bounding box of the object.
*/
Override
public IlvRect boundingBox(IlvTransformer t) {
IlvRect bbox;
IlvPoint p = new IlvPoint(position);
// Add Position
if (t != null)
t.apply(p);
IlvRect rect = new IlvRect(p.x - DELTA, p.y - DELTA, 2 * DELTA, 2 * DELTA);
bbox = new IlvRect(rect);
// Add Last Positions
int d = 2;
if (isShowingLastPositions()) {
for (int i = 0; i < TRACKMAXLASTPOSITION; ++i, ++d) {
p.move(lastPositions[i].x, lastPositions[i].y);
if (t != null)
t.apply(p);
rect.move(p.x - d, p.y - d);
rect.resize((2 * d), (2 * d));
bbox.add(rect);
}
}
// Add Speed
if (isShowingSpeed()) {
p.move(speedPosition.x, speedPosition.y);
if (t != null)
t.apply(p);
bbox.add(p);
}
// Add Labels
if (isShowingLabels()) {
int h = (int) fontHeight;
p.move(position.x, position.y);
if (t != null)
t.apply(p);
p.translate(DELTAX, 0);
rect.move(p.x, p.y - h + d);
rect.resize(nameWidth, h);
bbox.add(rect);
p.translate(0, DELTAY + h);
rect.move(p.x, p.y - h + d);
rect.resize(speedLabelWidth, h);
bbox.add(rect);
p.translate(0, DELTAY + h);
rect.move(p.x, p.y - h + d);
rect.resize(altitudeLabelWidth, h);
bbox.add(rect);
}
// Add destination
if (isShowingRoute()) {
p.move(destination.x, destination.y);
if (t != null)
t.apply(p);
bbox.add(p);
}
return bbox;
}
/**
* Returns false, this object is not fully zoomable.
*/
Override
public boolean zoomable() {
return false;
}
/**
* Applies a transformation to the object.
*/
Override
public void applyTransform(IlvTransformer t) {
t.apply(position);
for (int i = 0; i < TRACKMAXLASTPOSITION; ++i)
t.apply(lastPositions[i]);
t.apply(speedPosition);
t.apply(destination);
}
Override
public IlvGraphic copy() {
return null;
}
/**
* Returns true if the specified points are close to each other.
*/
static private boolean CloseTo(IlvPoint pos, IlvPoint dest, double limit) {
double X = dest.x - pos.x;
double Y = dest.y - pos.y;
return ((X * X + Y * Y) <= limit * limit);
}
}