package org.geogebra.common.kernel.prover;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.HashSet;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.algos.SymbolicParameters;
import org.geogebra.common.kernel.algos.SymbolicParametersAlgo;
import org.geogebra.common.kernel.algos.SymbolicParametersBotanaAlgo;
import org.geogebra.common.kernel.algos.SymbolicParametersBotanaAlgoAre;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoBoolean;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoLine;
import org.geogebra.common.kernel.prover.polynomial.PPolynomial;
import org.geogebra.common.kernel.prover.polynomial.PVariable;
import org.geogebra.common.util.debug.Log;
/**
* Decides if the lines are perpendicular. Can be embedded into the Prove
* command to work symbolically.
*
* @author Simon Weitzhofer 17th of May 2012
* @author Zoltan Kovacs <zoltan@geogebra.org>
*/
public class AlgoArePerpendicular extends AlgoElement
implements SymbolicParametersAlgo, SymbolicParametersBotanaAlgoAre {
private GeoLine inputLine1; // input
private GeoLine inputLine2; // input
private GeoBoolean outputBoolean; // output
private PPolynomial[] polynomials;
private PPolynomial[][] botanaPolynomials;
/**
* Tests if two lines are perpendicular
*
* @param cons
* The construction the lines depend on
* @param inputLine1
* the first line
* @param inputLine2
* the second line
*/
public AlgoArePerpendicular(Construction cons, GeoElement inputLine1,
GeoElement inputLine2) {
super(cons);
this.inputLine1 = (GeoLine) inputLine1;
this.inputLine2 = (GeoLine) inputLine2;
outputBoolean = new GeoBoolean(cons);
setInputOutput();
compute();
}
/**
* Tests if two lines are perpendicular
*
* @param cons
* The construction the lines depend on
* @param label
* the label for the AlgoArePerpendicular object
* @param inputLine1
* the first line
* @param inputLine2
* the second line
*/
public AlgoArePerpendicular(Construction cons, String label,
GeoElement inputLine1, GeoElement inputLine2) {
this(cons, inputLine1, inputLine2);
outputBoolean.setLabel(label);
}
@Override
public Commands getClassName() {
return Commands.ArePerpendicular;
}
@Override
protected void setInputOutput() {
input = new GeoElement[2];
input[0] = inputLine1;
input[1] = inputLine2;
super.setOutputLength(1);
super.setOutput(0, outputBoolean);
setDependencies(); // done by AlgoElement
}
/**
* Gets the result of the test
*
* @return true if the lines are perpendicular and false otherwise
*/
public GeoBoolean getResult() {
return outputBoolean;
}
@Override
public final void compute() {
outputBoolean.setValue(inputLine1.isPerpendicular(inputLine2));
}
@Override
public SymbolicParameters getSymbolicParameters() {
return new SymbolicParameters(this);
}
@Override
public void getFreeVariables(HashSet<PVariable> variables)
throws NoSymbolicParametersException {
if (inputLine1 != null && inputLine2 != null) {
inputLine1.getFreeVariables(variables);
inputLine2.getFreeVariables(variables);
return;
}
throw new NoSymbolicParametersException();
}
@Override
public int[] getDegrees() throws NoSymbolicParametersException {
if (inputLine1 != null && inputLine2 != null) {
int[] degree1 = inputLine1.getDegrees();
int[] degree2 = inputLine2.getDegrees();
int[] degree = new int[1];
degree[0] = Math.max(degree1[0] + degree2[0],
degree1[1] + degree2[1]);
return degree;
}
throw new NoSymbolicParametersException();
}
@Override
public BigInteger[] getExactCoordinates(
HashMap<PVariable, BigInteger> values)
throws NoSymbolicParametersException {
if (inputLine1 != null && inputLine2 != null) {
BigInteger[] coords1 = ((SymbolicParametersAlgo) input[0])
.getExactCoordinates(values);
BigInteger[] coords2 = ((SymbolicParametersAlgo) input[1])
.getExactCoordinates(values);
BigInteger[] coords = new BigInteger[1];
coords[0] = coords1[0].multiply(coords2[0])
.add(coords1[1].multiply(coords2[1]));
return coords;
}
throw new NoSymbolicParametersException();
}
@Override
public PPolynomial[] getPolynomials() throws NoSymbolicParametersException {
Log.debug(polynomials);
if (polynomials != null) {
return polynomials;
}
if (inputLine1 != null && inputLine2 != null) {
PPolynomial[] coords1 = ((SymbolicParametersAlgo) input[0])
.getPolynomials();
PPolynomial[] coords2 = ((SymbolicParametersAlgo) input[1])
.getPolynomials();
polynomials = new PPolynomial[1];
polynomials[0] = coords1[0].multiply(coords2[0])
.add(coords1[1].multiply(coords2[1]));
return polynomials;
}
throw new NoSymbolicParametersException();
}
@Override
public PPolynomial[][] getBotanaPolynomials()
throws NoSymbolicParametersException {
if (botanaPolynomials != null) {
return botanaPolynomials;
}
if (inputLine1 != null && inputLine2 != null) {
PVariable[] v1 = ((SymbolicParametersBotanaAlgo) inputLine1)
.getBotanaVars(inputLine1); // (a1,a2,b1,b2)
PVariable[] v2 = ((SymbolicParametersBotanaAlgo) inputLine2)
.getBotanaVars(inputLine2); // (c1,c2,d1,d2)
botanaPolynomials = new PPolynomial[1][1];
botanaPolynomials[0][0] = PPolynomial.perpendicular(v1[0], v1[1],
v1[2], v1[3], v2[0], v2[1], v2[2], v2[3]);
return botanaPolynomials;
}
return null;
}
}