/*
* Copyright 2006, United States Government as represented by the Administrator
* for the National Aeronautics and Space Administration. No copyright is
* claimed in the United States under Title 17, U.S. Code. All Other Rights
* Reserved.
*/
package gov.nasa.ial.mde.solver;
import java.util.ArrayList;
import gov.nasa.ial.mde.math.NumberModel;
import gov.nasa.ial.mde.math.PointXY;
import gov.nasa.ial.mde.solver.classifier.QuadraticClassifier;
import gov.nasa.ial.mde.solver.features.individual.AsymptoteFeature;
import gov.nasa.ial.mde.solver.features.individual.VertexFeature;
import gov.nasa.ial.mde.solver.symbolic.AnalyzedEquation;
/**
* Subclass of SolvedGraph responsible for recording features unique to hyperbolas.
*
* @author Dr. Robert Shelton
* @version 1.0
* @since 1.0
*/
public class SolvedHyperbola extends SolvedConic implements VertexFeature, AsymptoteFeature{
/** Identify new features so we can access them with SolvedGraph.putFeature */
protected String[] newFeatures = {
"center",
"focus",
"focalLength",
"eccentricity",
"transverseAxis",
"conjugateAxis", // axis described as lines
"transverseAxisInclination",
"conjugateAxisInclination",
"semiTransverseAxis",
"semiConjugateAxis", // lengths -- A and B
"vertex",
"asymptotes" };
/* enums for transverse axis direction */
private final static int NO_D = 0, HORIZONTAL = 1, VERTICAL = 2;
private int transverseAxisD = NO_D;
/**
* Constructs a solved hyperbola from the specifed analyzed equation.
*
* @param equation the analyzed equation.
*/
public SolvedHyperbola(AnalyzedEquation equation) {
super(equation);
/* QC is the QuadraticClassifier field in SolvedConic */
double alpha = QC.getRotation(); // rotation angle in degrees
/*
* coeffs={a, b, c, d, e} where a(u-h)^2 + b(v-k)^2 + cu + dv + e = 0
*/
double[] coeffs = QC.getNormalizedCoefficients();
PointXY center = new PointXY(QC.UV2XY(QC.getTranslation()));
String[] vars = analyzedEq.getActualVariables(); // saves a lot of typing
double transverseAxisInclination,
conjugateAxisInclination,
asymptoteInclination,
A, // semi-transverse axis
B, // semi-conjugate axis
C, // focal length
E; // eccentricity
putNewFeatures(newFeatures); // enable use of new features
putFeature("graphName", "hyperbola"); // self-explanatory
putFeature("equationType", "conic section"); // ditto
putFeature("center", center);
putFeature("graphClosure", "false"); // might be hard to determine in general
/* rule out the degenerate case */
if (coeffs[4] == 0.0)
throw new IllegalArgumentException("SolvedHyperbola.init found degenerate equation.");
/* normalize so that coeffs[4] = -1 in order to solve for A and B */
for (int i = 0; i < 5; i++)
coeffs[i] /= (-coeffs[4]);
/* Satisfy the java compiler's obsessive need for initializations */
A = B = -1.0;
/* coeffs[0] and coeffs[1] better have oppositve signs */
if (coeffs[0] * coeffs[1] >= 0.0 || coeffs[2] != 0.0 || coeffs[3] != 0.0)
throw new IllegalArgumentException("Attempt to initialize SolvedHyperbola on wrong equation.");
/*
* determine horizontal/vertical case and define A and B horizontal
* case : (u-h)^2)/A^2 - (v-k)^2/B^2 = 1 vertical case: (v-k)^2/A^2 -
* (u-h)^2/B^2 = 1
*/
if (coeffs[0] > 0) {
transverseAxisD = HORIZONTAL;
A = 1.0 / Math.sqrt(coeffs[0]);
B = 1.0 / Math.sqrt(-coeffs[1]);
} // end if
if (coeffs[1] > 0.0) {
transverseAxisD = VERTICAL;
A = 1.0 / Math.sqrt(coeffs[1]);
B = 1.0 / Math.sqrt(-coeffs[0]);
} // end if
/* might as well take care of the obvious */
putFeature("semiTransverseAxis", new NumberModel(A));
putFeature("semiConjugateAxis", new NumberModel(B));
/*
* Determine axis inclinations which depend on horizontal/vertical
* orientation
*/
switch (transverseAxisD) {
case HORIZONTAL :
transverseAxisInclination = alpha;
asymptoteInclination = 180.0 * Math.atan(B / A) / Math.PI;
break;
case VERTICAL :
transverseAxisInclination = alpha + 90.0;
asymptoteInclination = 180.0 * Math.atan(A / B) / Math.PI;
break;
default :
throw new IllegalStateException("Internal error in init");
} // end switch
conjugateAxisInclination = transverseAxisInclination + 90.0;
/* normalize angles between -179.9999 and 180.0 */
transverseAxisInclination = QuadraticClassifier.normalizeAngleInDegrees(transverseAxisInclination);
conjugateAxisInclination = QuadraticClassifier.normalizeAngleInDegrees(conjugateAxisInclination);
putFeature("transverseAxisInclination", new NumberModel(transverseAxisInclination));
putFeature("conjugateAxisInclination", new NumberModel(conjugateAxisInclination));
/* on with the rest of the calculations -- focalLength and vertices */
C = Math.sqrt(A * A + B * B);
E = C / A;
double[] vertexDisplacement = { A * Math.cos(Math.PI * transverseAxisInclination / 180.0), A * Math.sin(Math.PI * transverseAxisInclination / 180.0)};
double[] focalDisplacement = { E * vertexDisplacement[0], E * vertexDisplacement[1] };
PointXY F1 = center.sum(new PointXY(focalDisplacement));
PointXY F2 = center.difference(new PointXY(focalDisplacement));
PointXY V1 = center.sum(new PointXY(vertexDisplacement));
PointXY V2 = center.difference(new PointXY(vertexDisplacement));
putFeature("focalLength", new NumberModel(C));
putFeature("eccentricity", new NumberModel(E));
putFeature("focus", F1);
addToFeature("focus", F2);
putFeature("vertex", V1);
addToFeature("vertex", V2);
putFeature("transverseAxis", QuadraticClassifier.getEquationOfALine(center, transverseAxisInclination, vars));
putFeature("conjugateAxis", QuadraticClassifier.getEquationOfALine(center, conjugateAxisInclination, vars));
putFeature("asymptotes", QuadraticClassifier.getEquationOfALine(center, alpha + asymptoteInclination, vars));
addToFeature("asymptotes", QuadraticClassifier.getEquationOfALine(center, alpha - asymptoteInclination, vars));
addDomainAndRange();
//System.out.println(getXMLString());
//getAsymptotes();
} // end SolvedHyperbola
private void addDomainAndRange() {
String[] asymptotes = getAsymptotes();
if(asymptotes[0].contains("y")){
String D = getDomain(asymptotes[1]);
String R = getRange(asymptotes[0]);
putFeature("domain", D);
putFeature("range", R);
}else{
String D = getDomain(asymptotes[0]);
String R = getRange(asymptotes[1]);
putFeature("domain", D);
putFeature("range", R);
}
}
private String getDomain(String string) {
Solver solver = new Solver();
solver.add(string);
solver.solve();
Solution solution = solver.get(0);
SolvedGraph features = solution.getFeatures();
return ("{x such that x is all real numbers except where x = "+ ((SolvedLine) features).getXIntercept() + "}");
}
private String getRange(String string) {
Solver solver = new Solver();
solver.add(string);
solver.solve();
Solution solution = solver.get(0);
SolvedGraph features = solution.getFeatures();
return ("{y such that y is all real numbers except where y = "+ ((SolvedLine) features).getYIntercept() + "}");
}
@SuppressWarnings("unused")
private double getSlope(String string)
{
Solver solver = new Solver();
solver.add(string);
solver.solve();
Solution solution = solver.get(0);
SolvedGraph features = solution.getFeatures();
double y= ((SolvedLine)features).getYIntercept();
solver.removeAll();
return y;
}
public PointXY getVertex() {
Object value = this.getValue(VertexFeature.PATH, VertexFeature.KEY);
String vertexString = (String)value;
//System.out.println("Getting vertex.\nVertex is : " + vertexString);
String[] split = vertexString.split(",");
split[0] = split[0].replace("(", "");
split[1] = split[1].replace(")", "");
double xPos = Double.valueOf(split[0]);
double yPos = Double.valueOf(split[1]);
return (new PointXY(xPos,yPos));
}
public String[] getAsymptotes() {
Object values = this.getValues(AsymptoteFeature.PATH, AsymptoteFeature.KEY);
ArrayList<?> list = (ArrayList<?>)values;
//System.out.println("The size of the returned array is"+list.size());
String[] asymptotes = new String[list.size()];
for(int i=0;i<list.size();i++)
{
//System.out.println(list.get(i));
asymptotes[i]=(String) list.get(i);
}
return asymptotes;
}
} // end class SolvedHyperbola