|  | 
         
          | This program simulates both the drop experiment and 
              the detector:   
              
                 
                  |  |   
                  | 
                      DropTestDetectApplet.java 
                        - 
                        simulate an experiment that measures the acceleration 
                        of a dropped mass. The detector looks at the times when 
                        the mass crosses fixed positions and calculates the change 
                        in velocity between the top pair and the bottom pair of 
                        measurements.  + New 
                        Classes: DropPanelDetect.java 
                        - a subclass of PlotPanel 
                        that displays the experiment simulation, i.e. the falling 
                        mass, and also the detector. The Detector object is passed 
                        the Graphics context object so that it can draw itself 
                        onto the panel.
 
 DropModelDetect.java 
                        - generates the physics data for the simulation. It invokes 
                        the measure(-) method of the instance of the Detector 
                        type passed to it after every step in time.
 
 DropDetector1.java 
                        - implementation of Detector, this class simulates the 
                        detector that measures the times when the mass crosses 
                        set positions. It uses the information on the mass's position 
                        and time obtained from the DropModelDetect instance. It 
                        displays the detector on the DropPanelDetect display.
 
 Detector.java 
                        - interface to allow for generic detectors. DropModelDetect 
                        will invoke the method "measure(,,)" method 
                        for any implementation of this interface, such as DropDetector1. 
                        If other Detector implementations are are used, the code 
                        in DropModelDetect does not need modification.
  + Previous 
                        Classes:Chapter 
                        7: Tech: Histogram.java, 
                        HistPanel.java
 Chapter 
                        6: Tech: PlotPanel.java, 
                        PlotFormat.java
 
 |    The path of the dropping ball is now crossed by lines representing 
              sensors such as pairs of lights and photodiodes that detect the 
              shadowing as the ball goes by. The travel times between pairs of 
              marker lines are measured by the detector and displayed on a histogram.  
              
                 
                  | DropTestDetectApplet |   
                  | import 
                      javax.swing.*;import java.awt.*;
 import java.awt.event.*;
 
 /**
 * This program simulates an experiment in which 
                      the time of the
 * fall of a mass in a constant gravitational 
                      field is measured.
 * It illustrates the basic components of a simulation 
                      of any
 * physics experiment.
 *
 * The applet uses DropPanelDetect to simulate 
                      the dropping of a
 * mass in a constant gravitational field. A 
                      HistPanel displays
 * a histogram of the measurements of the acceleration. 
                      The
 * DropDetector class draws the detector.
 *
 * The java.util.Timer and java.util.TimerTask 
                      are used
 * to update the animation of the drop.
 *
 * Includes "Drop" button to initiate the dropping.
 *
 * The number of drops and a speed factor taken 
                      from 2 text fields.
 * "Reset"  button clears the histogram.
 * In standalone mode, the Exit button closes 
                      the program.
 *
 * This program will run as an applet inside
 * an application frame.
 *
 **/
 public class DropTestDetectApplet extends JApplet
 implements ActionListener
 {
 // The DropPanel displays the animation of the
 // falling mass.
 DropPanelDetect fDropPanel;
 
 // The DropModel generates the physics data.
 DropModelDetect fDropModel;
 
 // Use the HistPanel JPanel subclass here
 HistPanel fHistPanel;
 
 Histogram fHistogram;
 int fNumDataPoints = 100;
 
 boolean fMakingHist = false;
 boolean fUpdateDisplay = false;
 
 // Use the java.util Timer and TimerTask combo
 // for timing events.
 java.util.Timer fTimer;
 
 // A text field for getting number of drops 
                      per
 // run and the time factor
 JTextField fMaxNumDropsField;
 JTextField fTFactorField;
 
 // Flag for whether the applet is in a browser
 // or running via the main () below.
 boolean fInBrowser = true;
 
 //Buttons
 JButton fGoButton;   // start drop
 JButton fClearButton;// resets histogram
 JButton fExitButton;
 
 // Starting coordinates of drop
 double fXBallStart =  25.0; // cm
 double fYBallStart = 200.0; // cm
 double fYBallEnd   =   0.0; 
                      // cm
 
 // Use a detector to measure the drop times.
 Detector fDetector;
 
 // Mark the positions  (in cm) where 
                      the detector measures
 // the ball dropping.
 double [] fYMarkers = { 190.0,180.0, 30.0, 20.0};
 
 // SD in the measured values for the marker 
                      positions and t (sec).
 //  (Allow for smearing of marker 
                      position for further experimentation.)
 double []fYMarkerSigmas = {  0.1, 
                      0.0005};
 
 // Coordinate of ball.
 double fXBall;
 double fYBall;
 
 // Initial velocity.
 double fVyBallStart = 0.0;
 double fVxBallStart = 0.0;
 
 // Time in millisecs for the drop
 double fTDropTotal;
 double fTFrame = 0.020; // in secs
 
 // Speed up or slow down factor for animation:
 double fTFactor = 1.0;
 
 // Allow for multiple drops per "run"
 int fMaxNumDrops = 10;
 int fNumDrops = 0;
 
 /**
 *  Initialize the display. 
                      Create Detector and Model
 *  objects to use for 
                      the physics and experiment simulation.
 *  DropPanelDetect displays 
                      the dropping ball and the
 *  detector. Add a HistPanel 
                      to display the data.
 
 
 **/
 public void init () {
 
 // Create a detector
 fDetector = new DropDetector1 ();
 // Pass the detector the parameters 
                      to use.
 fDetector.init (null, fYMarkers,fYMarkerSigmas);
 
 // Create the drop physics model
 fDropModel = new DropModelDetect 
                      (fDetector);
 fDropModel.reset (fYBallStart, fVyBallStart);
 
 JPanel panel = new JPanel (new BorderLayout 
                      ());
 
 // Use a textfield to get the number 
                      of drops per run.
 fMaxNumDropsField =
 new JTextField (Integer.toString 
                      (fMaxNumDrops), 10);
 
 // Use a textfield to get the number 
                      of drops per run.
 fTFactorField =
 new JTextField (Double.toString 
                      (fTFactor), 10);
 
 // If return hit after entering 
                      text, the
 // actionPerformed will be invoked.
 fMaxNumDropsField.addActionListener 
                      (this);
 fTFactorField.addActionListener 
                      (this);
 
 fGoButton = new JButton ("Drop");
 fGoButton.addActionListener (this);
 
 // Here the clear button will reset 
                      the histogram
 fClearButton = new JButton ("Reset");
 fClearButton.addActionListener (this);
 
 fExitButton = new JButton ("Exit");
 fExitButton.addActionListener (this);
 
 JPanel control_panel = new JPanel 
                      (new GridLayout (1,2));
 JPanel panel1 = new JPanel (new 
                      GridLayout (1,2));
 JPanel panel2 = new JPanel (new 
                      GridLayout (1,3));
 
 panel1.add (fMaxNumDropsField);
 panel1.add (fTFactorField);
 
 panel2.add (fGoButton);
 panel2.add (fClearButton);
 panel2.add (fExitButton);
 
 control_panel.add (panel1);
 control_panel.add (panel2);
 
 // Create an instance of the DropPanel
 // Make the panel 10% taller than 
                      starting position.
 fDropPanel = new DropPanelDetect 
                      (fYBallStart*1.1, 0.0, fDetector);
 
 // Create a histogram to plot the 
                      variance in the
 // drop times.
 fHistogram = new Histogram ("Acceleration","dv/dt",
 25,500.0,1500.0);
 fHistPanel = new HistPanel (fHistogram);
 
 JPanel holder_panel = new JPanel 
                      (new GridLayout (1,2));
 holder_panel.add (fDropPanel);
 holder_panel.add (fHistPanel);
 
 panel.add (holder_panel,"Center");
 panel.add (control_panel,"South");
 
 // Add text area with scrolling 
                      to the content pane.
 add (panel);
 
 } // init
 
 /** Stop the timer if the browser page unloaded. 
                      **/
 public void stop () {
 runDone ();
 } //stop
 
 /**
 *  Respond to the buttons. 
                      For a click on "Drop" button,
 *  execute the number 
                      of drops in the text field.
 *  Also, obtain the animation 
                      speed factor from the other
 *  text field. The Reset 
                      button will clear the histogram
 *  and reset the drop 
                      stats.
 **/
 public void actionPerformed (ActionEvent e) 
                      {
 Object source = e.getSource ();
 if (source == fGoButton) {
 if (fGoButton.getText 
                      ().equals ("Drop")) {
 try {
 fMaxNumDrops 
                      =
 Integer.parseInt 
                      (fMaxNumDropsField.getText ());
 fTFactor 
                      =
 Double.parseDouble 
                      (fTFactorField.getText ());
 }
 catch (NumberFormatException 
                      ex) {
 // 
                      Could open an error dialog here but just
 // 
                      display a message on the browser status line.
 showStatus 
                      ("Bad input value");
 return;
 }
 dropReset 
                      ();
 fGoButton.setText 
                      ("Stop");
 fClearButton.setEnabled 
                      (false);
 
 } else {
 dropDone 
                      ();
 }
 }
 else if (source == fClearButton) 
                      {
 fHistogram.clear 
                      ();
 repaint 
                      ();
 }
 else if (!fInBrowser)
 System.exit 
                      (0);
 
 } // actionPerformed
 
 
 /**
 *  Before each set of 
                      drops, need to create a new timer,
 *  and set up its schedule. 
                      The PaintHistTask innner class
 *  object will do the 
                      setup for each frame of a drop animation.
 **/
 void dropReset () {
 
 // Before starting the drop, create 
                      the timer task
 // that will cause the histogram 
                      display to update
 // during the filling.
 // Create a timer. TimerTask created 
                      in MakeHist ()
 fTimer = new java.util.Timer ();
 
 fDropModel.reset (fYBallStart, fVyBallStart);
 fDropPanel.reset (fXBallStart, fYBallStart);
 
 // Start the timer after 20ms and 
                      then repeat calls
 // to run in PaintHistTask object 
                      by the rate set by
 // the fTFrame value.
 fTimer.schedule (new PaintHistTask 
                      (), 20, (int) (fTFrame*1000));
 
 // Reset time sum
 fTDropTotal = 0.0;
 fNumDrops = 0;
 fYBall = fYBallStart;
 fXBall = fXBallStart;
 
 // Reset the detector.
 fDetector.reset ();
 
 } // dropReset
 
 /**
 * Use the inner class technique 
                      to define the
 * TimerTask subclass for stepping 
                      through the
 * drop calculation and the frame 
                      refresh.
 *
 * Use the real time in the drop 
                      calculation instead
 * of the given frame rate times 
                      in case there were
 * delays from thread interruptions, 
                      the processing
 * in the parts of the program take 
                      extra time, etc.
 **/
 class PaintHistTask extends java.util.TimerTask
 {
 public void run () {
 
 // Drop the ball
 fYBall = fDropModel.step 
                      (fTFactor * fTFrame);
 
 // Update the position 
                      of the ball in the
 // animation and redraw 
                      the frame.
 fDropPanel.updatePosition 
                      (fXBall, fYBall);
 
 // Check if ball has 
                      crossed the finish line.
 if ( fYBall <= fYBallEnd) 
                      dropDone ();
 
 } // run
 } // PaintHistTask
 
 /**
 *  Invoked when all the 
                      drops are done. Reset
 *  all the parameters 
                      to set up for another drop.
 **/
 public void dropDone () {
 // Analyze the detector data
 analyseData ();
 
 ++fNumDrops;
 
 // Check if all drops completed.
 if ( fNumDrops == fMaxNumDrops){
 // If so 
                      then finish up the data recording
 // for this 
                      run and return.
 runDone 
                      ();
 return;
 }
 
 // Reset time sum
 fTDropTotal = 0.0;
 fYBall = fYBallStart;
 fXBall = fXBallStart;
 
 fDropPanel.reset (fXBallStart, fYBallStart);
 fDropModel.reset (fYBallStart, fVyBallStart);
 fDetector.reset ();
 
 } // dropDone
 
 /**
 *  Get the data measurements from 
                      the detector and calculate
 *  and plot data and derived values.
 */
 public void analyseData () {
 
 double [][] measuredTimes = fDetector.getResults 
                      ();
 int numMarkers = measuredTimes[0].length;
 
 // Get the average velocity over 
                      the top gap
 double dtMeasured = measuredTimes[0][1] 
                      - measuredTimes[0][0];
 double dy = fYMarkers[0] - fYMarkers[1];
 double velTop = dy/dtMeasured;
 
 // Get the average velocity over 
                      the bottom gap
 dtMeasured = measuredTimes[0][numMarkers-1] 
                      -
 measuredTimes[0][numMarkers-2];
 dy = fYMarkers[numMarkers-2] - fYMarkers[numMarkers-1];
 double velBot = dy/dtMeasured;
 
 
 double tTop =  (measuredTimes[0][1]+measuredTimes[0][0])/2.0;
 double tBot =
 (measuredTimes[0][numMarkers-1]+measuredTimes[0][numMarkers-2])/2.0;
 
 // Get the change in velocity between 
                      the two gaps.
 double accel =
 (velBot-velTop)/ (tBot-tTop);
 
 fHistogram.add (accel);
 } // analyseData
 
 /**
 *  Invoked when all the 
                      drops in a set are done. Kills
 *  the timer.  (A 
                      new timer will be created in dropReset ()
 *  for a new set of drops.)
 *  Display the histogram 
                      with the additional data.
 **/
 public void runDone () {
 
 // Stop the animation.
 fTimer.cancel ();
 
 // Update histogram
 fHistPanel.repaint ();
 
 // Reset the buttons.
 fGoButton.setText ("Drop");
 fClearButton.setEnabled (true);
 } // runDone
 
 /** Offer the option of running the applet in 
                      an app frame. **/
 public static void main (String[] args) {
 //
 int frame_width=450;
 int frame_height=300;
 
 //
 DropTestDetectApplet applet = new 
                      DropTestDetectApplet ();
 applet.fInBrowser = false;
 applet.init ();
 
 // Following anonymous class used 
                      to close window & exit program
 JFrame f = new JFrame ("Drop Test");
 f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
 
 // Add applet to the frame
 f.getContentPane ().add ( applet);
 f.setSize (new Dimension (frame_width,frame_height));
 f.setVisible (true);
 } // main
 
 } // DropTestDetectApplet
 |   
                  | DropPanelDetect |   
                  | import 
                    java.awt.*; import javax.swing.*;
 
 /**
 *  This subclass of PlotPanel provides 
                    a
 *  display for a dropped object.
 **/
 public class DropPanelDetect extends PlotPanel
 {
 
 Color fBgColor = Color.WHITE;
 Color fBallColor = Color.RED;
 
 double fXBall, fYBall;
 int fXBallOld=0,fYBallOld=-1;
 double fXStart,fYStart;
 
 // Limits for the vertical scale
 double fYDataMax = 2000.0; // Height in cm
 double fYDataMin =    0.0;
 
 // Limits for the horizontal scale
 double fXDataMax = 50.0;
 double fXDataMin =  0.0;
 
 // Numbers to use for plotting axes scale values
 double [] fXScaleValue = new double[2];
 double [] fYScaleValue;
 int fNumYScaleValues = 5;
 int fNumXScaleValues = 2;
 
 Detector fDetector;
 
 /**
 *  Create the panel and 
                    set up the scaling for the
 *  box in which to plot 
                    the dropped object.
 
 *  Pass a link to the detector, 
                    which will
 *  draw itself on the animation.
 *
 *  @param fYDataMax - vertical 
                    scale max limit  (cm)
 *  @param fYDataMin - vertical 
                    scale min limit  (cm)
 **/
 public DropPanelDetect (double y_data_max, double 
                    y_data_min,
 Detector detector) {
 fDetector = detector;
 
 fYDataMax = y_data_max;
 fYDataMin = fYDataMin;
 
 // Starting point
 fYStart = y_data_max * 0.9;
 fYBall = fYStart;
 fXBall = fXDataMax/2.0;// Put ball 
                    in middle
 
 // The horizontal axes scaling will 
                    be fixed
 // Use arbitrary default of 0 to 50 
                    for scale.
 fXScaleValue[0] = 0.0;
 fXScaleValue[fNumXScaleValues-1] = 
                    fXDataMax;
 
 // The vertical  (y) values 
                    can be changed
 // so do the scaling in this method.
 getScaling ();
 
 setBackground (fBgColor);
 } // ctor
 
 /**
 * Get the values for the scaling numbers on
 * the vertical axis in case the limits have
 * changed.
 */
 void getScaling () {
 getPositions ();
 
 fYScaleValue = new double[fNumYScaleValues];
 
 fYScaleValue[0] = fYDataMin;
 fYScaleValue[fNumYScaleValues-1] = 
                    fYDataMax;
 
 // Then calculate the difference between 
                    the values
 double range = fYScaleValue[fNumYScaleValues-1]
 - 
                    fYScaleValue[0];
 double del = range/ (fNumYScaleValues-1);
 
 // Now set the intermediate scale 
                    values.
 for (int i=1; i <  (fNumYScaleValues-1); 
                    i++) {
 fYScaleValue[i] 
                    = i*del + fYScaleValue[0];
 }
 } // getScaling
 
 /**
 *  For each time increment, 
                    update the position
 *  of the falling object.
 **/
 public void updatePosition (double x, double y){
 
 fXBall = x;
 fYBall = y;
 if (y >= fYDataMin){
 repaint ();
 }
 } // updatePosition
 
 /**
 *  For a new drop, reset 
                    the starting position
 *  and redraw the plot area.
 **/
 public void reset (double fXStart, double fYStart){
 fXBall = fXStart;
 fYBall = fYStart;
 fYBallOld=-1;
 
 fYDataMax = fYStart * 1.1;
 getScaling ();
 
 repaint ();
 
 } // reset
 
 /** Draw the ball falling. */
 void paintContents (Graphics g) {
 // Draw the numbers along the axes
 drawAxesNumbers (g, fXScaleValue, 
                    fYScaleValue);
 
 // Need conversion factor from data 
                    scale to pixel scale
 double y_convert = fFrameHeight/ (fYDataMax-fYDataMin);
 double x_convert = fFrameWidth/fXDataMax;
 
 // For dropped object use size relative 
                    to the frame.
 int sym_dim =  (int) (fFrameWidth 
                    *.02);
 
 // Clear previous  ball 
                    position
 if (fYBallOld > 0 ){
 g.setColor (fBgColor);
 g.fillOval (fXBallOld-sym_dim,fYBallOld-sym_dim, 
                    2*sym_dim, 2*sym_dim);
 }
 
 // Draw detector in first frame.
 fDetector.draw (g,fFrameX,fFrameY,fFrameWidth,fFrameHeight,
 x_convert,y_convert);
 
 // Set the foreground color back to 
                    the ball color
 g.setColor (fBallColor);
 
 int x =  (int)(fXBall*x_convert)+fFrameX;
 int y = fFrameHeight -  (int)(fYBall*y_convert)+fFrameY;
 
 g.fillOval (x-sym_dim,y-sym_dim, 2*sym_dim, 
                    2*sym_dim);
 
 // Save current ball coords for erasure 
                    in
 // next frame.
 fXBallOld=x;fYBallOld=y;
 
 } // paintContents
 
 /**
 * Return the title at the top of the 
                    plot.
 * Overrides method in PlotPanel.
 **/
 String getTitle ()
 {  return "Drop Tower Demo";}
 
 /**
 * Return the label on the horizontal 
                    axis.
 * Overrides method in PlotPanel.
 **/
 String getXLabel ()
 {  return "";}
 
 } // DropPanelDetect
 |   
                  | DropModelDetect |   
                  | /** *  This class models the dropping of 
                    a mass in
 *  a constant gravitational field.
 **/
 public class DropModelDetect
 {
 // Initial coordinates.
 double fYStart  = 100.0;
 double fVyStart = 0.0;
 
 // Parameters of the dropped mass.
 double t, y, vy;
 
 // Keep track of time in the drop.
 double fTotalT = 0.0;
 
 // Constant gravitational field at the surface 
                    of the earth.
 final static double G_ACCEL  = -980.0;// 
                    centimeter per sec**2
 
 // Need a reference to a detector
 Detector fDetector;
 
 // Need an array for passing data to the detector.
 double [] fVals = new double[2];
 
 /**
 * Pass a reference to the detector 
                    for this
 * physics model.
 **/
 public DropModelDetect (Detector detector){
 fDetector = detector;
 } // ctor
 
 /**
 *  Set the initial vertical 
                    position and velocity
 *  and the number of integration 
                    steps for a given
 *  delta time value.
 **/
 public void reset (double y_start, double vy_start){
 fYStart  = y_start;
 fVyStart = vy_start;
 y  = y_start;
 vy = vy_start;
 fTotalT = 0.0;
 } // reset
 
 /**
 *  Calculate the change 
                    in position and velocity
 *  for each increment in 
                    time between animation frames.
 *  For accurate measurements, 
                    the detector needs finer
 *  increments in time, so 
                    the integration of the equations
 *  of motion occur at a 
                    finer scale than the frame time.
 *
 *  As the speed increases, 
                    the distance covered in an fixed
 *  time interval increases. 
                    To maintain similar precision in
 *  vertical position measurements, 
                    the fine step sizes are made
 *  smaller in proportional 
                    to the speed.
 *
 *  @dt dt is the frame time 
                    for the animation.
 **/
 public double step (double dt) {
 
 // Measure the drop in substeps of 
                    the frame dt
 // Keep the substeps small enough 
                    for an inital vy
 // such that an increment in 0.01cm 
                    can be detected
 int n_increments = 40;
 double delT;
 
 delT = dt/n_increments;
 double total_del_t = 0.0;
 
 // Cycle through substeps
 for (int i=0; i < n_increments; i++) 
                    {
 y = y + vy * delT;
 vy = vy + G_ACCEL * delT;
 total_del_t = i * delT;
 
 // Now send the current 
                    position and time
 // info to the detector.
 fVals[0] = y;
 fVals[1] = fTotalT + total_del_t;
 fDetector.measure (fVals);
 }
 
 // Sum the accumlated time so far.
 fTotalT += dt;
 
 return y;
 } // step
 
 } // DropModelDetect
 |  
                  | DropDetector1 |   
                  | import 
                    java.awt.*; 
 /**
 *  This class simulates a detector measuring 
                    the
 *  the time it takes for a mass to drop 
                    in the
 *  drop simulation.
 **/
 public class DropDetector1 implements Detector
 {
 double [] fSigmas;
 double [][] fData;
 
 int fNumMarkers;
 double []  fMarkerLines;
 double []  fMarkerTimes;
 boolean [] fMarkerFlags;
 
 boolean fAllMarkersCrossed;
 
 // Create an instance of the Random class for
 // producing our random values.
 static java.util.Random fRan = new java.util.Random 
                    ();
 
 /** Setup the detector. **/
 public void init (int [] setup,
 double [] marker_lines,
 double [] sigmas){
 
 // Get the S.D. for the measured parameters 
                    of interest.
 fSigmas = sigmas;
 
 // Get the positions of the markers 
                    .
 fMarkerLines = marker_lines;
 fNumMarkers = marker_lines.length;
 fMarkerTimes = new double [fNumMarkers];
 fMarkerFlags = new boolean [fNumMarkers];
 
 // The data 2-D array used to pass 
                    measurements back.
 // For this case, only one array of 
                    data needed.
 fData = new double [1][];
 fData [0] = fMarkerTimes;
 
 reset ();
 }
 
 /**  Initialize for each drop. **/
 public void reset () {
 // Reset variables
 for (int i=0; i < fNumMarkers; i++) 
                    {
 fMarkerFlags[i] = false;
 }
 fAllMarkersCrossed = false;
 }
 
 /**
 *  For the y and accumulated 
                    drop time, obtain the
 *  simulated measured time 
                    by a Gaussian smearing.
 
 *  @param vals - 2 element 
                    array with the y and time values.
 *
 **/
 public void measure (double [] vals) {
 if ( fAllMarkersCrossed) return;
 
 // Find if a marker line reached yet.
 for (int i=0; i < fNumMarkers; i++) 
                    {
 if (!fMarkerFlags[i] &&
 fMarkerLines[i] 
                    >= vals[0]) {
 fMarkerFlags[i]=true;
 if (i == fNumMarkers-1) 
                    fAllMarkersCrossed = true;
 
 // Smear the 
                    time measure according to the given
 // Gaussian 
                    SD value.
 fMarkerTimes[i] 
                    = vals[1] +
 fSigmas[1] 
                    * fRan.nextGaussian ();      ;
 }
 }
 
 } // measure
 
 /** Return the measurement times at each marker. 
                    **/
 public double [][] getResults (){
 return fData;
 }
 
 
 /** Return the number of measured points along 
                    the drop. **/
 public int getNumMeasurements () {
 return fNumMarkers;
 }
 
 /**
 *  Draw the detector markers 
                    as horizonatal lines.
 *  Also draw some vertical 
                    lines it indicate a drop
 *  area.
 **/
 public void draw (Graphics g, int x0, int y0, 
                    int dx, int dy,
 double 
                    x_convert, double y_convert) {
 
 Color origColor = g.getColor ();
 g.setColor (Color.BLUE);
 
 // Draw the vertical sides of detector
 int x_side_left = x0 +  (int) 
                    (0.25 * dx);
 int x_side_rite = x0 +  (int) 
                    (0.75 * dx);
 int y_side_1 =    y0 
                    +  (int) (0.10 * dy);
 int y_side_2 =    y0 
                    +  (int) (0.95 * dy);
 
 g.drawLine (x_side_left,y_side_1,x_side_left,y_side_2);
 g.drawLine (x_side_rite,y_side_1,x_side_rite,y_side_2);
 
 // Draw the horizontal marker lines 
                    where the
 // falling mass is detected.
 g.setColor (Color.ORANGE);
 int x_marker_1 = x0 +  (int) 
                    (0.30 * dx);
 int x_marker_2 = x0 +  (int) 
                    (0.70 * dx);
 
 for (int i=0; i < fNumMarkers; i++) 
                    {
 int yMark 
                    = y0 + dy -  (int) (fMarkerLines[i]*y_convert);
 g.drawLine 
                    (x_marker_1,yMark,x_marker_2,yMark);
 }
 
 // Return to previous color.
 g.setColor (origColor);
 
 } // draw
 
 } // DropDetector1
 
 |   
                  | Detector 
                    (interface) |   
                  | import 
                    java.awt.*; 
 /** Interface for detectors to measure drop positions. **/
 public interface Detector {
 public void init (int [] setup, double [] params, 
                    double [] sigmas);
 public void reset ();
 public void measure (double [] x);
 public double [][] getResults ();
 public int getNumMeasurements ();
 
 public void draw (Graphics g, int x0, int y0, 
                    int dx, int dy,
 double x_convert, double y_convert);
 } // Detector
 |    Most recent update: Oct. 25, 2005 |  |  |