/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © 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); } }