Unit 6 The Trig Example
The working Applet Ass6p1.java 
|
You are to create an applet, that lets you enter 6 numbers representing the sides
and angles of a triangle: Three of these numbers are positive, and three are 0.
Your program should (using trigonometry) draw a properly scaled diagram of the
triangle, and replace the zeroes with the calculated values.
|
The Global Variables, Beans and Init Method 
|
The Labels, TextFields and Buttons inside their Layout appear at the top of
the Applet, the "North" end. The global variables are named
for triangle ABC and use single letters: a,b,c for sides, A,B,C
for angles. The local varables in contrast use the corresponding
double names: aa, bb, cc, AA, BB, CC.
|
Font f1 = new Font ("TimesRoman", Font.BOLD, 18);
Font f2 = new Font ("TimesRoman", Font.PLAIN, 12);
TextField sideA = new TextField (4);
TextField sideB = new TextField (4);
TextField sideC = new TextField (4);
TextField angleA = new TextField (4);
TextField angleB = new TextField (4);
TextField angleC = new TextField (4);
Label a_label = new Label ("side a ");
Label b_label = new Label ("side b ");
Label c_label = new Label ("side c ");
Label A_label = new Label ("angle A");
Label B_label = new Label ("angle B");
Label C_label = new Label ("angle C");
Button start = new Button ("start");
Button clear = new Button ("clear");
double a = 0;
double b = 0;
double c = 0;
double A = 0;
double B = 0;
double C = 0;
boolean ready = false;
public void init ()
{
setBackground (Color.white);
setLayout (new BorderLayout ());
Panel p = new Panel ();
add ("North", p);
p.setLayout (new GridLayout (2, 7));
p.add (a_label);
p.add (b_label);
p.add (c_label);
p.add (A_label);
p.add (B_label);
p.add (C_label);
p.add (clear);
p.add (sideA);
p.add (sideB);
p.add (sideC);
p.add (angleA);
p.add (angleB);
p.add (angleC);
p.add (start);
sideA.setText ("");
sideB.setText ("");
sideC.setText ("");
angleA.setText ("");
angleB.setText ("");
angleC.setText ("");
clear.addActionListener (this);
start.addActionListener (this);
} // end init
roundTo2
|
The Four Trigonometric Laws 
|
Given any combination of three data, the other three data may be found. There are three cautions:
There must be at least one side: Three angles are insufficient.
When all three sides are known, each side must be less than half the perimeter
An angle and one side will determine the height to the missing other side. If the third side is given, it must be larger than that height.
In the last case, there are two possibilities: One, where the other basis angle <90 and the other, where it is >90. This law should therefore be invokes only as a last resort, and then we will assume an angle <90.
|
//returns angle A of of triangle ABC
public double cosLawSSS (double bb, double aa, double cc)
{
double fraction = (bb * bb + cc * cc - aa * aa) / bb / cc / 2.0;
return Math.acos (fraction) * 57.295828;
} //end cosLawSSS
// returns side a of triangle ABC
public double cosLawSAS (double bb, double AA, double cc)
{
double aSquare = bb * bb + cc * cc - 2 * bb * cc * Math.cos (AA / 57.295828);
return Math.sqrt (aSquare);
} //end cosLawSAS
//finds angle B of triangle ABC
public double sinLawSSA (double aa, double bb, double AA)
{
double sinB = bb * Math.sin (AA / 57.295828) / aa;
return Math.asin (sinB) * 57.295828;
} //end sinLawSSA
//finds side a of triangle ABC
public double sinLawASA (double AA, double bb, double CC)
{
double BB = (180 - AA - CC) / 57.295828;
return bb * Math.sin (AA / 57.295828) / Math.sin (BB);
} //end sinLawASA
//rounds off to 2 digits
public String roundTo2 (double p)
{
return "" + Math.round (100 * p) / 100.0;
} //end roundTo2
|
Checking for valid data Ass5s3p1.java 
|
- If input data is blank or otherwise invalid, the appropriate variable becomes zero. Otherwise take the value.
- If all three angles are given, Z =0
- If all three sides are given, and they can't form a triangle, z=0
- If only two sides are given and a non-contained angle, which cannot form a triangle, the angle becomes 0.
- If more than 3 pieces of data is given, the extra pieces (angles) become 0.
- Update the text boxes.
|
// read the contents of a textfield
private double readTextBox (TextField text)
{
double val = -1;
try
{
val = Double.valueOf (text.getText ()).doubleValue ();
}
catch (NumberFormatException e)
{
val = -1;
}
if (val < 0)
val = 0;
return val;
} //end readTextBox
//zero all inputs except the first 3 positive ones
//false if there are not enough data
public boolean readySetGo ()
{
double temp;
a = readTextBox (sideA);
b = readTextBox (sideB);
c = readTextBox (sideC);
A = readTextBox (angleA);
if (A >= 180)
A = 0;
B = readTextBox (angleB);
if (B >= 180)
B = 0;
C = readTextBox (angleC);
if (C >= 180)
C = 0;
//check if all three angles are given, zero C
if (A > 0 && B > 0 && C > 0)
C = 0;
//check if 3 sides are given: if inconsistent, zero c
if (a > 0 && b > 0 && c > 0)
{
temp = (a + b + c) / 2.0;
if (temp < a || temp < b || temp < c)
c = 0;
}
//check for two sides and a noncontained angle (6 cases)
if (a == 0 && b * c * B > 0 && b < c * Math.sin (B / 57.295828))
B = 0;
if (a == 0 && b * c * C > 0 && c < b * Math.sin (C / 57.295828))
C = 0;
if (b == 0 && a * c * A > 0 && a < c * Math.sin (A / 57.295828))
A = 0;
if (b == 0 && a * c * C > 0 && c < a * Math.sin (C / 57.295828))
C = 0;
if (c == 0 && a * b * A > 0 && a < b * Math.sin (A / 57.295828))
A = 0;
if (c == 0 && a * b * B > 0 && b < a * Math.sin (B / 57.295828))
B = 0;
// discard more than 3 nonzero inputs
int count = 0;
if (a > 0)
count++;
if (b > 0)
count++;
if (c > 0)
count++;
if (A > 0 && count == 3)
A = 0;
if (A > 0)
count++;
if (B > 0 && count == 3)
B = 0;
if (B > 0)
count++;
if (C > 0 && count == 3)
C = 0;
if (C > 0)
count++;
sideA.setText (roundTo2 (a));
sideB.setText (roundTo2 (b));
sideC.setText (roundTo2 (c));
angleA.setText (roundTo2 (A));
angleB.setText (roundTo2 (B));
angleC.setText (roundTo2 (C));
if (count == 3)
return true;
return false;
} //end readySetGo
|
Find all missing information 
|
For finding the first piece of data, there are 23 distinct possibilities. However, we can reduce it to 6, if we let the angles and sides rotate. Of the 4 laws, only sinLawSSA() is not symmetric and must be used twice.
|
// rotate the values of a,b,c and of A,B,C
public void rotate ()
{
double temp = a;
a = b;
b = c;
c = temp;
temp = A;
A = B;
B = C;
C = temp;
}
public void findAll ()
{
while (a == 0 || b == 0 || c == 0 || A == 0 || B == 0 || C == 0)
{
boolean itemFound = false;
for (int i = 0 ; i < 3 ; i++)
{
if (A > 0 && B > 0 && C == 0)
{
itemFound = true;
C = 180 - A - B;
}
rotate ();
}
if (!itemFound)
for (int i = 0 ; i < 3 ; i++)
{
if (a > 0 && b > 0 && c > 0 && A == 0)
{
itemFound = true;
A = cosLawSSS (b, a, c);
}
rotate ();
}
if (!itemFound)
for (int i = 0 ; i < 3 ; i++)
{
if (a > 0 && b > 0 && C > 0 && c == 0)
{
itemFound = true;
c = cosLawSAS (a, C, b);
}
rotate ();
}
if (!itemFound)
for (int i = 0 ; i < 3 ; i++)
{
if (A > 0 && b > 0 && C > 0 && a == 0)
{
itemFound = true;
a = sinLawASA (A, b, C);
}
rotate ();
}
if (!itemFound)
for (int i = 0 ; i < 3 ; i++)
{
if (a > 0 && b > 0 && A > 0 && B == 0 && C == 0)
{
itemFound = true;
B = sinLawSSA (a, b, A);
}
rotate ();
}
if (!itemFound)
for (int i = 0 ; i < 3 ; i++)
{
if (a > 0 && b > 0 && B > 0 && A == 0 && C == 0)
{
itemFound = true;
A = sinLawSSA (b, a, B);
}
rotate ();
}
}
sideA.setText (roundTo2 (a));
sideB.setText (roundTo2 (b));
sideC.setText (roundTo2 (c));
angleA.setText (roundTo2 (A));
angleB.setText (roundTo2 (B));
angleC.setText (roundTo2 (C));
} //end findAll
|
Calculating the positions of the three Vertices and Draw the Triangle 
|
We do this in two steps:
In the standard Cartesian Coordinate system, let X be at the origin and Y along the positive x-axis
Calculating the rectangle that is then needed, and finding the scale so that its largest side will fit in 300 pixels.
Translating and reducing the points to scale
|
public void paint (Graphics g)
{
if (ready)
{
findAll ();
int xPts[] = new int [3];
int yPts[] = new int [3];
//in a Cartesian coordinate system:
// let A(0,0)
// let B along positive a-axis: B(c,0)
// then C(b*cos(A),b*sin(A))
// everything must fit inside box with diagonal (10,110) to (340,440)
double maxRight = Math.max (c, b * Math.cos (A / 57.295828));
double maxLeft = Math.min (0, b * Math.cos (A / 57.295828));
double maxTop = b * Math.sin (A / 57.295828);
double maxMin = 0;
//finding the scale factor
double scale = 300.0 / Math.max (maxRight - maxLeft, maxTop);
//recalculating the ordered pairs:
xPts [0] = (int) (-maxLeft * scale + 25);
yPts [0] = 425;
xPts [1] = (int) (xPts [0] + c * scale);
yPts [1] = 425;
xPts [2] = (int) (xPts [0] + b * Math.cos (A / 57.295828) * scale);
yPts [2] = (int) (425 - maxTop * scale);
g.setColor (Color.red);
g.fillPolygon (xPts, yPts, 3);
g.setFont (f1);
g.setColor (Color.blue);
g.drawString ("A", xPts [0] - 15, yPts [0] + 15);
g.drawString ("B", xPts [1] + 5, yPts [1] + 15);
g.drawString ("C", xPts [2] - 15, yPts [2] - 15);
g.setFont (f2);
g.setColor (Color.black);
g.drawString (roundTo2 (c), (xPts [0] + xPts [1]) / 2 - 15, 440);
g.drawString (roundTo2 (b), (xPts [0] + xPts [2]) / 2 - 24, (yPts [0] + yPts [2]) / 2);
g.drawString (roundTo2 (a), (xPts [1] + xPts [2]) / 2, (yPts [1] + yPts [2]) / 2 + 2);
}
else
g.drawString ("There is not enough data", 50, 300);
}
|
The actionPerformed method 
|
The Applet will becomes active only when one of the two buttons is pressed.
Since both the clear and start
buttons have actionListener(),
when they are pressed, the following method is executed.
|
public void actionPerformed (ActionEvent event)
{
if (event.getSource () == start)
ready = readySetGo ();
else
{
ready = false;
sideA.setText ("");
sideB.setText ("");
sideC.setText ("");
angleA.setText ("");
angleB.setText ("");
angleC.setText ("");
}
repaint ();
}
|
|
Sponsored by ECOO and SIG-Computer Science
.
|
|
|