package org.geogebra.common.kernel.barycentric;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.arithmetic.Equation;
import org.geogebra.common.kernel.arithmetic.ValidExpression;
import org.geogebra.common.kernel.commands.AlgebraProcessor;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoNumberValue;
import org.geogebra.common.kernel.geos.GeoPoint;
import org.geogebra.common.kernel.implicit.GeoImplicit;
import org.geogebra.common.kernel.parser.ParseException;
import org.geogebra.common.kernel.parser.Parser;
import org.geogebra.common.main.AlgoCubicSwitchParams;
import org.geogebra.common.util.debug.Log;
/**
* @author Darko Drakulic
* @version 23-10-2011
*
* This class makes a curve in barycentric coordinates
*
*/
public class AlgoCubic extends AlgoElement {
private GeoPoint A, B, C; // input
private GeoNumberValue n; // number of curve
private GeoImplicit poly; // output
/**
* Creates new triangle cubic algo
*
* @param cons
* construction
* @param label
* label
* @param A
* first point
* @param B
* second point
* @param C
* third point
* @param e
* index in CTC
*/
public AlgoCubic(Construction cons, String label, GeoPoint A, GeoPoint B,
GeoPoint C, GeoNumberValue e) {
super(cons);
kernel.getApplication().getAlgoCubicSwitch();
this.A = A;
this.B = B;
this.C = C;
this.n = e;
poly = kernel.newImplicitPoly(cons);
setInputOutput();
compute();
poly.setLabel(label);
}
@Override
public Commands getClassName() {
return Commands.Cubic;
}
// for AlgoElement
@Override
protected void setInputOutput() {
input = new GeoElement[4];
input[0] = A;
input[1] = B;
input[2] = C;
input[3] = n.toGeoElement();
setOutputLength(1);
setOutput(0, poly.toGeoElement());
setDependencies(); // done by AlgoElement
}
/**
* Returns the resulting curve
*
* @return the resulting curve
*/
public GeoImplicit getResult() {
return poly;
}
@Override
public final void compute() {
if (kernel.getApplication().getAlgoCubicSwitch() == null) {
poly.setUndefined();
return;
}
// Check if the points are aligned
double c = A.distance(B);
double b = C.distance(A);
double a = B.distance(C);
double x1 = A.inhomX;
double y1 = A.inhomY;
double x2 = B.inhomX;
double y2 = B.inhomY;
double x3 = C.inhomX;
double y3 = C.inhomY;
String equation = "";
double det = (-x2 + x3) * (y1 - y3) + (x1 - x3) * (y2 - y3);
if (Kernel.isZero(det)) {
poly.setUndefined();
return;
}
String Astr = "(" + (x3 - x2) / det + "*y + " + (y2 - y3) / det
+ "*x - " + ((x3 - x2) * y3 + (y2 - y3) * x3) / det + ")";
String Bstr = "(" + (x1 - x3) / det + "*y + " + (y3 - y1) / det
+ "*x - " + ((x1 - x3) * y1 + (y3 - y1) * x1) / det + ")";
String Cstr = "(" + (x2 - x1) / det + "*y + " + (y1 - y2) / det
+ "*x - " + ((x2 - x1) * y2 + (y1 - y2) * x2) / det + ")";
equation = kernel.getApplication()
.cubicSwitch(new AlgoCubicSwitchParams(n.getDouble(), a, b, c));
if (equation == null) {
poly.setUndefined();
return;
}
equation = equation.replace("A", Astr);
equation = equation.replace("B", Bstr);
equation = equation.replace("C", Cstr);
equation = equation.replace("a", "" + a);
equation = equation.replace("b", "" + b);
equation = equation.replace("c", "" + c);
Parser parser = getKernel().getParser();
AlgebraProcessor algebraProcessor = getKernel().getAlgebraProcessor();
ValidExpression ve = null;
try {
ve = parser.parseGeoGebraExpression(equation);
GeoImplicit result = (GeoImplicit) (algebraProcessor
.processEquation((Equation) ve, ve.wrap(), true)[0]);
result.remove();
poly.setCoeff(result.getCoeff());
poly.setDefined();
} catch (ParseException e) {
poly.setUndefined();
Log.error(equation);
}
}
}