// --------------------------------------------------------------------------- // NAME : atc.java // VERSION : 1.0 // AUTHOR : Craig Wilcox // --------------------------------------------------------------------------- // ----------------------- // Import java class libs. // ----------------------- import java.awt.*; import java.awt.event.*; import java.applet.*; import java.beans.*; // ------------------ // Define main class. // ------------------ public class atc extends Applet implements AdjustmentListener, PropertyChangeListener { // -------------------------------- // Define private member variables. // -------------------------------- private Label titleLabel = null; private Label xLabel = null; private Label planeStartLabel = null; private Label yLabel = null; private Label zLabel = null; private Label planeVelocityLabel = null; private Label spaceMaxLabel = null; private Label spaceMinLabel = null; private Label deltaTLabel = null; private Label finalPosLabel = null; private Label inEndBox = null; private Label inDuringBox = null; private DoubleBox planeStartField[] = {null, null, null}; private DoubleBox planeVelocityField[] = {null, null, null}; private DoubleBox spaceMaxField[] = {null, null, null}; private DoubleBox spaceMinField[] = {null, null, null}; private DoubleBox finalPosField[] = {null, null, null}; private DoubleBox deltaTField = null; private TextField statusField = null; private Scrollbar deltaTBar = null; private double deltaTMax = 100.0; private static int deltaTPrecision = 1000; private long eventCount = 0; // ----------------------------- // Define constructor for class which does nothing... // ----------------------------- public atc() { } // --------------------------------- // Initialize the GUI and variables. // --------------------------------- public void init() { // Make the GUI makeGUI(); } public void start() { // verify the state of the values updateValues(); } // --------------------------------------------------- // Define initializer for GUI with come help from Lava // --------------------------------------------------- private void makeGUI() { // Create the GUI system. LavaLayout mainLayout = new LavaLayout( 14, 11 ); setLayout( mainLayout ); titleLabel = new Label( "Java ATC System", Label.CENTER ); mainLayout.setConstraints( titleLabel, makeLavaCons( 0, 0, 15, 2 ) ); add( titleLabel ); titleLabel.setBackground( new Color( 148, 0, 100 ) ); titleLabel.setForeground( new Color( 255, 255, 0 ) ); xLabel = new Label( "x", Label.CENTER ); mainLayout.setConstraints( xLabel, makeLavaCons( 0, 4, 2, 1 ) ); add( xLabel ); planeStartLabel = new Label( "Plane Start", Label.CENTER ); mainLayout.setConstraints( planeStartLabel, makeLavaCons( 2, 3, 3, 1 ) ); add( planeStartLabel ); yLabel = new Label( "y", Label.CENTER ); mainLayout.setConstraints( yLabel, makeLavaCons( 0, 5, 2, 1 ) ); add( yLabel ); zLabel = new Label( "z", Label.CENTER ); mainLayout.setConstraints( zLabel, makeLavaCons( 0, 6, 2, 1 ) ); add( zLabel ); planeStartField[0] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( planeStartField[0], makeLavaCons( 2, 4, 3, 1 ) ); add( planeStartField[0] ); planeStartField[0].addPropertyChangeListener(this); planeStartField[1] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( planeStartField[1], makeLavaCons( 2, 5, 3, 1 ) ); add( planeStartField[1] ); planeStartField[1].addPropertyChangeListener(this); planeStartField[2] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( planeStartField[2], makeLavaCons( 2, 6, 3, 1 ) ); add( planeStartField[2] ); planeStartField[2].addPropertyChangeListener(this); planeVelocityLabel = new Label( "Plane Velocity", Label.CENTER ); mainLayout.setConstraints( planeVelocityLabel, makeLavaCons( 5, 3, 3, 1 ) ); add( planeVelocityLabel ); planeVelocityField[0] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( planeVelocityField[0], makeLavaCons( 5, 4, 3, 1 ) ); add( planeVelocityField[0] ); planeVelocityField[0].addPropertyChangeListener(this); planeVelocityField[1] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( planeVelocityField[1], makeLavaCons( 5, 5, 3, 1 ) ); add( planeVelocityField[1] ); planeVelocityField[1].addPropertyChangeListener(this); planeVelocityField[2] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( planeVelocityField[2], makeLavaCons( 5, 6, 3, 1 ) ); add( planeVelocityField[2] ); planeVelocityField[2].addPropertyChangeListener(this); spaceMaxLabel = new Label( "Airspace Max", Label.CENTER ); mainLayout.setConstraints( spaceMaxLabel, makeLavaCons( 8, 3, 3, 1 ) ); add( spaceMaxLabel ); spaceMinLabel = new Label( "Airspace Min", Label.CENTER ); mainLayout.setConstraints( spaceMinLabel, makeLavaCons( 11, 3, 3, 1 ) ); add( spaceMinLabel ); spaceMaxField[0] = new DoubleBox(10, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( spaceMaxField[0], makeLavaCons( 8, 4, 3, 1 ) ); add( spaceMaxField[0] ); spaceMaxField[0].addPropertyChangeListener(this); spaceMaxField[1] = new DoubleBox(10, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( spaceMaxField[1], makeLavaCons( 8, 5, 3, 1 ) ); add( spaceMaxField[1] ); spaceMaxField[1].addPropertyChangeListener(this); spaceMaxField[2] = new DoubleBox(10, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( spaceMaxField[2], makeLavaCons( 8, 6, 3, 1 ) ); add( spaceMaxField[2] ); spaceMaxField[0].addPropertyChangeListener(this); spaceMinField[0] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( spaceMinField[0], makeLavaCons( 11, 4, 3, 1 ) ); add( spaceMinField[0] ); spaceMinField[0].addPropertyChangeListener(this); spaceMinField[1] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( spaceMinField[1], makeLavaCons( 11, 5, 3, 1 ) ); add( spaceMinField[1] ); spaceMinField[1].addPropertyChangeListener(this); spaceMinField[2] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( spaceMinField[2], makeLavaCons( 11, 6, 3, 1 ) ); add( spaceMinField[2] ); spaceMinField[2].addPropertyChangeListener(this); deltaTBar = new Scrollbar( Scrollbar.HORIZONTAL, 1, deltaTPrecision/10, 0, deltaTPrecision ); mainLayout.setConstraints( deltaTBar, makeLavaCons( 4, 7, 10, 1 ) ); deltaTBar.addAdjustmentListener(this); add( deltaTBar ); deltaTLabel = new Label( "Delta t", Label.CENTER ); mainLayout.setConstraints( deltaTLabel, makeLavaCons( 0, 7, 2, 1 ) ); add( deltaTLabel ); deltaTField = new DoubleBox(0, 0, Double.MAX_VALUE, 20); mainLayout.setConstraints( deltaTField, makeLavaCons( 2, 7, 2, 1 ) ); add( deltaTField ); deltaTField.addPropertyChangeListener(this); finalPosLabel = new Label( "Final Position", Label.CENTER ); mainLayout.setConstraints( finalPosLabel, makeLavaCons( 2, 8, 3, 1 ) ); add( finalPosLabel ); finalPosField[0] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( finalPosField[0], makeLavaCons( 5, 8, 3, 1 ) ); add( finalPosField[0] ); finalPosField[0].setEnabled( false ); finalPosField[1] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( finalPosField[1], makeLavaCons( 8, 8, 3, 1 ) ); add( finalPosField[1] ); finalPosField[1].setEnabled( false ); finalPosField[2] = new DoubleBox(0, -Double.MAX_VALUE, Double.MAX_VALUE, 20); mainLayout.setConstraints( finalPosField[2], makeLavaCons( 11, 8, 3, 1 ) ); add( finalPosField[2] ); finalPosField[2].setEnabled( false ); inDuringBox = new Label( "In airspace during time period", Label.CENTER ); mainLayout.setConstraints( inDuringBox, makeLavaCons( 0, 9, 6, 1 ) ); add( inDuringBox ); inDuringBox.setEnabled( false ); inEndBox = new Label( "In airspace at the end of the time period", Label.CENTER ); mainLayout.setConstraints( inEndBox, makeLavaCons( 7, 9, 7, 1 ) ); add( inEndBox ); inEndBox.setEnabled( false ); statusField = new TextField( "", 80 ); mainLayout.setConstraints( statusField, makeLavaCons( 1, 10, 13, 1 ) ); add( statusField ); statusField.setEnabled( false ); } // -------------------------------------------- // Define a 'make grid bag constraints' method. // -------------------------------------------- public GridBagConstraints makeGridCons( int x, int y, int dx, int dy, int wx, int wy, int fill, int anch, int it, int il, int ib, int ir, int px, int py ) { // Define local variables. GridBagConstraints cons = new GridBagConstraints(); // Set the constraints. cons.weightx = wx; cons.weighty = wy; cons.gridx = x; cons.gridy = y; cons.gridwidth = dx; cons.gridheight = dy; cons.anchor = anch; cons.insets = new Insets( it, il, ib, ir ); cons.ipadx = px; cons.ipady = py; // Return the constraints to the caller. return cons; } // ---------------------------------------------- // Define a 'make LavaLayout constraints' method. // ---------------------------------------------- public LavaLayoutConstraints makeLavaCons( int x, int y, int dx, int dy ) { // Define local variables. LavaLayoutConstraints cons = new LavaLayoutConstraints(); // Set the constraints. cons.gridX = x; cons.gridY = y; cons.gridWidth = dx; cons.gridHeight = dy; // Return the constraints to the caller. return cons; } public void adjustmentValueChanged(AdjustmentEvent e) { int tempint = deltaTBar.getValue(); deltaTField.setValue(tempint*deltaTMax / (double)deltaTPrecision); validate(); updateValues(); } public void propertyChange(PropertyChangeEvent e) { double tempDouble = deltaTField.getValue(); if (tempDouble > deltaTMax) deltaTMax = tempDouble; deltaTBar.setValue((int)(tempDouble / deltaTMax * deltaTPrecision)); validate(); updateValues(); } public void validate() { boolean validRange = true; double tempMax; double tempMin; for (int i=0; i<3; i++) { tempMax = spaceMaxField[i].getValue(); tempMin = spaceMinField[i].getValue(); if (tempMin > tempMax) { spaceMaxField[i].setValue(tempMin); spaceMinField[i].setValue(tempMax); validRange = false; } } if (!validRange) { statusField.setText("Error: Airspace max must be greater than min."); } else { statusField.setText("Status OK."); } } public void updateValues() { double deltaTime = deltaTField.getValue(); double finalPos[] = {0,0,0}; boolean finalInside = true; for (int i=0; i<3; i++) { finalPos[i] = planeStartField[i].getValue() + planeVelocityField[i].getValue() * deltaTime; finalPosField[i].setValue(finalPos[i]); if (finalPos[i] < spaceMinField[i].getValue()) finalInside = false; if (finalPos[i] > spaceMaxField[i].getValue()) finalInside = false; } inEndBox.setEnabled( finalInside ); double t = rayBoxIntersect(); if ((t >= 0.0) && (t <= deltaTime) || finalInside) inDuringBox.setEnabled( true );// intersection else inDuringBox.setEnabled( false );// no intersection } // returns the time of intersection for a ray and a box // NOTE: assumes that all field values are valid double rayBoxIntersect() { // algorithm from Glassner p66 double S[] = {0,0,0}; double D[] = {0,0,0}; double max[] = {0,0,0}; double min[] = {0,0,0}; for (int i=0; i<3; i++) { S[i] = planeStartField[i].getValue(); D[i] = planeVelocityField[i].getValue(); min[i] = spaceMinField[i].getValue(); max[i] = spaceMaxField[i].getValue(); } double tnear = -100000; double tfar = 100000; double t1, t2; for (int i=0; i<3; i++) { if (Math.abs(D[i]) < 0.00001) { if ((S[i] < min[i]) || (S[i] > max[i])) { return -1; //false } } else { t1 = (min[i] - S[i]) / D[i]; // distance to first slab t2 = (max[i] - S[i]) / D[i]; // dist to second slab if (t1 > t2) { double temp = t1; t1 = t2; t2 = temp; } if (t1 > tnear) tnear = t1; if (t2 < tfar) tfar = t2; if (tnear > tfar) return -1; // missed the box if (tfar < 0) return -1; // going away from the box } } if (tnear > 0) return tnear; // true else return tfar; } }