Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I have a question about generalpath(). I am implementing a clock in java. I have

ID: 3736601 • Letter: I

Question

I have a question about generalpath().

I am implementing a clock in java. I have a formula to determine the position of the hands. It is degrees * (2 pi / 360) and then the cos and sin is taken. My problem is when using the following code:


   public void paintComponent(Graphics g)
   {
       Graphics2D g2 = (Graphics2D) g;
       super.paintComponent(g2);
       // draw the ticks
       int tickLen = 10;
       int medTickLen = 15;
       int longTickLen = 20;
       int r = width/2; //radius of clock
       int cX = x+(width)/2;
       int cY = y+(width)/2;
       Stroke tickStroke = new BasicStroke(2f, BasicStroke.CAP_BUTT,
               BasicStroke.JOIN_ROUND, 1f);
       GeneralPath ticksPath = new GeneralPath();
       Ellipse2D.Double clockFace = new Ellipse2D.Double(this.x,this.y,width, width);
       g2.setColor(Color.WHITE);
       g2.fill(clockFace);
       for ( int i=1; i<= 60; i++){
           // default tick length is short
           int len = tickLen;
           if ( i % 15 == 0 ){
               // Longest tick on quarters (every 15 ticks)
               len = longTickLen;
           } else if ( i % 5 == 0 ){
               // Medium ticks on the '5's (every 5 ticks)
               len = medTickLen;
           }
          
           double di = (double)i; // tick num as double for easier math
           // Get the angle from 12 O'Clock to this tick (radians)
           double angleFrom12 = di/60.0*2.0*Math.PI;
           // Get the angle from 3 O'Clock to this tick
           // Note: 3 O'Clock corresponds with zero angle in unit circle
           // Makes it easier to do the math.
           double angleFrom3 = Math.PI/2.0-angleFrom12;
           // Move to the outer edge of the circle at correct position
           // for this tick.
           ticksPath.moveTo(
                   (float)(cX+Math.cos(angleFrom3)*r),
                   (float)(cY-Math.sin(angleFrom3)*r)
                   );
      
           // Draw line inward along radius for length of tick mark
           ticksPath.lineTo(
                   (float)(cX+Math.cos(angleFrom3)*(r-len)),
                   (float)(cY-Math.sin(angleFrom3)*(r-len))
                   );
      

       }
      
       // Draw the full shape onto the graphics context.
       g2.setColor(Color.BLACK);
       g2.setStroke(tickStroke);
       g2.draw(ticksPath);
       g2.setColor(Color.RED);
       for ( int i=1; i<=12; i++){
           String numStr = ""+i;
           FontMetrics fm = g2.getFontMetrics(g2.getFont());
           int charWidth = fm.stringWidth(numStr);
           int charHeight = fm.getHeight();
           double di = (double)i;
           double angleFrom12 = di/12.0*2.0*Math.PI;
           double angleFrom3 = Math.PI/2.0-angleFrom12;
           int tx = (int)(Math.cos(angleFrom3)*(r-longTickLen-charWidth));
           int ty = (int)(-Math.sin(angleFrom3)*(r-longTickLen-charHeight));
           g2.drawString(numStr, (int)cX+tx, (int)cY+ty);
       }
      
       GeneralPath newPath = new GeneralPath();
      
       double minute = 180 * (2 * Math.PI/360);
      
       double minX = Math.cos(minute);
       double minY = Math.sin(minute);
      
       newPath.moveTo(r, r);
       newPath.lineTo(minX , minY );
      
       g2.setColor(Color.BLUE);
       g2.draw(newPath);
      
       /*
       double minuteHand = 55/60.0*2.0*Math.PI;
       double minute = Math.PI/2.0-minuteHand;
      
      
       GeneralPath minutePath = new GeneralPath();
      
       minutePath.moveTo(r, r);
       minutePath.lineTo((float)cX+Math.cos(minute)*450,(float) (cY+Math.sin(minute)*450));
       g2.draw(minutePath);
       */
   }
  
   private int x;
   private int y;
   private int width;
}

The position of the line from the generalpath only moves with very large values. WIth smaller values it always shows the line in the same place. Is there a way to scale this down so that my formula will accurately place the hands?

Thanks.

Explanation / Answer

REQUIREMENTS
Produce a Java class that will return the sine, cosine and tangent of a given angle between 0.0 and 90.0 degrees (Figure 1).


SINE, COSINE AND TANGENT TRIGONOMETRIC IDENTITIES
Figure 1: Sine, cosine and tangent trigonometric identities

2. ANALYSIS AND DESIGN
The design comprises a single class, TrigIdentitiesApp; all other methods used are contained in existing classes that come with the Java API.

2.1 TrigIdentitiesApp Class
A Nassi-Shneiderman presented in Figure 2.

NASSI-SHNEIDERMAN CHART FOR TRIG IDENTITIES APP METHOD
Fig 2: Nassi-Shneidermancharts for TrigIdentitiesApp class method

Field Summary
private static Scanner keyboardInput
           A class instance to facilitate input from the keyboard.
private static final double DEC_2_RAD
           A class constant facilitate conversion from degrees to radians.

Method Summary
public static void main(String[] args)
           Allows user to input an angle (in degrees) which is then converted to radians and the appropriate values tangent, sine and cosine ratios produced.

3. IMPLEMENTATION
// TRIGONOMETRIC IDENTITIES
// Frans Coenen
// Tuesday 12 March 1999
// Modified: Saturday 17 September 2005 (Java 2.5)
// The University of Liverpool, UK  

import java.util.*;

class TrigIdentitiesApp {

   
    public static void main(String[] args) {
    double angle;

    // Input an angle   
    System.out.print("Input an anagle between 0 and 90 " +
        "degrees inclusive: ");
    angle = keyboardInput.nextDouble();

// Convert to radians
angle = angle*DEG_2_RAD;

// Sine Angle
System.out.println("Sine is:    " + Math.sin(angle));

// Cosine Angle
System.out.println("Cosine is: " + Math.cos(angle));

// Tangent Angle
System.out.println("Tangent is: " + Math.tan(angle));
}
    }

Note that the implementation given in Table 1 uses the constant, DEG_2_RAD, to convert input in degrees to radians.

4. TESTING
TEST CASE EXPECTED RESULT
RADIUS
e java.lang.NumberFormatException
10.e java.lang.NumberFormatException
Arithmetic testing: We have one input therefore we should test negative, zero and positive inputs. A suitable set of test cases is given in the table to the right. Note that we have include a number of positive values (30, 45, 60 and 90) because these have well known results.


TEST CASE EXPECTED RESULT
angle Sine Cosine Tangent
-90 -1.00000 6.12303 -1.63318
0 0.00000 1.00000 0.00000
30 0.50000 0.86602 0.57735
45 0.70711 0.70711 1.00000
60 0.86602 0.50000 1.73205
90 1.00000 6.12303 1.63318
An alternative implementation is given in Table 2 where the toRadians class methhod from the Math is used.

import java.util.*;

class TrigIdentitiesVer2App {
   
    public static void main(String[] args) {
    double angle;

    // Input an angle   
    System.out.print("Input an anagle between 0 and 90 " +
      "degrees inclusive: ");
    angle = keyboardInput.nextDouble();

// Convert to radians
angle = Math.toRadians(angle);

// Sine Angle
System.out.println("Sine is:    " + Math.sin(angle));

// Cosine Angle
System.out.println("Cosine is: " + Math.cos(angle));

// Tangent Angle
System.out.println("Tangent is: " + Math.tan(angle));
}